oira666_pi-limits-wait 0.6.4 → 0.6.5
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/README.md +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/index.ts +3 -3
- package/src/prompt.ts +48 -2
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Restart Pi or run `/reload` after installing.
|
|
|
30
30
|
- During a wait, pressing Enter in an empty editor retries immediately. Typed commands, autocomplete, and model-picker navigation still work normally. Choosing another model with `/model` immediately ends the pending wait and tries that exact model, even if it was previously marked unavailable.
|
|
31
31
|
- Keeps a manually chosen model ahead of the configured priority list until it fails. After failure, normal retry/fallback rules apply and subsequent calls use the configured order again.
|
|
32
32
|
- Optionally falls back to configured models when the current/default model is rate-limited. Every fallback to a different model—even on the same provider—deliberately discards request-owned credentials, headers, environment overrides, and provider-specific options so the target runtime resolves its own configuration.
|
|
33
|
-
- Preserves Pi's `before_provider_request` / `after_provider_response` callback flow
|
|
33
|
+
- Preserves Pi's `before_provider_request` / `after_provider_response` callback flow. When Pi's exact Anthropic OAuth identity block is present, sanitises both the initial prompt and later system-message updates, repeating the Claude Code identity in textual updates. User/assistant messages and tool blocks stay untouched. Pi remains responsible for initial OAuth identity insertion and authentication; this does not repair invalid credentials.
|
|
34
34
|
|
|
35
35
|
### Unsupported interception limitation
|
|
36
36
|
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -43,7 +43,7 @@ export const DEFAULT_LIVELINESS_INTERVAL_MS = 15 * 1_000; // 15 seconds
|
|
|
43
43
|
export const LIVELINESS_JSON_STATUS_KEY = "oira666.pi-limits-wait.json";
|
|
44
44
|
/** Payload schema version for LIVELINESS_JSON_STATUS_KEY. Bump only on a breaking change. */
|
|
45
45
|
export const LIVELINESS_JSON_VERSION = 1;
|
|
46
|
-
export const EXTENSION_VERSION = "0.6.
|
|
46
|
+
export const EXTENSION_VERSION = "0.6.5";
|
|
47
47
|
|
|
48
48
|
export const SETTINGS_FILE_NAME = "limits-wait.json";
|
|
49
49
|
export const FALLBACK_MODELS_KEY = "fallback-models";
|
package/src/index.ts
CHANGED
|
@@ -100,9 +100,9 @@ export type { FallbackModel } from "./types.js";
|
|
|
100
100
|
|
|
101
101
|
export default function (pi: ExtensionAPI) {
|
|
102
102
|
// Current pi-ai inserts the Claude Code identity as the first system block
|
|
103
|
-
// for Anthropic OAuth.
|
|
104
|
-
//
|
|
105
|
-
// remain owned
|
|
103
|
+
// for Anthropic OAuth. Use that exact shape to guard sanitisation of the
|
|
104
|
+
// initial prompt and later system updates, which repeat the identity.
|
|
105
|
+
// Authentication, initial identity insertion, and headers remain runtime-owned.
|
|
106
106
|
pi.on("before_provider_request", (event) => sanitiseAnthropicPayloadSystem(event.payload));
|
|
107
107
|
|
|
108
108
|
// Keep prompt sanitisation and the runtime's normal Anthropic header path,
|
package/src/prompt.ts
CHANGED
|
@@ -34,7 +34,8 @@ function isPiClaudeCodeIdentityBlock(block: unknown): block is SystemTextBlock {
|
|
|
34
34
|
* current pi-ai runtime: the Claude Code identity is the first system block.
|
|
35
35
|
* Looking only at that exact first block avoids treating a later user-authored
|
|
36
36
|
* identity mention as proof of OAuth. The runtime remains solely responsible
|
|
37
|
-
* for inserting the identity and selecting OAuth headers.
|
|
37
|
+
* for inserting the initial identity and selecting OAuth headers. Later system
|
|
38
|
+
* updates are sanitised too and repeat the identity alongside their instructions.
|
|
38
39
|
*/
|
|
39
40
|
export function sanitiseAnthropicPayloadSystem(payload: unknown): unknown {
|
|
40
41
|
if (!payload || typeof payload !== "object") return payload;
|
|
@@ -60,5 +61,50 @@ export function sanitiseAnthropicPayloadSystem(payload: unknown): unknown {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
// Pi 0.86+ can send prompt updates as system messages in the transcript.
|
|
65
|
+
// Only transform their text; tool additions/removals and conversation content
|
|
66
|
+
// must remain unchanged. Keep the OAuth guard above for every transformation.
|
|
67
|
+
const messages = (payload as { messages?: unknown }).messages;
|
|
68
|
+
const newMessages = Array.isArray(messages) ? messages.map((message: unknown) => {
|
|
69
|
+
if (!message || typeof message !== "object") return message;
|
|
70
|
+
const candidate = message as { role?: unknown; content?: unknown };
|
|
71
|
+
if (candidate.role !== "system") return message;
|
|
72
|
+
|
|
73
|
+
if (typeof candidate.content === "string") {
|
|
74
|
+
const cleaned = sanitiseSystemPrompt(candidate.content);
|
|
75
|
+
const content = cleaned ? `${CLAUDE_CODE_IDENTITY}\n\n${cleaned}` : CLAUDE_CODE_IDENTITY;
|
|
76
|
+
if (content === candidate.content) return message;
|
|
77
|
+
changed = true;
|
|
78
|
+
return { ...message, content };
|
|
79
|
+
}
|
|
80
|
+
if (!Array.isArray(candidate.content)) return message;
|
|
81
|
+
|
|
82
|
+
let messageChanged = false;
|
|
83
|
+
let hasIdentity = false;
|
|
84
|
+
const content = candidate.content.map((block: unknown) => {
|
|
85
|
+
if (!block || typeof block !== "object") return block;
|
|
86
|
+
const textBlock = block as SystemTextBlock;
|
|
87
|
+
if (textBlock.type !== "text" || typeof textBlock.text !== "string") return block;
|
|
88
|
+
const cleaned = sanitiseSystemPrompt(textBlock.text);
|
|
89
|
+
const text = hasIdentity ? cleaned
|
|
90
|
+
: cleaned ? `${CLAUDE_CODE_IDENTITY}\n\n${cleaned}` : CLAUDE_CODE_IDENTITY;
|
|
91
|
+
hasIdentity = true;
|
|
92
|
+
if (text === textBlock.text) return block;
|
|
93
|
+
messageChanged = true;
|
|
94
|
+
return { ...textBlock, text };
|
|
95
|
+
}).filter((block: unknown) => {
|
|
96
|
+
if (!block || typeof block !== "object") return true;
|
|
97
|
+
const candidate = block as SystemTextBlock;
|
|
98
|
+
return candidate.type !== "text" || candidate.text !== "";
|
|
99
|
+
});
|
|
100
|
+
if (!messageChanged) return message;
|
|
101
|
+
changed = true;
|
|
102
|
+
return { ...message, content };
|
|
103
|
+
}) : undefined;
|
|
104
|
+
|
|
105
|
+
return changed ? {
|
|
106
|
+
...payload,
|
|
107
|
+
system: newSystem,
|
|
108
|
+
...(newMessages ? { messages: newMessages } : {}),
|
|
109
|
+
} : payload;
|
|
64
110
|
}
|