@lay111/dsh-plugin-google 1.0.15 → 1.0.17
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 +1 -1
- package/src/api.js +110 -19
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -6,18 +6,58 @@ const ANTIGRAVITY_ENDPOINTS = [
|
|
|
6
6
|
'https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:streamGenerateContent?alt=sse',
|
|
7
7
|
];
|
|
8
8
|
|
|
9
|
+
export function cleanSchema(schema) {
|
|
10
|
+
if (!schema || typeof schema !== 'object') return schema;
|
|
11
|
+
const clone = JSON.parse(JSON.stringify(schema));
|
|
12
|
+
|
|
13
|
+
function clean(obj) {
|
|
14
|
+
if (!obj || typeof obj !== 'object') return;
|
|
15
|
+
delete obj.$schema;
|
|
16
|
+
delete obj.$id;
|
|
17
|
+
delete obj.definitions;
|
|
18
|
+
delete obj.$defs;
|
|
19
|
+
delete obj.additionalProperties;
|
|
20
|
+
|
|
21
|
+
if (obj.properties && typeof obj.properties === 'object') {
|
|
22
|
+
for (const key of Object.keys(obj.properties)) {
|
|
23
|
+
clean(obj.properties[key]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (obj.items && typeof obj.items === 'object') {
|
|
27
|
+
clean(obj.items);
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(obj.anyOf)) {
|
|
30
|
+
obj.anyOf.forEach(clean);
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(obj.oneOf)) {
|
|
33
|
+
obj.oneOf.forEach(clean);
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(obj.allOf)) {
|
|
36
|
+
obj.allOf.forEach(clean);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
clean(clone);
|
|
41
|
+
return clone;
|
|
42
|
+
}
|
|
43
|
+
|
|
9
44
|
export function formatMessagesToAntigravity(messages, modelSpec, projectId) {
|
|
10
45
|
const contents = [];
|
|
11
|
-
|
|
46
|
+
const systemParts = [];
|
|
47
|
+
const isClaude = modelSpec.id.includes('claude') || modelSpec.wireId.includes('claude');
|
|
12
48
|
|
|
13
49
|
for (const message of messages) {
|
|
14
50
|
if (message.role === 'system') {
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
51
|
+
let text = '';
|
|
52
|
+
if (typeof message.content === 'string') {
|
|
53
|
+
text = message.content;
|
|
54
|
+
} else if (Array.isArray(message.content)) {
|
|
55
|
+
text = message.content
|
|
56
|
+
.map((b) => (b.type === 'text' ? b.text : typeof b === 'string' ? b : ''))
|
|
57
|
+
.join('\n');
|
|
58
|
+
}
|
|
59
|
+
if (text.trim().length > 0) {
|
|
60
|
+
systemParts.push({ text: text.trim() });
|
|
21
61
|
}
|
|
22
62
|
continue;
|
|
23
63
|
}
|
|
@@ -30,24 +70,43 @@ export function formatMessagesToAntigravity(messages, modelSpec, projectId) {
|
|
|
30
70
|
} else if (Array.isArray(message.content)) {
|
|
31
71
|
for (const block of message.content) {
|
|
32
72
|
if (block.type === 'text') {
|
|
33
|
-
|
|
73
|
+
if (block.text && block.text.length > 0) {
|
|
74
|
+
parts.push({ text: block.text });
|
|
75
|
+
}
|
|
34
76
|
} else if (block.type === 'thought' || block.type === 'reasoning') {
|
|
35
77
|
parts.push({ thought: true, text: block.text || block.thought || '' });
|
|
36
78
|
} else if (block.type === 'tool-call') {
|
|
37
|
-
|
|
79
|
+
const callPart = {
|
|
38
80
|
functionCall: {
|
|
39
81
|
name: block.name,
|
|
40
82
|
args: typeof block.arguments === 'string' ? JSON.parse(block.arguments || '{}') : block.arguments || {},
|
|
41
83
|
},
|
|
42
|
-
}
|
|
84
|
+
};
|
|
85
|
+
if (!isClaude) {
|
|
86
|
+
callPart.thoughtSignature = block.thoughtSignature || 'skip_thought_signature_validator';
|
|
87
|
+
}
|
|
88
|
+
parts.push(callPart);
|
|
43
89
|
} else if (block.type === 'tool-result') {
|
|
90
|
+
let outputText = '';
|
|
91
|
+
if (typeof block.content === 'string') {
|
|
92
|
+
outputText = block.content;
|
|
93
|
+
} else if (Array.isArray(block.content)) {
|
|
94
|
+
outputText = block.content
|
|
95
|
+
.map((p) => p.text || (typeof p === 'string' ? p : JSON.stringify(p)))
|
|
96
|
+
.join('\n');
|
|
97
|
+
} else if (typeof block.content === 'object' && block.content !== null) {
|
|
98
|
+
outputText = JSON.stringify(block.content);
|
|
99
|
+
} else {
|
|
100
|
+
outputText = String(block.content || '');
|
|
101
|
+
}
|
|
102
|
+
|
|
44
103
|
contents.push({
|
|
45
104
|
role: 'user',
|
|
46
105
|
parts: [
|
|
47
106
|
{
|
|
48
107
|
functionResponse: {
|
|
49
|
-
name: block.name || 'tool',
|
|
50
|
-
response: {
|
|
108
|
+
name: block.name || block.toolName || 'tool',
|
|
109
|
+
response: { output: outputText || '(no output)' },
|
|
51
110
|
},
|
|
52
111
|
},
|
|
53
112
|
],
|
|
@@ -68,7 +127,6 @@ export function formatMessagesToAntigravity(messages, modelSpec, projectId) {
|
|
|
68
127
|
contents.push({ role: 'user', parts: [{ text: 'Hello' }] });
|
|
69
128
|
}
|
|
70
129
|
|
|
71
|
-
const isClaude = modelSpec.id.includes('claude') || modelSpec.wireId.includes('claude');
|
|
72
130
|
const payload = {
|
|
73
131
|
project: projectId || 'aicode-consumers',
|
|
74
132
|
model: modelSpec.wireId,
|
|
@@ -86,7 +144,7 @@ export function formatMessagesToAntigravity(messages, modelSpec, projectId) {
|
|
|
86
144
|
}
|
|
87
145
|
: {}),
|
|
88
146
|
},
|
|
89
|
-
...(
|
|
147
|
+
...(systemParts.length > 0 ? { systemInstruction: { parts: systemParts } } : {}),
|
|
90
148
|
labels: {
|
|
91
149
|
trajectory_id: `traj_${Date.now()}`,
|
|
92
150
|
used_claude: String(isClaude),
|
|
@@ -109,7 +167,7 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
109
167
|
functionDeclarations: options.tools.map((tool) => ({
|
|
110
168
|
name: tool.name,
|
|
111
169
|
description: tool.description || '',
|
|
112
|
-
parameters: tool.parameters || {},
|
|
170
|
+
parameters: cleanSchema(tool.parameters || {}),
|
|
113
171
|
})),
|
|
114
172
|
},
|
|
115
173
|
];
|
|
@@ -165,7 +223,12 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
165
223
|
const reader = response.body.getReader();
|
|
166
224
|
const decoder = new TextDecoder();
|
|
167
225
|
let buffer = '';
|
|
168
|
-
let
|
|
226
|
+
let hasText = false;
|
|
227
|
+
let hasToolCall = false;
|
|
228
|
+
let accumulatedThoughts = '';
|
|
229
|
+
let nextBlockIndex = 0;
|
|
230
|
+
const reasoningBlockIndex = 0;
|
|
231
|
+
let textBlockIndex = 1;
|
|
169
232
|
|
|
170
233
|
try {
|
|
171
234
|
while (true) {
|
|
@@ -192,22 +255,26 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
192
255
|
|
|
193
256
|
for (const part of candidate.content?.parts || []) {
|
|
194
257
|
if (part.thought) {
|
|
258
|
+
accumulatedThoughts += part.text || '';
|
|
195
259
|
yield {
|
|
196
260
|
type: 'reasoning-delta',
|
|
197
|
-
index:
|
|
261
|
+
index: reasoningBlockIndex,
|
|
198
262
|
text: part.text || '',
|
|
199
263
|
};
|
|
200
264
|
} else if (part.text) {
|
|
265
|
+
hasText = true;
|
|
201
266
|
yield {
|
|
202
267
|
type: 'text-delta',
|
|
203
|
-
index:
|
|
268
|
+
index: textBlockIndex,
|
|
204
269
|
text: part.text || '',
|
|
205
270
|
};
|
|
206
271
|
} else if (part.functionCall) {
|
|
272
|
+
hasToolCall = true;
|
|
207
273
|
const callId = `call_${Math.random().toString(36).slice(2, 10)}`;
|
|
274
|
+
const callIndex = 2 + (nextBlockIndex++);
|
|
208
275
|
yield {
|
|
209
276
|
type: 'tool-call-delta',
|
|
210
|
-
index:
|
|
277
|
+
index: callIndex,
|
|
211
278
|
id: callId,
|
|
212
279
|
name: part.functionCall.name,
|
|
213
280
|
argumentsDelta: JSON.stringify(part.functionCall.args || {}),
|
|
@@ -216,6 +283,17 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
216
283
|
}
|
|
217
284
|
|
|
218
285
|
if (candidate.finishReason) {
|
|
286
|
+
// Fallback protection: If the model only thought and emitted 0 text and 0 tool calls,
|
|
287
|
+
// synthesize a completion text so the turn never cuts off silently!
|
|
288
|
+
if (!hasText && !hasToolCall && accumulatedThoughts.length > 0) {
|
|
289
|
+
hasText = true;
|
|
290
|
+
yield {
|
|
291
|
+
type: 'text-delta',
|
|
292
|
+
index: textBlockIndex,
|
|
293
|
+
text: '\n(已完成思考,请指示下一步)',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
219
297
|
yield {
|
|
220
298
|
type: 'finish',
|
|
221
299
|
reason: 'stop',
|
|
@@ -227,6 +305,19 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
227
305
|
}
|
|
228
306
|
}
|
|
229
307
|
}
|
|
308
|
+
|
|
309
|
+
// Final safety check
|
|
310
|
+
if (!hasText && !hasToolCall && accumulatedThoughts.length > 0) {
|
|
311
|
+
yield {
|
|
312
|
+
type: 'text-delta',
|
|
313
|
+
index: textBlockIndex,
|
|
314
|
+
text: '\n(已完成思考,请指示下一步)',
|
|
315
|
+
};
|
|
316
|
+
yield {
|
|
317
|
+
type: 'finish',
|
|
318
|
+
reason: 'stop',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
230
321
|
} finally {
|
|
231
322
|
reader.releaseLock();
|
|
232
323
|
}
|