@oh-my-pi/pi-ai 4.5.0 → 4.6.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/package.json
CHANGED
|
@@ -30,7 +30,7 @@ import { sanitizeSurrogates } from "../utils/sanitize-unicode";
|
|
|
30
30
|
import { transformMessages } from "./transorm-messages";
|
|
31
31
|
|
|
32
32
|
// Stealth mode: Mimic Claude Code headers while avoiding tool name collisions.
|
|
33
|
-
export const claudeCodeVersion = "1.
|
|
33
|
+
export const claudeCodeVersion = "2.1.2";
|
|
34
34
|
export const claudeToolPrefix = "proxy_";
|
|
35
35
|
export const claudeCodeSystemInstruction = "You are Claude Code, Anthropic's official CLI for Claude.";
|
|
36
36
|
export const claudeCodeHeaders = {
|
|
@@ -512,6 +512,10 @@ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli"> = (
|
|
|
512
512
|
});
|
|
513
513
|
} else {
|
|
514
514
|
currentBlock.text += part.text;
|
|
515
|
+
currentBlock.textSignature = retainThoughtSignature(
|
|
516
|
+
currentBlock.textSignature,
|
|
517
|
+
part.thoughtSignature,
|
|
518
|
+
);
|
|
515
519
|
stream.push({
|
|
516
520
|
type: "text_delta",
|
|
517
521
|
contentIndex: blockIndex(),
|
|
@@ -13,18 +13,19 @@ type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vert
|
|
|
13
13
|
* Determines whether a streamed Gemini `Part` should be treated as "thinking".
|
|
14
14
|
*
|
|
15
15
|
* Protocol note (Gemini / Vertex AI thought signatures):
|
|
16
|
-
* - `
|
|
16
|
+
* - `thought: true` is the definitive marker for thinking content (thought summaries).
|
|
17
|
+
* - `thoughtSignature` is an encrypted representation of the model's internal thought process
|
|
18
|
+
* used to preserve reasoning context across multi-turn interactions.
|
|
19
|
+
* - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
|
|
20
|
+
* indicate the part itself is thinking content.
|
|
21
|
+
* - For non-functionCall responses, the signature appears on the last part for context replay.
|
|
17
22
|
* - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
|
|
18
23
|
* do not merge/move signatures across parts.
|
|
19
|
-
* - Our streaming representation uses content blocks, so we classify any non-empty `thoughtSignature`
|
|
20
|
-
* as thinking to avoid leaking thought content into normal assistant text.
|
|
21
24
|
*
|
|
22
|
-
*
|
|
23
|
-
* on subsequent deltas. We treat any non-empty `thoughtSignature` as thinking to avoid
|
|
24
|
-
* leaking thought text into the normal assistant text stream.
|
|
25
|
+
* See: https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
25
26
|
*/
|
|
26
27
|
export function isThinkingPart(part: Pick<Part, "thought" | "thoughtSignature">): boolean {
|
|
27
|
-
return part.thought === true
|
|
28
|
+
return part.thought === true;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
/**
|
|
@@ -214,9 +215,9 @@ const UNSUPPORTED_SCHEMA_FIELDS = new Set([
|
|
|
214
215
|
"format",
|
|
215
216
|
]);
|
|
216
217
|
|
|
217
|
-
|
|
218
|
+
function sanitizeSchemaImpl(value: unknown, isInsideProperties: boolean): unknown {
|
|
218
219
|
if (Array.isArray(value)) {
|
|
219
|
-
return value.map((entry) =>
|
|
220
|
+
return value.map((entry) => sanitizeSchemaImpl(entry, isInsideProperties));
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
if (!value || typeof value !== "object") {
|
|
@@ -247,7 +248,7 @@ export function sanitizeSchemaForGoogle(value: unknown): unknown {
|
|
|
247
248
|
// Copy description and other top-level fields (not the combiner)
|
|
248
249
|
for (const [key, entry] of Object.entries(obj)) {
|
|
249
250
|
if (key !== combiner && !(key in result)) {
|
|
250
|
-
result[key] =
|
|
251
|
+
result[key] = sanitizeSchemaImpl(entry, false);
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
254
|
return result;
|
|
@@ -258,13 +259,16 @@ export function sanitizeSchemaForGoogle(value: unknown): unknown {
|
|
|
258
259
|
// Regular field processing
|
|
259
260
|
let constValue: unknown;
|
|
260
261
|
for (const [key, entry] of Object.entries(obj)) {
|
|
261
|
-
|
|
262
|
+
// Only strip unsupported schema keywords when NOT inside "properties" object
|
|
263
|
+
// Inside "properties", keys are property names (e.g., "pattern") not schema keywords
|
|
264
|
+
if (!isInsideProperties && UNSUPPORTED_SCHEMA_FIELDS.has(key)) continue;
|
|
262
265
|
if (key === "const") {
|
|
263
266
|
constValue = entry;
|
|
264
267
|
continue;
|
|
265
268
|
}
|
|
266
269
|
if (key === "additionalProperties" && entry === false) continue;
|
|
267
|
-
|
|
270
|
+
// When key is "properties", child keys are property names, not schema keywords
|
|
271
|
+
result[key] = sanitizeSchemaImpl(entry, key === "properties");
|
|
268
272
|
}
|
|
269
273
|
|
|
270
274
|
if (constValue !== undefined) {
|
|
@@ -289,6 +293,10 @@ export function sanitizeSchemaForGoogle(value: unknown): unknown {
|
|
|
289
293
|
return result;
|
|
290
294
|
}
|
|
291
295
|
|
|
296
|
+
export function sanitizeSchemaForGoogle(value: unknown): unknown {
|
|
297
|
+
return sanitizeSchemaImpl(value, false);
|
|
298
|
+
}
|
|
299
|
+
|
|
292
300
|
function sanitizeToolForGoogle(tool: Tool): Tool {
|
|
293
301
|
return {
|
|
294
302
|
name: tool.name,
|
|
@@ -143,6 +143,10 @@ export const streamGoogleVertex: StreamFunction<"google-vertex"> = (
|
|
|
143
143
|
});
|
|
144
144
|
} else {
|
|
145
145
|
currentBlock.text += part.text;
|
|
146
|
+
currentBlock.textSignature = retainThoughtSignature(
|
|
147
|
+
currentBlock.textSignature,
|
|
148
|
+
part.thoughtSignature,
|
|
149
|
+
);
|
|
146
150
|
stream.push({
|
|
147
151
|
type: "text_delta",
|
|
148
152
|
contentIndex: blockIndex(),
|