@madgagarin/pi-agentrouter 1.2.0 → 1.2.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 (3) hide show
  1. package/README.md +3 -0
  2. package/index.ts +40 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -120,6 +120,9 @@ AgentRouter performs client fingerprint verification. Raw summarization requests
120
120
  #### Q: Does the 2.5s pacing delay affect local or other cloud models?
121
121
  No. The pacing logic specifically filters for AgentRouter endpoints (`isAgentRouter`). Native OpenAI, Anthropic, Gemini, or local models run at full speed without delay.
122
122
 
123
+ #### Q: How to use custom subagents with AgentRouter?
124
+ AgentRouter strictly verifies client authenticity (`pi-code` / `claude-code` prompt signature). If you define custom subagents in extensions like `pi-subagents`, make sure to specify `systemPromptMode: append` in your agent definition frontmatter so the base Pi system prompt identity is preserved.
125
+
123
126
  ---
124
127
 
125
128
  ## 📄 License
package/index.ts CHANGED
@@ -90,7 +90,27 @@ export function fixPackagePriorityInSettings(): boolean {
90
90
  const initialConfig = loadConfig();
91
91
  let currentApiKey = normalizeApiKey(process.env.AGENTROUTER_API_KEY || initialConfig.apiKey || "");
92
92
  let minIntervalMs = initialConfig.minIntervalMs ?? 2500;
93
- let lastRequestEndTime = 0;
93
+ const PACING_FILE = path.join(process.env.HOME || "", ".pi/agent/.agentrouter-pacing");
94
+
95
+ export function getLastRequestEndTime(): number {
96
+ try {
97
+ if (fs.existsSync(PACING_FILE)) {
98
+ const val = parseInt(fs.readFileSync(PACING_FILE, "utf-8").trim(), 10);
99
+ if (!isNaN(val)) return val;
100
+ }
101
+ } catch {}
102
+ return 0;
103
+ }
104
+
105
+ export function setLastRequestEndTime(ts: number): void {
106
+ try {
107
+ const dir = path.dirname(PACING_FILE);
108
+ if (!fs.existsSync(dir)) {
109
+ fs.mkdirSync(dir, { recursive: true });
110
+ }
111
+ fs.writeFileSync(PACING_FILE, String(ts), "utf-8");
112
+ } catch {}
113
+ }
94
114
 
95
115
  export function isAgentRouter(providerName?: string, baseUrl?: string): boolean {
96
116
  if (providerName && providerName.toLowerCase().includes("agentrouter")) return true;
@@ -129,8 +149,18 @@ export default function (pi: ExtensionAPI) {
129
149
  baseUrl: "https://agentrouter.org",
130
150
  apiKey,
131
151
  api: "anthropic-messages",
152
+ headers: {
153
+ "User-Agent": "claude-cli/1.0.108 (external, cli)",
154
+ "anthropic-beta": "claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27",
155
+ "x-stainless-lang": "js",
156
+ "x-stainless-package-version": "0.38.0",
157
+ "x-stainless-os": "Linux",
158
+ "x-stainless-arch": "x64",
159
+ "x-stainless-runtime": "node"
160
+ },
132
161
  compat: {
133
162
  forceAdaptiveThinking: true,
163
+ sendSessionAffinityHeaders: true,
134
164
  },
135
165
  models: [
136
166
  {
@@ -143,6 +173,7 @@ export default function (pi: ExtensionAPI) {
143
173
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
144
174
  compat: {
145
175
  forceAdaptiveThinking: true,
176
+ sendSessionAffinityHeaders: true,
146
177
  },
147
178
  },
148
179
  {
@@ -155,6 +186,7 @@ export default function (pi: ExtensionAPI) {
155
186
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
156
187
  compat: {
157
188
  forceAdaptiveThinking: true,
189
+ sendSessionAffinityHeaders: true,
158
190
  },
159
191
  },
160
192
  ],
@@ -173,7 +205,7 @@ export default function (pi: ExtensionAPI) {
173
205
 
174
206
  pi.on("session_start", async (_event, ctx) => {
175
207
  updatePromptRewriteEnvForModel(ctx.model);
176
- lastRequestEndTime = Date.now();
208
+ setLastRequestEndTime(Date.now());
177
209
 
178
210
  const order = getPackageOrderState();
179
211
  if (order.needsFix && ctx.hasUI && typeof (ctx.ui as any).confirm === "function") {
@@ -209,10 +241,11 @@ export default function (pi: ExtensionAPI) {
209
241
  return;
210
242
  }
211
243
 
244
+ const lastEnd = getLastRequestEndTime();
212
245
  const now = Date.now();
213
- const elapsed = now - lastRequestEndTime;
246
+ const elapsed = now - lastEnd;
214
247
 
215
- if (lastRequestEndTime > 0 && elapsed < minIntervalMs) {
248
+ if (lastEnd > 0 && elapsed < minIntervalMs) {
216
249
  const waitMs = minIntervalMs - elapsed;
217
250
  await new Promise((resolve) => setTimeout(resolve, waitMs));
218
251
  }
@@ -221,14 +254,14 @@ export default function (pi: ExtensionAPI) {
221
254
  pi.on("turn_end", async (_event, ctx) => {
222
255
  const model = ctx.model;
223
256
  if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
224
- lastRequestEndTime = Date.now();
257
+ setLastRequestEndTime(Date.now());
225
258
  }
226
259
  });
227
260
 
228
261
  pi.on("agent_end", async (_event, ctx) => {
229
262
  const model = ctx.model;
230
263
  if (isAgentRouter(model?.provider, (model as any)?.baseUrl)) {
231
- lastRequestEndTime = Date.now();
264
+ setLastRequestEndTime(Date.now());
232
265
  }
233
266
  });
234
267
 
@@ -276,6 +309,7 @@ export default function (pi: ExtensionAPI) {
276
309
  signal,
277
310
  }
278
311
  );
312
+ setLastRequestEndTime(Date.now());
279
313
 
280
314
  const summary = response.content
281
315
  .filter((c: any): c is { type: "text"; text: string } => c.type === "text")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madgagarin/pi-agentrouter",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Pi coding agent extension for AgentRouter (GPT-5.6 Sol & Claude Opus 5) with rate-limit pacing and caching.",
5
5
  "publishConfig": {
6
6
  "access": "public"