@a-t-h-i/bot-lobby 0.5.1 → 0.6.1
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 +180 -44
- package/package.json +1 -1
- package/prompts/panel.md +6 -2
- package/prompts/planner.md +29 -16
- package/src/execution/pi-runner.ts +1 -1
- package/src/index.ts +4 -2
- package/src/lobby/feed.ts +65 -9
- package/src/lobby/keys.ts +5 -1
- package/src/lobby/layout.ts +17 -2
- package/src/lobby/planner.ts +16 -5
- package/src/lobby/runtime.ts +317 -61
- package/src/lobby/session-files.ts +138 -0
- package/src/lobby/sessions.ts +314 -0
- package/src/lobby/tabs/home.ts +145 -29
- package/src/lobby/tabs/plan.ts +25 -30
- package/src/lobby/tabs/quickfix.ts +5 -8
- package/src/lobby/tabs/tasks.ts +200 -51
- package/src/lobby/view.ts +763 -89
- package/src/pi/commands.ts +52 -6
- package/src/pi/events.ts +5 -2
- package/src/pi/notify.ts +18 -0
- package/src/pi/owner.ts +265 -0
- package/src/pi/settings-ui.ts +6 -2
- package/src/pi/start-task.ts +33 -2
- package/src/pi/ui.ts +3 -3
- package/src/pi/zen-large.ts +9 -1
- package/src/pi/zen.ts +7 -3
- package/src/schemas/configuration.ts +8 -3
- package/src/schemas/task.ts +4 -0
- package/src/state/archive.ts +99 -0
- package/src/state/auto.ts +40 -0
- package/src/state/inbox.ts +124 -0
- package/src/state/presence.ts +99 -0
- package/src/workflow/workflow.ts +27 -3
package/README.md
CHANGED
|
@@ -70,15 +70,16 @@ pi install npm:@juicesharp/rpiv-ask-user-question
|
|
|
70
70
|
It is optional for the Master. Without it `clarify` still works through Pi's
|
|
71
71
|
built-in `select`/`input` prompts (or the Master asks in plain text), just with
|
|
72
72
|
less structure. The lobby's planning panel uses the same questionnaire on its
|
|
73
|
-
own — the library ships as a bot-lobby dependency, so
|
|
74
|
-
arrive
|
|
75
|
-
Master (see [The lobby](#the-lobby)).
|
|
73
|
+
own — the library ships as a bot-lobby dependency, so each round's questions
|
|
74
|
+
arrive together in one dialog with options whether or not you install the tool
|
|
75
|
+
for the Master (see [The lobby](#the-lobby)).
|
|
76
76
|
|
|
77
77
|
## Usage
|
|
78
78
|
|
|
79
79
|
```
|
|
80
80
|
/bot-lobby Open the lobby (alt+l): tasks, planning, quick fixes, metrics
|
|
81
81
|
/bot-lobby <request> Start a task and hand it to the Master
|
|
82
|
+
/bot-lobby --task [--auto] <request> Start a task even when the request begins with a subcommand word
|
|
82
83
|
/bot-lobby status [taskId] Active task, state, approvals, blockers, legal next states
|
|
83
84
|
/bot-lobby tasks Task list (plus any unreadable task state)
|
|
84
85
|
/bot-lobby pause | resume Stop or allow further workflow steps
|
|
@@ -93,6 +94,9 @@ Master (see [The lobby](#the-lobby)).
|
|
|
93
94
|
/bot-lobby-settings Same as the settings subcommand
|
|
94
95
|
/bot-lobby minimize|restore Hide or restore bot-lobby for this session (ctrl+shift+m)
|
|
95
96
|
/bot-lobby claim <taskId> Take ownership of an orphaned task
|
|
97
|
+
/bot-lobby auto [on|off] Auto mode: the oracle drives this session's task to completion (alt+g)
|
|
98
|
+
/bot-lobby start-plan PLAN-… [auto] Start a saved plan here; its agreed plan needs no approval
|
|
99
|
+
/bot-lobby switch <session.jsonl> Run a saved session in this window (the session browser's s)
|
|
96
100
|
/bot-lobby lobby | help Open the lobby, or show this list
|
|
97
101
|
```
|
|
98
102
|
|
|
@@ -107,43 +111,73 @@ or without a task.
|
|
|
107
111
|
|
|
108
112
|
```
|
|
109
113
|
◆ bot-lobby │ 1 Lobby 2 Tasks 2 3 Plan 2? 4 Quick fix ⠋ 5 Metrics ⠋ TASK-add-login implementing Alt+H keys
|
|
110
|
-
(the
|
|
111
|
-
╭ Conversation
|
|
112
|
-
│
|
|
113
|
-
│
|
|
114
|
-
│
|
|
115
|
-
│
|
|
116
|
-
|
|
114
|
+
(the task's status: state, what the agents are doing, the plan checklist)
|
|
115
|
+
╭ Conversation ──────────────────────────────── Alt+C ╮ ╭ Activity ──────────────────────────────── Alt+A ╮
|
|
116
|
+
│ ──────── task started · add login · 12:04 ───────── │ │ 12:04 MASTER ✓ scouting designer, backend │
|
|
117
|
+
│ 12:04 You ● │ │ 12:06 DEV ⠋ reading auth.ts… │
|
|
118
|
+
│ add a login page with email + password ▐ │ │ 12:06 DESIGN ⠋ editing LoginForm.tsx… │
|
|
119
|
+
│ ◆ Oracle 12:06 │ │ 12:06 QUICK FIX ✓ done: rename getUser │
|
|
120
|
+
│ Proposal │ │ │
|
|
121
|
+
│ • LoginForm component │ │ │
|
|
122
|
+
│ • POST /api/login with rate limiting │ │ │
|
|
123
|
+
╰─────────────────────────────────────────────────────╯ ╰─────────────────────────────────────────────────╯
|
|
117
124
|
╭ Thinking ────────────────────────────────────────────────────────────────────────────────── DEV · 12s ago ╮
|
|
118
125
|
│ The auth module already exposes a session helper; reuse it rather than adding a new one. │
|
|
119
126
|
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
120
127
|
── message the oracle ───────────────────────────────────────────────────────────────────────────────────────
|
|
121
128
|
_
|
|
122
|
-
TYPE enter send
|
|
129
|
+
TYPE enter send esc browse alt+l hide
|
|
123
130
|
```
|
|
124
131
|
|
|
125
|
-
- **1 Lobby** — the task's
|
|
126
|
-
|
|
132
|
+
- **1 Lobby** — the task's status (its state box, what the agents are
|
|
133
|
+
doing and the plan checklist), then the conversation with the oracle
|
|
134
|
+
laid out like a chat (its text only: no tool rows, no thinking): your
|
|
135
|
+
messages on the right as bubbles in the accent colour on pi's
|
|
136
|
+
user-message background, each only as wide as its text (at most about
|
|
137
|
+
three quarters of the pane), under `12:04 You ●`; the oracle's replies on
|
|
138
|
+
the left as Markdown under `◆ Oracle 12:06`; and events such as a task
|
|
139
|
+
starting as a centred rule), an activity log that narrates
|
|
127
140
|
every tool call in plain words (`reading index.html…`, `searching for
|
|
128
141
|
"router" in src`, `running npm test`, `delegating to backend: Step 2 …`) from
|
|
129
142
|
the Master and every subagent, and a single **Thinking** pane — the one place
|
|
130
143
|
thoughts show up: the oracle's live thought as it streams, and each finished
|
|
131
144
|
thought from a subagent, quick fix or the planner (pi's own transcript,
|
|
132
145
|
behind the lobby, still carries the oracle's thinking blocks; `ctrl+t`
|
|
133
|
-
collapses them there). The oracle's replies render as Markdown.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
collapses them there). The oracle's replies render as Markdown. To keep
|
|
147
|
+
the lobby clean, the animated oracle and agents stay out of it by default:
|
|
148
|
+
they show above pi's editor while the lobby is hidden, and `alt+z` brings
|
|
149
|
+
them into the lobby too (the status box names the key in its corner). `alt+c`, `alt+a` and `alt+k` hide or bring back the conversation,
|
|
150
|
+
the activity log and thinking, and the rest take their room; every choice is
|
|
151
|
+
remembered (`lobby.panels`). Each pane scrolls on
|
|
137
152
|
its own (see **Scrolling** below), and a pane scrolled back stays on what
|
|
138
153
|
you are reading while new lines arrive. The prompt talks to the
|
|
139
154
|
oracle (while it works, enter steers the running turn; `esc` stops it); with
|
|
140
155
|
no task, it starts one.
|
|
141
|
-
- **2 Tasks** — every task in the project: this session's, the
|
|
142
|
-
sessions are driving, pending plans saved from the planner, and
|
|
143
|
-
finished ones
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
- **2 Tasks** — every task in the project as a checklist: this session's, the
|
|
157
|
+
ones other pi sessions are driving, pending plans saved from the planner, and
|
|
158
|
+
recently finished ones, each section under a rule with its count. A task or
|
|
159
|
+
plan still to do wears an empty box `☐` (coloured by its state) with its
|
|
160
|
+
state, auto mode and owner beneath and its plan progress as pips
|
|
161
|
+
(`▰▰▱▱ 2/4`); a completed task is ticked `☑`, and an abandoned one is crossed
|
|
162
|
+
`☒` with its title struck through. The detail pane shows the task's box,
|
|
163
|
+
state and progress bar, then the request, the plan's steps (`☑` done, `☐`
|
|
164
|
+
to do, `◂ now` on the current one), the approved plan, your comments on it,
|
|
165
|
+
amendments, what the task waits on and its recent runs. `c` comments on the selected task's plan (see below), `s`
|
|
166
|
+
starts a pending plan as a task **in a new session** and `h` starts it
|
|
167
|
+
here, in this window (either way its agreed plan needs no approval), `d`
|
|
168
|
+
twice discards one. `n` types a new task that starts in its own session, `o`
|
|
169
|
+
shows the session driving the selected task, `x` twice stops a background
|
|
170
|
+
session, and `alt+g` switches auto mode for the selected task. Rows say who
|
|
171
|
+
drives each task (`this session`, `background`, another running session, or
|
|
172
|
+
`not running` once its session has ended) and mark auto mode `⟳ auto`.
|
|
173
|
+
**Cleaning up:** every finished task is listed, and `a` archives the
|
|
174
|
+
selected one — it leaves every list and moves, folder and all, to
|
|
175
|
+
`.pi/bot-lobby/archive/tasks/` (a task still under way is abandoned first,
|
|
176
|
+
so `a` asks twice). `A` twice archives every finished task at once. `v`
|
|
177
|
+
shows the archive as an ARCHIVED section, where `a` restores a task as it
|
|
178
|
+
was. `d` twice deletes a task, on the list or in the archive, for good. A
|
|
179
|
+
task a running session drives (this window's, a background one, or another
|
|
180
|
+
terminal's) is left alone until that session stops or cancels it.
|
|
147
181
|
- **3 Plan** — task planning mode with a planning panel. Describe what you
|
|
148
182
|
want and every seat grills you from its own domain, on the model and
|
|
149
183
|
thinking level its settings name: **DEV** (APIs, data, errors, security,
|
|
@@ -151,15 +185,18 @@ or without a task.
|
|
|
151
185
|
accessibility), **QA** (acceptance criteria, test strategy, edge cases,
|
|
152
186
|
definition of done) and **RESEARCH** (libraries, versions, docs and prior
|
|
153
187
|
art, with the web tools when `pi-web-access` is installed). The **oracle**
|
|
154
|
-
chairs on the Planner model: it reads the seats' questions and notes
|
|
155
|
-
every answer into the draft plan (with a *Decisions by domain*
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
188
|
+
chairs on the Planner model: it reads the seats' questions and notes and
|
|
189
|
+
folds every answer into the draft plan (with a *Decisions by domain*
|
|
190
|
+
section). Each round the seats run in parallel, read-only, then the oracle,
|
|
191
|
+
which **chooses at most four questions** for you from the seats' and its own
|
|
192
|
+
— merged, in plain words, the most decisive first — and decides the rest
|
|
193
|
+
with the recommended option, listed under *Assumptions* in the draft so you
|
|
194
|
+
can see and overrule them (comment on the line). The round's questions come
|
|
195
|
+
in **one** ask-user-question dialog: a tab per question labelled with the
|
|
196
|
+
seat it serves (`QA`, `DEV`…), two to four options with what each means,
|
|
197
|
+
the recommendation first (so `enter` on each accepts it), a row to type your
|
|
198
|
+
own answer or add a note, and a Submit tab that reviews everything and lets
|
|
199
|
+
you leave a question blank (the oracle then takes its recommendation). It opens by itself when a
|
|
163
200
|
round ends while the Plan tab is showing (`lobby.autoAsk`), and otherwise
|
|
164
201
|
when you press `enter` on the empty prompt or `a` while browsing; `esc` puts
|
|
165
202
|
it away with your answers so far kept, and `enter` resumes. Your answers go
|
|
@@ -176,8 +213,7 @@ or without a task.
|
|
|
176
213
|
line is marked `◆` with your comment beneath it, and the comment goes to the
|
|
177
214
|
panel with your answers — or starts a round by itself when no question is
|
|
178
215
|
open. While browsing, `1`–`4` seat or unseat DEV, DESIGN, QA and RESEARCH
|
|
179
|
-
for the next round, `
|
|
180
|
-
over, `r` retries a round that failed or lost a seat, `x` stops one, and `m`
|
|
216
|
+
for the next round, `n` starts over, `r` retries a round that failed or lost a seat, `x` stops one, and `m`
|
|
181
217
|
opens the oracle's (Planner) settings.
|
|
182
218
|
- **4 Quick fix** — a direct prompt, the way you would ask pi, that skips the
|
|
183
219
|
whole workflow: one coding agent (full tools) makes the change right away
|
|
@@ -214,13 +250,19 @@ typing). These work in both modes:
|
|
|
214
250
|
| `alt+h` (or `?` while browsing) | show every key, and the current tab's |
|
|
215
251
|
| `alt+s` | bot-lobby settings: every agent's model, thinking and time limit, and the lobby's switches |
|
|
216
252
|
| `ctrl+f` (or `/` while browsing) | search the current tab |
|
|
253
|
+
| `ctrl+s` | save the plan from the Plan tab to the pending tasks — while typing too, from any tab |
|
|
254
|
+
| `alt+o` | the session browser: view, message or switch to any session in the project |
|
|
255
|
+
| `alt+n` | type a new task that starts in its own session, named after it |
|
|
256
|
+
| `alt+g` | auto mode on or off for the task in view (the selected one on Tasks) |
|
|
217
257
|
| `tab` / `shift+tab`, `alt+1`…`alt+5` | switch tabs |
|
|
218
|
-
| `alt+z`
|
|
258
|
+
| `alt+z` | show or hide the oracle and agent animations in the lobby (off by default; the task's status always shows) |
|
|
259
|
+
| `alt+c` / `alt+a` / `alt+k` | show or hide the conversation / activity log / thinking |
|
|
219
260
|
| `pageup` / `pagedown` | scroll the focused pane a page |
|
|
220
261
|
| `ctrl+c` | clear the prompt, or hide the lobby when it is empty |
|
|
221
262
|
|
|
222
263
|
Every shortcut can be rebound under `lobby.keys` in the config, by action name:
|
|
223
|
-
`hide`, `help`, `settings`, `search`, `
|
|
264
|
+
`hide`, `help`, `settings`, `search`, `savePlan`, `sessions`, `newSession`,
|
|
265
|
+
`toggleAuto`, `nextTab`, `prevTab`, `toggleScene`,
|
|
224
266
|
`toggleConversation`, `toggleActivity`, `toggleThinking`, `scrollUp`,
|
|
225
267
|
`scrollDown` — e.g. `"keys": { "toggleThinking": "alt+t" }`. Pick keys that
|
|
226
268
|
never type a character (`alt+…`, `ctrl+…`, `f1`…).
|
|
@@ -268,6 +310,91 @@ approved plan while implementing or reviewing, keeps finished steps done and
|
|
|
268
310
|
marks the comments addressed (`○` waiting, `◐` sent to the oracle, `✓` plan
|
|
269
311
|
amended). Before a plan exists, a comment asks for a revised proposal instead.
|
|
270
312
|
|
|
313
|
+
## Several sessions from one window
|
|
314
|
+
|
|
315
|
+
Start a task in a new session without leaving your terminal, and switch
|
|
316
|
+
between sessions from the lobby.
|
|
317
|
+
|
|
318
|
+
- **Start one.** `alt+n` (or `n` on the Tasks tab) opens the prompt for a new
|
|
319
|
+
task; `enter` starts it in its own pi session. `s` on a saved plan does the
|
|
320
|
+
same for the plan. The new session is a headless pi (`pi --mode rpc`) this
|
|
321
|
+
window launches with the same pi build, model and extensions, and it is an
|
|
322
|
+
ordinary saved session **named after its task** — `/resume` lists it by
|
|
323
|
+
that name. Sessions a task starts are named after it too (`/bot-lobby
|
|
324
|
+
<request>` in a fresh session names that session).
|
|
325
|
+
- **Watch and talk to it.** The Lobby tab then shows that session: its task's
|
|
326
|
+
status, its conversation, activity log and thoughts, live. The tab bar names
|
|
327
|
+
the session in view (`◆ add signup form · working`), the prompt messages
|
|
328
|
+
its oracle (steering it while it works) and `esc` stops its running turn.
|
|
329
|
+
- **Answer it.** When a background session asks something — an approval, a
|
|
330
|
+
clarifying question — the tab bar shows `● 1 waiting`, and `enter` on the
|
|
331
|
+
empty prompt puts the question to you in this window with pi's own dialog
|
|
332
|
+
(`esc` there cancels it, as it would in that session). With the lobby
|
|
333
|
+
hidden, a notice says who is waiting.
|
|
334
|
+
- **Browse.** `alt+o` opens the session browser: every session in the
|
|
335
|
+
project, grouped by where it runs — **this window**, the **background**
|
|
336
|
+
sessions it started (working, idle or ended, `⟳` auto mode, `●` questions
|
|
337
|
+
waiting), sessions running in **other terminals** (with or without a task),
|
|
338
|
+
and tasks whose session is **not running** (it ended, or none ever took
|
|
339
|
+
the task). Beside the list, a preview of the one picked: where it runs, its
|
|
340
|
+
task and progress, what `enter` and `s` do with it, and the end of its
|
|
341
|
+
conversation. Every running session keeps a heartbeat in
|
|
342
|
+
`.pi/bot-lobby/sessions/` so the others can see it; one that goes quiet or
|
|
343
|
+
whose process ends drops off.
|
|
344
|
+
- **View.** `enter` shows the picked session in the Lobby tab. A background
|
|
345
|
+
session streams live; for another terminal's session or a task that is not
|
|
346
|
+
running, the conversation comes from its saved session file. What you type
|
|
347
|
+
goes to its oracle: a background session is steered directly, another
|
|
348
|
+
terminal's session gets it through its inbox within a few seconds, and a
|
|
349
|
+
task that is not running keeps it in its task inbox (`inbox.jsonl`) until a
|
|
350
|
+
session picks the task up.
|
|
351
|
+
- **Switch.** `s` — in the browser, or while browsing a session shown in the
|
|
352
|
+
Lobby tab — runs that session in this window with pi's own session switch
|
|
353
|
+
(through `/bot-lobby switch`), and the lobby comes back on it. A background
|
|
354
|
+
session's process is stopped first, so only this window writes its
|
|
355
|
+
session; a task that is not running resumes its session here (one that no
|
|
356
|
+
session ever owned is taken over instead, like `/bot-lobby claim`). A
|
|
357
|
+
session running in another terminal stays there: switch in that terminal,
|
|
358
|
+
or close it and resume it here. Not while this window's oracle is working.
|
|
359
|
+
The session this window leaves keeps its task, which then shows as not
|
|
360
|
+
running until you switch back.
|
|
361
|
+
- **Stop or start.** `x` twice stops a background session; `n` starts a new
|
|
362
|
+
task in a new session.
|
|
363
|
+
|
|
364
|
+
Background sessions belong to the window that started them: they keep running
|
|
365
|
+
while you switch pi sessions there, and stop when that pi exits. Their tasks
|
|
366
|
+
keep their state, so `/resume` (by the task's name) or `/bot-lobby claim`
|
|
367
|
+
picks one up later.
|
|
368
|
+
|
|
369
|
+
## Auto mode
|
|
370
|
+
|
|
371
|
+
Auto mode lets the oracle drive a task to completion without asking you
|
|
372
|
+
anything. Switch it with `alt+g` — in the lobby for the task in view (or the
|
|
373
|
+
one selected on Tasks), outside it for this session's task — or with
|
|
374
|
+
`/bot-lobby auto [on|off]`; `/bot-lobby --task --auto <request>` and
|
|
375
|
+
`/bot-lobby start-plan PLAN-… auto` start a task with it on. The tab bar shows
|
|
376
|
+
`⟳ AUTO`. While it is on:
|
|
377
|
+
|
|
378
|
+
- clarifying questions are not asked: the oracle decides from the request,
|
|
379
|
+
the plan and its reconnaissance, and each decision is recorded
|
|
380
|
+
(`Not asked (auto mode): …`); the ask-user-question tool is blocked with the
|
|
381
|
+
same instruction;
|
|
382
|
+
- the proposal is approved without asking, and dependency and architecture
|
|
383
|
+
approvals a worker asks for are granted and recorded;
|
|
384
|
+
- when the oracle's turn ends before the task is done, the session nudges it
|
|
385
|
+
to keep going. A nudge that changes nothing counts; after three in a row
|
|
386
|
+
auto mode pauses and says the task needs you, and it resumes as soon as the
|
|
387
|
+
task moves again.
|
|
388
|
+
|
|
389
|
+
The switch lives beside the task (`auto.json`), so any session can flip it for
|
|
390
|
+
any task and the session that drives it follows within a few seconds.
|
|
391
|
+
|
|
392
|
+
**Agreed plans skip approval.** A task started from a plan saved in the Plan
|
|
393
|
+
tab (`s`/`h` on Tasks, or `/bot-lobby start-plan`) records the plan it came
|
|
394
|
+
from, and its proposal is approved without asking you again — you agreed the
|
|
395
|
+
plan with the panel already. Clarifying questions are still decided by the
|
|
396
|
+
oracle for such a task, since the plan answered them.
|
|
397
|
+
|
|
271
398
|
## Sessions and ownership
|
|
272
399
|
|
|
273
400
|
A task is owned by the pi session that started it (`ctx.sessionManager` id,
|
|
@@ -293,8 +420,8 @@ every in-flight subagent process.
|
|
|
293
420
|
|
|
294
421
|
While the owning session has a task active, its transcript switches to a zen view: `orchestrate` rows
|
|
295
422
|
and the built-in spinner are hidden, and a widget above the editor animates the
|
|
296
|
-
task (the
|
|
297
|
-
|
|
423
|
+
task (the widget shows while the lobby is hidden; inside the lobby the same
|
|
424
|
+
scene shows only with `alt+z`, its status box otherwise). At 72 columns and wider it draws a large scene: a header box with the task
|
|
298
425
|
title and state in its top border, a progress bar, and a metadata row with
|
|
299
426
|
elapsed time, quiet-mode hint and task id; an oracle tower with a twinkling
|
|
300
427
|
aura (drifting z's while dormant), a radiant orb crown, two window eyes, a
|
|
@@ -572,7 +699,7 @@ flips its switches, and key rebinding lives in the file:
|
|
|
572
699
|
"autoAsk": true,
|
|
573
700
|
"issues": false,
|
|
574
701
|
"mouse": true,
|
|
575
|
-
"panels": { "
|
|
702
|
+
"panels": { "animations": false, "conversation": true, "activity": true, "thinking": true },
|
|
576
703
|
"keys": { "toggleThinking": "alt+t" }
|
|
577
704
|
}
|
|
578
705
|
```
|
|
@@ -583,7 +710,9 @@ by itself when this session starts or resumes a task; `autoAsk` puts the
|
|
|
583
710
|
panel's questions to you as soon as a round ends while the Plan tab is
|
|
584
711
|
showing (otherwise `enter` on the empty prompt does); `issues` shows the
|
|
585
712
|
GitHub Issues tab (off for now); `mouse` turns clicks and the wheel on;
|
|
586
|
-
`panels` is which Lobby panes show
|
|
713
|
+
`panels` is which Lobby panes show, with `animations: true` bringing the
|
|
714
|
+
animated oracle and agents into the lobby (off by default; the older
|
|
715
|
+
`scene` key is no longer read, and the pane keys update it); `keys` rebinds
|
|
587
716
|
shortcuts by action name.
|
|
588
717
|
|
|
589
718
|
`thinking` must be one of `off`, `minimal`, `low`, `medium`, `high`, `xhigh`,
|
|
@@ -629,11 +758,16 @@ and the output contract — and an empty layer is dropped.
|
|
|
629
758
|
├── Backend/knowledge/ knowledge.md, engineering-standards.md, decisions.md, completed-tasks.md
|
|
630
759
|
├── QA/knowledge/ knowledge.md, testing-standards.md, decisions.md, completed-tasks.md
|
|
631
760
|
├── archive/<Agent>/ previous knowledge versions (outside all retrieval paths)
|
|
761
|
+
├── archive/tasks/TASK-…/ archived tasks, whole, out of every list until restored
|
|
762
|
+
├── sessions/<id>.json heartbeats of the pi sessions running in the project
|
|
763
|
+
├── sessions/<id>.inbox.jsonl messages for a running session's oracle, and their delivery
|
|
632
764
|
├── backlog/PLAN-<slug>.json pending tasks saved from the planner (optionally linked to an issue)
|
|
633
765
|
├── metrics.jsonl one line per finished run of any agent, for the Metrics tab
|
|
634
766
|
└── tasks/TASK-<stamp>/
|
|
635
767
|
├── state.json the task record (kept after completion)
|
|
636
768
|
├── comments.jsonl your lobby comments on the plan and their delivery (append-only)
|
|
769
|
+
├── inbox.jsonl messages for the oracle from other sessions and their delivery (append-only)
|
|
770
|
+
├── auto.json auto mode, when switched on for the task
|
|
637
771
|
├── proposal.md scratchpads: deleted on completion
|
|
638
772
|
├── plan.md
|
|
639
773
|
├── designer.md backend.md qa.md
|
|
@@ -682,8 +816,10 @@ src/
|
|
|
682
816
|
├── knowledge/ Paths, store (single write path), selector, compactor
|
|
683
817
|
├── prompts/ Layer loader + compiler
|
|
684
818
|
├── lobby/
|
|
685
|
-
│ ├── runtime.ts Mounts the full-screen lobby on pi's TUI, dialogs hand-off,
|
|
686
|
-
│ ├── view.ts The tabbed view: tab bar, per-tab prompt, typing/browsing modes, search, help, mouse
|
|
819
|
+
│ ├── runtime.ts Mounts the full-screen lobby on pi's TUI, dialogs hand-off, background sessions, Master metrics
|
|
820
|
+
│ ├── view.ts The tabbed view: tab bar, per-tab prompt, typing/browsing modes, session switcher, search, help, mouse
|
|
821
|
+
│ ├── sessions.ts Background sessions: headless pi children driven over RPC, their feeds and questions
|
|
822
|
+
│ ├── session-files.ts Other sessions' conversations, read from their saved session files
|
|
687
823
|
│ ├── keys.ts The shortcut table and its config overrides
|
|
688
824
|
│ ├── ask.ts The panel's questions through the ask-user-question questionnaire (or pi's dialogs)
|
|
689
825
|
│ ├── markdown.ts Markdown through pi's renderer, cached per theme and width
|
|
@@ -693,9 +829,9 @@ src/
|
|
|
693
829
|
│ ├── planner.ts The planning panel: seats and the oracle per round, reply parsing, saving a plan
|
|
694
830
|
│ ├── issues.ts GitHub issues through the gh CLI
|
|
695
831
|
│ └── layout.ts Boxes, exact-width columns, wrapping, highlights, bars, meters and sparklines
|
|
696
|
-
├── state/ Project root, config, task persistence, state mutation, comments, backlog, metrics
|
|
832
|
+
├── state/ Project root, config, task persistence, state mutation, comments, inbox, auto mode, backlog, metrics
|
|
697
833
|
├── schemas/ Task, agent, findings, configuration types
|
|
698
|
-
└── pi/ Commands, lifecycle, orchestrate tool, status widget
|
|
834
|
+
└── pi/ Commands, lifecycle, orchestrate tool, status widget, the owner's clock (deliveries, auto mode)
|
|
699
835
|
prompts/ global, master, designer, backend, qa, scout, worker, reviewer, researcher, quickfix, planner, panel
|
|
700
836
|
```
|
|
701
837
|
|
package/package.json
CHANGED
package/prompts/panel.md
CHANGED
|
@@ -16,10 +16,14 @@ questions and the user's answers, and the oracle's current draft plan.
|
|
|
16
16
|
- Ask only what your seat owns (below), and only what would change how the
|
|
17
17
|
task is built or verified. Never repeat a question that has been answered,
|
|
18
18
|
or one another member already asked this round.
|
|
19
|
-
- Ask at most two questions, the most important first.
|
|
20
|
-
|
|
19
|
+
- Ask at most two questions, the most important first. They go to the
|
|
20
|
+
oracle, who picks at most four for the user each round across the whole
|
|
21
|
+
panel and decides the rest with your recommendation, so make each one
|
|
22
|
+
short, plain and specific, and give it two to four options, your
|
|
21
23
|
recommendation first with `(Recommended)` after its label. The user can
|
|
22
24
|
always type their own answer instead, so do not add an "Other" option.
|
|
25
|
+
- Read the draft's Assumptions: if one the oracle made for your seat is
|
|
26
|
+
wrong, say so under Notes and ask about it again.
|
|
23
27
|
- If an answer from the user is vague or conflicts with what you see in the
|
|
24
28
|
repository, say so and ask again.
|
|
25
29
|
- Report what the plan must respect from your seat under Notes: facts from
|
package/prompts/planner.md
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
You are the oracle chairing a planning panel: you help the user turn an idea
|
|
4
4
|
(or a GitHub issue) into a task plan that the team of agents can execute
|
|
5
5
|
without guessing. The panel's domain members — DEV, DESIGN, QA and RESEARCH —
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
user
|
|
6
|
+
bring you their questions each round, and you decide which ones reach the
|
|
7
|
+
user: you own the plan and the questions. You are thorough but you spare the
|
|
8
|
+
user: every decision that changes the implementation gets made, either by the
|
|
9
|
+
user or by you with the recommended option, written down as an assumption the
|
|
10
|
+
user can overrule. You never
|
|
9
11
|
write code and never change files; you may read the repository to ask
|
|
10
12
|
informed questions and to ground the plan in what exists.
|
|
11
13
|
|
|
@@ -17,16 +19,24 @@ and notes. Read the repository when it helps, then reply in the output format
|
|
|
17
19
|
below.
|
|
18
20
|
|
|
19
21
|
- Fold every member's notes and every answer into the draft plan, so each
|
|
20
|
-
domain's decisions are written down where all agents will read them.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
domain's decisions are written down where all agents will read them.
|
|
23
|
+
- Choose the round's questions: **at most four in all**, from the members'
|
|
24
|
+
questions and your own cross-cutting ones (scope and non-goals, priorities,
|
|
25
|
+
trade-offs between domains, sequencing, rollout). Merge duplicates, drop
|
|
26
|
+
what the repository or an earlier answer already settles, and keep only the
|
|
27
|
+
ones whose answer changes what gets built. Put the most important first and
|
|
28
|
+
start each with the seat it serves — `[DEV]`, `[DESIGN]`, `[QA]`,
|
|
29
|
+
`[RESEARCH]`, or `[ORACLE]` for your own. When members disagree, make that
|
|
30
|
+
one of the questions.
|
|
31
|
+
- Keep each question short and plain: one line the user can answer at a
|
|
32
|
+
glance. Give it two to four options — labels of one to five words and a
|
|
33
|
+
short clause on what each means — your recommendation first with
|
|
34
|
+
`(Recommended)` after its label. The user answers all of them together in
|
|
35
|
+
one dialog and can type their own answer, so never add an "Other" option.
|
|
36
|
+
- Decide every question you do not ask, and any the user leaves unanswered,
|
|
37
|
+
with its recommended option, and list those decisions under
|
|
38
|
+
`### Assumptions` in the plan, one line each, so the user can see and
|
|
39
|
+
overrule them.
|
|
30
40
|
- Challenge answers that are vague, contradictory or risky, and ask again.
|
|
31
41
|
Do not accept "whatever you think" for a decision with real trade-offs:
|
|
32
42
|
propose one and ask the user to confirm it.
|
|
@@ -46,13 +56,14 @@ GRILLING or READY
|
|
|
46
56
|
Three to six words naming the task.
|
|
47
57
|
|
|
48
58
|
## Questions
|
|
49
|
-
1. The most important open question?
|
|
59
|
+
1. [DEV] The most important open question?
|
|
50
60
|
- Short label (Recommended) — what choosing it means
|
|
51
61
|
- Another label — what choosing it means
|
|
52
62
|
2. …
|
|
53
63
|
|
|
54
|
-
(
|
|
55
|
-
Questions section when READY
|
|
64
|
+
(At most four questions, each tagged with its seat; two to four options per
|
|
65
|
+
question, labels of one to five words. Omit the Questions section when READY
|
|
66
|
+
or when you decided everything yourself.)
|
|
56
67
|
|
|
57
68
|
## Plan
|
|
58
69
|
The current draft, in Markdown:
|
|
@@ -64,6 +75,8 @@ The current draft, in Markdown:
|
|
|
64
75
|
(files, modules and domains: designer, backend, qa)
|
|
65
76
|
### Decisions by domain
|
|
66
77
|
(what the user decided for DEV, DESIGN, QA and RESEARCH, one bullet each)
|
|
78
|
+
### Assumptions
|
|
79
|
+
(what you decided without asking, each with its seat: "[QA] Test in evergreen browsers only")
|
|
67
80
|
### Steps
|
|
68
81
|
1. …
|
|
69
82
|
### Risks and open points
|
|
@@ -348,7 +348,7 @@ export function parsePiStream(stdout: string): ParsedStream {
|
|
|
348
348
|
* every child process, including test runners and scripts, where argv[1] is
|
|
349
349
|
* not pi at all.
|
|
350
350
|
*/
|
|
351
|
-
function resolvePiInvocation(args: string[]): { command: string; args: string[] } {
|
|
351
|
+
export function resolvePiInvocation(args: string[]): { command: string; args: string[] } {
|
|
352
352
|
const launcher = process.argv[1];
|
|
353
353
|
if (launcher && existsSync(launcher) && isPiLauncher(launcher)) {
|
|
354
354
|
return { command: launcher, args };
|
package/src/index.ts
CHANGED
|
@@ -3,16 +3,18 @@ import { registerCommands } from "./pi/commands.ts";
|
|
|
3
3
|
import { registerLifecycle } from "./pi/events.ts";
|
|
4
4
|
import { registerOrchestrateTool } from "./pi/tools.ts";
|
|
5
5
|
import { onTransition } from "./state/task-state.ts";
|
|
6
|
-
import {
|
|
6
|
+
import { pingTransition } from "./pi/notify.ts";
|
|
7
7
|
import { isSubagentProcess } from "./pi/quiet.ts";
|
|
8
8
|
import { registerDeskClient } from "./desk/client-extension.ts";
|
|
9
9
|
import { registerLobbyEvents } from "./lobby/runtime.ts";
|
|
10
|
+
import { registerOwner } from "./pi/owner.ts";
|
|
10
11
|
|
|
11
12
|
export default function (pi: ExtensionAPI): void {
|
|
12
13
|
registerLifecycle(pi, CONFIG_DIR_NAME);
|
|
13
14
|
// After the lifecycle, so the lobby opens over a task the widget state already knows.
|
|
14
15
|
registerLobbyEvents(pi, CONFIG_DIR_NAME);
|
|
15
|
-
|
|
16
|
+
registerOwner(pi, CONFIG_DIR_NAME);
|
|
17
|
+
onTransition((task) => pingTransition(task));
|
|
16
18
|
registerCommands(pi, CONFIG_DIR_NAME);
|
|
17
19
|
registerOrchestrateTool(pi, CONFIG_DIR_NAME);
|
|
18
20
|
// Parallel workers share files through the master's file desk.
|
package/src/lobby/feed.ts
CHANGED
|
@@ -225,15 +225,19 @@ export function textOf(content: unknown): string {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/** The long kickoff message bot-lobby sends reads as a short note in the conversation. */
|
|
228
|
-
export function chatText(role: "user" | "assistant", text: string): { role: ChatRole; text: string }
|
|
228
|
+
export function chatText(role: "user" | "assistant", text: string): Array<{ role: ChatRole; text: string }> {
|
|
229
229
|
const body = text.trim();
|
|
230
|
-
if (!body) return
|
|
231
|
-
if (role === "assistant") return { role: "oracle", text: body };
|
|
230
|
+
if (!body) return [];
|
|
231
|
+
if (role === "assistant") return [{ role: "oracle", text: body }];
|
|
232
|
+
// bot-lobby's kickoff: the task starting, then what the user asked for, in their words.
|
|
232
233
|
const kickoff = /^A bot-lobby task is active: (\S+)\nTitle: (.*)/.exec(body);
|
|
233
|
-
if (kickoff)
|
|
234
|
+
if (kickoff) {
|
|
235
|
+
const request = /\nRequest: ([\s\S]*?)(?:\nState: |$)/.exec(body)?.[1]?.trim();
|
|
236
|
+
return [{ role: "note", text: `task started · ${kickoff[2]}` }, ...(request ? [{ role: "you" as const, text: request }] : [])];
|
|
237
|
+
}
|
|
234
238
|
const comment = /^The user left (?:a comment|\d+ comments) on (the approved plan|the proposal) of (\S+) from the lobby:/.exec(body);
|
|
235
|
-
if (comment) return { role: "note", text: `
|
|
236
|
-
return { role: "you", text: body };
|
|
239
|
+
if (comment) return [{ role: "note", text: `your comment on ${comment[1]} went to the oracle` }];
|
|
240
|
+
return [{ role: "you", text: body }];
|
|
237
241
|
}
|
|
238
242
|
|
|
239
243
|
/** Session entries (`{ type: "message", message }`) as conversation entries, oldest first. */
|
|
@@ -244,10 +248,62 @@ export function chatFromEntries(entries: readonly unknown[], max = MAX_CHAT): Ar
|
|
|
244
248
|
if (record?.type !== "message") continue;
|
|
245
249
|
const role = record.message?.role;
|
|
246
250
|
if (role !== "user" && role !== "assistant") continue;
|
|
247
|
-
const line = chatText(role, textOf(record.message?.content));
|
|
248
|
-
if (!line) continue;
|
|
249
251
|
const at = record.timestamp ? Date.parse(record.timestamp) : undefined;
|
|
250
|
-
chat.push({ ...line, ...(at !== undefined && Number.isFinite(at) ? { at } : {}) });
|
|
252
|
+
for (const line of chatText(role, textOf(record.message?.content))) chat.push({ ...line, ...(at !== undefined && Number.isFinite(at) ? { at } : {}) });
|
|
251
253
|
}
|
|
252
254
|
return chat.slice(-max);
|
|
253
255
|
}
|
|
256
|
+
|
|
257
|
+
/** The parts of pi's agent events the lobby narrates; the same shape in process and over RPC. */
|
|
258
|
+
export interface AgentEventLike {
|
|
259
|
+
type: string;
|
|
260
|
+
toolName?: string;
|
|
261
|
+
args?: unknown;
|
|
262
|
+
toolCallId?: string;
|
|
263
|
+
isError?: boolean;
|
|
264
|
+
assistantMessageEvent?: { type: string; delta?: string; content?: string };
|
|
265
|
+
message?: { role?: string; content?: unknown; stopReason?: string; errorMessage?: string };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* One of a Master's agent events into a feed: tool calls become plain-words
|
|
270
|
+
* activity, thinking goes to the thinking pane, the reply streams, and
|
|
271
|
+
* finished messages join the conversation (a failed turn says so there too).
|
|
272
|
+
*/
|
|
273
|
+
export function narrateEvent(feed: LobbyFeed, event: AgentEventLike, describe: (toolName: string, args: unknown) => string): void {
|
|
274
|
+
switch (event.type) {
|
|
275
|
+
case "tool_execution_start":
|
|
276
|
+
feed.begin("MASTER", describe(event.toolName ?? "tool", event.args), event.toolCallId);
|
|
277
|
+
return;
|
|
278
|
+
case "tool_execution_end":
|
|
279
|
+
if (event.toolCallId) feed.end(event.toolCallId, event.isError === true);
|
|
280
|
+
return;
|
|
281
|
+
case "message_update": {
|
|
282
|
+
const update = event.assistantMessageEvent;
|
|
283
|
+
if (update?.type === "thinking_delta" && update.delta) feed.thinkDelta("MASTER", update.delta);
|
|
284
|
+
else if (update?.type === "thinking_end") feed.thinkEnd("MASTER", update.content);
|
|
285
|
+
else if (update?.type === "text_delta" && update.delta) feed.replyDelta(update.delta);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
case "message_end": {
|
|
289
|
+
const message = event.message ?? {};
|
|
290
|
+
if (message.role === "assistant") {
|
|
291
|
+
feed.replyEnd();
|
|
292
|
+
feed.thinkEnd("MASTER");
|
|
293
|
+
if (message.stopReason === "error") {
|
|
294
|
+
const error = (message.errorMessage ?? "the model call failed").split("\n")[0]!;
|
|
295
|
+
feed.say("note", `✗ the oracle's turn failed: ${error}`);
|
|
296
|
+
feed.log("MASTER", `turn failed — ${error}`, "error");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (message.role !== "user" && message.role !== "assistant") return;
|
|
300
|
+
for (const line of chatText(message.role, textOf(message.content))) feed.say(line.role, line.text);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
case "agent_end":
|
|
304
|
+
feed.replyEnd();
|
|
305
|
+
return;
|
|
306
|
+
default:
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
package/src/lobby/keys.ts
CHANGED
|
@@ -11,9 +11,13 @@ export const LOBBY_ACTIONS = {
|
|
|
11
11
|
help: { key: "alt+h", help: "show or hide these keys" },
|
|
12
12
|
settings: { key: "alt+s", help: "bot-lobby settings: each agent's model and thinking, the lobby" },
|
|
13
13
|
search: { key: "ctrl+f", help: "search the current tab" },
|
|
14
|
+
savePlan: { key: "ctrl+s", help: "save the plan being made in the Plan tab to the pending tasks" },
|
|
15
|
+
sessions: { key: "alt+o", help: "browse sessions: view one, message it, or switch this window to it" },
|
|
16
|
+
newSession: { key: "alt+n", help: "start a task in a new session, named after it" },
|
|
17
|
+
toggleAuto: { key: "alt+g", help: "auto mode: the oracle drives the task to completion without asking" },
|
|
14
18
|
nextTab: { key: "tab", help: "next tab" },
|
|
15
19
|
prevTab: { key: "shift+tab", help: "previous tab" },
|
|
16
|
-
toggleScene: { key: "alt+z", help: "show or hide the
|
|
20
|
+
toggleScene: { key: "alt+z", help: "show or hide the oracle and agent animations" },
|
|
17
21
|
toggleConversation: { key: "alt+c", help: "show or hide the conversation" },
|
|
18
22
|
toggleActivity: { key: "alt+a", help: "show or hide the activity log" },
|
|
19
23
|
toggleThinking: { key: "alt+k", help: "show or hide thinking" },
|