bloby-bot 0.47.6 → 0.47.7
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
|
@@ -100,8 +100,12 @@ function toGeminiParts(content: PiContentBlock[]): any[] {
|
|
|
100
100
|
} else if (b.type === 'image') {
|
|
101
101
|
parts.push({ inlineData: { mimeType: b.mediaType, data: b.data } });
|
|
102
102
|
} else if (b.type === 'tool_use') {
|
|
103
|
-
// Assistant turn: the model asked to invoke a tool.
|
|
104
|
-
|
|
103
|
+
// Assistant turn: the model asked to invoke a tool. Thinking-capable
|
|
104
|
+
// Gemini 3.x rejects (HTTP 400) any echoed functionCall whose
|
|
105
|
+
// thoughtSignature is missing, so we forward it verbatim when present.
|
|
106
|
+
const part: any = { functionCall: { name: b.name, args: b.input || {} } };
|
|
107
|
+
if (b.thoughtSignature) part.thoughtSignature = b.thoughtSignature;
|
|
108
|
+
parts.push(part);
|
|
105
109
|
} else if (b.type === 'tool_result') {
|
|
106
110
|
// Function responses can be strings, objects, or even error markers.
|
|
107
111
|
// Wrap text in `{ output: ... }` (Gemini's docs use a flexible
|
|
@@ -262,6 +266,9 @@ export async function* streamGoogle(req: PiStreamRequest): AsyncIterable<PiStrea
|
|
|
262
266
|
id,
|
|
263
267
|
name: part.functionCall.name,
|
|
264
268
|
input: part.functionCall.args || {},
|
|
269
|
+
// Thinking-capable models attach a signature that we must echo
|
|
270
|
+
// back unchanged on the next turn. Optional on non-thinking models.
|
|
271
|
+
thoughtSignature: typeof part.thoughtSignature === 'string' ? part.thoughtSignature : undefined,
|
|
265
272
|
};
|
|
266
273
|
continue;
|
|
267
274
|
}
|
|
@@ -17,7 +17,10 @@ export type PiRole = 'user' | 'assistant' | 'tool';
|
|
|
17
17
|
export type PiContentBlock =
|
|
18
18
|
| { type: 'text'; text: string }
|
|
19
19
|
| { type: 'image'; mediaType: string; data: string } // base64
|
|
20
|
-
|
|
20
|
+
// `thoughtSignature` is a Gemini 3.x thinking-model field. Pi-flavored
|
|
21
|
+
// providers that emit reasoning attach it to function-call parts; the API
|
|
22
|
+
// rejects the next turn with HTTP 400 if we don't echo it back verbatim.
|
|
23
|
+
| { type: 'tool_use'; id: string; name: string; input: any; thoughtSignature?: string }
|
|
21
24
|
| { type: 'tool_result'; toolUseId: string; content: string; isError?: boolean };
|
|
22
25
|
|
|
23
26
|
export interface PiMessage {
|
|
@@ -50,7 +53,7 @@ export type PiStopReason = 'end_turn' | 'tool_use' | 'max_tokens' | 'error' | 'a
|
|
|
50
53
|
export type PiStreamEvent =
|
|
51
54
|
| { type: 'text_delta'; delta: string }
|
|
52
55
|
| { type: 'text_end'; text: string }
|
|
53
|
-
| { type: 'tool_use'; id: string; name: string; input: any }
|
|
56
|
+
| { type: 'tool_use'; id: string; name: string; input: any; thoughtSignature?: string }
|
|
54
57
|
| { type: 'done'; stopReason: PiStopReason; usage?: PiUsage }
|
|
55
58
|
| { type: 'error'; error: string };
|
|
56
59
|
|
|
@@ -68,7 +68,7 @@ export function createPiSession(init: PiSessionInit): PiSession {
|
|
|
68
68
|
/** One stream round — collect the assistant blocks the model emits this pass. */
|
|
69
69
|
interface RoundResult {
|
|
70
70
|
text: string;
|
|
71
|
-
toolUses: { id: string; name: string; input: any }[];
|
|
71
|
+
toolUses: { id: string; name: string; input: any; thoughtSignature?: string }[];
|
|
72
72
|
errored: boolean;
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -100,7 +100,12 @@ export function createPiSession(init: PiSessionInit): PiSession {
|
|
|
100
100
|
result.text = evt.text;
|
|
101
101
|
break;
|
|
102
102
|
case 'tool_use':
|
|
103
|
-
result.toolUses.push({
|
|
103
|
+
result.toolUses.push({
|
|
104
|
+
id: evt.id,
|
|
105
|
+
name: evt.name,
|
|
106
|
+
input: evt.input,
|
|
107
|
+
thoughtSignature: evt.thoughtSignature,
|
|
108
|
+
});
|
|
104
109
|
init.onEvent({ type: 'tool_use', id: evt.id, name: evt.name, input: evt.input });
|
|
105
110
|
break;
|
|
106
111
|
case 'error':
|
|
@@ -157,7 +162,15 @@ export function createPiSession(init: PiSessionInit): PiSession {
|
|
|
157
162
|
assistantContent.push({ type: 'text', text });
|
|
158
163
|
}
|
|
159
164
|
for (const tu of toolUses) {
|
|
160
|
-
assistantContent.push({
|
|
165
|
+
assistantContent.push({
|
|
166
|
+
type: 'tool_use',
|
|
167
|
+
id: tu.id,
|
|
168
|
+
name: tu.name,
|
|
169
|
+
input: tu.input,
|
|
170
|
+
// Forward Gemini's thoughtSignature unchanged so the next turn's
|
|
171
|
+
// request echoes it back; without it the API rejects with 400.
|
|
172
|
+
thoughtSignature: tu.thoughtSignature,
|
|
173
|
+
});
|
|
161
174
|
}
|
|
162
175
|
if (assistantContent.length > 0) {
|
|
163
176
|
messages.push({ role: 'assistant', content: assistantContent });
|