pi-cliproxyapi-native 0.3.5 → 0.3.6
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 +12 -0
- package/README.md +17 -8
- package/package.json +5 -4
- package/src/catalog.ts +6 -0
- package/src/claude-quota.ts +2 -1
- package/src/picker.ts +1 -0
- package/src/provider.ts +5 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
For releases before 0.3.6, see the [GitHub releases](https://github.com/hawkff/pi-cliproxyapi-native/releases).
|
|
4
|
+
|
|
5
|
+
## [0.3.6] - 2026-11-10
|
|
6
|
+
|
|
7
|
+
- Pi's background prompt-cache refreshes skip the quota wait. Before, a refresh that hit a quota limit showed a quota countdown while Pi sat idle, then sent the whole request again after the reset.
|
|
8
|
+
- Claude on unprefixed, `oauth/`, `vertex/`, and `antigravity/` routes reports a one-hour cache lifetime, so Pi stops refreshing those caches every five minutes. CLIProxyAPI keeps OAuth Claude caches for an hour. `api/` routes keep Pi's five-minute refreshes.
|
|
9
|
+
- Claude message threads stay off. A proxy route that drops the `thread` field would send only the newest messages.
|
|
10
|
+
- Live Claude quota lookups send the Claude Code version that CLIProxyAPI 8.0.63 uses.
|
|
11
|
+
- The `/cli:model` picker reports Pi as waiting for input in terminals that show program status.
|
|
12
|
+
- The extension targets Pi 1.5.1 and CLIProxyAPI 8.0.63.
|
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ Chat uses Pi's native API adapters and model metadata, with availability from yo
|
|
|
21
21
|
- [Refresh](#refresh)
|
|
22
22
|
- [Wait for quota reset](#wait-for-quota-reset)
|
|
23
23
|
- [Retry failed turns](#retry-failed-turns)
|
|
24
|
+
- [Prompt cache refreshes](#prompt-cache-refreshes)
|
|
24
25
|
- [Compaction](#compaction)
|
|
25
26
|
- [Aliases and model limits](#aliases-and-model-limits)
|
|
26
27
|
- [Backend routes](#backend-routes)
|
|
@@ -31,15 +32,15 @@ Chat uses Pi's native API adapters and model metadata, with availability from yo
|
|
|
31
32
|
|
|
32
33
|
## Install
|
|
33
34
|
|
|
34
|
-
The extension targets Pi 1.5.
|
|
35
|
+
The extension targets Pi 1.5.1 and CLIProxyAPI 8.0.63, with Node.js 22.19 or newer. Run CLIProxyAPI with your upstream accounts configured before connecting Pi. The extension uses Pi's host-provided packages, adds no runtime dependencies, and needs no compilation.
|
|
35
36
|
|
|
36
37
|
If you installed `pi-cliproxy-native`, remove it before installing the renamed package. Both register the same `cliproxyapi` provider.
|
|
37
38
|
|
|
38
39
|
```sh
|
|
39
|
-
pi install npm:pi-cliproxyapi-native@0.3.
|
|
40
|
+
pi install npm:pi-cliproxyapi-native@0.3.6
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
For Git installation, use `pi install git:github.com/hawkff/pi-cliproxyapi-native@v0.3.
|
|
43
|
+
For Git installation, use `pi install git:github.com/hawkff/pi-cliproxyapi-native@v0.3.6`. For a local checkout, use `pi install /path/to/pi-cliproxyapi-native`. After an update, Pi shows the new [changelog](CHANGELOG.md) entries under "Extension Updates" on its next launch.
|
|
43
44
|
|
|
44
45
|
The default proxy address is `http://localhost:8317`. For another address, set the [connection](#connection) before logging in. Restart Pi, then run:
|
|
45
46
|
|
|
@@ -93,7 +94,7 @@ Open `/cli:model` to search the live image/video catalog, or use its subcommands
|
|
|
93
94
|
|
|
94
95
|
Search by friendly name, exact ID, backend, owner, or image/video purpose. The picker shows known media models, including disabled entries with a reason. It omits chat models and unknown IDs.
|
|
95
96
|
|
|
96
|
-
The terminal picker is keyboard-only. Type to search, use the selection keys to move, press Enter to select, or Escape to cancel. It respects custom selection keybindings. Mouse clicks and wheel events do not change selection.
|
|
97
|
+
The terminal picker is keyboard-only. Type to search, use the selection keys to move, press Enter to select, or Escape to cancel. It respects custom selection keybindings. Mouse clicks and wheel events do not change selection. Terminals that show program status mark Pi as waiting for input while the picker is open.
|
|
97
98
|
|
|
98
99
|
Starting session or branch navigation discards pending picker commands, even if another extension later cancels navigation. Run the selection again if you stay on the same branch.
|
|
99
100
|
|
|
@@ -291,6 +292,14 @@ Escape or Ctrl+C cancels a pending retry in the terminal. New input, a model cha
|
|
|
291
292
|
|
|
292
293
|
Retries preserve the conversation rather than replaying the original prompt. They do not fix credentials or increase quotas, and resumed work can incur provider charges. Use `/auto-retry off` if a persistent error needs manual correction.
|
|
293
294
|
|
|
295
|
+
### Prompt cache refreshes
|
|
296
|
+
|
|
297
|
+
Pi refreshes a Claude prompt cache in the background so it doesn't expire between requests. Pi 1.5.1 does this by default, during runs and for up to 30 minutes after them. Set Pi's `cacheWarming` setting to `"streaming"` to limit refreshes to active runs, or to `"off"` to stop them.
|
|
298
|
+
|
|
299
|
+
CLIProxyAPI keeps OAuth Claude caches for an hour. The extension reports a one-hour cache lifetime for Claude on unprefixed, `oauth/`, `vertex/`, and `antigravity/` routes, so Pi doesn't refresh those caches. `api/` routes keep Anthropic's five-minute lifetime. Pi refreshes them when it estimates that a refresh saves at least $0.05. If your unprefixed Claude IDs reach API keys, select their `api/` IDs, or set `promptCache` for those IDs through `modelOverrides` in Pi's `models.json`.
|
|
300
|
+
|
|
301
|
+
A refresh that hits a quota limit fails without waiting for the reset. Chat and compaction requests keep the quota waits described above.
|
|
302
|
+
|
|
294
303
|
### Compaction
|
|
295
304
|
|
|
296
305
|
For automatic compaction and `/compact`, the extension limits medium or higher thinking to low without changing your chat thinking level. It uses Pi's default thinking budgets for these requests. Without an explicit output cap, summaries use the model's output limit. Pi's native adapters reduce the output allowance when needed to fit the remaining context space.
|
|
@@ -303,7 +312,7 @@ Authentication failures, exhausted quotas, and inputs that exceed the model's co
|
|
|
303
312
|
|
|
304
313
|
### Aliases and model limits
|
|
305
314
|
|
|
306
|
-
The chat catalog skips unknown IDs rather than guessing their capabilities. Recognized catalog owners resolve duplicate metadata IDs; ambiguous cross-family matches stay out.
|
|
315
|
+
The chat catalog skips unknown IDs rather than guessing their capabilities. Recognized catalog owners resolve duplicate metadata IDs; ambiguous cross-family matches stay out. For example, CLIProxyAPI 8.0.63 lists `gpt-6-chat-thinking` and `gemini-omni-1.2-flash`, which have no metadata in Pi 1.5.1, so `/cliproxyapi-refresh` reports them as not registered until you add an alias. Pi 1.5.1 includes `claude-fable-5-2`, which registers without one.
|
|
307
316
|
|
|
308
317
|
To describe a proxy alias, add a canonical metadata reference to `~/.pi/agent/pi-cliproxyapi.json`:
|
|
309
318
|
|
|
@@ -385,7 +394,7 @@ Run `/reload` after changing settings and `/cliproxyapi-refresh` before starting
|
|
|
385
394
|
|
|
386
395
|
## Protocol notes
|
|
387
396
|
|
|
388
|
-
Claude uses the legacy fine-grained tool-streaming header in place of eager tool fields.
|
|
397
|
+
Claude uses the legacy fine-grained tool-streaming header in place of eager tool fields. Claude message threads stay off, because a proxy route that drops the `thread` field would send only the newest messages.
|
|
389
398
|
|
|
390
399
|
GPT models keep Pi's OpenAI Responses capabilities when the proxy lists them as owned by OpenAI. These capabilities are strict tools, grammar tools such as codemode, tool declarations added mid-conversation, tool search, and instructions placed mid-conversation. Each passed live checks through CLIProxyAPI 8.0.48 with an OpenAI API key and with a ChatGPT subscription. OpenAI-compatible providers and other model families keep these capabilities off.
|
|
391
400
|
|
|
@@ -393,11 +402,11 @@ On `api/` routes, Pi can send thinking effort as a `configuration_update` item.
|
|
|
393
402
|
|
|
394
403
|
When Pi omits strictness in the top-level Responses tool list, the extension sends `strict: null`, so optional arguments remain optional. Tools declared inside the conversation keep Pi's strictness values. Explicit payload hooks retain final control.
|
|
395
404
|
|
|
396
|
-
OpenAI images POST `model`, `prompt`, `n`, and supplied controls to `/v1/images/generations`, without `response_format`. Editing uses `/v1/images/edits` with JSON `images` and optional `mask` or `markup` data URLs. A nonzero `partial_images` adds `stream: true`, and the extension reads server-sent events. Each `*.partial_image` frame becomes a progress preview, and the `*.completed` frame carries the final image and usage. xAI uses the same route with `response_format: "b64_json"`. Gemini uses `/v1beta/models/{id}:generateContent`. Media generation sends the prompt and generation options without chat history, system instructions, or tools.
|
|
405
|
+
OpenAI images POST `model`, `prompt`, `n`, and supplied controls to `/v1/images/generations`, without `response_format`. Editing uses `/v1/images/edits` with JSON `images` and optional `mask` or `markup` data URLs. A nonzero `partial_images` adds `stream: true`, and the extension reads server-sent events. With `streaming.keepalive-seconds` set, streamed previews need CLIProxyAPI 8.0.60 or newer, because older versions could insert keep-alive comments inside an image event. Each `*.partial_image` frame becomes a progress preview, and the `*.completed` frame carries the final image and usage. xAI uses the same route with `response_format: "b64_json"`. Gemini uses `/v1beta/models/{id}:generateContent`. Media generation sends the prompt and generation options without chat history, system instructions, or tools.
|
|
397
406
|
|
|
398
407
|
OpenAI image POSTs use a dedicated HTTP connection. It follows `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` from the environment, where Pi also places its `httpProxy` setting, on Node 22.21+ and 24.5+. Older Node versions connect directly. The connection disables socket timeouts so the ten-minute deadline controls the request, requests identity encoding, and rejects compressed responses.
|
|
399
408
|
|
|
400
|
-
The OpenAI image implementation follows CLIProxyAPI v8.0.
|
|
409
|
+
The OpenAI image implementation follows CLIProxyAPI v8.0.63's [image handler](https://github.com/router-for-me/CLIProxyAPI/blob/v8.0.63/sdk/api/handlers/openai/openai_images_handlers.go) and [Codex image executor](https://github.com/router-for-me/CLIProxyAPI/blob/v8.0.63/internal/runtime/executor/codex_openai_images.go), plus the OpenAI [generation](https://developers.openai.com/api/reference/resources/images/methods/generate) and [editing](https://developers.openai.com/api/reference/resources/images/methods/edit) references. The xAI and Google routes follow v7.2.158's [video handler](https://github.com/router-for-me/CLIProxyAPI/blob/v7.2.158/sdk/api/handlers/openai/openai_videos_handlers.go), [Gemini handler](https://github.com/router-for-me/CLIProxyAPI/blob/v7.2.158/sdk/api/handlers/gemini/gemini_handlers.go), and [Vertex executor](https://github.com/router-for-me/CLIProxyAPI/blob/v7.2.158/internal/runtime/executor/gemini_vertex_executor.go). See [xAI's video documentation](https://docs.x.ai/developers/model-capabilities/video/generation) for duration and status semantics.
|
|
401
410
|
|
|
402
411
|
## License
|
|
403
412
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cliproxyapi-native",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "CLIProxyAPI chat discovery, image generation and editing, and video generation with Pi's native adapters",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"extensions",
|
|
24
24
|
"src",
|
|
25
25
|
"README.md",
|
|
26
|
+
"CHANGELOG.md",
|
|
26
27
|
"LICENSE"
|
|
27
28
|
],
|
|
28
29
|
"pi": {
|
|
@@ -39,9 +40,9 @@
|
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@biomejs/biome": "^2.6.5",
|
|
42
|
-
"@earendil-works/pi-ai": "^1.5.
|
|
43
|
-
"@earendil-works/pi-coding-agent": "^1.5.
|
|
44
|
-
"@earendil-works/pi-tui": "^1.5.
|
|
43
|
+
"@earendil-works/pi-ai": "^1.5.1",
|
|
44
|
+
"@earendil-works/pi-coding-agent": "^1.5.1",
|
|
45
|
+
"@earendil-works/pi-tui": "^1.5.1",
|
|
45
46
|
"@types/node": "^24.19.2",
|
|
46
47
|
"typebox": "1.3.27",
|
|
47
48
|
"typescript": "7.0.2"
|
package/src/catalog.ts
CHANGED
|
@@ -365,6 +365,10 @@ export function mapCatalog(value: unknown, config: Config, known: readonly Model
|
|
|
365
365
|
api,
|
|
366
366
|
baseUrl: endpoint(config.baseUrl, api),
|
|
367
367
|
headers: undefined,
|
|
368
|
+
// CLIProxyAPI gives OAuth Claude caches a one-hour TTL. Only api/ routes keep Pi's five-minute refreshes.
|
|
369
|
+
...(api === "anthropic-messages" && prefix !== "api"
|
|
370
|
+
? { promptCache: { short: 3600, long: 3600 } }
|
|
371
|
+
: {}),
|
|
368
372
|
compat:
|
|
369
373
|
api === "anthropic-messages"
|
|
370
374
|
? {
|
|
@@ -374,6 +378,8 @@ export function mapCatalog(value: unknown, config: Config, known: readonly Model
|
|
|
374
378
|
supportsMidConvoSystemMessages: false,
|
|
375
379
|
supportsMidConvoToolChanges: false,
|
|
376
380
|
supportsMidConvoEffort: false,
|
|
381
|
+
// A route that drops the thread field would send only the newest messages.
|
|
382
|
+
supportsMessageThreads: false,
|
|
377
383
|
allowedFallbackModels: undefined,
|
|
378
384
|
}
|
|
379
385
|
: api === "google-generative-ai"
|
package/src/claude-quota.ts
CHANGED
|
@@ -182,7 +182,8 @@ export async function fetchClaudeQuota(
|
|
|
182
182
|
Authorization: "Bearer $TOKEN$",
|
|
183
183
|
"Content-Type": "application/json",
|
|
184
184
|
"anthropic-beta": "oauth-2025-04-20",
|
|
185
|
-
|
|
185
|
+
// CLIProxyAPI 8.0.63 presents this Claude Code version for OAuth accounts.
|
|
186
|
+
"User-Agent": "claude-cli/2.1.321 (external, cli)",
|
|
186
187
|
},
|
|
187
188
|
});
|
|
188
189
|
if (!isRecord(response) || typeof response.status_code !== "number")
|
package/src/picker.ts
CHANGED
|
@@ -295,6 +295,7 @@ export function registerModelPicker(pi: ExtensionAPI, config: Config) {
|
|
|
295
295
|
() => tui.requestRender(),
|
|
296
296
|
done,
|
|
297
297
|
),
|
|
298
|
+
{ blocked: { kind: "question", message: "Choose a CLIProxyAPI image or video model" } },
|
|
298
299
|
);
|
|
299
300
|
} else {
|
|
300
301
|
const matches = searchPickerItems(items, query);
|
package/src/provider.ts
CHANGED
|
@@ -161,6 +161,9 @@ function route(
|
|
|
161
161
|
options?.env?.CLIPROXYAPI_MANAGEMENT_KEY ?? process.env.CLIPROXYAPI_MANAGEMENT_KEY ?? "";
|
|
162
162
|
const liveClaude =
|
|
163
163
|
model.api === "anthropic-messages" && !backend && authType !== "api-key" && managementKey !== "";
|
|
164
|
+
// Pi's cache warmer replays a request with these options. A delayed replay cannot keep a cache warm.
|
|
165
|
+
const warming =
|
|
166
|
+
options?.disableContinuation === true && options.maxTokens === 1 && options.maxRetries === 0;
|
|
164
167
|
const adapterModel = google ? { ...model, id: metadataId } : model;
|
|
165
168
|
// Google needs canonical IDs for tool turns. Swap identities to keep bare history cross-route.
|
|
166
169
|
const adapterContext = google
|
|
@@ -231,7 +234,7 @@ function route(
|
|
|
231
234
|
let started = false;
|
|
232
235
|
let retry = false;
|
|
233
236
|
for await (const event of run()) {
|
|
234
|
-
if (event.type === "error" && event.reason === "error" && !started) {
|
|
237
|
+
if (event.type === "error" && event.reason === "error" && !started && !warming) {
|
|
235
238
|
const resetAt = quotaRetryAt(event.error.errorMessage, response);
|
|
236
239
|
const failure = quotaError(event.error.errorMessage);
|
|
237
240
|
const upstream =
|
|
@@ -320,7 +323,7 @@ export function createCliproxyProvider(
|
|
|
320
323
|
let skipped: string[] = [];
|
|
321
324
|
const standardAuth = envApiKeyAuth("CLIProxyAPI API key", ["CLIPROXYAPI_API_KEY"]);
|
|
322
325
|
const scope = createHash("sha256")
|
|
323
|
-
.update(JSON.stringify([
|
|
326
|
+
.update(JSON.stringify([6, { baseUrl: config.baseUrl, aliases: config.aliases }]))
|
|
324
327
|
.digest("hex");
|
|
325
328
|
const provider = createProvider<CpaApi>({
|
|
326
329
|
id: PROVIDER_ID,
|