@madgagarin/pi-agentrouter 1.3.0 β†’ 1.4.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 (3) hide show
  1. package/README.md +22 -12
  2. package/index.ts +52 -20
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -3,8 +3,13 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@madgagarin/pi-agentrouter.svg?color=blue)](https://www.npmjs.com/package/@madgagarin/pi-agentrouter)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
5
5
  [![Pi Plugin](https://img.shields.io/badge/Pi-Extension-purple.svg)](https://pi.dev)
6
+ **`pi-agentrouter`** seamlessly connects 4 powerful flagship AI coding models (**GPT-5.6 Sol**, **Claude Opus 4.8**, **Claude Opus 5**, and **DeepSeek V4F**) to your [Pi Coding Agent](https://pi.dev) using a single, unified API key from [AgentRouter](https://agentrouter.org).
6
7
 
7
- A native, zero-config extension for the [Pi Coding Agent](https://pi.dev) that connects and optimizes [AgentRouter](https://agentrouter.org) models (GPT-5.6 Sol, Claude Opus 4.8 / 5) with built-in WAF rate-limit pacing, client fingerprint preservation, prompt caching, and seamless compaction.
8
+ ### πŸ’‘ Why use this plugin?
9
+ * πŸ”‘ **All 4 Top Models in One Place:** Instantly switch between GPT-5.6 Sol, Claude Opus 4.8, Claude Opus 5, and DeepSeek V4F without managing separate subscriptions or multiple API keys.
10
+ * πŸ’° **Save up to 80% on Tokens:** Smart prompt caching and session affinity drastically cut token usage and speed up responses.
11
+ * ⚑ **Zero-Config Setup:** Installs in seconds β€” all models are automatically registered with native reasoning, tool calling, and thinking support.
12
+ * πŸ›‘οΈ **Built-in Stability:** Automatic cross-process pacing and authentication guards eliminate 401 and 429 errors during long coding sessions and multi-agent tasks.
8
13
 
9
14
  ---
10
15
 
@@ -12,7 +17,7 @@ A native, zero-config extension for the [Pi Coding Agent](https://pi.dev) that c
12
17
 
13
18
  AgentRouter is a non-profit AI API gateway providing unified access to cutting-edge models:
14
19
 
15
- * **Increased Trial Credits:** By signing up through the referral link below, you unlock **increased trial credits (up to $175 / extra +$50 bonus)** to explore GPT-5.6 Sol and Claude Opus models.
20
+ * **Increased Trial Credits:** By signing up through the referral link below, you unlock **increased trial credits (up to $175 / extra +$50 bonus)** to explore GPT-5.6 Sol, Claude Opus, and DeepSeek models.
16
21
  * **Support the Author:** Using this link directly supports the author and the ongoing maintenance of this open-source plugin!
17
22
 
18
23
  πŸ‘‰ **[Sign up on AgentRouter (Referral Link with Bonus)](https://agentrouter.org/register?aff=34dc)** πŸ‘ˆ
@@ -23,15 +28,18 @@ AgentRouter is a non-profit AI API gateway providing unified access to cutting-e
23
28
 
24
29
  ## ✨ Features
25
30
 
26
- - πŸ”‘ **Unified API Key**: Use a single `sk-...` (or custom token) for all modelsβ€”both OpenAI GPT and Anthropic Claude endpoints are authenticated seamlessly.
31
+ - πŸ”‘ **Unified API Key**: Use a single `sk-...` (or custom token) for all modelsβ€”both OpenAI GPT, DeepSeek, and Anthropic Claude endpoints are authenticated seamlessly.
27
32
  - πŸš€ **Zero-Config Model Auto-Registration**: Automatically registers:
28
33
  - `agentrouter-openai/gpt-5.6-sol` (1M Context Window, Native Reasoning, Session Affinity).
29
- - `agentrouter-clode/claude-opus-4-8` (512K Context Window, Adaptive Thinking).
30
- - `agentrouter-clode/claude-opus-5` (1M Context Window, Adaptive Thinking).
31
- - ⚑ **Optimized Prompt Caching**: Bundles and configures session affinity headers and thinking structures, achieving **>80% cache hit rates** on consecutive turns.
32
- - πŸ›‘οΈ **WAF & Rate-Limit Pacing**: Smart 2.5s throttling applied specifically to AgentRouter calls to avoid cloud WAF / 405 rate-limit blocks.
34
+ - `agentrouter-openai/deepseek-v4f` (128K Context Window, Reasoning Support, Session Affinity).
35
+ - `agentrouter-clode/claude-opus-4-8` (512K Context Window, Adaptive Thinking, Empty Signature Compat).
36
+ - `agentrouter-clode/claude-opus-5` (1M Context Window, Adaptive Thinking, Empty Signature Compat).
37
+ - πŸ›‘οΈ **Cross-Process Request Pacing**: Shared file-based rate limiter (`~/.pi/agent/.agentrouter-pacing`) synchronizing delays across concurrent subagents, background workers, and the main Pi process to prevent WAF burst blocks.
38
+ - πŸ”’ **Transport-Level Root Prompt Guard**: Enforces canonical `pi-code` harness header at `index: 0` on every outbound request (`before_provider_request`), preventing 401 unauthorized client errors across multi-turn tool executions.
39
+ - ⚑ **Optimized Prompt Caching & Dynamic Bypass**: Automatically disables aggressive prompt rewriting on AgentRouter routes (`PI_CACHE_OPTIMIZER_NO_PROMPT_REWRITE=1`) while preserving session affinity headers, achieving **>80% cache hit rates** on consecutive turns.
40
+ - πŸ“‹ **Package Priority Guard & Auto-Fix**: Automatically checks package order in `settings.json` on startup and offers interactive one-click placement directly above `pi-cache-optimizer`.
33
41
  - πŸ“¦ **Seamless Compaction (Fixes 401)**: Solves the `401 unauthorized client` error during `/compact` by ensuring valid Pi client fingerprint headers are passed during summarization.
34
- - ⌨️ **Interactive Terminal Controls**: Change API keys, adjust throttle pacing, and cycle through models or thinking depths directly in the TUI.
42
+ - ⌨️ **Interactive Terminal Controls**: Change API keys, adjust throttle pacing, fix package priority, and cycle through models or thinking depths directly in the TUI.
35
43
 
36
44
  ---
37
45
 
@@ -83,6 +91,7 @@ To enable quick model cycling with `Ctrl+P` and set default thinking levels, add
83
91
  "defaultThinkingLevel": "medium",
84
92
  "enabledModels": [
85
93
  "agentrouter-openai/gpt-5.6-sol",
94
+ "agentrouter-openai/deepseek-v4f",
86
95
  "agentrouter-clode/claude-opus-4-8",
87
96
  "agentrouter-clode/claude-opus-5"
88
97
  ]
@@ -95,7 +104,7 @@ To enable quick model cycling with `Ctrl+P` and set default thinking levels, add
95
104
 
96
105
  | Shortcut | Action | Description |
97
106
  | :--- | :--- | :--- |
98
- | `Ctrl + P` | πŸ”„ **Next Model** | Cycles to the next model (`gpt-5.6-sol` βž” `claude-opus-4-8` βž” `claude-opus-5`). |
107
+ | `Ctrl + P` | πŸ”„ **Next Model** | Cycles to the next model (`gpt-5.6-sol` βž” `deepseek-v4f` βž” `claude-opus-4-8` βž” `claude-opus-5`). |
99
108
  | `Shift + Ctrl + P` | πŸ”„ **Previous Model** | Cycles to the previous model. |
100
109
  | `Shift + Tab` | 🧠 **Cycle Thinking Level** | Toggles reasoning depth: `off` βž” `minimal` βž” `low` βž” `medium` βž” `high`. |
101
110
  | `Ctrl + T` | πŸ‘ **Toggle Thinking Visibility** | Collapses or expands thinking/reasoning blocks on screen. |
@@ -105,9 +114,10 @@ To enable quick model cycling with `Ctrl+P` and set default thinking levels, add
105
114
 
106
115
  ## πŸ› οΈ In-Chat Commands
107
116
 
108
- * `/agentrouter` β€” View current plugin status, active model, masked key, and pacing interval.
117
+ * `/agentrouter` β€” View current plugin status, active model, priority position, masked key, and pacing interval.
109
118
  * `/agentrouter key <your-key>` β€” Update API key for all AgentRouter models on the fly.
110
- * `/agentrouter pacing <ms>` β€” Adjust the minimum delay between consecutive requests (default: `2500` ms).
119
+ * `/agentrouter pacing <ms>` β€” Adjust the minimum delay between consecutive requests (default: `3500` ms).
120
+ * `/agentrouter fix-order` β€” Automatically reorder `settings.json` packages to place this plugin directly before `pi-cache-optimizer`.
111
121
  * `/compact` β€” Compress conversation history safely without 401 authorization errors.
112
122
 
113
123
  ---
@@ -117,7 +127,7 @@ To enable quick model cycling with `Ctrl+P` and set default thinking levels, add
117
127
  #### Q: Why does `/compact` fail on raw proxy configurations?
118
128
  AgentRouter performs client fingerprint verification. Raw summarization requests without Pi's standard prompt signatures get rejected with `401 unauthorized client`. This plugin intercepts the `session_before_compact` event and automatically injects proper authentication signatures.
119
129
 
120
- #### Q: Does the 2.5s pacing delay affect local or other cloud models?
130
+ #### Q: Does the 3.5s pacing delay affect local or other cloud models?
121
131
  No. The pacing logic specifically filters for AgentRouter endpoints (`isAgentRouter`). Native OpenAI, Anthropic, Gemini, or local models run at full speed without delay.
122
132
 
123
133
  #### Q: How to use custom subagents with AgentRouter?
package/index.ts CHANGED
@@ -89,7 +89,7 @@ export function fixPackagePriorityInSettings(): boolean {
89
89
 
90
90
  const initialConfig = loadConfig();
91
91
  let currentApiKey = normalizeApiKey(process.env.AGENTROUTER_API_KEY || initialConfig.apiKey || "");
92
- let minIntervalMs = initialConfig.minIntervalMs ?? 2500;
92
+ let minIntervalMs = initialConfig.minIntervalMs ?? 3500;
93
93
  const PACING_FILE = path.join(process.env.HOME || "", ".pi/agent/.agentrouter-pacing");
94
94
 
95
95
  export function getLastRequestEndTime(): number {
@@ -188,6 +188,18 @@ export default function (pi: ExtensionAPI) {
188
188
  sendSessionAffinityHeaders: true,
189
189
  },
190
190
  },
191
+ {
192
+ id: "deepseek-v4f",
193
+ name: "deepseek-v4f",
194
+ reasoning: true,
195
+ input: ["text"],
196
+ contextWindow: 131072,
197
+ maxTokens: 65536,
198
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
199
+ compat: {
200
+ sendSessionAffinityHeaders: true,
201
+ },
202
+ },
191
203
  ],
192
204
  });
193
205
 
@@ -196,10 +208,11 @@ export default function (pi: ExtensionAPI) {
196
208
  baseUrl: "https://agentrouter.org",
197
209
  apiKey,
198
210
  api: "anthropic-messages",
199
-
200
211
  compat: {
201
212
  forceAdaptiveThinking: true,
213
+ allowEmptySignature: true,
202
214
  sendSessionAffinityHeaders: true,
215
+ supportsEagerToolInputStreaming: false,
203
216
  },
204
217
  models: [
205
218
  {
@@ -212,7 +225,9 @@ export default function (pi: ExtensionAPI) {
212
225
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
213
226
  compat: {
214
227
  forceAdaptiveThinking: true,
228
+ allowEmptySignature: true,
215
229
  sendSessionAffinityHeaders: true,
230
+ supportsEagerToolInputStreaming: false,
216
231
  },
217
232
  },
218
233
  {
@@ -225,7 +240,9 @@ export default function (pi: ExtensionAPI) {
225
240
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
226
241
  compat: {
227
242
  forceAdaptiveThinking: true,
243
+ allowEmptySignature: true,
228
244
  sendSessionAffinityHeaders: true,
245
+ supportsEagerToolInputStreaming: false,
229
246
  },
230
247
  },
231
248
  ],
@@ -242,20 +259,27 @@ export default function (pi: ExtensionAPI) {
242
259
  }
243
260
  }
244
261
 
245
- // Enforce root system prompt signature and prompt prefix stability at the lowest transport level
262
+ // Inter-request pacing to respect AgentRouter WAF rate limits and enforce canonical root prompt
246
263
  pi.on("before_provider_request", async (event, ctx) => {
247
264
  const provider = ((event as any)?.model?.provider || ctx?.model?.provider || "").toLowerCase();
248
265
  const baseUrl = ((event as any)?.model?.baseUrl || (ctx?.model as any)?.baseUrl || "");
249
266
 
250
267
  if (isAgentRouter(provider, baseUrl)) {
268
+ // 1. Cross-process request pacing
269
+ const lastEnd = getLastRequestEndTime();
270
+ const now = Date.now();
271
+ const elapsed = now - lastEnd;
272
+ if (lastEnd > 0 && elapsed < minIntervalMs) {
273
+ const waitMs = minIntervalMs - elapsed;
274
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
275
+ }
276
+
277
+ // 2. Enforce canonical root system prompt in payload (Anthropic & OpenAI formats)
251
278
  const payload = event.payload;
252
279
  if (payload) {
253
- // 1. Enforce canonical root system prompt in payload.system (Anthropic format)
254
280
  if (payload.system !== undefined) {
255
281
  payload.system = enforceCanonicalRootPrompt(payload.system);
256
282
  }
257
-
258
- // 2. Enforce canonical root system prompt in payload.messages[0] (OpenAI format)
259
283
  if (Array.isArray(payload.messages) && payload.messages.length > 0) {
260
284
  const firstMsg = payload.messages[0];
261
285
  if (firstMsg && firstMsg.role === "system") {
@@ -268,6 +292,28 @@ export default function (pi: ExtensionAPI) {
268
292
  }
269
293
  }
270
294
  }
295
+ return undefined;
296
+ });
297
+
298
+ pi.on("message_end", async (_event, ctx) => {
299
+ const model = ctx?.model;
300
+ if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
301
+ setLastRequestEndTime(Date.now());
302
+ }
303
+ });
304
+
305
+ pi.on("turn_end", async (_event, ctx) => {
306
+ const model = ctx?.model;
307
+ if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
308
+ setLastRequestEndTime(Date.now());
309
+ }
310
+ });
311
+
312
+ pi.on("agent_end", async (_event, ctx) => {
313
+ const model = ctx?.model;
314
+ if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
315
+ setLastRequestEndTime(Date.now());
316
+ }
271
317
  });
272
318
 
273
319
  pi.on("session_start", async (_event, ctx) => {
@@ -318,20 +364,6 @@ export default function (pi: ExtensionAPI) {
318
364
  }
319
365
  });
320
366
 
321
- pi.on("turn_end", async (_event, ctx) => {
322
- const model = ctx.model;
323
- if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
324
- setLastRequestEndTime(Date.now());
325
- }
326
- });
327
-
328
- pi.on("agent_end", async (_event, ctx) => {
329
- const model = ctx.model;
330
- if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
331
- setLastRequestEndTime(Date.now());
332
- }
333
- });
334
-
335
367
  pi.on("session_before_compact", async (event, ctx) => {
336
368
  const model = ctx.model;
337
369
  if (!model || !isAgentRouter(model.provider, (model as any).baseUrl)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@madgagarin/pi-agentrouter",
3
- "version": "1.3.0",
4
- "description": "Pi coding agent extension for AgentRouter (GPT-5.6 Sol & Claude Opus 5) with rate-limit pacing and caching.",
3
+ "version": "1.4.0",
4
+ "description": "Pi coding agent extension for AgentRouter (GPT-5.6 Sol, Claude Opus 5, DeepSeek V4F) with rate-limit pacing, prompt caching, and WAF protection.",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -17,6 +17,8 @@
17
17
  "gpt-5.6-sol",
18
18
  "claude-opus-5",
19
19
  "claude-opus-4-8",
20
+ "deepseek-v4f",
21
+ "deepseek",
20
22
  "prompt-caching",
21
23
  "openai",
22
24
  "claude",