pi-bro 0.14.0 → 0.15.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 +6 -0
- package/README.md +68 -17
- package/bro.ts +48 -35
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pi-bro are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.15.0] - 2026-09-22
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- In the `/bro btw` modal, `/copy` and `/copy-all` now copy the latest answer or the full thread to the **system clipboard** instead of the main editor. New `/insert` and `/insert-all` commands (with `/insert!`/`/insert-all!` force variants to replace an existing main-editor draft) insert into the main editor without submitting. Removed the legacy `/send` aliases and the spaced `/copy all`/`/insert all` spellings.
|
|
10
|
+
|
|
5
11
|
## [0.14.0] - 2026-09-20
|
|
6
12
|
|
|
7
13
|
### Added
|
package/README.md
CHANGED
|
@@ -111,22 +111,28 @@ your terminal mode; press **C** to copy the complete explanation reliably.
|
|
|
111
111
|
`/bro btw` opens a separate multi-turn conversation in a modal, so you can ask
|
|
112
112
|
a quick side question while the main agent keeps working. It runs through Agy,
|
|
113
113
|
the same backend as the rest of Bro, and never adds anything to Pi's
|
|
114
|
-
conversation unless you explicitly
|
|
114
|
+
conversation unless you explicitly insert it into the editor.
|
|
115
115
|
|
|
116
116
|
- **Sandboxed by default**: the side conversation is read-only (no project
|
|
117
117
|
access). Add `--full` to let it read and edit the workspace.
|
|
118
118
|
- `/bro btw <question>` asks immediately; `/bro btw` opens an empty thread.
|
|
119
119
|
- `--fresh` starts a thread without seeding the main session's recent
|
|
120
|
-
conversation text.
|
|
120
|
+
conversation text. Reopening without an access flag preserves the existing
|
|
121
|
+
thread's access mode, including `--full`. Use `--sandbox` to return to sandbox
|
|
122
|
+
mode; changing access mode starts a new thread. `--fresh` alone does not reset
|
|
123
|
+
the access mode.
|
|
121
124
|
- The first turn is seeded with up to the last 8 turns of user/assistant
|
|
122
125
|
conversation text (40,000 characters max, with a truncation notice); the
|
|
123
126
|
side agent can also read the repo itself when running in `--full` mode.
|
|
124
127
|
- **In the modal**: type a question and press Enter (empty Enter re-asks the
|
|
125
|
-
last question).
|
|
126
|
-
|
|
127
|
-
copies the full thread
|
|
128
|
-
the
|
|
129
|
-
|
|
128
|
+
last question). Composer actions trigger only on these exact commands:
|
|
129
|
+
- `/copy`: copies the latest answer to the system clipboard
|
|
130
|
+
- `/copy-all`: copies the full thread to the system clipboard
|
|
131
|
+
- `/insert`: inserts the latest answer into the main editor without submitting (use `/insert!` to replace an existing editor draft)
|
|
132
|
+
- `/insert-all`: inserts the full thread into the main editor without submitting (use `/insert-all!` to replace an existing editor draft)
|
|
133
|
+
- `/retry`: re-asks the last question (empty Enter does the same)
|
|
134
|
+
- `/clear`: resets the thread
|
|
135
|
+
Any other text or slash-prefixed input (such as `/send` or `/copy!`) is not a composer command and is submitted directly as a question to the side conversation. Esc closes the modal. A visible `full · edits repo` badge shows whenever `--full` mode is active.
|
|
130
136
|
- The thread lives in memory only — it clears when you switch Pi sessions,
|
|
131
137
|
reload extensions, or quit Pi.
|
|
132
138
|
|
|
@@ -157,8 +163,9 @@ gives an `agy update` action when it is too old.
|
|
|
157
163
|
tool access in the workspace with permissions auto-approved
|
|
158
164
|
(`--dangerously-skip-permissions`) — there is no enforced read-only
|
|
159
165
|
isolation. It is instructed to verify claims itself and return advice,
|
|
160
|
-
leaving edits to the executor, but that
|
|
161
|
-
|
|
166
|
+
leaving edits to the executor, but that boundary is a behavioral prompt
|
|
167
|
+
instruction rather than an enforced sandbox constraint, so treat its
|
|
168
|
+
findings as advice to verify, not a guaranteed hands-off review.
|
|
162
169
|
- **Steering**: `/bro advisor-steer` opens an editor for one persistent
|
|
163
170
|
steering brief — e.g. "quick prototype; keep A and B careful, everything
|
|
164
171
|
else minimal" — that the advisor always reads. **Ctrl+S** saves and keeps
|
|
@@ -170,9 +177,10 @@ gives an `agy update` action when it is too old.
|
|
|
170
177
|
conversation or sent to the main model** — the advisor is the only thing
|
|
171
178
|
that reads it.
|
|
172
179
|
- **Persistence**: the steering brief persists with the Pi session (not
|
|
173
|
-
globally, not per project)
|
|
174
|
-
|
|
175
|
-
original branch.
|
|
180
|
+
globally, not per project) as custom extension data in the session file and
|
|
181
|
+
is restored on resume or reload. Forking a session inherits it; edits made
|
|
182
|
+
after the fork are independent of the original branch. The advisor tool has
|
|
183
|
+
no separate activation state persisted or toggled.
|
|
176
184
|
- **Retries**: on an invocation failure (not a completed answer — "I need
|
|
177
185
|
more evidence" is a normal result, not a failure), Bro retries with the
|
|
178
186
|
identical snapshot, steering, and question: once after 5 seconds, once more
|
|
@@ -235,11 +243,14 @@ changed in the auth flow`. The query is used as a lens on the captured turns,
|
|
|
235
243
|
not as additional evidence, and its casing is preserved as typed. Pressing
|
|
236
244
|
**R** retries with the same turn count and query.
|
|
237
245
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
on "
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
Any leading whitespace-delimited word that looks like a number is treated as the
|
|
247
|
+
requested turn count: for example, `/bro show 3 what changed` captures 3 turns
|
|
248
|
+
and steers on "what changed", while `/bro show 404 handler` parses "404" as the
|
|
249
|
+
turn count and "handler" as the steering query. To steer on a phrase that starts
|
|
250
|
+
with digits while choosing a turn count, specify the turn count explicitly
|
|
251
|
+
first: `/bro show 1 404 handler` captures 1 turn and steers on "404 handler".
|
|
252
|
+
If the first word is not a number, the whole input is treated as the steering
|
|
253
|
+
query using the saved `showTurns` default.
|
|
243
254
|
|
|
244
255
|
### A slow session-create, traced
|
|
245
256
|
|
|
@@ -728,6 +739,23 @@ chooses the initial model only when Bro creates a missing settings file:
|
|
|
728
739
|
PI_BRO_MODEL=gemini-3.7-flash-low pi
|
|
729
740
|
```
|
|
730
741
|
|
|
742
|
+
### Configuration precedence
|
|
743
|
+
|
|
744
|
+
When resolving model and reasoning effort:
|
|
745
|
+
1. **Per-capability override**: If configured under `overrides.<capability>` (`explain`, `show`, `btw`, or `advisor`) in `bro-settings.json`, that capability pins its own `{ "model": ..., "effort": ... }` pair and ignores the shared default.
|
|
746
|
+
2. **Shared default**: If no override is set for that capability, it inherits the root `model` and `effort` in `bro-settings.json`.
|
|
747
|
+
3. **Catalog normalization**: Bro normalizes the resolved `{ model, effort }` against Agy's installed model catalog (mapping suffixed variant IDs and handling fixed-effort models).
|
|
748
|
+
4. **Initial file creation only**: `PI_BRO_MODEL` selects the initial default model only when Bro creates a missing `bro-settings.json` file. It has no effect once the file exists.
|
|
749
|
+
|
|
750
|
+
When resolving turn count for `/bro show`:
|
|
751
|
+
1. **Command argument**: An explicit count like `/bro show 3` or `/bro show 1 query` overrides for that single execution.
|
|
752
|
+
2. **Saved setting**: `showTurns` in `bro-settings.json` (defaults to 1; configurable interactively via `/bro config` or direct file edit).
|
|
753
|
+
|
|
754
|
+
When resolving explanation prompt (`explain` capability only):
|
|
755
|
+
1. **Custom prompt**: `~/.pi/agent/bro-prompt.md` (or `$PI_CODING_AGENT_DIR/bro-prompt.md`), if present and valid (`{{response}}` exactly once), completely overrides all built-in modes.
|
|
756
|
+
2. **Saved mode**: `mode` in `bro-settings.json` (`brief`, `balanced`, or `faithful`; defaults to `balanced`).
|
|
757
|
+
3. Note: `bro-prompt.md` applies only to `/bro`, `/bro text`, `/bro file`, and `/bro url`; it does not affect `/bro show`, `/bro btw`, or `bro_advisor`.
|
|
758
|
+
|
|
731
759
|
## Custom prompt
|
|
732
760
|
|
|
733
761
|
Bro uses a built-in prompt by default. To use your own, create:
|
|
@@ -806,6 +834,24 @@ run `/bro doctor` for the exact problem.
|
|
|
806
834
|
according to their own settings and privacy policies.
|
|
807
835
|
- **Clipboard**: Pressing **C** copies the text to your system clipboard, where
|
|
808
836
|
your operating system or clipboard manager may retain it.
|
|
837
|
+
- **Advisor requests**: `bro_advisor` sends the executor agent's system
|
|
838
|
+
instructions, active tool list (excluding `bro_advisor`), ordered
|
|
839
|
+
conversation history including tool calls and tool results (unlike Show, which
|
|
840
|
+
omits them), human steering brief, and the executor's optional question to
|
|
841
|
+
Agy and your configured model provider. Reasoning and image bodies are
|
|
842
|
+
omitted with explicit markers (`[reasoning omitted]`, `[image omitted]`).
|
|
843
|
+
- **Advisor tool execution & safety boundary**: The advisor process runs
|
|
844
|
+
directly in your workspace (`cwd`) with auto-approved permissions
|
|
845
|
+
(`--dangerously-skip-permissions`). It has real tool access (file reading,
|
|
846
|
+
search, command execution). The directive to only advise and leave edits to
|
|
847
|
+
the executor is a **behavioral prompt instruction**, not an enforced sandbox
|
|
848
|
+
or security boundary. Treat its findings as advice to verify before applying.
|
|
849
|
+
- **Advisor steering persistence**: The steering brief is saved as
|
|
850
|
+
session-scoped custom extension data (`bro-advisor-steering`) in the session
|
|
851
|
+
file. It persists across session resume and reload, and is inherited on
|
|
852
|
+
session fork (post-fork edits on branches remain independent). It is never
|
|
853
|
+
sent to the main model or added to Pi's conversation. The advisor tool has
|
|
854
|
+
no separate activation state.
|
|
809
855
|
|
|
810
856
|
## Troubleshooting and current limits
|
|
811
857
|
|
|
@@ -825,6 +871,11 @@ tool before giving it to Bro.
|
|
|
825
871
|
- `/bro btw` threads are memory-only and do not survive reloads or restarts.
|
|
826
872
|
The side conversation needs Agy's `--conversation` resume support; sandbox
|
|
827
873
|
mode caps a turn at 2 minutes and full mode at 10 minutes.
|
|
874
|
+
- `bro_advisor` requires Agy CLI `>=1.1.15` (for `--input-format stream-json`).
|
|
875
|
+
Consultations run directly in the workspace with auto-approved permissions
|
|
876
|
+
without enforced file-modification isolation; an attempt is capped at 10
|
|
877
|
+
minutes (`--print-timeout 10m`) and retries up to 2 times on invocation
|
|
878
|
+
failure (5-second, then 10-second backoff).
|
|
828
879
|
- Show captures only the conversation text of what already happened in the
|
|
829
880
|
current session — the last few turns' user and assistant messages, with
|
|
830
881
|
tool calls, tool results, reasoning, and images always omitted; it cannot
|
package/bro.ts
CHANGED
|
@@ -100,10 +100,10 @@ const COMMANDS = [
|
|
|
100
100
|
{ value: "open", label: "open", description: "Reopen the last explanation" },
|
|
101
101
|
{ value: "doctor", label: "doctor", description: "Check whether Bro is ready" },
|
|
102
102
|
{ value: "usage", label: "usage", description: "Show current Agy usage" },
|
|
103
|
-
{ value: "model", label: "model", description: "
|
|
104
|
-
{ value: "effort", label: "effort", description: "
|
|
103
|
+
{ value: "model", label: "model", description: "View or choose the shared default Agy model" },
|
|
104
|
+
{ value: "effort", label: "effort", description: "View or choose the shared default reasoning effort" },
|
|
105
105
|
{ value: "show", label: "show", description: "Draw what happened in recent session turns as shapes" },
|
|
106
|
-
{ value: "mode", label: "mode", description: "
|
|
106
|
+
{ value: "mode", label: "mode", description: "View or choose explanation mode (brief, balanced, faithful)" },
|
|
107
107
|
{ value: "btw", label: "btw", description: "Open a side conversation (sandboxed by default; --full edits files)" },
|
|
108
108
|
{ value: "config", label: "config", description: "Configure shared defaults and per-capability model/effort overrides" },
|
|
109
109
|
{ value: "advisor", label: "advisor", description: "Check whether the executor's advisor tool is available right now" },
|
|
@@ -2170,7 +2170,7 @@ Press **R** to simplify the captured source again. Run a new \`/bro text\`, \`/b
|
|
|
2170
2170
|
|
|
2171
2171
|
## Side conversation
|
|
2172
2172
|
|
|
2173
|
-
- \`/bro btw [--fresh] [--full] [question]\` — open a side conversation. Sandboxed (read-only) by default; add \`--full\` to let it read and edit the workspace, and \`--fresh\` to start without main-session context. Inside the side thread, type questions and press Enter (empty Enter re-asks); \`/copy\`
|
|
2173
|
+
- \`/bro btw [--fresh] [--full] [question]\` — open a side conversation. Sandboxed (read-only) by default; add \`--full\` to let it read and edit the workspace, and \`--fresh\` to start without main-session context. Reopening preserves the thread's access mode (even with \`--fresh\`); use \`--sandbox\` to return to sandbox mode. Changing access mode starts a new thread. Inside the side thread, type questions and press Enter (empty Enter re-asks); exact commands \`/copy\` and \`/copy-all\` copy the latest answer or full thread to the system clipboard; exact commands \`/insert\` and \`/insert-all\` insert into the main editor without submitting (use \`/insert!\` or \`/insert-all!\` to replace an existing draft); \`/retry\` re-asks the last question; \`/clear\` resets the thread. Any other input is sent as a question. Esc closes.
|
|
2174
2174
|
|
|
2175
2175
|
## Advisor
|
|
2176
2176
|
|
|
@@ -2179,13 +2179,13 @@ Press **R** to simplify the captured source again. Run a new \`/bro text\`, \`/b
|
|
|
2179
2179
|
- \`/bro advisor-steer\` — open an editor for one persistent steering brief the advisor always sees. **Ctrl+S** saves, **Enter**/**Shift+Enter** insert newlines, **Ctrl+K** clears the saved brief and draft, **Ctrl+C** copies the full draft, and **Esc** closes without saving unsaved edits
|
|
2180
2180
|
- \`/bro doctor\` — the full advisor diagnostic: whether this host exposes and activates \`bro_advisor\`, its resolved model/effort, steering presence, and the Agy compatibility floor
|
|
2181
2181
|
|
|
2182
|
-
Each consultation is a fresh, standalone Agy process — never resumed, never looping, never automatically triggered. Bro captures the context snapshot (system instructions, active tools, and the conversation so far) automatically; the executor never has to assemble one. The advisor has real tool access in the workspace, running with permissions auto-approved, so it can verify claims itself
|
|
2182
|
+
Each consultation is a fresh, standalone Agy process — never resumed, never looping, never automatically triggered. Bro captures the context snapshot (system instructions, active tools, and the conversation so far including tool calls and results) automatically; the executor never has to assemble one. The advisor has real tool access in the workspace, running with permissions auto-approved, so it can verify claims itself; it is instructed to only return advice and leave edits to the executor, but that instruction is behavioral rather than an enforced sandbox constraint. The steering brief persists in the session (not sent to the model) and is restored on resume or reload; forking a session inherits it, and edits after the fork are independent of the original branch.
|
|
2183
2183
|
|
|
2184
2184
|
## Current settings
|
|
2185
2185
|
|
|
2186
2186
|
${settingsSummary}
|
|
2187
2187
|
|
|
2188
|
-
Saved in \`${SETTINGS_FILE}\`. Use the commands above or edit the file directly. Changes apply to future explanations. \`showTurns\`
|
|
2188
|
+
Saved in \`${SETTINGS_FILE}\`. Use the commands above, configure interactively via \`/bro config\`, or edit the file directly. Changes apply to future explanations. \`showTurns\` can be configured interactively in \`/bro config\` or edited directly in \`${SETTINGS_FILE}\`, and overridden per run with \`/bro show <n-turns>\`. Add a query after the count — or on its own, e.g. \`/bro show what changed in the auth flow\` — to steer what the shapes focus on.
|
|
2189
2189
|
|
|
2190
2190
|
## Explanation modes
|
|
2191
2191
|
|
|
@@ -2213,7 +2213,7 @@ Bro temporarily captures mouse input while the modal is open. Native mouse selec
|
|
|
2213
2213
|
- Show draws only what already happened in this session — the conversation text of the last few turns, with tool calls, tool results, reasoning, and images always omitted — and cannot read the repository or other files on its own. On a remote or headless session with no display, pressing **O** reports a failure instead of opening the diagram.
|
|
2214
2214
|
- Show reflects what was reported in the conversation, not independent verification against the actual code or system state.
|
|
2215
2215
|
- Btw threads are memory-only and do not survive reloads or restarts. A turn is capped at 2 minutes in sandbox mode and 10 minutes in full mode; the side conversation resumes through Agy's \`--conversation\` support.
|
|
2216
|
-
- Advisor consultations run with real tool access and auto-approved permissions (\`--dangerously-skip-permissions\`) — there is no enforced read-only isolation, only the advisor's own instructions to advise rather than implement. On invocation failure (not a completed answer), Bro retries with the identical snapshot, steering, and question: once after 5 seconds, once more after 10 seconds, then returns Agy's own diagnostic as the failure.
|
|
2216
|
+
- Advisor consultations run with real tool access and auto-approved permissions (\`--dangerously-skip-permissions\`) — there is no enforced read-only isolation, only the advisor's own behavioral instructions to advise rather than implement. On invocation failure (not a completed answer), Bro retries with the identical snapshot, steering, and question: once after 5 seconds, once more after 10 seconds, then returns Agy's own diagnostic as the failure.
|
|
2217
2217
|
|
|
2218
2218
|
## Privacy and safety
|
|
2219
2219
|
|
|
@@ -2226,7 +2226,7 @@ For webpages, it connects directly to the site without browser cookies; the site
|
|
|
2226
2226
|
|
|
2227
2227
|
Usage and Doctor checks contact Agy but do not send source text or run a model turn. Pressing **C** sends the explanation to your system clipboard.
|
|
2228
2228
|
|
|
2229
|
-
Each advisor consultation sends the executor's system instructions, active tool list, ordered conversation (including tool calls and results, since the advisor needs to verify claims), your steering brief, and the executor's optional question to Agy and your model provider; the advisor process itself can read and edit the workspace with no permission prompts. The steering brief
|
|
2229
|
+
Each advisor consultation sends the executor's system instructions, active tool list, ordered conversation (including tool calls and results, since the advisor needs to verify claims), your steering brief, and the executor's optional question to Agy and your model provider; the advisor process itself can read and edit the workspace with no permission prompts. The steering brief is stored as session-only extension data — never added to the main conversation Pi or the model sees; the advisor tool has no separate activation state.
|
|
2230
2230
|
|
|
2231
2231
|
## Custom prompt
|
|
2232
2232
|
|
|
@@ -2595,30 +2595,24 @@ export function parseBtwAgyLine(line: string): { delta?: string; result?: string
|
|
|
2595
2595
|
export type BtwComposerAction =
|
|
2596
2596
|
| { kind: "clear" }
|
|
2597
2597
|
| { kind: "retry" }
|
|
2598
|
-
| { kind: "
|
|
2598
|
+
| { kind: "clipboard"; all: boolean }
|
|
2599
|
+
| { kind: "insert"; all: boolean; force: boolean }
|
|
2599
2600
|
| { kind: "question"; text: string };
|
|
2600
2601
|
|
|
2601
2602
|
export function parseBtwComposerCommand(value: string): BtwComposerAction {
|
|
2602
2603
|
const command = value.trim();
|
|
2603
2604
|
if (command === "/clear") return { kind: "clear" };
|
|
2604
2605
|
if (command === "/retry" || command === "") return { kind: "retry" };
|
|
2606
|
+
if (command === "/copy" || command === "/copy-all") {
|
|
2607
|
+
return { kind: "clipboard", all: command === "/copy-all" };
|
|
2608
|
+
}
|
|
2605
2609
|
if (
|
|
2606
|
-
command === "/
|
|
2607
|
-
command === "/
|
|
2608
|
-
command === "/
|
|
2609
|
-
command === "/
|
|
2610
|
-
command === "/copy all" ||
|
|
2611
|
-
command === "/copy all!" ||
|
|
2612
|
-
command === "/send" ||
|
|
2613
|
-
command === "/send!" ||
|
|
2614
|
-
command === "/send all" ||
|
|
2615
|
-
command === "/send all!"
|
|
2610
|
+
command === "/insert" ||
|
|
2611
|
+
command === "/insert!" ||
|
|
2612
|
+
command === "/insert-all" ||
|
|
2613
|
+
command === "/insert-all!"
|
|
2616
2614
|
) {
|
|
2617
|
-
|
|
2618
|
-
command.startsWith("/copy-all") ||
|
|
2619
|
-
command.startsWith("/copy all") ||
|
|
2620
|
-
command.startsWith("/send all");
|
|
2621
|
-
return { kind: "copy", all, force: command.endsWith("!") };
|
|
2615
|
+
return { kind: "insert", all: command.startsWith("/insert-all"), force: command.endsWith("!") };
|
|
2622
2616
|
}
|
|
2623
2617
|
return { kind: "question", text: command };
|
|
2624
2618
|
}
|
|
@@ -2852,7 +2846,7 @@ class BtwModal implements Focusable {
|
|
|
2852
2846
|
|
|
2853
2847
|
const controls = this.running
|
|
2854
2848
|
? this.theme.fg("dim", "Thinking… · Esc cancel")
|
|
2855
|
-
: this.theme.fg("dim", "Enter ask · Esc close · /copy · /copy-all · /clear · /retry");
|
|
2849
|
+
: this.theme.fg("dim", "Enter ask · Esc close · /copy · /copy-all · /insert · /insert-all · /clear · /retry");
|
|
2856
2850
|
|
|
2857
2851
|
const lines = [
|
|
2858
2852
|
this.borderLine(innerWidth, "top"),
|
|
@@ -2969,18 +2963,32 @@ async function openBtwModal(
|
|
|
2969
2963
|
void runTurn(last.question);
|
|
2970
2964
|
};
|
|
2971
2965
|
|
|
2972
|
-
const
|
|
2966
|
+
const copyOut = async (all: boolean) => {
|
|
2973
2967
|
const text = all ? transcript() : (thread.turns.at(-1)?.answer ?? "");
|
|
2974
2968
|
if (!text.trim()) {
|
|
2975
2969
|
modal.setNotice("Nothing to copy yet.");
|
|
2976
2970
|
return;
|
|
2977
2971
|
}
|
|
2972
|
+
try {
|
|
2973
|
+
await copyToClipboard(text);
|
|
2974
|
+
modal.setNotice(all ? "Copied the full thread to the clipboard." : "Copied the latest answer to the clipboard.");
|
|
2975
|
+
} catch (error) {
|
|
2976
|
+
modal.setNotice(`Copy failed: ${errorMessage(error)}`);
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
|
|
2980
|
+
const insert = (all: boolean, force: boolean) => {
|
|
2981
|
+
const text = all ? transcript() : (thread.turns.at(-1)?.answer ?? "");
|
|
2982
|
+
if (!text.trim()) {
|
|
2983
|
+
modal.setNotice("Nothing to insert yet.");
|
|
2984
|
+
return;
|
|
2985
|
+
}
|
|
2978
2986
|
if (ctx.ui.getEditorText().trim() && !force) {
|
|
2979
|
-
modal.setNotice("Main editor has a draft. Use /
|
|
2987
|
+
modal.setNotice("Main editor has a draft. Use /insert! (or /insert-all!) to replace it.");
|
|
2980
2988
|
return;
|
|
2981
2989
|
}
|
|
2982
2990
|
ctx.ui.setEditorText(text);
|
|
2983
|
-
modal.setNotice(all ? "
|
|
2991
|
+
modal.setNotice(all ? "Inserted the full thread into the main editor." : "Inserted the latest answer into the main editor.");
|
|
2984
2992
|
};
|
|
2985
2993
|
|
|
2986
2994
|
function submit(value: string): void {
|
|
@@ -2990,9 +2998,14 @@ async function openBtwModal(
|
|
|
2990
2998
|
clear();
|
|
2991
2999
|
return;
|
|
2992
3000
|
}
|
|
2993
|
-
if (action.kind === "
|
|
3001
|
+
if (action.kind === "clipboard") {
|
|
3002
|
+
modal.clearComposer();
|
|
3003
|
+
void copyOut(action.all);
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
if (action.kind === "insert") {
|
|
2994
3007
|
modal.clearComposer();
|
|
2995
|
-
|
|
3008
|
+
insert(action.all, action.force);
|
|
2996
3009
|
return;
|
|
2997
3010
|
}
|
|
2998
3011
|
if (action.kind === "retry") {
|
|
@@ -3040,12 +3053,12 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
3040
3053
|
label: "Bro advisor",
|
|
3041
3054
|
description:
|
|
3042
3055
|
"Consult a fresh, independent Agy process for a second opinion mid-task. It has real, unsandboxed tool access in the current workspace (read files, search, run commands) with permissions auto-approved, and is instructed to investigate before advising and to leave edits to you — that is a behavioral instruction to the advisor, not an enforced restriction, so treat its findings as advice rather than a delegated implementation. You never need to prepare a summary or evidence first: Bro automatically captures your system instructions, active tools, and the conversation so far, plus any human-set steering priorities, and sends them to the advisor.",
|
|
3043
|
-
promptSnippet: "
|
|
3056
|
+
promptSnippet: "Consult a fresh Agy process for a second opinion mid-task; it investigates the workspace itself and returns advice",
|
|
3044
3057
|
promptGuidelines: [
|
|
3045
3058
|
"Call bro_advisor before or after a non-trivial design or scope decision, or when genuinely uncertain, for a second opinion from a fresh, independent Agy process.",
|
|
3046
|
-
"question is optional — never delay a call to first prepare a summary or evidence; Bro captures
|
|
3047
|
-
"Any human-set steering priorities are applied automatically by
|
|
3048
|
-
"
|
|
3059
|
+
"bro_advisor's question parameter is optional — never delay a call to first prepare a summary or evidence; Bro captures context automatically.",
|
|
3060
|
+
"Any human-set steering priorities are applied automatically by bro_advisor; you don't need to relay or repeat them.",
|
|
3061
|
+
"bro_advisor is instructed to only return advice and leave edits to you — that instruction is not enforced, so verify its findings yourself rather than treating them as a completed implementation.",
|
|
3049
3062
|
],
|
|
3050
3063
|
parameters: Type.Object({
|
|
3051
3064
|
question: Type.Optional(
|
|
@@ -3137,7 +3150,7 @@ export default async function bro(pi: ExtensionAPI) {
|
|
|
3137
3150
|
});
|
|
3138
3151
|
|
|
3139
3152
|
pi.registerCommand("bro", {
|
|
3140
|
-
description: "Explain
|
|
3153
|
+
description: "Explain text, documents, and webpages; draw session turns; open a side conversation; configure Bro and the executor's advisor tool",
|
|
3141
3154
|
getArgumentCompletions: (prefix) => {
|
|
3142
3155
|
const normalized = prefix.trim().toLowerCase();
|
|
3143
3156
|
const matches = COMMANDS.filter((command) => command.value.startsWith(normalized));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-bro",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "An Earendil Pi extension that explains pasted text, assistant responses, local documents, public webpages, and recent session turns (as shapes) in a context-isolated window,
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"description": "An Earendil Pi extension that explains pasted text, assistant responses, local documents, public webpages, and recent session turns (as shapes) in a context-isolated window, opens a sandboxed side conversation with /bro btw, and provides a second-opinion advisor tool for executor agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Tran Hoang Nguyen",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"diagram",
|
|
30
30
|
"show",
|
|
31
31
|
"btw",
|
|
32
|
-
"side-conversation"
|
|
32
|
+
"side-conversation",
|
|
33
|
+
"advisor",
|
|
34
|
+
"second-opinion"
|
|
33
35
|
],
|
|
34
36
|
"files": [
|
|
35
37
|
"bro.ts",
|