@robhowley/pi-openrouter 0.8.3 → 0.9.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.
Files changed (40) hide show
  1. package/README.md +87 -4
  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 +276 -0
  8. package/extensions/openrouter/__tests__/index.test.ts +163 -0
  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/account-client.ts +11 -61
  15. package/extensions/openrouter/cache.ts +203 -91
  16. package/extensions/openrouter/client.ts +49 -3
  17. package/extensions/openrouter/commands.ts +555 -0
  18. package/extensions/openrouter/format.ts +7 -4
  19. package/extensions/openrouter/hooks.ts +229 -0
  20. package/extensions/openrouter/index.ts +13 -589
  21. package/extensions/openrouter/local-usage.ts +145 -22
  22. package/extensions/openrouter/models/__tests__/cache.test.ts +63 -2
  23. package/extensions/openrouter/models/__tests__/mapper-overrides.test.ts +102 -0
  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__/overrides.test.ts +237 -0
  27. package/extensions/openrouter/models/__tests__/sync.test.ts +156 -4
  28. package/extensions/openrouter/models/cache.ts +27 -2
  29. package/extensions/openrouter/models/mapper.ts +60 -77
  30. package/extensions/openrouter/models/override-commands.ts +434 -0
  31. package/extensions/openrouter/models/overrides.ts +174 -0
  32. package/extensions/openrouter/models/skip-hints.ts +19 -0
  33. package/extensions/openrouter/models/sync.ts +22 -10
  34. package/extensions/openrouter/models/types.ts +31 -1
  35. package/extensions/openrouter/normalizers.ts +128 -0
  36. package/extensions/openrouter/overlay.ts +19 -8
  37. package/extensions/openrouter/session-state.ts +110 -0
  38. package/extensions/openrouter/session.ts +16 -0
  39. package/extensions/openrouter/types.ts +28 -9
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pi-openrouter
2
2
 
3
- A [Pi](https://pi.dev/) extension for live OpenRouter visibility and environment sync: usage/account TUI overlays, automatic `session_id` tagging, and user-scoped model catalog sync.
3
+ A [Pi](https://pi.dev/) extension for live OpenRouter visibility and environment sync: usage/account TUI overlays, automatic `session_id` tagging, user-scoped model catalog sync, and local model field overrides.
4
4
 
5
5
  ## Installation
6
6
 
@@ -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
@@ -28,6 +33,9 @@ export OPENROUTER_MANAGEMENT_KEY=sk-or-...
28
33
  /openrouter models-sync # sync user-scoped OpenRouter models into Pi
29
34
  /openrouter models-status # show model sync/cache status
30
35
  /openrouter models-status --skipped # show skipped model reasons
36
+ /openrouter model-override-set # set local model field overrides
37
+ /openrouter model-override-list # list local model field overrides
38
+ /openrouter model-override-clear # clear local model field overrides
31
39
  ```
32
40
 
33
41
  ## Model catalog sync
@@ -36,7 +44,7 @@ export OPENROUTER_MANAGEMENT_KEY=sk-or-...
36
44
 
37
45
  `/openrouter models-sync`
38
46
 
39
- 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.
40
48
 
41
49
  `/openrouter models-status`
42
50
 
@@ -51,6 +59,8 @@ To see why models were skipped:
51
59
 
52
60
  `/openrouter models-status --skipped`
53
61
 
62
+ 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.
63
+
54
64
  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:
55
65
 
56
66
  ```text
@@ -64,6 +74,7 @@ Run '/openrouter models-sync' to register models
64
74
  Type `/openrouter usage` in Pi to open the usage overlay.
65
75
 
66
76
  The overlay shows:
77
+
67
78
  - **Month spend** vs cap with percentage
68
79
  - **7-day spend** with burn rate projection
69
80
  - **Today's spend** from live tracked turns while Activity API data catches up
@@ -98,6 +109,8 @@ Select a key from the list to inspect its limit, usage, reset cadence, and BYOK
98
109
 
99
110
  `pi-openrouter` automatically tags OpenRouter requests with a `session_id` derived from the Pi session ID.
100
111
 
112
+ 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.
113
+
101
114
  View the OpenRouter session tag with:
102
115
 
103
116
  ```bash
@@ -107,6 +120,76 @@ View the OpenRouter session tag with:
107
120
  pi:[uuid]
108
121
  ```
109
122
 
123
+ ## Local usage tracking
124
+
125
+ The extension logs completed OpenRouter turns to local JSONL files in `~/.pi/openrouter/usage/` to provide near-real-time usage data for "Today's spend" in the usage overlay. This supplements the OpenRouter Activity API, which typically has a delay.
126
+
127
+ **Retention:** Local usage files are automatically cleaned up after 90 days.
128
+
129
+ **Debug logging:** By default, file operations are quiet (fail-open). To enable verbose logging for troubleshooting:
130
+
131
+ ```bash
132
+ export PI_OPENROUTER_DEBUG_USAGE=1
133
+ ```
134
+
135
+ This logs write/read errors, malformed lines, and cleanup operations to the console.
136
+
137
+ ## Model field overrides
138
+
139
+ 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:
140
+
141
+ ```bash
142
+ # Override thinking levels for DeepSeek V4 Pro
143
+ /openrouter model-override-set deepseek/deepseek-v4-pro thinking.high=high thinking.xhigh=max
144
+
145
+ # Same thing with exact field names
146
+ /openrouter model-override-set deepseek/deepseek-v4-pro thinkingLevelMap.high=high thinkingLevelMap.xhigh=max
147
+
148
+ # Override context window or max tokens
149
+ /openrouter model-override-set custom/model contextWindow=128000 maxTokens=8192
150
+ ```
151
+
152
+ **Scoped field names:**
153
+
154
+ - `thinking.off`, `thinking.minimal`, `thinking.low`, `thinking.medium`, `thinking.high`, `thinking.xhigh` → map to `thinkingLevelMap.*`
155
+ - `contextWindow` → `contextWindow` (number)
156
+ - `maxTokens` → `maxTokens` (number)
157
+ - `reasoning` → `reasoning` (boolean)
158
+
159
+ For CLI `thinking.*` / `thinkingLevelMap.*` assignments, `pi-openrouter` only accepts the conservative documented value set: `off`, `minimal`, `low`, `medium`, `high`, `max`, `xhigh`, or `null`.
160
+
161
+ Use `null` to hide a level from Pi's UI:
162
+
163
+ ```bash
164
+ /openrouter model-override-set deepseek/deepseek-v4-pro thinking.off=null
165
+ ```
166
+
167
+ 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.
168
+
169
+ List your overrides:
170
+
171
+ ```bash
172
+ /openrouter model-override-list # all models
173
+ /openrouter model-override-list --fields # available fields
174
+ /openrouter model-override-list deepseek/deepseek-v4-pro # specific model
175
+ ```
176
+
177
+ Clear overrides:
178
+
179
+ ```bash
180
+ /openrouter model-override-clear deepseek/deepseek-v4-pro
181
+ ```
182
+
183
+ Overrides are stored in `~/.pi/openrouter/model-overrides.json`.
184
+
185
+ Precedence is:
186
+
187
+ 1. Pi's built-in registry
188
+ 2. OpenRouter's user-scoped model catalog
189
+ 3. Local overrides from `~/.pi/openrouter/model-overrides.json`
190
+
191
+ That means local overrides win. Run `/openrouter models-sync` after changing overrides to apply them to the registered OpenRouter model list.
192
+
110
193
  ## License
111
194
 
112
195
  MIT