@coool/pi-adaptive 1.0.0 → 1.0.1
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/README.md +98 -196
- package/dist/index.d.ts +2 -1
- package/dist/index.js +603 -343
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,84 +1,73 @@
|
|
|
1
1
|
# Pi Adaptive
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@coool/pi-adaptive)
|
|
4
|
+
[](https://www.npmjs.com/package/@coool/pi-adaptive)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
[test strategy](docs/TEST_STRATEGY.md) for the evidence each release requires.
|
|
11
|
-
|
|
12
|
-
## Install
|
|
13
|
-
|
|
14
|
-
After publication:
|
|
6
|
+
**Keep working when your models stop working.** Pi Adaptive is a resilience layer for
|
|
7
|
+
[Pi](https://github.com/earendil-works/pi): it spends your subscriptions before your paid
|
|
8
|
+
credits, rides out rate limits, outages, and quota walls, and finishes parked goals on its
|
|
9
|
+
own — across restarts. You configure the models; Adaptive handles everything that goes
|
|
10
|
+
wrong behind them.
|
|
15
11
|
|
|
16
12
|
```sh
|
|
17
13
|
pi install npm:@coool/pi-adaptive
|
|
18
14
|
```
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
and
|
|
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
|
-
Configure credentials and models in Pi first
|
|
74
|
-
|
|
75
|
-
memberships. Do not run multiple automatic routers in the same session.
|
|
76
|
-
|
|
77
|
-
Settings live under Pi's agent directory, normally
|
|
78
|
-
`~/.pi/agent/adaptive/settings.json`. The shared settings include `mode`
|
|
79
|
-
(`off`, `observe`, `active`), ordered `tiers`, and a concrete-model `pin`
|
|
80
|
-
(`null` means unpinned). For example, replace these placeholders with your
|
|
81
|
-
actual Pi provider/model IDs:
|
|
16
|
+
Requires Pi `>=1.5.0 <2`. Published as
|
|
17
|
+
[`@coool/pi-adaptive`](https://www.npmjs.com/package/@coool/pi-adaptive).
|
|
18
|
+
|
|
19
|
+
## Why it's different
|
|
20
|
+
|
|
21
|
+
Most routers guess. Adaptive doesn't.
|
|
22
|
+
|
|
23
|
+
- **Subscriptions first, credits last.** Order your tiers — Claude and OpenAI before
|
|
24
|
+
OpenRouter, say. When a subscription limit lifts mid-goal, Adaptive switches back
|
|
25
|
+
automatically instead of burning paid tokens.
|
|
26
|
+
- **No classifier, no keyword sniffing.** Tiers are explicit, pins always win, and moving
|
|
27
|
+
a task up a tier requires recorded evidence — never an LLM judge.
|
|
28
|
+
- **Goals survive restarts.** A known reset waits with a countdown; anything longer parks
|
|
29
|
+
durably and wakes itself later. Recovery continues from the real session state — tool
|
|
30
|
+
effects are never repeated.
|
|
31
|
+
- **Bounded by design, and it tells you.** At most five failed resume deliveries and two
|
|
32
|
+
restarts per task, then a clear note in the transcript. `/adaptive resume` retries on
|
|
33
|
+
your word. Auth and config errors never enter retry loops.
|
|
34
|
+
- **Nothing leaves your machine.** No telemetry, no daemon, no classifier requests.
|
|
35
|
+
Health, receipts, and parked-work metadata stay under Pi's agent directory.
|
|
36
|
+
|
|
37
|
+
Not sure yet? Run it in **Observe mode** (the default): it shows what it would route and
|
|
38
|
+
recover without touching your manually selected model.
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
1. Install the plugin and start Pi. The **first run proposes tiers** from your configured
|
|
43
|
+
models — confirm or edit them, nothing is saved until you do.
|
|
44
|
+
2. Pick an Adaptive entry in the model picker — `adaptive/auto` for tier routing, or pin
|
|
45
|
+
`adaptive/quick`, `adaptive/standard`, `adaptive/advanced`. You can also let the agent
|
|
46
|
+
request a tier itself with its `adaptive_tier` tool.
|
|
47
|
+
3. Work. When something fails, watch the transcript: recovery, parking, and resumes show
|
|
48
|
+
up as one-line notes. `/adaptive status` and `/adaptive why` explain any decision.
|
|
49
|
+
|
|
50
|
+
Real-terminal frames at 80 columns: [screenshots](docs/screenshots/README.md).
|
|
51
|
+
|
|
52
|
+
## Your goals, unattended
|
|
53
|
+
|
|
54
|
+
When every model in a tier is exhausted, Adaptive parks the goal — session state, partial
|
|
55
|
+
progress, and all — and resumes it when a model recovers:
|
|
56
|
+
|
|
57
|
+
- Reopening Pi re-arms the wait; already-due work asks before resuming.
|
|
58
|
+
- A wake that finds everything still down is free: it re-arms and tries again later.
|
|
59
|
+
- Recovery continues from where the work stopped, via one hidden continuation — the
|
|
60
|
+
original prompt is never replayed.
|
|
61
|
+
- A new message or a manual model pick cancels parked work. You always have the final
|
|
62
|
+
say; user aborts never trigger failover.
|
|
63
|
+
|
|
64
|
+
Headless print/JSON runs stay dialog-free and end with a clear error instead of
|
|
65
|
+
background waits — there is no daemon.
|
|
66
|
+
|
|
67
|
+
## Setup
|
|
68
|
+
|
|
69
|
+
Configure credentials and models in Pi first; Adaptive routes only what Pi already knows.
|
|
70
|
+
Settings live at `~/.pi/agent/adaptive/settings.json`:
|
|
82
71
|
|
|
83
72
|
```json
|
|
84
73
|
{
|
|
@@ -92,134 +81,47 @@ actual Pi provider/model IDs:
|
|
|
92
81
|
}
|
|
93
82
|
```
|
|
94
83
|
|
|
95
|
-
List
|
|
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
|
-
are `changes` (default: model changes or problems), `all` (every unit), and
|
|
130
|
-
`quiet` (no transcript notes). The footer and receipts remain useful with
|
|
131
|
-
`quiet`; neither depends on note verbosity.
|
|
132
|
-
Real-terminal frames at 80 columns are in [docs/screenshots](docs/screenshots/README.md):
|
|
133
|
-
[first-run proposal](docs/screenshots/first-run-proposal-80x24.txt),
|
|
134
|
-
[routed note](docs/screenshots/routed-note-80x24.txt),
|
|
135
|
-
[parked card](docs/screenshots/parked-card-80x24.txt), and
|
|
136
|
-
[doctor](docs/screenshots/doctor-80x24.txt). Dialogs are checked at 60, 80, and
|
|
137
|
-
120 columns.
|
|
138
|
-
|
|
139
|
-
The `/adaptive` command (also `Ctrl+Alt+A`) uses the same dialog flow as OpenCode:
|
|
140
|
-
|
|
141
|
-
| Command | Purpose |
|
|
142
|
-
| --------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
143
|
-
| `/adaptive` | Open the main menu. |
|
|
144
|
-
| `/adaptive status` | Show tiers, resource health, and available capacity evidence. |
|
|
145
|
-
| `/adaptive why` | Explain the latest routing receipt. |
|
|
146
|
-
| `/adaptive tiers` | Edit ordered tier membership. |
|
|
147
|
-
| `/adaptive health` | Inspect health and manually mark a resource healthy. |
|
|
148
|
-
| `/adaptive resume` | Act on parked work. |
|
|
149
|
-
| `/adaptive cancel` | Cancel parked work. |
|
|
150
|
-
| `/adaptive observe on\|off` | Enable or disable observation of manual-model sessions. |
|
|
151
|
-
| `/adaptive doctor` | Check host compatibility, credentials, capability declarations, storage, router conflicts, health, and parking. |
|
|
152
|
-
|
|
153
|
-
Typed subcommands complete in Pi's argument menu; the first Enter accepts the
|
|
154
|
-
completion and the second runs it.
|
|
155
|
-
|
|
156
|
-
## Waiting, parking, and cancellation
|
|
157
|
-
|
|
158
|
-
Parking keeps work in the required tier:
|
|
159
|
-
|
|
160
|
-
- A known reset within two minutes waits in place with a countdown; Esc cancels.
|
|
161
|
-
- Longer waits persist parked work with its session and a shared local index.
|
|
162
|
-
A cross-process claim permits at most one wake for a parked record.
|
|
163
|
-
- No provider request is dispatched while parked. An initial prompt is saved as
|
|
164
|
-
normal Pi conversation history before parking at the routing boundary, so it
|
|
165
|
-
survives closing and reopening Pi. Cancelling its parked work leaves that
|
|
166
|
-
message in history. Later intercepted prompts are kept in session-only payloads
|
|
167
|
-
until resumed. After partial execution, recovery uses one hidden continuation message telling the agent to
|
|
168
|
-
continue from existing session/workspace state, not replay the original prompt
|
|
169
|
-
or redo completed steps. That small continuation **does** enter model context;
|
|
170
|
-
operational notes and receipts do not.
|
|
171
|
-
- A new user message or manual model selection cancels parked work. User aborts
|
|
172
|
-
never trigger failover or restart. A manual choice of another tier is explicit
|
|
173
|
-
user intent, not automatic cross-tier recovery.
|
|
174
|
-
- Reopening a parked interactive session re-arms its wait; already-due work asks
|
|
175
|
-
for confirmation. An owned wake writes a resumed note unless verbosity is
|
|
176
|
-
quiet. Automatic wakes are limited to **three per task**. Terminal
|
|
177
|
-
infrastructure failures get at most **two automatic restarts per task**;
|
|
178
|
-
capability escalation is separately bounded. Permanent auth/configuration
|
|
179
|
-
errors do not enter recovery loops.
|
|
180
|
-
|
|
181
|
-
Headless print/JSON runs never show dialogs. Detached wake timers are not a
|
|
182
|
-
supported headless continuation mechanism: Pi can exit or invalidate the
|
|
183
|
-
extension context after the owned handler returns. Only an awaited, owned
|
|
184
|
-
recovery may continue that process; otherwise the run ends with a clear
|
|
185
|
-
unavailability error. There is no background daemon.
|
|
186
|
-
|
|
187
|
-
## Privacy
|
|
188
|
-
|
|
189
|
-
Adaptive sends no external telemetry and makes no classifier requests. Normal
|
|
190
|
-
model requests still go through the providers you configured in Pi. Shared
|
|
191
|
-
health, capacity, receipts, and parking metadata stay locally under Pi's agent
|
|
192
|
-
directory; credentials and raw response headers do not belong in those records.
|
|
193
|
-
Receipts are bounded and never injected into prompts. Pi retains its own session
|
|
194
|
-
content, including any input parked before dispatch; the shared parked index
|
|
195
|
-
must contain metadata only, not a second copy of your prompt.
|
|
196
|
-
|
|
197
|
-
## Small router comparison
|
|
198
|
-
|
|
199
|
-
These are **source-audit facts, not runtime benchmarks**, from the
|
|
200
|
-
[2026-11-08 audit](../../research_notes/Pi%20port%20feasibility/pi_auto_model_audit.md).
|
|
201
|
-
They apply only to the inspected versions; none of those packages was run.
|
|
202
|
-
|
|
203
|
-
| Inspected router | Selection and recovery found in source |
|
|
204
|
-
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
205
|
-
| `pi-auto-model` **0.9.2** | Keyword analysis, optional LLM classification (off by default), and utility ranking; its failover target list spans tiers. |
|
|
206
|
-
| `pi-shift-router` **1.8.0** | An LLM judge chooses fast/smart; its failover explicitly stays within the tier. |
|
|
207
|
-
| `@pedro_klein/pi-gateway` **0.6.0** | User-declared tier aliases with same-slot fallback and atomically persisted unhealthy-until times. |
|
|
208
|
-
| Pi Adaptive | Explicit capability tiers without a classifier; same-tier recovery, evidence-backed escalation, and durable parking. |
|
|
209
|
-
|
|
210
|
-
The audit found no durable park-and-auto-resume path in those three inspected
|
|
211
|
-
routers. This does not establish behavior of later versions.
|
|
212
|
-
|
|
213
|
-
## Development and release evidence
|
|
84
|
+
List several models per tier in your preference order — that order is the recovery path.
|
|
85
|
+
A tier entry may carry a Pi thinking level as `"variant": "high"`. The interactive editor
|
|
86
|
+
(`/adaptive tiers`) builds tiers from model metadata, never from prompts.
|
|
87
|
+
|
|
88
|
+
Pi's catalogue doesn't declare tool support, and Adaptive never guesses from a
|
|
89
|
+
name. Declare it from `/adaptive tools` (also in the main menu): pick a model,
|
|
90
|
+
answer whether it calls tools, and confirm — the declaration is stored in
|
|
91
|
+
`adaptive/capabilities.json` beside the settings file. An undeclared model is
|
|
92
|
+
treated as unknown and skipped on tool turns.
|
|
93
|
+
|
|
94
|
+
## Commands
|
|
95
|
+
|
|
96
|
+
| Command | Purpose |
|
|
97
|
+
| --------------------------- | ------------------------------------------------------------ |
|
|
98
|
+
| `/adaptive` | Main menu (also `Ctrl+Alt+A`). |
|
|
99
|
+
| `/adaptive status` | Tiers, resource health, capacity evidence. |
|
|
100
|
+
| `/adaptive why` | Explain the latest routing decision. |
|
|
101
|
+
| `/adaptive tiers` | Edit ordered tier membership. |
|
|
102
|
+
| `/adaptive tools` | Declare which models can call tools. |
|
|
103
|
+
| `/adaptive health` | Inspect health; manually mark a resource healthy. |
|
|
104
|
+
| `/adaptive resume` | Retry parked work now (bypasses the give-up budget). |
|
|
105
|
+
| `/adaptive cancel` | Cancel parked work. |
|
|
106
|
+
| `/adaptive observe on\|off` | Enable or disable observation of manual-model sessions. |
|
|
107
|
+
| `/adaptive doctor` | Check host, credentials, capabilities, storage, and parking. |
|
|
108
|
+
|
|
109
|
+
## For comparison
|
|
110
|
+
|
|
111
|
+
A source-level audit of alternative Pi routers (2026-11-08; no runtime benchmarks) found
|
|
112
|
+
keyword or LLM-judge selection in `pi-auto-model` and `pi-shift-router`, and no durable
|
|
113
|
+
park-and-auto-resume path in any of them. Adaptive's approach is explicit tiers,
|
|
114
|
+
evidence-backed escalation, and durable parking. Details in the
|
|
115
|
+
[audit notes](../../research_notes/Pi%20port%20feasibility/pi_auto_model_audit.md).
|
|
116
|
+
|
|
117
|
+
## Development
|
|
214
118
|
|
|
215
119
|
From the repository root:
|
|
216
120
|
|
|
217
121
|
```sh
|
|
218
122
|
npm run check -- --pkg pi
|
|
219
123
|
npm run verify -- --pkg pi
|
|
220
|
-
npm run verify -- --all
|
|
221
124
|
```
|
|
222
125
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
`npm run verify -- --all`; a scoped run alone is not release evidence.
|
|
126
|
+
The [design plan](../../docs/plans/pi-plugin.md) and
|
|
127
|
+
[test strategy](docs/TEST_STRATEGY.md) cover the architecture and the release evidence.
|
package/dist/index.d.ts
CHANGED
|
@@ -69,9 +69,10 @@ interface SharedCapacity {
|
|
|
69
69
|
readonly file: JsonFile;
|
|
70
70
|
readonly clock: () => number;
|
|
71
71
|
}
|
|
72
|
-
/** What only the packaged entry knows: the
|
|
72
|
+
/** What only the packaged entry knows: the writable files and the Pi version. */
|
|
73
73
|
interface HostSources {
|
|
74
74
|
readonly settings: JsonFile;
|
|
75
|
+
readonly capabilities: JsonFile;
|
|
75
76
|
readonly version: string;
|
|
76
77
|
readonly minimum: string;
|
|
77
78
|
readonly testedUpTo: string | undefined;
|