@robhowley/pi-openrouter 0.9.0 → 0.10.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 (39) hide show
  1. package/README.md +46 -5
  2. package/extensions/openrouter/__tests__/cache.test.ts +769 -0
  3. package/extensions/openrouter/__tests__/client.test.ts +333 -15
  4. package/extensions/openrouter/__tests__/commands.test.ts +816 -0
  5. package/extensions/openrouter/__tests__/fixtures.ts +140 -1
  6. package/extensions/openrouter/__tests__/format.test.ts +19 -0
  7. package/extensions/openrouter/__tests__/hooks.test.ts +529 -0
  8. package/extensions/openrouter/__tests__/index.test.ts +112 -363
  9. package/extensions/openrouter/__tests__/local-usage.test.ts +777 -0
  10. package/extensions/openrouter/__tests__/normalizers.test.ts +288 -0
  11. package/extensions/openrouter/__tests__/overlay.test.ts +225 -0
  12. package/extensions/openrouter/__tests__/session-state.test.ts +233 -0
  13. package/extensions/openrouter/__tests__/session.test.ts +44 -43
  14. package/extensions/openrouter/__tests__/status-bar.test.ts +262 -0
  15. package/extensions/openrouter/account-client.ts +11 -61
  16. package/extensions/openrouter/cache.ts +203 -91
  17. package/extensions/openrouter/client.ts +49 -3
  18. package/extensions/openrouter/commands.ts +555 -0
  19. package/extensions/openrouter/format.ts +7 -4
  20. package/extensions/openrouter/hooks.ts +288 -0
  21. package/extensions/openrouter/index.ts +13 -990
  22. package/extensions/openrouter/local-usage.ts +158 -30
  23. package/extensions/openrouter/models/__tests__/cache.test.ts +63 -2
  24. package/extensions/openrouter/models/__tests__/mapper.test.ts +29 -0
  25. package/extensions/openrouter/models/__tests__/override-commands.test.ts +668 -0
  26. package/extensions/openrouter/models/__tests__/sync.test.ts +156 -4
  27. package/extensions/openrouter/models/cache.ts +27 -2
  28. package/extensions/openrouter/models/mapper.ts +35 -69
  29. package/extensions/openrouter/models/override-commands.ts +434 -0
  30. package/extensions/openrouter/models/skip-hints.ts +19 -0
  31. package/extensions/openrouter/models/sync.ts +22 -10
  32. package/extensions/openrouter/models/types.ts +2 -1
  33. package/extensions/openrouter/normalizers.ts +128 -0
  34. package/extensions/openrouter/overlay.ts +19 -8
  35. package/extensions/openrouter/session-state.ts +110 -0
  36. package/extensions/openrouter/session.ts +16 -0
  37. package/extensions/openrouter/status-bar.ts +101 -0
  38. package/extensions/openrouter/types.ts +28 -9
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -12,13 +12,18 @@ pi install npm:@robhowley/pi-openrouter
12
12
 
13
13
  Set one of these environment variables:
14
14
 
15
- - `OPENROUTER_MANAGEMENT_KEY` (preferred), provides full usage data including model breakdowns
16
- - `OPENROUTER_API_KEY`, basic usage data plus user-scoped model sync
15
+ - `OPENROUTER_MANAGEMENT_KEY` (preferred) provides full usage/analytics and can be used for model sync
16
+ - `OPENROUTER_API_KEY` basic usage data and user-scoped model sync
17
17
 
18
18
  ```shell
19
19
  export OPENROUTER_MANAGEMENT_KEY=sk-or-...
20
20
  ```
21
21
 
22
+ **Key selection:**
23
+
24
+ - Usage/account commands prefer `OPENROUTER_MANAGEMENT_KEY` for full analytics, falling back to `OPENROUTER_API_KEY`
25
+ - Model sync prefers `OPENROUTER_API_KEY` but will attempt `OPENROUTER_MANAGEMENT_KEY` if only that is set
26
+
22
27
  ## Commands
23
28
 
24
29
  ```bash
@@ -39,10 +44,12 @@ export OPENROUTER_MANAGEMENT_KEY=sk-or-...
39
44
 
40
45
  `/openrouter models-sync`
41
46
 
42
- The sync uses OpenRouter’s authenticated user model catalog, so Pi can see the models available to your account instead of only the default provider list.
47
+ The sync uses OpenRouter’s authenticated user model catalog, so Pi can see the models available to your account instead of only the default provider list. This intentionally replaces Pi's OpenRouter provider model list with your user-scoped catalog plus OpenRouter's built-in router aliases (`openrouter/auto`, `openrouter/free`, and `openrouter/owl-alpha`). It does not merge in every built-in model unless that model is returned by your OpenRouter account catalog.
43
48
 
44
49
  `/openrouter models-status`
45
50
 
51
+ Model count and cache health live here. The Pi footer/status bar does not persistently show `OpenRouter {N} models` anymore.
52
+
46
53
  Example status output:
47
54
 
48
55
  ```text
@@ -54,7 +61,9 @@ To see why models were skipped:
54
61
 
55
62
  `/openrouter models-status --skipped`
56
63
 
57
- Skipped models do not make the sync fail; models are skipped when required metadata cannot be safely mapped into Pi’s provider model config. The last successful catalog is cached so Pi can keep using it if a later refresh fails, and the cache persists across sessions. If a session starts with a cached catalog that has not been registered yet, status will show:
64
+ Skipped output may include a grouped suggestion when Pi can offer a safe next step, such as adding a local `contextWindow` override for incomplete metadata.
65
+
66
+ Skipped models do not make the sync fail; models are skipped when required metadata cannot be safely mapped into Pi’s provider model config. The last successful catalog is cached so Pi can keep using it if a later refresh fails, and the cache persists across sessions. If a session starts with a cached catalog that has not been registered yet, `/openrouter models-status` will show:
58
67
 
59
68
  ```text
60
69
  OpenRouter models cached
@@ -102,6 +111,8 @@ Select a key from the list to inspect its limit, usage, reset cadence, and BYOK
102
111
 
103
112
  `pi-openrouter` automatically tags OpenRouter requests with a `session_id` derived from the Pi session ID.
104
113
 
114
+ Request detection is intentionally broad: the extension checks provider metadata, `openrouter/...` model ids, configured OpenRouter base URLs, Shopify's ZDR provider flag, and request URLs/endpoints so tagging still works across different Pi event shapes.
115
+
105
116
  View the OpenRouter session tag with:
106
117
 
107
118
  ```bash
@@ -111,6 +122,24 @@ View the OpenRouter session tag with:
111
122
  pi:[uuid]
112
123
  ```
113
124
 
125
+ ## Local usage tracking
126
+
127
+ The extension logs completed OpenRouter turns to local JSONL files in `~/.pi/openrouter/usage/` to provide near-real-time usage data for the footer/status bar and for "Today's spend" in the usage overlay. This supplements the OpenRouter Activity API, which typically has a delay.
128
+
129
+ When positive local spend exists in the last 30 UTC days, the footer/status bar shows local-only Today spend and a 30-day average multiplier, for example `OR $2.14 today · 1.3x 30d avg`.
130
+
131
+ Model count and cache health remain available through `/openrouter models-status`.
132
+
133
+ **Retention:** Local usage files are automatically cleaned up after 90 days.
134
+
135
+ **Debug logging:** By default, file operations are quiet (fail-open). To enable verbose logging for troubleshooting:
136
+
137
+ ```bash
138
+ export PI_OPENROUTER_DEBUG_USAGE=1
139
+ ```
140
+
141
+ This logs write/read errors, malformed lines, and cleanup operations to the console.
142
+
114
143
  ## Model field overrides
115
144
 
116
145
  Some OpenRouter models don't have complete metadata in Pi's built-in registry or the OpenRouter model catalog. You can manually configure supported `PiModelConfig` fields using scoped syntax:
@@ -133,12 +162,16 @@ Some OpenRouter models don't have complete metadata in Pi's built-in registry or
133
162
  - `maxTokens` → `maxTokens` (number)
134
163
  - `reasoning` → `reasoning` (boolean)
135
164
 
165
+ For CLI `thinking.*` / `thinkingLevelMap.*` assignments, `pi-openrouter` only accepts the conservative documented value set: `off`, `minimal`, `low`, `medium`, `high`, `max`, `xhigh`, or `null`.
166
+
136
167
  Use `null` to hide a level from Pi's UI:
137
168
 
138
169
  ```bash
139
170
  /openrouter model-override-set deepseek/deepseek-v4-pro thinking.off=null
140
171
  ```
141
172
 
173
+ If you need an advanced or experimental thinking value outside that CLI set, edit `~/.pi/openrouter/model-overrides.json` directly. The JSON file is the escape hatch; the CLI intentionally stays conservative.
174
+
142
175
  List your overrides:
143
176
 
144
177
  ```bash
@@ -153,7 +186,15 @@ Clear overrides:
153
186
  /openrouter model-override-clear deepseek/deepseek-v4-pro
154
187
  ```
155
188
 
156
- Overrides are stored in `~/.pi/openrouter/model-overrides.json` and merge on top of OpenRouter catalog data and Pi's built-in registry. Run `/openrouter models-sync` after changing overrides to apply them to the registered OpenRouter model list.
189
+ Overrides are stored in `~/.pi/openrouter/model-overrides.json`.
190
+
191
+ Precedence is:
192
+
193
+ 1. Pi's built-in registry
194
+ 2. OpenRouter's user-scoped model catalog
195
+ 3. Local overrides from `~/.pi/openrouter/model-overrides.json`
196
+
197
+ That means local overrides win. Run `/openrouter models-sync` after changing overrides to apply them to the registered OpenRouter model list.
157
198
 
158
199
  ## License
159
200