pi-bro 0.26.0 → 0.28.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/CHANGELOG.md +31 -0
- package/README.md +6 -1
- package/docs/README.md +2 -0
- package/docs/grill-me.md +63 -0
- package/docs/reference/commands.md +10 -3
- package/docs/reference/data-and-permissions.md +1 -0
- package/docs/reference/settings.md +4 -0
- package/docs/remember-me.md +90 -0
- package/docs/user-guide.md +4 -0
- package/package.json +12 -2
- package/src/bro.ts +59 -40
- package/src/btw.ts +27 -5
- package/src/explain-modal.ts +7 -2
- package/src/grill-engine.ts +116 -0
- package/src/grill.ts +312 -0
- package/src/remember-engine.ts +141 -0
- package/src/remember-store.ts +193 -0
- package/src/remember-tool.ts +22 -0
- package/src/remember.ts +294 -0
- package/src/simplify-engine.ts +37 -0
- package/src/simplify-ui.ts +156 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pi-bro are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.28.0] - 2026-11-05
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
|
|
9
|
+
- Simplify gains a source-focused modal with internal /simplify, /text, /file, /url, /copy, /clear and /help commands.
|
|
10
|
+
- Bare /bro captures a fresh latest assistant response; /bro simplify reopens the last Simplify view without a new model call.
|
|
11
|
+
- M changes explanation mode for that source without rewriting the saved default; R retries the same source.
|
|
12
|
+
- Existing explicit top-level source forms and backend selection remain compatible.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [0.27.0] - 2026-10-30
|
|
16
|
+
|
|
17
|
+
### Highlights
|
|
18
|
+
|
|
19
|
+
- `/bro remember-me` helps you write and explicitly approve personal memory entries with a short, scan-friendly statement and expandable context.
|
|
20
|
+
- `about_user` lets the main Pi agent read an overview, find memories by topic, and unfold selected entries without extra model calls.
|
|
21
|
+
- Memory-writing guidance preserves conditions, scope, source, exceptions, user attribution and unresolved conflicts across short and expanded views.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Private Remember Me modal: `/save`, `/list`, `/expand`, `/edit`, `/delete`, `/new`, `/help`.
|
|
26
|
+
- Versioned local store with stable IDs, validated entries, bounded file size, revision checks and atomic writes.
|
|
27
|
+
- Focused tests and `docs/remember-me.md`.
|
|
28
|
+
|
|
29
|
+
### Limits
|
|
30
|
+
|
|
31
|
+
- Automatic semantic conflict detection depends on model judgment and is not exhaustive.
|
|
32
|
+
- External CLI agents do not receive the main Pi `about_user` tool automatically.
|
|
33
|
+
- The old `/bro preferences` file remains separate until a reviewed migration; no automatic import occurs.
|
|
34
|
+
|
|
35
|
+
|
|
5
36
|
## [0.26.0] - 2026-10-20
|
|
6
37
|
|
|
7
38
|
### Highlights
|
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ For a first success, type this in Pi after setting up a backend:
|
|
|
49
49
|
| `/bro` | Explains the agent's latest completed reply (requires one) |
|
|
50
50
|
| `/bro btw What is a race condition?` | Asks a private side question |
|
|
51
51
|
| `/bro show` | Draws the current session's recent conversation, if any |
|
|
52
|
+
| `/bro grill-me Should agents talk freely to each other?` | Questions your assumptions privately, one at a time |
|
|
52
53
|
| `/bro elevate Improve how we search company documents` | Find expert gaps before giving Pi a task |
|
|
53
54
|
|
|
54
55
|
File and webpage examples need your own real path or URL; see [how to explain them](docs/features/explain.md#explain-a-document). For a step-by-step first run, see [Getting started](docs/getting-started.md).
|
|
@@ -60,6 +61,8 @@ File and webpage examples need your own real path or URL; see [how to explain th
|
|
|
60
61
|
| `/bro`, `/bro text`, `/bro file`, `/bro url` | **[Explain](docs/features/explain.md).** A plain-language version of the agent's last reply, pasted text, a PDF/DOCX/Markdown file, or a public webpage. Three modes: `brief`, `balanced`, `faithful`. |
|
|
61
62
|
| `/bro show` | **[Show](docs/features/show.md#bro-show).** The last few turns drawn as a shape (call tree, file tree, diff, pseudocode, a sequence diagram, or an HTML layout) instead of prose. |
|
|
62
63
|
| `/bro elevate` or **Ctrl+Shift+E** | **[Elevate](docs/elevate.md).** Discover missing expert considerations, select useful improvements, and rewrite your task without submitting it. Shares BTW backend settings. |
|
|
64
|
+
| `/bro remember-me [thought]` | **[Remember Me](docs/remember-me.md).** Privately clarify and approve short personal memories with unfoldable background. Agents can call `about_user` to read summaries and expand IDs. |
|
|
65
|
+
| `/bro grill-me` | **[Grill Me](docs/grill-me.md) (experimental).** A private, opinionated decision interview: light, balanced or exhaustive; one question per round; `/consolidate` drafts a brief without ending the interview; `/insert-last-message` explicitly returns the latest reply to the editor. Uses BTW model settings; read-only restrictions vary by backend. |
|
|
63
66
|
| `/bro btw` | **[Side questions](docs/features/btw.md#bro-btw-side-conversation).** A separate conversation seeded with recent context, so you can ask without interrupting the agent. ⚠️ [Full-permission mode](#what-leaves-your-machine) can edit files. |
|
|
64
67
|
| `/bro guided-review <PR>` | **[Guided Review](docs/guided-review.md).** An explanation and quality assessment of a GitHub PR, with ranked findings, source evidence and private questions. Claude, Muse, or Pi is recommended for untrusted PRs. |
|
|
65
68
|
| `bro_advisor` tool | **[Second opinion](docs/features/advisor.md#bro-advisor).** A tool your agent can call mid-task; a fresh backend process reviews the session snapshot, can inspect the workspace when needed, and returns advice to the agent. ⚠️ [Runs with permissions bypassed](#what-leaves-your-machine). |
|
|
@@ -101,6 +104,7 @@ which may keep it under their own policies. Paths below are under
|
|
|
101
104
|
| Explain | The agent's last reply, your pasted text, or text extracted from your file or webpage, plus your preferences | Nothing; the last result stays in memory |
|
|
102
105
|
| Show | User and assistant text from recent turns (no tool calls, tool results, reasoning or images), plus your preferences | Diagram pages in `pi-bro-<uid>/` in your system temp folder |
|
|
103
106
|
| Side questions | Your questions and up to the last 8 turns of conversation text, plus your preferences | Nothing; the thread stays in memory |
|
|
107
|
+
| Grill Me | Topic, interview turns, up to the last 8 main-session text turns and preferences; any workspace files the selected inspector reads | Nothing; interview and brief are in memory |
|
|
104
108
|
| Elevate | Your objective, selected findings, all current-branch user/assistant text; Full also includes tool-call arguments and text results, and preferences | Nothing; the workflow stays in memory |
|
|
105
109
|
| Guided Review | The PR description and diff, the files the backend reads, your questions, plus your preferences | Reviews and captured source in `bro-reviews/`, with no automatic cleanup |
|
|
106
110
|
| Advisor | The agent's system instructions, tool list and whole conversation, including tool calls and results (reasoning and images omitted), plus your steering | Steering in `bro-advisor.md` and the session file |
|
|
@@ -118,6 +122,7 @@ the agent as tool results.
|
|
|
118
122
|
> These run the backend in your workspace with its permission checks bypassed:
|
|
119
123
|
> - **Advisor:** it can read, edit and run commands. "Advise, don't edit" is
|
|
120
124
|
> only an instruction.
|
|
125
|
+
> - **Grill Me `/access full`:** explicitly opts into unrestricted workspace permissions. The no-edits prompt is not an access control.
|
|
121
126
|
> - **BTW full-permission mode** (turned on with `/mode` inside BTW): it is
|
|
122
127
|
> meant to edit files and run commands.
|
|
123
128
|
> - **Grok:** its sandbox is off except during Guided Review, which uses the
|
|
@@ -137,7 +142,7 @@ and [Privacy and safety](docs/reference/data-and-permissions.md#privacy-and-safe
|
|
|
137
142
|
- No fallback: if the chosen backend, model or effort fails, Bro shows that
|
|
138
143
|
backend's error instead of switching. → Run `/bro doctor`.
|
|
139
144
|
- Elevate runs fresh restricted calls through the BTW model setting. Restricted does not always mean sandboxed; see [access and retention](docs/reference/data-and-permissions.md). The shortcut may not work in all terminals: use `/bro elevate` instead.
|
|
140
|
-
- BTW threads and the last explanation live in memory only and clear on
|
|
145
|
+
- BTW and Grill Me threads and the last explanation live in memory only and clear on
|
|
141
146
|
reload or restart.
|
|
142
147
|
- Guided Review runs in local interactive Pi only and does not post to
|
|
143
148
|
GitHub.
|
package/docs/README.md
CHANGED
|
@@ -13,6 +13,8 @@ Start with what you want to do. The [README](../README.md) explains the product,
|
|
|
13
13
|
- [Explain a local file](features/explain.md#explain-a-document) or [webpage](features/explain.md#explain-a-webpage).
|
|
14
14
|
- [Visualize a conversation](features/show.md#bro-show) — Show diagrams.
|
|
15
15
|
- [Ask a private side question](features/btw.md#bro-btw-side-conversation) — BTW.
|
|
16
|
+
- [Remember personal context for agents](remember-me.md) — approved short memories, expandable background and the read-only `about_user` tool.
|
|
17
|
+
- [Get grilled on a decision](grill-me.md) — one question at a time in a private modal, then copy a decision brief.
|
|
16
18
|
- [Improve a request before sending it](elevate.md) — Elevate: discover expert gaps, choose improvements, rewrite the task.
|
|
17
19
|
- [Investigate a PR](guided-review.md) — Guided Review.
|
|
18
20
|
- [Get an agent's second opinion](features/advisor.md#bro-advisor) — Advisor; review its permissions first.
|
package/docs/grill-me.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Grill Me (experimental)
|
|
2
|
+
|
|
3
|
+
[Docs home](README.md) · [Commands](reference/commands.md) · [Safety](reference/data-and-permissions.md)
|
|
4
|
+
|
|
5
|
+
`/bro grill-me` opens an independent decision interview in Bro's modal, without adding turns to Pi's main conversation.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
/bro grill-me Should child agents communicate freely?
|
|
9
|
+
/bro grill-me
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
With a topic, start a new interview. Without one, reopen the current interview or enter a topic inside the modal. A proposal prompts scrutiny; an open question prompts discovery. Bro offers reasoned pushback, then one question with lettered choices, including an open-ended alternative. Answer with a letter or your own words. Questions request a horizontal divider, a distinct **Question** heading, and exactly one **(Recommended)** option with a short reason. Recommendations are provisional; model adherence is not guaranteed.
|
|
13
|
+
|
|
14
|
+
## How Bro works with you
|
|
15
|
+
|
|
16
|
+
Grill Me is a **context-rich thinking partner**, not a review pipeline. It can help you discover a position from an open question or test a proposal you already have. If you propose a solution before explaining the problem, Bro looks for the goal and constraints that matter; when those are already clear, it uses them rather than repeating an intake checklist.
|
|
17
|
+
|
|
18
|
+
Bro contributes options and reasons, asks about the most consequential choice still open, and may inspect relevant workspace material when its backend permits it. It should check available facts rather than guessing, ask *you* about preferences and trade-offs, and explain meaningful uncertainty. Good arguments can persuade Bro; it should not invent objections to prolong the interview.
|
|
19
|
+
|
|
20
|
+
As the discussion develops, Bro treats your **agreed choices and reasons** differently from untested assumptions and Bro's own suggestions. You can correct or change a constraint in normal conversation. Bro should carry that change forward and avoid reopening settled ground without a reason.
|
|
21
|
+
|
|
22
|
+
`/consolidate` captures the current position for a handoff, at whatever level of detail the topic warrants: goals, key constraints, endorsed decisions and why, material trade-offs, unresolved questions, and a next step. It does not promote Bro's recommendations into decisions you never made. You can consolidate early, then continue and consolidate again.
|
|
23
|
+
|
|
24
|
+
This takes inspiration from the context-rich **Elephant** in Google's [Elephant–Goldfish Model](https://github.com/google/elephant-goldfish-model). Grill Me does **not** dispatch Goldfish reviewers, require a design document, or impose review/approval stages. It remains one dialogue in Bro's modal.
|
|
25
|
+
|
|
26
|
+
## Controls
|
|
27
|
+
|
|
28
|
+
| Command inside the modal | Effect |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `/consolidate` | Generate a current decision brief. Does not end the interview or insert anything. |
|
|
31
|
+
| `/insert-last-message` | Insert the latest completed Bro reply, including a consolidated brief, into an empty Pi editor **without sending**. No model call. |
|
|
32
|
+
| `/depth light` | Quick, focused questioning |
|
|
33
|
+
| `/depth balanced` | Default: material assumptions and trade-offs |
|
|
34
|
+
| `/depth exhaustive` | Deeper alternatives, evidence and failure cases |
|
|
35
|
+
| `/retry` | Retry the failed/cancelled operation, otherwise regenerate the latest reply. Never repeats insertion. |
|
|
36
|
+
| `/new <topic>` | Start over after confirmation. Resets depth to balanced and access to inspection. |
|
|
37
|
+
| `/access inspect` | Request inspection tools; enforcement depends on backend |
|
|
38
|
+
| `/access full` | Request full permissions; requires typing `yes` after a warning |
|
|
39
|
+
| `/help` | Show commands on demand; **Esc returns to the interview** |
|
|
40
|
+
| Esc | Close and cancel active work; preserve completed discussion |
|
|
41
|
+
|
|
42
|
+
Type `/` to see matching commands; keep typing to narrow suggestions and press **Tab** to complete the first match. Completion never submits. From help, Esc returns to the discussion; a second Esc closes the modal.
|
|
43
|
+
|
|
44
|
+
For confirmation prompts, type `yes` to proceed; anything else cancels. Depth can change between replies without losing the discussion. There are no question quotas or finished/locked states. Consolidate whenever useful, inspect the brief, then explicitly insert it or continue talking. The brief includes the current position, reasons, objections, unresolved questions and next actions. Insertion never overwrites a draft or submits it.
|
|
45
|
+
|
|
46
|
+
The old `/finish`, `/copy`, `/copy-all`, `/insert`, `/insert-all`, `/clear`, and entry depth flags have been removed from this experimental interface. BTW commands are unchanged.
|
|
47
|
+
|
|
48
|
+
Grill Me uses the **BTW model/backend/effort** selection from `/bro config`, but has its own independent thread. The header shows depth and effective access; `/help` keeps the footer short. Full access and Agy write risks remain visible in the header even when another notice is shown.
|
|
49
|
+
|
|
50
|
+
## Access, privacy and limits
|
|
51
|
+
|
|
52
|
+
- Inspection uses the Guided Review backend path in your current workspace. Claude, Muse and Pi have file-only tools. Codex and Grok have read-only sandboxes with shell access. **Agy inspection can still write project files.** No-edit prompts are not security controls.
|
|
53
|
+
- Full access can read, edit and execute commands. Bro instructs the model not to make changes, but cannot enforce that instruction. There is no automatic escalation.
|
|
54
|
+
- Each turn makes a fresh backend call replaying the complete interview. Long interviews cost more and may exceed context limits; there is no hidden truncation or fallback.
|
|
55
|
+
- The provider receives your topic, interview history, Bro preferences and up to eight recent main-session user/assistant text turns (40,000 characters). Captured context excludes tool calls/results, hidden reasoning and images. Backend tools can inspect additional workspace content.
|
|
56
|
+
- Bro keeps the interview in memory, lost on reload, session change or exit. Backend/provider retention is separate; see [backend retention](reference/data-and-permissions.md#backends-access-and-retention).
|
|
57
|
+
- Closing discards partial output, preserves completed replies, and restores cancelled input unless a newer draft exists. Retry preserves the previous reply until replacement succeeds. Cancellation cannot undo backend changes; descendant cleanup on Windows and abrupt host shutdown are not guaranteed.
|
|
58
|
+
|
|
59
|
+
## Comparison
|
|
60
|
+
|
|
61
|
+
BTW is for side questions. Elevate improves an assignment. Grill Me tests a decision through dialogue. Its advantage over a standalone questioning skill is modal isolation and explicit return to Pi, not a claim of smarter questioning.
|
|
62
|
+
|
|
63
|
+
See the [evaluation record](plans/grill-me-evaluation.md). Historical live results predate the command redesign and multiple-choice guidance; they do not validate the revised experience.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
| Source | Command | What Bro does |
|
|
8
8
|
| --- | --- | --- |
|
|
9
|
-
| Latest assistant reply | `/bro` |
|
|
9
|
+
| Latest assistant reply | `/bro` | Opens Simplify and explains the latest completed reply without inserting the result into Pi's conversation. |
|
|
10
10
|
| Pasted text | `/bro text <text>` | Explains text supplied directly in the command. |
|
|
11
11
|
| Local document | `/bro file <path>` | Extracts text from a workspace-local Markdown, text, PDF, or DOCX file. |
|
|
12
12
|
| Public webpage | `/bro url <url>` | Fetches one public HTML page and extracts its main readable content. |
|
|
@@ -22,12 +22,13 @@ text directly captures a new source the same way.
|
|
|
22
22
|
|
|
23
23
|
| Command | Description |
|
|
24
24
|
| --- | --- |
|
|
25
|
-
| `/bro
|
|
25
|
+
| `/bro` | Open Simplify and explain the latest completed assistant reply. |
|
|
26
|
+
| `/bro simplify` | Reopen the last Simplify screen within this Pi session, without a new model call. |
|
|
26
27
|
| `/bro text <text>` | Explain pasted text. |
|
|
27
28
|
| `/bro <input>` | Explain it directly: a lone URL runs the webpage reader, an existing workspace file with a supported extension runs the document reader, and anything else is pasted text. A quoted path with spaces is routed too when the file exists. |
|
|
28
29
|
| `/bro file <path>` | Explain a workspace-local `.md`, `.markdown`, `.txt`, `.pdf`, or `.docx` file. |
|
|
29
30
|
| `/bro url <url>` | Explain one public, text-based webpage. |
|
|
30
|
-
| `/bro open` |
|
|
31
|
+
| `/bro open` | Legacy compatibility shortcut to the last result. No `/open` command inside Simplify. |
|
|
31
32
|
| `/bro show [n-turns] [query]` | Draw recent session turns (default last 1) as shapes instead of prose, from user and assistant conversation text only — tool calls, tool results, reasoning, and images are omitted. An optional query steers what the shapes focus on, with or without a leading turn count. |
|
|
32
33
|
| `/bro doctor` | Check Bro's settings, preferences, and each selected backend, with the effective backend/model/effort per feature. |
|
|
33
34
|
| `/bro mode [brief\|balanced\|faithful]` | View or choose the explanation mode. |
|
|
@@ -35,6 +36,8 @@ text directly captures a new source the same way.
|
|
|
35
36
|
| `/bro config` | Open settings for the shared backend/model/effort, explain mode, show turns, and per-capability (explain/show/btw/advisor/review) overrides. |
|
|
36
37
|
| `/bro guided-review <PR number or URL>` | Automatically explain and assess a captured PR in local Pi, with source evidence and optional private questions. Opening the same PR restores its saved review. |
|
|
37
38
|
| `/bro guided-review` | List saved reviews; `resume` is an alias. |
|
|
39
|
+
| `/bro remember-me [thought]` | Start a private memory-writing conversation, browse and expand memories, and approve saves explicitly. [Guide](../remember-me.md). |
|
|
40
|
+
| `/bro grill-me [topic]` | Private one-question-at-a-time decision interview. Supply a topic to start fresh; omit it to resume. `/consolidate` drafts a brief; `/insert-last-message` inserts explicitly without sending. `/help` lists modal controls. [Guide](../grill-me.md). |
|
|
38
41
|
| `/bro elevate [request]` | Improve an assignment before execution. Discover up to five gaps, choose useful findings, and insert a revised request without submitting it. **Ctrl+Shift+E** can use your unsent draft. See [Elevate](../elevate.md). |
|
|
39
42
|
| `/bro btw [question]` | Open a side conversation in a modal, seeded with recent main-session context. Starts conversation-only; type `/mode` inside to toggle full permission (read and edit the workspace) without losing the thread. |
|
|
40
43
|
| `/bro advisor` | Quick notice of whether the executor's `bro_advisor` tool is available right now, pointing at `/bro config`, `/bro advisor-steer`, and `/bro doctor`. |
|
|
@@ -48,3 +51,7 @@ Giving `/bro` the input directly works the same way:
|
|
|
48
51
|
/bro docs/report.pdf
|
|
49
52
|
/bro any other text is explained as pasted text
|
|
50
53
|
```
|
|
54
|
+
|
|
55
|
+
## Simplify modal (single-source explanation)
|
|
56
|
+
|
|
57
|
+
Once inside Simplify, use `/simplify` for the latest completed reply; `/text <text>`, `/file <path>`, `/url <url>` for a new source; `/copy` to copy the current explanation; `/clear` to return to the empty screen; and `/help` for controls. **M** changes the one-off Brief/Balanced/Faithful mode and re-explains the captured source; **R** retries the same source. This modal is not a conversation and does not persist history across restarts. Legacy `/bro text|file|url` shortcuts keep working. The global menu consolidation is tracked separately.
|
|
@@ -93,6 +93,7 @@ When shaping an answer, each part has one owner:
|
|
|
93
93
|
seeded main-session conversation text (plus earlier turns when a native
|
|
94
94
|
session is reseeded) to the selected backend. In full permission mode the
|
|
95
95
|
side agent can additionally read and edit the workspace.
|
|
96
|
+
- **Grill Me requests**: `/bro grill-me` sends the user-supplied topic, their answers, the full private Grill Me transcript so far, preferences, and up to 8 recent main-session text turns (40,000 characters) to the BTW-selected provider. It runs **fresh** each turn in the current workspace, via the Guided Review *inspection execution path* (not the Guided Review UI or checkout). Claude, Muse and Pi use file-only tools; Codex and Grok use a read-only sandbox with shell; **Agy can still write inside the project**. The model is always told not to edit or run mutating commands, but that prompt is not enforced. Optional `/access full` explicitly uses a fresh, full-permission backend call and gives the backend unrestricted tools; it never happens automatically. Grill Me and BTW hold separate in-memory threads, and nothing enters the main agent unless the user inserts it into an empty editor. See [Grill Me](../grill-me.md).
|
|
96
97
|
- **Guided Review requests**: PR identity/description, captured diff, relevant private discussion and preferences go to the selected backend, which can inspect captured files. Main-session context is not attached. Claude (`--restricted`, file tools only), Muse (write/shell/web disabled), and Pi (`read/grep/find/ls` only, in-process) use strict file-only inspection and are recommended for untrusted PRs. Codex and Grok inspect the captured checkout under a read-only sandbox; Agy's `--sandbox` still allows in-project writes. All three run shell commands and show an advisory. Prompt injection can still corrupt conclusions or reveal captured content to the provider; this is not a general confidentiality guarantee. See [Guided Review access and storage](../guided-review.md#access-privacy-and-storage).
|
|
97
98
|
- **Preferences**: `bro-preferences.md` is sent with every explain, Show,
|
|
98
99
|
BTW, Elevate, and Guided Review request to the selected backend. It is never sent to the advisor or
|
|
@@ -111,3 +111,7 @@ that is set):
|
|
|
111
111
|
`bro-prompt.md`, the full prompt template from earlier versions, is no longer
|
|
112
112
|
read. Move what you want to keep into `/bro preferences`, and choose
|
|
113
113
|
`/bro mode brief` for the original ELI-simpleton instruction.
|
|
114
|
+
|
|
115
|
+
## Remember Me
|
|
116
|
+
|
|
117
|
+
`/bro remember-me` manages approved personal memories in `bro-memories.json` in the same user agent directory. Each entry has a stable ID, a scan-first short statement, and optional scope, exceptions, uncertainty and source context in an expanded view. The agent-facing `about_user` tool reads them on demand. `/bro preferences` remains a separate legacy file; no automatic migration or duplicate injection occurs. See [Remember Me](../remember-me.md).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Remember Me
|
|
2
|
+
|
|
3
|
+
[Docs home](README.md) · [Commands](reference/commands.md) · [Preferences](reference/settings.md#preferences)
|
|
4
|
+
|
|
5
|
+
Use `/bro remember-me` to browse your approved personal memories, or `/bro remember-me <thought>` to start drafting from your words and recent Pi conversation.
|
|
6
|
+
|
|
7
|
+
## Write through conversation
|
|
8
|
+
|
|
9
|
+
Bro reviews your statement and existing memories. It may ask one material question, flag a competing entry, or propose a short statement with deeper background. **Nothing saves until you type `/save`.** You can reply normally to refine a proposal. When you correct it, the old draft remains visible but cannot be approved until Bro returns a revised proposal. Questions and failed model calls never silently re-enable `/save`.
|
|
10
|
+
|
|
11
|
+
A proposed memory always has:
|
|
12
|
+
- **Subject:** a distinct topic, such as Testing or Delegation
|
|
13
|
+
- **Short statement:** active, clear and usable on its own; include qualifications that change its meaning
|
|
14
|
+
- **Expanded background:** context, explanations and original wording; optional scope, exceptions, source context, uncertainty and whether wording reflects a user statement or user-approved interpretation
|
|
15
|
+
|
|
16
|
+
Use the same vocabulary across related memories. Put useful distinguishing words first. Never convert “prefers lean tests” into “dislikes tests,” or “autonomy within an approved plan” into “unrestricted autonomy.” Summaries and expanded content must agree.
|
|
17
|
+
|
|
18
|
+
If the user hasn't resolved a conflict, don't pretend it is settled. Bro shows a potential conflict in the proposal. The user decides whether to revise it, update an existing memory or save a qualified entry.
|
|
19
|
+
|
|
20
|
+
## Controls
|
|
21
|
+
|
|
22
|
+
| Input | Action |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| Free text | Continue clarifying or refining |
|
|
25
|
+
| `/save` | Approve and persist the current proposal |
|
|
26
|
+
| `/list [page|all]` | Page through the current search (20 per page), or use `/list all` to return to all memories; preserve the proposal |
|
|
27
|
+
| `/search <words>` | Start a filtered search; `/list 2` continues its second page without dropping the proposal |
|
|
28
|
+
| `/expand <id>` | Show background, source, scope, exceptions and uncertainty |
|
|
29
|
+
| `/edit <id>` | Edit an existing memory while keeping its stable ID |
|
|
30
|
+
| `/delete <id>` | Delete after typing yes |
|
|
31
|
+
| `/context show|on|off` | See or omit the captured Pi context before transmitting |
|
|
32
|
+
| `/confirm-revision` | Approve after comparing a stale proposal with changed memories |
|
|
33
|
+
| `/new` | Discard the draft without changing saved memories |
|
|
34
|
+
| `/help` | Explain commands and boundaries |
|
|
35
|
+
|
|
36
|
+
Before the first model call, Bro identifies the selected model/backend, the captured main-session context, and that related saved memories and legacy style preferences will be sent. The initial thought is prefilled but not sent until the user presses Enter. Use `/context show` to inspect what was captured or `/context off` to omit it.
|
|
37
|
+
|
|
38
|
+
Browsing and failed saves preserve the proposal. If the store changed after the proposal was reviewed, `/save` compares the original and current target (and related entries) and **does not save**. An explicit `/confirm-revision` approves against that exact new revision; if it changes again, another review is required. Durable drafts across restarts are not implemented.
|
|
39
|
+
|
|
40
|
+
Esc closes the modal and cancels an active model call. The draft conversation is not durable; **approved saved memories are durable**. Saved entries survive Pi restarts and project changes.
|
|
41
|
+
|
|
42
|
+
## Agent access
|
|
43
|
+
|
|
44
|
+
The main Pi agent gets a read-only `about_user` tool:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
about_user() → short statements and IDs
|
|
48
|
+
about_user({query:"testing"}) → matching summaries
|
|
49
|
+
about_user({offset:20,limit:20}) → next page of memories
|
|
50
|
+
about_user({expand:["m-..."]}) → approved background for an ID
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The agent can scan a summary before deciding what to unfold. The reader performs no new model call. It does not mutate stored entries. The user's current request wins over a standing memory.
|
|
54
|
+
|
|
55
|
+
## Boundaries
|
|
56
|
+
|
|
57
|
+
Stored memories live in `~/.pi/agent/bro-memories.json` (or under `$PI_CODING_AGENT_DIR`), not project Git repos. Files are personal: keep private backups and avoid sharing them in logs. Selected model providers receive the words you provide to Remember Me, recent session text captured at opening, and existing memory statements for conflict checking. Read-only `about_user` returns only the requested summaries/expansions to the calling main Pi agent; that agent may send returned content to its model provider.
|
|
58
|
+
|
|
59
|
+
**Agent access is currently the registered main Pi tool only.** External CLIs and isolated Bro sessions do not receive it automatically. The existing `/bro preferences` file remains unchanged; no automatic migration or conflict reconciliation is claimed.
|
|
60
|
+
|
|
61
|
+
Remember Me uses **the backend and model selected for BTW**. Every valid BTW backend is supported through Bro's existing restricted **explain** execution path. It never silently changes provider or model. Restricted means different things across backends, not a universal promise of no tools or no side effects:
|
|
62
|
+
|
|
63
|
+
| Backend | Current restricted drafting behavior |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Agy (default) | `--sandbox`, temporary working directory. Sandbox limits shell actions; it is **not** a no-tools or no-write guarantee. |
|
|
66
|
+
| Codex | `--sandbox read-only`, ephemeral execution and temporary working directory; read-only sandbox, **not** no-tools. |
|
|
67
|
+
| Claude | CLI tools disabled with `--tools ""`, strict empty MCP config, temporary working directory, no session persistence. |
|
|
68
|
+
| Pi | Fresh SDK session with no tools, extensions, skills, or project context files, using the **selected configured physical model**. |
|
|
69
|
+
| Muse | Write and shell disabled, approvals disabled, temporary working directory. Do not infer that all other abilities are disabled. |
|
|
70
|
+
| Grok | A restricted **prompt request**, but CLI sandbox off and permissions bypassed; it is **not** a technical tool/write boundary. |
|
|
71
|
+
|
|
72
|
+
The modal shows a backend-specific notice before sending data. Bro's `/save` gate controls **only writes to its approved memory store**. It does not prevent any action that the selected backend's own permissions might allow. See [execution configuration](reference/settings.md) for backend details.
|
|
73
|
+
|
|
74
|
+
Live model behavior and the actual backend installation are separate from controlled-response tests.
|
|
75
|
+
|
|
76
|
+
**Coexistence policy:** `/bro preferences` remains active as a legacy *answer-style* file for older Bro features. `about_user` reads only approved Remember Me memories. Current user instructions take precedence. If an approved memory conflicts with legacy preferences, the approved memory is the source for the personal fact or lasting rule; do not treat two conflicting stores as equally authoritative. Bro should surface the disagreement during drafting. There is no silent migration or overwrite; a reviewed migration remains a separate task.
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
**Short:** `Testing: Seek sufficient confidence at the lowest reasonable maintenance cost; do not optimize for raw test count.`
|
|
81
|
+
|
|
82
|
+
**Expanded:** The user values tests that protect meaningful behavior and rejects needless duplication. This does **not** mean the user dislikes tests. Scope: project test strategy. Source: explicit user preference.
|
|
83
|
+
|
|
84
|
+
**Short:** `Delegation: Allow agents to act independently within an approved coordination plan; reserve consequential scope changes for human approval.`
|
|
85
|
+
|
|
86
|
+
**Expanded:** The user wants strong initiative after authorizing the plan, not unrestricted delegation. An agent can coordinate approved subtasks but should return for approval when changing agreed goals or major commitments.
|
|
87
|
+
|
|
88
|
+
**Short:** `Answer length: Lead with a short answer; give enough detail for consequential design reviews. [Apparent tension: brevity versus depth depends on task.]`
|
|
89
|
+
|
|
90
|
+
**Expanded:** “Keep answers concise” and “go deep on important trade-offs” are not necessarily conflicting. Their scope differs: routine replies versus material design decisions. Preserve that distinction rather than deciding the user dislikes detailed work.
|
package/docs/user-guide.md
CHANGED
|
@@ -163,3 +163,7 @@ See [Privacy and safety](reference/data-and-permissions.md#privacy-and-safety).
|
|
|
163
163
|
## Troubleshooting and current limits
|
|
164
164
|
|
|
165
165
|
See [Troubleshooting and current limits](reference/troubleshooting.md#troubleshooting-and-current-limits).
|
|
166
|
+
|
|
167
|
+
## Simplify modal
|
|
168
|
+
|
|
169
|
+
`/bro` opens Simplify and explains the latest completed assistant reply. `/bro simplify` returns to the most recent Simplify screen without another model request. Inside, `/simplify`, `/text <text>`, `/file <path>` and `/url <url>` produce one explanation at a time; `/copy` copies the answer, `/clear` clears it, and `/help` shows controls. Press **M** with an empty composer to change the explanation mode and rerun; **R** retries. The saved default mode remains unchanged. The current screen is kept only within the Pi session. Old `/bro text|file|url|open` forms remain callable for compatibility.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-bro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "A sidekick for you and your Pi agent: plain-language explanations, side questions, diagrams, PR review and second opinions, without cluttering the agent's context.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,6 +48,14 @@
|
|
|
48
48
|
"src/btw.ts",
|
|
49
49
|
"src/elevate.ts",
|
|
50
50
|
"src/elevate-engine.ts",
|
|
51
|
+
"src/grill.ts",
|
|
52
|
+
"src/grill-engine.ts",
|
|
53
|
+
"src/remember-store.ts",
|
|
54
|
+
"src/remember-engine.ts",
|
|
55
|
+
"src/remember-tool.ts",
|
|
56
|
+
"src/remember.ts",
|
|
57
|
+
"src/simplify-engine.ts",
|
|
58
|
+
"src/simplify-ui.ts",
|
|
51
59
|
"src/explain-modal.ts",
|
|
52
60
|
"src/review.ts",
|
|
53
61
|
"src/review-source.ts",
|
|
@@ -72,6 +80,8 @@
|
|
|
72
80
|
"docs/pig-compatibility.md",
|
|
73
81
|
"docs/guided-review.md",
|
|
74
82
|
"docs/elevate.md",
|
|
83
|
+
"docs/grill-me.md",
|
|
84
|
+
"docs/remember-me.md",
|
|
75
85
|
"docs/examples.md",
|
|
76
86
|
"docs/features",
|
|
77
87
|
"docs/reference"
|
|
@@ -85,7 +95,7 @@
|
|
|
85
95
|
"scripts": {
|
|
86
96
|
"docs:check": "node scripts/check-docs.mjs && node --test test/docs-quality.test.mjs",
|
|
87
97
|
"typecheck": "tsc --noEmit",
|
|
88
|
-
"test": "npm run typecheck && npm run docs:check && node .github/scripts/release-utils.mjs selftest && node --test test/elevate-docs.test.mjs test/elevate.test.ts test/review-ux.test.mjs test/review-doctor.test.mjs test/review-versions.test.mjs test/review-regeneration.test.mjs test/review-modal.test.mjs test/review.test.ts test/review-ui.test.mjs test/review-session.test.mjs test/helpers.test.mjs test/prompt.test.ts test/backend.test.ts test/claude.test.ts test/grok.test.ts test/codex.test.ts test/muse.test.ts test/settings.test.ts test/sources.test.ts test/release.test.ts test/show-html.test.ts test/smoke-rpc.test.ts test/ui-capabilities.test.ts test/modal-contract.test.mjs benchmark/*.test.ts && sh ./test/smoke-test.sh",
|
|
98
|
+
"test": "npm run typecheck && npm run docs:check && node .github/scripts/release-utils.mjs selftest && node --test test/elevate-docs.test.mjs test/elevate.test.ts test/simplify.test.ts test/simplify-modal.test.mjs test/grill.test.ts test/remember.test.ts test/remember-modal.test.mjs test/review-ux.test.mjs test/review-doctor.test.mjs test/review-versions.test.mjs test/review-regeneration.test.mjs test/review-modal.test.mjs test/review.test.ts test/review-ui.test.mjs test/review-session.test.mjs test/helpers.test.mjs test/prompt.test.ts test/backend.test.ts test/claude.test.ts test/grok.test.ts test/codex.test.ts test/muse.test.ts test/settings.test.ts test/sources.test.ts test/release.test.ts test/show-html.test.ts test/smoke-rpc.test.ts test/ui-capabilities.test.ts test/modal-contract.test.mjs benchmark/*.test.ts && sh ./test/smoke-test.sh",
|
|
89
99
|
"benchmark:dry-run": "node benchmark/run.ts dry-run",
|
|
90
100
|
"benchmark:run": "node benchmark/run.ts run",
|
|
91
101
|
"benchmark:report": "node benchmark/run.ts report",
|
package/src/bro.ts
CHANGED
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
import { doctorReport, showBroConfigModal } from "./doctor.ts";
|
|
11
11
|
import { setPiHostContext } from "./backend.ts";
|
|
12
12
|
import { openElevateModal } from "./elevate.ts";
|
|
13
|
+
import { openGrillModal } from "./grill.ts";
|
|
14
|
+
import { openRememberModal } from "./remember.ts";
|
|
15
|
+
import { openSimplifyWorkflow, type SimplifyState } from "./simplify-ui.ts";
|
|
16
|
+
import { registerAboutUserTool } from "./remember-tool.ts";
|
|
17
|
+
import { parseGrillArguments, type GrillThread } from "./grill-engine.ts";
|
|
13
18
|
import {
|
|
14
19
|
type BroResult,
|
|
15
20
|
type ModalResult,
|
|
@@ -38,8 +43,6 @@ import {
|
|
|
38
43
|
} from "./show.ts";
|
|
39
44
|
import {
|
|
40
45
|
type BroSource,
|
|
41
|
-
extractDocumentText,
|
|
42
|
-
extractWebPage,
|
|
43
46
|
isWorkspaceFile,
|
|
44
47
|
looksLikeWebUrl,
|
|
45
48
|
} from "./sources.ts";
|
|
@@ -57,10 +60,16 @@ export * from "./doctor.ts";
|
|
|
57
60
|
export * from "./btw.ts";
|
|
58
61
|
export * from "./elevate.ts";
|
|
59
62
|
export * from "./elevate-engine.ts";
|
|
63
|
+
export * from "./grill.ts";
|
|
64
|
+
export * from "./grill-engine.ts";
|
|
65
|
+
export * from "./remember-store.ts";
|
|
66
|
+
export * from "./remember-engine.ts";
|
|
60
67
|
export * from "./explain-modal.ts";
|
|
68
|
+
export * from "./simplify-engine.ts";
|
|
69
|
+
export * from "./simplify-ui.ts";
|
|
61
70
|
|
|
62
71
|
const COMMANDS = [
|
|
63
|
-
{ value: "simplify", label: "simplify", description: "
|
|
72
|
+
{ value: "simplify", label: "simplify", description: "Reopen the last Simplify screen without a new model call" },
|
|
64
73
|
{ value: "text", label: "text", description: "Explain pasted text, or the latest reply when text is omitted" },
|
|
65
74
|
{ value: "file", label: "file", description: "Explain a local document" },
|
|
66
75
|
{ value: "url", label: "url", description: "Explain a public webpage" },
|
|
@@ -72,6 +81,8 @@ const COMMANDS = [
|
|
|
72
81
|
{ value: "guided-review", label: "guided-review", description: "Understand and assess a PR with captured code and optional private questions" },
|
|
73
82
|
{ value: "btw", label: "btw", description: "Open a side conversation (starts conversation-only; /mode toggles full permission)" },
|
|
74
83
|
{ value: "elevate", label: "elevate", description: "Discover missing expert considerations, then improve a request" },
|
|
84
|
+
{ value: "remember-me", label: "remember-me", description: "Help write and review personal memories; agents can unfold them on demand" },
|
|
85
|
+
{ value: "grill-me", label: "grill-me", description: "A private, one-question-at-a-time decision interview" },
|
|
75
86
|
{ value: "config", label: "config", description: "Configure shared defaults and per-capability model/effort overrides" },
|
|
76
87
|
{ value: "advisor", label: "advisor", description: "Check whether the executor's advisor tool is available right now" },
|
|
77
88
|
{ value: "advisor-steer", label: "advisor-steer", description: "View, edit, save, or clear the advisor's persistent steering brief" },
|
|
@@ -81,8 +92,10 @@ const KNOWN_ACTIONS = new Set(COMMANDS.map((command) => command.value));
|
|
|
81
92
|
|
|
82
93
|
export default async function bro(pi: ExtensionAPI) {
|
|
83
94
|
let lastResult: ModalResult | undefined;
|
|
95
|
+
let simplifyState: SimplifyState = {};
|
|
84
96
|
let lastShowSteering: string | undefined;
|
|
85
97
|
let btwThread: BtwThread | undefined;
|
|
98
|
+
let grillThread: GrillThread | undefined;
|
|
86
99
|
const remember = (result: ModalResult, showSteering?: string) => {
|
|
87
100
|
if (result.source) {
|
|
88
101
|
lastResult = result;
|
|
@@ -94,10 +107,13 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
94
107
|
|
|
95
108
|
pi.on("session_start", async (_event, _ctx) => {
|
|
96
109
|
lastResult = undefined;
|
|
110
|
+
simplifyState = {};
|
|
97
111
|
btwThread = undefined;
|
|
112
|
+
grillThread = undefined;
|
|
98
113
|
});
|
|
99
114
|
|
|
100
115
|
registerAdvisorTool(pi);
|
|
116
|
+
registerAboutUserTool(pi);
|
|
101
117
|
|
|
102
118
|
pi.registerCommand("bro", {
|
|
103
119
|
description: "Explain text, documents, and webpages; draw session turns; open a side conversation; configure Bro and the executor's advisor tool",
|
|
@@ -116,8 +132,10 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
116
132
|
let value = raw.slice(raw.split(/\s+/, 1)[0]?.length ?? 0).trim();
|
|
117
133
|
|
|
118
134
|
if (action === "simplify") {
|
|
119
|
-
if (value) { ctx.ui.notify("Use /bro simplify
|
|
120
|
-
|
|
135
|
+
if (value) { ctx.ui.notify("Use /bro simplify to reopen the last Simplify view; use /text, /file or /url inside it.", "warning"); return; }
|
|
136
|
+
try { await openSimplifyWorkflow(ctx, simplifyState, {kind:"resume"}); if (simplifyState.result) remember(simplifyState.result); }
|
|
137
|
+
catch (error) { ctx.ui.notify(withDoctor(error), "error"); }
|
|
138
|
+
return;
|
|
121
139
|
}
|
|
122
140
|
|
|
123
141
|
// Removed commands must never fall through to a paid text explanation.
|
|
@@ -140,6 +158,23 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
140
158
|
value = raw;
|
|
141
159
|
}
|
|
142
160
|
|
|
161
|
+
// Source operations open the same single-purpose Simplify modal, not separate
|
|
162
|
+
// top-level workflows. Old /bro text|file|url commands remain valid aliases.
|
|
163
|
+
if (!action || action === "text" || action === "file" || action === "url") {
|
|
164
|
+
if ((action === "file" || action === "url") && !value) {
|
|
165
|
+
ctx.ui.notify(`Use /bro ${action} <${action === "file" ? "path" : "url"}>.`, "warning");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const initial = !action || (action === "text" && !value)
|
|
169
|
+
? {kind:"latest" as const}
|
|
170
|
+
: {kind:action as "text" | "file" | "url", input:value};
|
|
171
|
+
try {
|
|
172
|
+
await openSimplifyWorkflow(ctx, simplifyState, initial);
|
|
173
|
+
if (simplifyState.result) remember(simplifyState.result);
|
|
174
|
+
} catch (error) { ctx.ui.notify(withDoctor(error), "error"); }
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
143
178
|
if (action === "show") {
|
|
144
179
|
const { requested, steering, invalid } = parseShowArguments(value);
|
|
145
180
|
if (invalid) {
|
|
@@ -178,41 +213,6 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
178
213
|
return;
|
|
179
214
|
}
|
|
180
215
|
|
|
181
|
-
if (action === "file" || action === "url") {
|
|
182
|
-
if (!value) {
|
|
183
|
-
ctx.ui.notify(`Use /bro ${action} <${action === "file" ? "path" : "url"}>.`, "warning");
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const runInput = async (
|
|
187
|
-
signal: AbortSignal,
|
|
188
|
-
source?: BroSource,
|
|
189
|
-
onProgress?: (text: string) => void,
|
|
190
|
-
mode?: BroMode,
|
|
191
|
-
): Promise<BroResult> => {
|
|
192
|
-
const target = source ?? (action === "url"
|
|
193
|
-
? await extractWebPage(value, signal)
|
|
194
|
-
: { text: await extractDocumentText(value, ctx.cwd, signal), label: unquote(value) });
|
|
195
|
-
try {
|
|
196
|
-
return {
|
|
197
|
-
source: target,
|
|
198
|
-
...(await simplify(target.text, signal, await readSettings(), onProgress, mode)),
|
|
199
|
-
};
|
|
200
|
-
} catch (error) {
|
|
201
|
-
throw new Error(withDoctor(error));
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
try {
|
|
205
|
-
await showBroModal(ctx, {
|
|
206
|
-
loadingText: action === "url" ? "Fetching and simplifying webpage…" : "Reading and simplifying document…",
|
|
207
|
-
run: runInput,
|
|
208
|
-
onResult: remember,
|
|
209
|
-
});
|
|
210
|
-
} catch (error) {
|
|
211
|
-
ctx.ui.notify(errorMessage(error), "error");
|
|
212
|
-
}
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
216
|
if (action === "doctor") {
|
|
217
217
|
if (parts.length !== 1) {
|
|
218
218
|
ctx.ui.notify("Use /bro doctor.", "warning");
|
|
@@ -288,6 +288,25 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
288
288
|
return;
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
if (action === "remember-me") {
|
|
292
|
+
if (!hasBroCustomUi(ctx)) { ctx.ui.notify("Use /bro remember-me in Pi interactive UI.", "warning"); return; }
|
|
293
|
+
try { await openRememberModal(ctx, value); }
|
|
294
|
+
catch (error) { ctx.ui.notify(withDoctor(error), "error"); }
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (action === "grill-me") {
|
|
299
|
+
if (!hasBroCustomUi(ctx)) { ctx.ui.notify("Use /bro grill-me in Pi's interactive UI.", "warning"); return; }
|
|
300
|
+
const parsed = parseGrillArguments(value);
|
|
301
|
+
if (parsed.invalid) { ctx.ui.notify(parsed.invalid, "warning"); return; }
|
|
302
|
+
const start = Boolean(parsed.topic);
|
|
303
|
+
if (start) grillThread = { topic: parsed.topic, depth: parsed.depth, turns: [], fullAccess: false };
|
|
304
|
+
else grillThread ??= { topic: "", depth: parsed.depth, turns: [], fullAccess: false };
|
|
305
|
+
try { await openGrillModal(ctx, grillThread, { start }); }
|
|
306
|
+
catch (error) { ctx.ui.notify(withDoctor(error), "error"); }
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
291
310
|
if (action === "elevate") {
|
|
292
311
|
if (!hasBroCustomUi(ctx)) { ctx.ui.notify("Use /bro elevate in Pi interactive UI.", "warning"); return; }
|
|
293
312
|
try { await openElevateModal(ctx, value); }
|
package/src/btw.ts
CHANGED
|
@@ -194,8 +194,16 @@ export class BtwModal implements Focusable {
|
|
|
194
194
|
private running = false;
|
|
195
195
|
private full = false;
|
|
196
196
|
private model = "";
|
|
197
|
+
private customMode = "";
|
|
197
198
|
private disposed = false;
|
|
198
199
|
onInput?: () => void;
|
|
200
|
+
onKey?: (data: string) => boolean;
|
|
201
|
+
private suggestions = "";
|
|
202
|
+
|
|
203
|
+
setSuggestions(text: string): void {
|
|
204
|
+
this.suggestions = text;
|
|
205
|
+
this.tui.requestRender();
|
|
206
|
+
}
|
|
199
207
|
|
|
200
208
|
get focused(): boolean {
|
|
201
209
|
return this._focused;
|
|
@@ -212,6 +220,7 @@ export class BtwModal implements Focusable {
|
|
|
212
220
|
private readonly onClose: () => void,
|
|
213
221
|
private readonly onSubmit: (value: string) => void,
|
|
214
222
|
private readonly onDispose: () => void,
|
|
223
|
+
private readonly appearance: { title?: string; commands?: string; inputLabel?: string; idleHint?: string } = {},
|
|
215
224
|
) {
|
|
216
225
|
this.input.onSubmit = (value) => {
|
|
217
226
|
if (!this.running) this.onSubmit(value);
|
|
@@ -260,6 +269,12 @@ export class BtwModal implements Focusable {
|
|
|
260
269
|
this.tui.requestRender();
|
|
261
270
|
}
|
|
262
271
|
|
|
272
|
+
/** Reuse the BTW modal for independent interview flows without sharing BTW state. */
|
|
273
|
+
setCustomMode(label: string): void {
|
|
274
|
+
this.customMode = label;
|
|
275
|
+
this.tui.requestRender();
|
|
276
|
+
}
|
|
277
|
+
|
|
263
278
|
clearComposer(): void {
|
|
264
279
|
this.input.setValue("");
|
|
265
280
|
this.tui.requestRender();
|
|
@@ -285,6 +300,7 @@ export class BtwModal implements Focusable {
|
|
|
285
300
|
}
|
|
286
301
|
|
|
287
302
|
handleInput(data: string): void {
|
|
303
|
+
if (this.onKey?.(data)) return;
|
|
288
304
|
if (matchesKey(data, "escape")) {
|
|
289
305
|
this.onClose();
|
|
290
306
|
return;
|
|
@@ -303,18 +319,24 @@ export class BtwModal implements Focusable {
|
|
|
303
319
|
header: () => {
|
|
304
320
|
const scroll = this.scroller.indicator();
|
|
305
321
|
const model = this.model ? this.theme.fg("dim", ` · ${this.model}`) : "";
|
|
306
|
-
const mode = this.
|
|
307
|
-
|
|
322
|
+
const mode = this.customMode
|
|
323
|
+
? this.theme.fg("dim", this.customMode)
|
|
324
|
+
: this.theme.fg("dim", " · ") + (this.full ? this.theme.fg("accent", this.theme.bold(btwModeLabel(true))) : this.theme.fg("dim", btwModeLabel(false)));
|
|
325
|
+
const title = this.theme.fg("accent", this.theme.bold(this.appearance.title ?? "Bro · btw"));
|
|
326
|
+
// Keep Grill's access warning ahead of text the frame may truncate.
|
|
327
|
+
const header = this.customMode ? `${mode} · ${title}${model}` : title + model + mode;
|
|
328
|
+
return header + this.theme.fg("dim", scroll ? ` · ${scroll}` : "");
|
|
308
329
|
},
|
|
309
330
|
body: (rows, innerWidth) => this.scroller.view(this.markdown.render(innerWidth), rows),
|
|
310
331
|
// The frame drops lines from the top when space runs out, so the composer goes last.
|
|
311
332
|
footer: [
|
|
312
|
-
...wrapTextWithAnsi("Commands: /mode · /copy · /copy-all · /insert · /insert-all · /clear · /retry", inner),
|
|
313
|
-
this.theme.fg("accent", this.
|
|
333
|
+
...(this.appearance.commands === "" ? [] : wrapTextWithAnsi(this.appearance.commands ?? "Commands: /mode · /copy · /copy-all · /insert · /insert-all · /clear · /retry", inner)),
|
|
334
|
+
...(this.suggestions ? wrapTextWithAnsi(this.theme.fg("accent", this.suggestions), inner) : []),
|
|
335
|
+
this.theme.fg("accent", this.theme.bold(this.appearance.inputLabel ?? "Your message to Bro")),
|
|
314
336
|
this.input.render(inner)[0] ?? "",
|
|
315
337
|
],
|
|
316
338
|
notice: this.noticeText ? formatNotice(this.theme, this.noticeText, this.noticeTone) : undefined,
|
|
317
|
-
hints: this.running ? "Bro is thinking… · Esc close (stops reply)" : "Enter send · Esc close",
|
|
339
|
+
hints: this.running ? "Bro is thinking… · Esc close (stops reply)" : (this.appearance.idleHint ?? "Enter send · Esc close"),
|
|
318
340
|
});
|
|
319
341
|
}
|
|
320
342
|
|