@madgagarin/pi-agentrouter 1.2.1 → 1.3.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.
- package/index.ts +76 -9
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -118,6 +118,53 @@ export function isAgentRouter(providerName?: string, baseUrl?: string): boolean
|
|
|
118
118
|
return false;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
export const CANONICAL_PI_HEADER =
|
|
122
|
+
"You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.";
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Enforces that the canonical pi-code system prompt signature is strictly at index 0.
|
|
126
|
+
* If another plugin or wrapper prepended text before the canonical header, it reorders
|
|
127
|
+
* the header to the very top and shifts the injected prefix right after it.
|
|
128
|
+
* If the header is missing entirely (e.g. from replace mode), it prepends the canonical header.
|
|
129
|
+
* This guarantees both WAF client authentication and stable prompt cache prefix matching.
|
|
130
|
+
*/
|
|
131
|
+
export function enforceCanonicalRootPrompt(systemPrompt: string | any[] | undefined): string | any[] {
|
|
132
|
+
if (!systemPrompt) {
|
|
133
|
+
return CANONICAL_PI_HEADER;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (typeof systemPrompt === "string") {
|
|
137
|
+
const text = systemPrompt.trim();
|
|
138
|
+
const piHeaderRegex = /(?:You are [^\n\r]*operating inside pi[^\n\r]*\n?|You are (?:pi|Pi)[^\n\r]*\n?)/i;
|
|
139
|
+
|
|
140
|
+
if (piHeaderRegex.test(text)) {
|
|
141
|
+
const match = text.match(piHeaderRegex);
|
|
142
|
+
if (match && match.index !== undefined && match.index > 0) {
|
|
143
|
+
const header = match[0].trim();
|
|
144
|
+
const prefix = text.slice(0, match.index).trim();
|
|
145
|
+
const rest = text.slice(match.index + match[0].length).trim();
|
|
146
|
+
return `${header}\n\n${prefix}${rest ? "\n\n" + rest : ""}`;
|
|
147
|
+
}
|
|
148
|
+
return text;
|
|
149
|
+
} else {
|
|
150
|
+
return `${CANONICAL_PI_HEADER}\n\n${text}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (Array.isArray(systemPrompt)) {
|
|
155
|
+
if (systemPrompt.length === 0) {
|
|
156
|
+
return [{ type: "text", text: CANONICAL_PI_HEADER }];
|
|
157
|
+
}
|
|
158
|
+
const firstBlock = systemPrompt[0];
|
|
159
|
+
if (firstBlock && typeof firstBlock.text === "string") {
|
|
160
|
+
firstBlock.text = enforceCanonicalRootPrompt(firstBlock.text) as string;
|
|
161
|
+
}
|
|
162
|
+
return systemPrompt;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return systemPrompt;
|
|
166
|
+
}
|
|
167
|
+
|
|
121
168
|
export default function (pi: ExtensionAPI) {
|
|
122
169
|
function registerAgentRouterProviders(apiKey: string): void {
|
|
123
170
|
pi.registerProvider("agentrouter-openai", {
|
|
@@ -149,15 +196,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
149
196
|
baseUrl: "https://agentrouter.org",
|
|
150
197
|
apiKey,
|
|
151
198
|
api: "anthropic-messages",
|
|
152
|
-
|
|
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
|
-
},
|
|
199
|
+
|
|
161
200
|
compat: {
|
|
162
201
|
forceAdaptiveThinking: true,
|
|
163
202
|
sendSessionAffinityHeaders: true,
|
|
@@ -203,6 +242,34 @@ export default function (pi: ExtensionAPI) {
|
|
|
203
242
|
}
|
|
204
243
|
}
|
|
205
244
|
|
|
245
|
+
// Enforce root system prompt signature and prompt prefix stability at the lowest transport level
|
|
246
|
+
pi.on("before_provider_request", async (event, ctx) => {
|
|
247
|
+
const provider = ((event as any)?.model?.provider || ctx?.model?.provider || "").toLowerCase();
|
|
248
|
+
const baseUrl = ((event as any)?.model?.baseUrl || (ctx?.model as any)?.baseUrl || "");
|
|
249
|
+
|
|
250
|
+
if (isAgentRouter(provider, baseUrl)) {
|
|
251
|
+
const payload = event.payload;
|
|
252
|
+
if (payload) {
|
|
253
|
+
// 1. Enforce canonical root system prompt in payload.system (Anthropic format)
|
|
254
|
+
if (payload.system !== undefined) {
|
|
255
|
+
payload.system = enforceCanonicalRootPrompt(payload.system);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// 2. Enforce canonical root system prompt in payload.messages[0] (OpenAI format)
|
|
259
|
+
if (Array.isArray(payload.messages) && payload.messages.length > 0) {
|
|
260
|
+
const firstMsg = payload.messages[0];
|
|
261
|
+
if (firstMsg && firstMsg.role === "system") {
|
|
262
|
+
if (typeof firstMsg.content === "string") {
|
|
263
|
+
firstMsg.content = enforceCanonicalRootPrompt(firstMsg.content);
|
|
264
|
+
} else if (Array.isArray(firstMsg.content)) {
|
|
265
|
+
firstMsg.content = enforceCanonicalRootPrompt(firstMsg.content);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
206
273
|
pi.on("session_start", async (_event, ctx) => {
|
|
207
274
|
updatePromptRewriteEnvForModel(ctx.model);
|
|
208
275
|
setLastRequestEndTime(Date.now());
|
package/package.json
CHANGED