@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 CHANGED
@@ -1,84 +1,73 @@
1
1
  # Pi Adaptive
2
2
 
3
- Not yet published. Release is gated on maintainer approval.
3
+ [![npm version](https://img.shields.io/npm/v/@coool/pi-adaptive)](https://www.npmjs.com/package/@coool/pi-adaptive)
4
+ [![npm downloads](https://img.shields.io/npm/dt/@coool/pi-adaptive)](https://www.npmjs.com/package/@coool/pi-adaptive)
4
5
 
5
- Capability-tier routing and bounded recovery for Pi. You choose the available
6
- models and their tier order; Adaptive keeps provider failures separate from
7
- capability gaps. Pi still owns the agent, tools, sessions, and model calls.
8
-
9
- See the [Pi plan](../../docs/plans/pi-plugin.md) for the design and the
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
- The package declares Pi `>=1.5.0 <2`. The declared range is not itself a
21
- compatibility test: the packed minimum (1.5.0) and latest Pi hosts run the
22
- SDK, JSON, and real-terminal matrix before release, and `/adaptive doctor`
23
- reports the last host version that matrix recorded. For local development, run
24
- `pi install ./packages/pi` from the repository root after building.
25
-
26
- ## How it decides
27
-
28
- - **Use an explicit tier, not a classifier.** A user pin wins, then the agent's
29
- `adaptive_tier` request under Auto; otherwise the tier is `standard`. No prompt
30
- keywords or extra LLM call decide the tier.
31
- - **Check fit before preference.** Only your configured, authenticated models
32
- are candidates. Context size, input modalities, declared tool support, health,
33
- and available capacity evidence constrain selection before tier order.
34
- - **Keep productive work on its model.** Ordinary tool continuations stay on the
35
- selected resource. A recovered preferred model becomes eligible at a later
36
- safe boundary, not just to make an ongoing run cheaper.
37
- - **Recover horizontally.** Rate limits, quota exhaustion, timeouts, and outages
38
- use another eligible resource in the same tier, or wait/park. Availability
39
- never silently borrows a weaker or stronger tier; 429s do not trip the breaker.
40
- - **Escalate only on capability evidence.** `adaptive_escalate` requires a reason
41
- and concrete evidence. Recording it switches nothing; a terminal capability
42
- failure can continue the same task exactly one tier higher, within its budget.
43
-
44
- ## Models and modes
45
-
46
- | Picker entry | Meaning |
47
- | ------------------- | ------------------------------------------------------------------------ |
48
- | `adaptive/auto` | Use the requested tier, or `standard`; allow evidence-backed escalation. |
49
- | `adaptive/quick` | Pin the quick tier; recover within it. |
50
- | `adaptive/standard` | Pin the standard tier; recover within it. |
51
- | `adaptive/advanced` | Pin the advanced tier; recover within it. |
52
-
53
- **Observe is the default.** It explains what the same scheduler would choose
54
- without changing a manually selected model. Choosing an Adaptive entry
55
- activates routing for that session; choosing any normal model hands control back
56
- immediately. With observation disabled and a normal model selected, Adaptive is
57
- off. Off mode does not route or recover work.
58
-
59
- Pinned tier entries ignore the agent's tier request and do not automatically
60
- escalate by default. The Preferences dialog can explicitly enable
61
- `escalateFromPinned`; evidence and task budgets still apply. A concrete model
62
- pin always wins over automatic routing and recovery. Use Auto for the default
63
- evidence-backed movement between tiers.
64
-
65
- The agent tool `adaptive_tier` takes `quick`, `standard`, or `advanced`. Its
66
- declaration applies from the next user prompt and stays on the session branch
67
- until replaced. A new user prompt starts a new task at that base tier; it does
68
- not inherit the last task's escalation. Forking or rewinding follows Pi's branch
69
- state. `adaptive_escalate` is evidence reporting, not a planning tool.
70
-
71
- ## Providers, capabilities, and settings
72
-
73
- Configure credentials and models in Pi first. Adaptive uses Pi's available-model
74
- registry; it does not add providers, fetch a marketplace, or invent tier
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 multiple models in a tier in your preferred order for same-tier recovery.
96
- Empty tiers do not authorize cross-tier fallback. The interactive tier editor
97
- and the first-run proposal build tiers from available-model metadata, never
98
- from prompt classification, and nothing is saved until you confirm.
99
-
100
- A tier entry can include a Pi-supported thinking level as `variant`, such as
101
- `"variant": "high"`. Admission checks that exact variant, and dispatch uses it;
102
- unsupported variants are not silently replaced with a different thinking level.
103
-
104
- Pi's catalogue does not declare model-level tool capability. Explicit
105
- declarations live in `adaptive/capabilities.json` beside the settings file:
106
-
107
- ```json
108
- {
109
- "models": [{ "providerID": "your-provider", "id": "your-model", "tools": true }]
110
- }
111
- ```
112
-
113
- Declare support only after verifying that model's tool calls. Missing declarations
114
- remain unknown; `tools: false` explicitly excludes a model from tool-enabled
115
- requests. Declarations do not add providers, tier memberships, or credentials.
116
- Malformed capability files produce field-specific errors rather than guessed
117
- declarations. Capacity is evidence-driven: unknown capacity is not a promise of
118
- remaining quota, and not every provider exposes usable capacity readings.
119
-
120
- ## Status, notes, and commands
121
-
122
- Adaptive uses one footer item for the current tier and model, recovery,
123
- task escalation, observation of a manual model, tier setup, or degraded
124
- operation. Waiting countdowns and parked-work status take priority in that same
125
- item; parked work also has a card. A manual model pick or session change clears
126
- stale status, and disabling observation clears its manual-model footer.
127
-
128
- One-line transcript notes stay out of model context. The note verbosity choices
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
- See the [test strategy](docs/TEST_STRATEGY.md) for the unit, real-SDK,
224
- packed-host, and PTY evidence. Publication requires a full, unskipped
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 settings file and the Pi version. */
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;