@hk_net/pi-advisor 0.1.6 → 0.1.8

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 (5) hide show
  1. package/CHANGELOG.md +94 -73
  2. package/LICENSE +287 -287
  3. package/README.md +193 -182
  4. package/advisor.ts +1110 -1082
  5. package/package.json +53 -39
package/README.md CHANGED
@@ -1,182 +1,193 @@
1
- # pi-advisor
2
-
3
- A [pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) extension for pi `>=0.81.1` that offers a
4
- parameterless `advisor` tool — inspired by Claude Code's advisor, but expanded with additional
5
- nudges and a manual review procedure. The regular model calls `advisor` to get a second opinion
6
- from an explicitly configured **stronger reviewer model** that sees the *entire* conversation transcript. Beyond the
7
- callable tool, the extension can also **auto-consult** the reviewer when the agent seems stuck
8
- or finishes a task, and the human can invoke a manual review via `/advise`.
9
-
10
- ## What it does
11
-
12
- When the model calls `advisor` (no arguments), the extension serializes the full active branch —
13
- user/assistant text, assistant **reasoning**, every **tool call (with args)** and its **result** —
14
- and forwards it to a stronger reviewer model with a reviewer system prompt. The reviewer returns
15
- direct, actionable advice (flag wrong assumptions, name what's likely to bite, scrutinize "I'm
16
- done" claims). Individual tool-call arguments are truncated at 800 characters and tool results at
17
- 2,000 characters so huge outputs do not dominate the review; after that, the transcript is truncated
18
- oldest-first only if it would overflow the reviewer's context window.
19
-
20
- Beyond the callable tool, the extension provides two additional ways to get advice:
21
-
22
- - **Automatic nudges** the tool's `promptGuidelines` encourage the model to call advisor
23
- *before substantive work*, *when stuck*, and *when it believes the task is complete*. Two
24
- opt-in deterministic triggers (`onDone`, `whenStuck`) go further: they auto-consult the
25
- reviewer and inject the feedback directly into the conversation so the agent sees it.
26
- - **Manual review via `/advise`** the human can invoke a one-off review at any time. Feedback
27
- can be shown UI-only (informal, for the human), piped into the chat as a user message, or
28
- injected as a steering message so the running agent sees and acts on it.
29
-
30
- ## Files & install
31
-
32
- - `advisor.ts` canonical source (this repo).
33
- - Package-installed copy: loaded from this package's `pi.extensions` manifest after `pi install`.
34
-
35
- Install just this extension from npm:
36
-
37
- ```bash
38
- pi install npm:@hk_net/pi-advisor
39
- ```
40
-
41
- Or install the full collection from GitHub:
42
-
43
- ```bash
44
- pi install git:git@github.com:hknet/pi-extensions@main
45
- pi install https://github.com/hknet/pi-extensions
46
- ```
47
-
48
- Or install manually (copy just this extension):
49
-
50
- ```bash
51
- cp packages/pi-advisor/advisor.ts ~/.pi/agent/extensions/advisor.ts
52
- ```
53
-
54
- > When installed as an npm package, pi loads `advisor.ts` through this package's `pi.extensions`
55
- > manifest. When installed through the GitHub collection, pi loads it through the root package
56
- > manifest. If you manually copy the file instead, that copied production file is separate from this
57
- > source; re-copy it after edits and run `/reload`.
58
-
59
- ## Configuration
60
-
61
- JSON, resolved **project-over-global** (first scope that defines a key wins):
62
-
63
- - Project: `<cwd>/.pi/advisor.json` (honored only when pi considers the project trusted)
64
- - Global: `~/.pi/agent/advisor.json`
65
-
66
- ```jsonc
67
- {
68
- "model": "openai-codex/gpt-5.5", // "provider/id", or "none" to disable + hide the tool
69
- "thinking": "high", // a level supported by the selected reviewer model (default high)
70
- "onDone": false, // auto-review when the agent finishes a task
71
- "whenStuck": 0, // auto-consult after N consecutive errors or N repeated identical tool calls (0 = off)
72
- "timeoutMs": 120000 // advisor call timeout in ms (0 = use provider default)
73
- }
74
- ```
75
-
76
- **Model precedence:** env `PI_ADVISOR_MODEL` > project > global. If no model is explicitly
77
- configured, advisor remains discoverable but sends no transcript and asks the user to choose a
78
- trusted reviewer model with `/advisor`. Thinking level uses the same order via
79
- `PI_ADVISOR_EFFORT` / project / global, default `high`. Timeout uses env
80
- `PI_ADVISOR_TIMEOUT_MS` > project > global, default 120 000 ms (2 minutes).
81
-
82
- **Why the timeout?** When the running model calls `advisor`, it waits for the tool result.
83
- Without a timeout, a slow reviewer model or dropped connection would hang the entire turn.
84
- The timeout ensures the running model always makes progress.
85
-
86
- **No implicit reviewer fallback:** the extension does not auto-pick a reviewer model. This avoids
87
- surprising cross-provider transcript sharing. The model picker refreshes the registry before listing
88
- so API-key models and OAuth/subscription-backed models (for example providers added with `/login`)
89
- are selectable.
90
-
91
- ## Commands
92
-
93
- | Command | Effect |
94
- |---|---|
95
- | `/advisor <enter>` | Open the interactive model-picker dialog (scrollable list of available models), then choose project vs global scope, then pick a thinking level |
96
- | `/advisor none` | Disable advisor for a scope choose scope |
97
- | `/advisor default` | Clear a scope; if no env/lower-scope model remains, advisor becomes not configured |
98
- | `/advisor on-done on\|off` | Toggle auto-review-on-finish → choose scope |
99
- | `/advisor when-stuck off\|<N>` | Trigger advisor on N consecutive errors or N repeated identical tool calls → choose scope |
100
- | `/advisor status` | Show the resolved configuration |
101
- | `/advise [show\|pipe\|steer]` | Run a one-off review now; default is `pipe` when idle and `steer` while the agent is running |
102
-
103
- Autocomplete completes `/adviso...` to `/advisor` without Pi's trailing-space insertion. A completed reviewer model opens that model's supported thinking-level picker on the next Tab. `/advisor on-done` and `/advisor when-stuck` open their value pickers directly. `/advise` keeps Pi's standard completion behavior.
104
-
105
- ### `/advise` modes
106
-
107
- - **`/advise`** quick advice injection: sends feedback as a user message when idle, or as a
108
- steering message while the agent is running.
109
- - **`/advise show`** display advisor feedback to the human only. Clearly marked as
110
- **not sent to the model** useful for informal review.
111
- - **`/advise pipe`** — inject the advisor feedback into the active chat as a user message. If the
112
- agent is already running, it is queued as a follow-up so the agent sees it in the next turn.
113
- - **`/advise steer`** — inject the advisor feedback as a steering message when the agent is running,
114
- so the agent sees it immediately without waiting for the current turn to complete.
115
-
116
- ## Automatic triggers
117
-
118
- Default **off**out of the box the regular model decides when to call `advisor`, nudged by the
119
- tool's `promptGuidelines`. Two opt-in deterministic triggers, configurable per project and global:
120
-
121
- - **`onDone`** on `agent_end`, auto-review and steer one follow-up so the agent addresses any
122
- issues before truly stopping (guarded to at most once per user prompt).
123
- - **`whenStuck: N`** after N consecutive tool errors **or** N repeated identical tool calls
124
- (same tool name + same arguments), auto-consult the reviewer and inject the advice as a
125
- steering message to get unstuck.
126
-
127
- ## Privacy & security
128
-
129
- - **No transcript is sent until a reviewer model is explicitly configured.** Out of the box,
130
- advisor is discoverable but unconfigured; calls return setup guidance instead of falling back to
131
- another model.
132
- - **Project config follows pi project trust.** A global install ignores `<cwd>/.pi/advisor.json`
133
- while the current project is untrusted, so an untrusted checkout cannot silently choose a reviewer
134
- model or enable auto-triggers.
135
- - **Auto-triggers are off by default.** The `onDone` and `whenStuck` features must be explicitly
136
- enabled in configuration, and they do nothing unless a reviewer model is configured.
137
- - **Data sent to the reviewer model.** When `advisor` is called, the extension sends the full
138
- active conversation branch to the configured reviewer model via the provider's API. This
139
- includes:
140
- - User messages and assistant text
141
- - Assistant reasoning/thinking blocks
142
- - Tool call names, arguments, and results (file paths, command output, etc.; tool-call arguments
143
- are truncated at 800 characters and tool results at 2,000 characters)
144
- - Tool result errors
145
- - **You control which model receives the data.** Configure `model` in `advisor.json` to point
146
- to a provider/model you trust. If no model is configured, no reviewer API call is made.
147
- - **No data is stored or logged by this extension.** The transcript is sent in-memory to the
148
- reviewer model's API and not persisted locally.
149
- - **Be mindful of secrets.** Tool results may contain secrets (API keys, credentials, tokens)
150
- from `bash` output or file contents. If your project contains sensitive data, consider
151
- configuring advisor to use a provider with a strong privacy policy, or disable auto-triggers.
152
-
153
- ## Implementation notes (pi extension API)
154
-
155
- - **Call a model from an extension:** `complete(model, { systemPrompt, messages }, { apiKey, headers,
156
- signal, reasoningEffort, maxTokens })` from `@earendil-works/pi-ai/compat`. Resolve auth with
157
- `ctx.modelRegistry.find(provider, id)` `await ctx.modelRegistry.getApiKeyAndHeaders(model)`
158
- (`{ ok, apiKey, headers }`). `getAvailable()` lists only auth-configured models; `ctx.model` is the
159
- current one; `Model` carries `.contextWindow` / `.maxTokens`. `reasoningEffort` is a passthrough
160
- extra, not in the typed `StreamOptions`.
161
- - **Read the conversation:** `ctx.sessionManager.getBranch()` (active path). Entries are
162
- `{ type:"message", message }` with `role` `user|assistant|toolResult`; assistant content blocks are
163
- `text` / `thinking` / `toolCall`; toolResult has `toolName`, `content`, `isError`.
164
- - **Show output to the human without injecting it:** `pi.sendMessage({ customType, content, display:true })` +
165
- `pi.registerMessageRenderer(customType, …)`. To make the agent *act* on injected advice, use
166
- `pi.sendUserMessage(text, { deliverAs })` (it reaches the LLM and triggers a turn).
167
- - **Hide/show a tool:** `pi.setActiveTools(pi.getActiveTools()…)`. `promptSnippet`/`promptGuidelines`
168
- only appear while the tool is active.
169
- - **Argument autocomplete:** the extension keeps `getArgumentCompletions` for command metadata and
170
- also layers a `ctx.ui.addAutocompleteProvider()` on `session_start` so `/advisor ...` and
171
- `/advise ...` completions replace the whole argument segment and suppress irrelevant path
172
- completion while typing command arguments (pi ≥ 0.79.1).
173
- - Use `complete()` from `@earendil-works/pi-ai/compat` for Pi's compatibility streaming helper.
174
-
175
- ## Issues and feedback
176
-
177
- Found a bug or have a feature request? Please report it on
178
- [GitHub Issues](https://github.com/hknet/pi-extensions/issues).
179
-
180
- For security vulnerabilities, please use
181
- [GitHub's private vulnerability reporting](https://github.com/hknet/pi-extensions/security/advisories/new)
182
- instead of opening a public issue.
1
+ # pi-advisor
2
+
3
+ A [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) extension for Pi 0.84.1 or newer (tested with the current Pi 0.84.2 release) that offers a
4
+ parameterless `advisor` tool — inspired by Claude Code's advisor, but expanded with additional
5
+ nudges and a manual review procedure. The regular model calls `advisor` to get a second opinion
6
+ from an explicitly configured **stronger reviewer model** that sees the *entire* conversation transcript. Beyond the
7
+ callable tool, the extension can also **auto-consult** the reviewer when the agent seems stuck
8
+ or finishes a task, and the human can invoke a manual review via `/advise`.
9
+
10
+ ## What it does
11
+
12
+ When the model calls `advisor` (no arguments), the extension serializes the full active branch —
13
+ user/assistant text, assistant **reasoning**, every **tool call (with args)** and its **result** —
14
+ and forwards it to a stronger reviewer model with a reviewer system prompt. The reviewer infers whether it is assessing a plan,
15
+ a concrete failure, or claimed completion; checks the work against user and repository instructions
16
+ and primary-source evidence; and returns a verdict plus at most three prioritized actions. A
17
+ premature consultation asks for the specific missing evidence instead of inventing a verdict.
18
+ Individual tool-call arguments are truncated at 800 characters and tool results at
19
+ 2,000 characters so huge outputs do not dominate the review; after that, the transcript is truncated
20
+ oldest-first only if it would overflow the reviewer's context window.
21
+
22
+ Beyond the callable tool, the extension provides two additional ways to get advice:
23
+
24
+ - **Automatic nudges** the tool's `promptGuidelines` tell the model to call advisor at a
25
+ useful checkpoint in every non-trivial task: after enough investigation to form an
26
+ evidence-backed approach and before a consequential edit, when stuck, or after implementation
27
+ and verification before claiming completion. A mandatory pre-final check tells the model not to
28
+ finish non-trivial work unless it has called advisor at least once after gathering evidence.
29
+ The guidance explicitly prohibits an advisor call as the first action or while there is no
30
+ substantive evidence or work to review. Two opt-in
31
+ deterministic triggers (`onDone`, `whenStuck`) go further: they auto-consult the reviewer and
32
+ inject the feedback directly into the conversation so the agent sees it.
33
+ - **Manual review via `/advise`** the human can invoke a one-off review at any time. Feedback
34
+ can be shown UI-only (informal, for the human), piped into the chat as a user message, or
35
+ injected as a steering message so the running agent sees and acts on it.
36
+
37
+ ## Files & install
38
+
39
+ > **Avoid duplicate installation.** Install this npm package or the GitHub bundle, not both. Loading both copies can duplicate tools, commands, and automatic event handlers.
40
+
41
+ - `advisor.ts` canonical source (this repo).
42
+ - Package-installed copy: loaded from this package's `pi.extensions` manifest after `pi install`.
43
+
44
+ Install just this extension from npm:
45
+
46
+ ```bash
47
+ pi install npm:@hk_net/pi-advisor
48
+ ```
49
+
50
+ Or install the full collection from GitHub:
51
+
52
+ ```bash
53
+ pi install git:git@github.com:hknet/pi-extensions@main
54
+ pi install https://github.com/hknet/pi-extensions
55
+ ```
56
+
57
+ Or install manually (copy just this extension):
58
+
59
+ ```bash
60
+ cp packages/pi-advisor/advisor.ts ~/.pi/agent/extensions/advisor.ts
61
+ ```
62
+
63
+ > When installed as an npm package, pi loads `advisor.ts` through this package's `pi.extensions`
64
+ > manifest. When installed through the GitHub collection, pi loads it through the root package
65
+ > manifest. If you manually copy the file instead, that copied production file is separate from this
66
+ > source; re-copy it after edits and run `/reload`.
67
+
68
+ ## Configuration
69
+
70
+ JSON, resolved **project-over-global** (first scope that defines a key wins):
71
+
72
+ - Project: `<cwd>/.pi/advisor.json` (honored only when pi considers the project trusted)
73
+ - Global: `~/.pi/agent/advisor.json`
74
+
75
+ ```jsonc
76
+ {
77
+ "model": "openai-codex/gpt-5.5", // "provider/id", or "none" to disable + hide the tool
78
+ "thinking": "high", // a level supported by the selected reviewer model (default high)
79
+ "onDone": false, // auto-review when the agent finishes a task
80
+ "whenStuck": 0, // auto-consult after N consecutive errors or N repeated identical tool calls (0 = off)
81
+ "timeoutMs": 120000 // advisor call timeout in ms (0 = use provider default)
82
+ }
83
+ ```
84
+
85
+ **Model precedence:** env `PI_ADVISOR_MODEL` > project > global. If no model is explicitly
86
+ configured, advisor remains discoverable but sends no transcript and asks the user to choose a
87
+ trusted reviewer model with `/advisor`. Thinking level uses the same order via
88
+ `PI_ADVISOR_EFFORT` / project / global, default `high`. Timeout uses env
89
+ `PI_ADVISOR_TIMEOUT_MS` > project > global, default 120 000 ms (2 minutes).
90
+
91
+ **Why the timeout?** When the running model calls `advisor`, it waits for the tool result.
92
+ Without a timeout, a slow reviewer model or dropped connection would hang the entire turn.
93
+ The timeout ensures the running model always makes progress.
94
+
95
+ **No implicit reviewer fallback:** the extension does not auto-pick a reviewer model. This avoids
96
+ surprising cross-provider transcript sharing. The model picker refreshes the registry before listing
97
+ so API-key models and OAuth/subscription-backed models (for example providers added with `/login`)
98
+ are selectable.
99
+
100
+ ## Commands
101
+
102
+ | Command | Effect |
103
+ |---|---|
104
+ | `/advisor <enter>` | Open the interactive model-picker dialog (scrollable list of available models), then choose project vs global scope, then pick a thinking level |
105
+ | `/advisor none` | Disable advisor for a scope → choose scope |
106
+ | `/advisor default` | Clear a scope; if no env/lower-scope model remains, advisor becomes not configured |
107
+ | `/advisor on-done on\|off` | Toggle auto-review-on-finish choose scope |
108
+ | `/advisor when-stuck off\|<N>` | Trigger advisor on N consecutive errors or N repeated identical tool calls → choose scope |
109
+ | `/advisor status` | Show the resolved configuration |
110
+ | `/advise [show\|pipe\|steer]` | Run a one-off review now; default is `pipe` when idle and `steer` while the agent is running |
111
+
112
+ Autocomplete completes `/adviso...` to `/advisor` without Pi's trailing-space insertion. A completed reviewer model opens that model's supported thinking-level picker on the next Tab. `/advisor on-done` and `/advisor when-stuck` open their value pickers directly. `/advise` keeps Pi's standard completion behavior.
113
+
114
+ ### `/advise` modes
115
+
116
+ - **`/advise`** — quick advice injection: sends feedback as a user message when idle, or as a
117
+ steering message while the agent is running.
118
+ - **`/advise show`** display advisor feedback to the human only. Clearly marked as
119
+ **not sent to the model** useful for informal review.
120
+ - **`/advise pipe`** — inject the advisor feedback into the active chat as a user message. If the
121
+ agent is already running, it is queued as a follow-up so the agent sees it in the next turn.
122
+ - **`/advise steer`** inject the advisor feedback as a steering message when the agent is running,
123
+ so the agent sees it immediately without waiting for the current turn to complete.
124
+
125
+ ## Automatic triggers
126
+
127
+ Default **off** out of the box the regular model decides when to call `advisor`, nudged by the
128
+ tool's `promptGuidelines`. Two opt-in deterministic triggers, configurable per project and global:
129
+
130
+ - **`onDone`** on `agent_settled`, after automatic retries, compaction recovery, and queued
131
+ continuations finish, auto-review and steer one follow-up so the agent addresses any issues
132
+ before truly stopping (guarded to at most once per user prompt).
133
+ - **`whenStuck: N`** after N consecutive tool errors **or** N repeated identical tool calls
134
+ (same tool name + same arguments), auto-consult the reviewer and inject the advice as a
135
+ steering message to get unstuck.
136
+
137
+ ## Privacy & security
138
+
139
+ - **No transcript is sent until a reviewer model is explicitly configured.** Out of the box,
140
+ advisor is discoverable but unconfigured; calls return setup guidance instead of falling back to
141
+ another model.
142
+ - **Project config follows pi project trust.** A global install ignores `<cwd>/.pi/advisor.json`
143
+ while the current project is untrusted, so an untrusted checkout cannot silently choose a reviewer
144
+ model or enable auto-triggers. `/advisor` also withholds the project scope from its configuration
145
+ picker until the project is trusted; global configuration remains available.
146
+ - **Auto-triggers are off by default.** The `onDone` and `whenStuck` features must be explicitly
147
+ enabled in configuration, and they do nothing unless a reviewer model is configured.
148
+ - **Data sent to the reviewer model.** When `advisor` is called, the extension sends the full
149
+ active conversation branch to the configured reviewer model via the provider's API. This
150
+ includes:
151
+ - User messages and assistant text
152
+ - Assistant reasoning/thinking blocks
153
+ - Tool call names, arguments, and results (file paths, command output, etc.; tool-call arguments
154
+ are truncated at 800 characters and tool results at 2,000 characters)
155
+ - Tool result errors
156
+ - **You control which model receives the data.** Configure `model` in `advisor.json` to point
157
+ to a provider/model you trust. If no model is configured, no reviewer API call is made.
158
+ - **No data is stored or logged by this extension.** The transcript is sent in-memory to the
159
+ reviewer model's API and not persisted locally.
160
+ - **Be mindful of secrets.** Tool results may contain secrets (API keys, credentials, tokens)
161
+ from `bash` output or file contents. If your project contains sensitive data, consider
162
+ configuring advisor to use a provider with a strong privacy policy, or disable auto-triggers.
163
+
164
+ ## Implementation notes (pi extension API)
165
+
166
+ - **Call a model from an extension:** `complete(model, { systemPrompt, messages }, { apiKey, headers,
167
+ signal, reasoningEffort, maxTokens })` from `@earendil-works/pi-ai/compat`. Resolve auth with
168
+ `ctx.modelRegistry.find(provider, id)` `await ctx.modelRegistry.getApiKeyAndHeaders(model)`
169
+ (`{ ok, apiKey, headers }`). `getAvailable()` lists only auth-configured models; `ctx.model` is the
170
+ current one; `Model` carries `.contextWindow` / `.maxTokens`. `reasoningEffort` is a passthrough
171
+ extra, not in the typed `StreamOptions`.
172
+ - **Read the conversation:** `ctx.sessionManager.getBranch()` (active path). Entries are
173
+ `{ type:"message", message }` with `role` `user|assistant|toolResult`; assistant content blocks are
174
+ `text` / `thinking` / `toolCall`; toolResult has `toolName`, `content`, `isError`.
175
+ - **Show output to the human without injecting it:** `pi.sendMessage({ customType, content, display:true })` +
176
+ `pi.registerMessageRenderer(customType, …)`. To make the agent *act* on injected advice, use
177
+ `pi.sendUserMessage(text, { deliverAs })` (it reaches the LLM and triggers a turn).
178
+ - **Hide/show a tool:** `pi.setActiveTools(pi.getActiveTools()…)`. `promptSnippet`/`promptGuidelines`
179
+ only appear while the tool is active.
180
+ - **Argument autocomplete:** the extension keeps `getArgumentCompletions` for command metadata and
181
+ also layers a `ctx.ui.addAutocompleteProvider()` on `session_start` so `/advisor ...` and
182
+ `/advise ...` completions replace the whole argument segment and suppress irrelevant path
183
+ completion while typing command arguments (pi ≥ 0.79.1).
184
+ - Use `complete()` from `@earendil-works/pi-ai/compat` for Pi's compatibility streaming helper.
185
+
186
+ ## Issues and feedback
187
+
188
+ Found a bug or have a feature request? Please report it on
189
+ [GitHub Issues](https://github.com/hknet/pi-extensions/issues).
190
+
191
+ For security vulnerabilities, please use
192
+ [GitHub's private vulnerability reporting](https://github.com/hknet/pi-extensions/security/advisories/new)
193
+ instead of opening a public issue.