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.
Files changed (4) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +68 -17
  3. package/bro.ts +48 -35
  4. 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 copy it into the editor.
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). `/copy` copies the latest answer into the main editor
126
- without submitting (use `/copy!` to replace an existing draft); `/copy-all`
127
- copies the full thread; `/retry` re-asks
128
- the last question; `/clear` resets the thread; Esc closes. A visible
129
- `full · edits repo` badge shows whenever `--full` mode is active.
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 instruction is not enforced, so
161
- treat its findings as advice to verify, not a guaranteed hands-off review.
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) and is restored on resume or reload. Forking a
174
- session inherits it; edits made after the fork are independent of the
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
- Only the first word is ever read as the turn count — a query that starts with
239
- digits is not ambiguous. `/bro show 1 404 handler` captures 1 turn and steers
240
- on "404 handler"; `/bro show 404 handler` (no leading count) steers on the
241
- whole phrase "404 handler" using the default turn count, since "404" alone
242
- would be a count but "404 handler" is not.
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: "Choose the Agy model" },
104
- { value: "effort", label: "effort", description: "Choose the Agy reasoning effort" },
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: "Choose brief, balanced, or faithful explanations" },
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\` copies the latest answer to the main editor without submitting (use \`/copy!\` to replace an existing draft), \`/copy-all\` the full thread, \`/retry\` re-asks the last question, and \`/clear\` resets the thread. Esc closes.
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 — it only ever returns advice, and the executor stays responsible for any actual change. 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.
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\` has no setter command — edit the file directly, or override it 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.
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 and activation state are stored as session-only extension data — never added to the main conversation Pi or the model sees.
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: "copy"; all: boolean; force: boolean }
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 === "/copy" ||
2607
- command === "/copy!" ||
2608
- command === "/copy-all" ||
2609
- command === "/copy-all!" ||
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
- const all =
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 handoff = (all: boolean, force: boolean) => {
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 /copy! (or /copy-all!) to replace it.");
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 ? "Copied the full thread to the editor." : "Copied the latest answer to the editor.");
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 === "copy") {
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
- handoff(action.all, action.force);
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: "bro_advisor({question?}): consult a fresh Agy process for a second opinion; it investigates the workspace itself and returns advice",
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 your context automatically.",
3047
- "Any human-set steering priorities are applied automatically by the advisor; you don't need to relay or repeat them.",
3048
- "The 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.",
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 replies, pasted text, documents, and webpages, draw recent session turns, or open a sandboxed side conversation with /bro btw",
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.14.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, and opens a sandboxed side conversation with /bro btw.",
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",