@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.
- package/CHANGELOG.md +94 -73
- package/LICENSE +287 -287
- package/README.md +193 -182
- package/advisor.ts +1110 -1082
- package/package.json +53 -39
package/README.md
CHANGED
|
@@ -1,182 +1,193 @@
|
|
|
1
|
-
# pi-advisor
|
|
2
|
-
|
|
3
|
-
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
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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.
|