@lay111/dsh-plugin-google 1.0.16 → 1.0.18
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 +7 -2
- package/src/api.js +90 -32
- package/src/index.js +5 -0
- package/src/models.js +10 -0
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lay111/dsh-plugin-google",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"description": "Community-driven DeepSeek Harness Plugin for Google Antigravity & Gemini/Claude Models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js",
|
|
9
|
-
"./package.json": "./package.json"
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
"./auth": "./src/auth.js",
|
|
11
|
+
"./models": "./src/models.js",
|
|
12
|
+
"./api": "./src/api.js",
|
|
13
|
+
"./adapter": "./src/adapter.js",
|
|
14
|
+
"./src/*": "./src/*"
|
|
10
15
|
},
|
|
11
16
|
"bin": {
|
|
12
17
|
"dsh-plugin-google": "bin/setup.js",
|
package/src/api.js
CHANGED
|
@@ -8,37 +8,62 @@ const ANTIGRAVITY_ENDPOINTS = [
|
|
|
8
8
|
|
|
9
9
|
export function cleanSchema(schema) {
|
|
10
10
|
if (!schema || typeof schema !== 'object') return schema;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
11
|
+
if (Array.isArray(schema)) return schema.map(cleanSchema);
|
|
12
|
+
|
|
13
|
+
// Handle anyOf / oneOf (Google Gemini rejects siblings with anyOf)
|
|
14
|
+
if (Array.isArray(schema.anyOf) || Array.isArray(schema.oneOf)) {
|
|
15
|
+
const variants = schema.anyOf || schema.oneOf;
|
|
16
|
+
const nonNull = variants.find((v) => v && v.type !== 'null') || variants[0];
|
|
17
|
+
const isNullable = variants.some((v) => v && v.type === 'null');
|
|
18
|
+
const merged = cleanSchema(nonNull);
|
|
19
|
+
if (isNullable && typeof merged === 'object' && merged !== null) merged.nullable = true;
|
|
20
|
+
return merged;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const cleaned = {};
|
|
24
|
+
|
|
25
|
+
// Normalize type array e.g. ["string", "null"] -> type: "string", nullable: true
|
|
26
|
+
if (Array.isArray(schema.type)) {
|
|
27
|
+
const hasNull = schema.type.includes('null');
|
|
28
|
+
const mainType = schema.type.find((t) => t !== 'null') || 'string';
|
|
29
|
+
cleaned.type = mainType;
|
|
30
|
+
if (hasNull) cleaned.nullable = true;
|
|
31
|
+
} else if (schema.type) {
|
|
32
|
+
cleaned.type = schema.type;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof schema.description === 'string' && schema.description.length > 0) {
|
|
36
|
+
cleaned.description = schema.description;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (schema.nullable === true) {
|
|
40
|
+
cleaned.nullable = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (typeof schema.format === 'string' && schema.format.length > 0) {
|
|
44
|
+
cleaned.format = schema.format;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Array.isArray(schema.enum)) {
|
|
48
|
+
cleaned.enum = schema.enum;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (Array.isArray(schema.required)) {
|
|
52
|
+
cleaned.required = schema.required;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (schema.properties && typeof schema.properties === 'object' && !Array.isArray(schema.properties)) {
|
|
56
|
+
cleaned.properties = {};
|
|
57
|
+
for (const [k, v] of Object.entries(schema.properties)) {
|
|
58
|
+
cleaned.properties[k] = cleanSchema(v);
|
|
37
59
|
}
|
|
38
60
|
}
|
|
39
61
|
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
if (schema.items && typeof schema.items === 'object') {
|
|
63
|
+
cleaned.items = cleanSchema(schema.items);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return cleaned;
|
|
42
67
|
}
|
|
43
68
|
|
|
44
69
|
export function formatMessagesToAntigravity(messages, modelSpec, projectId) {
|
|
@@ -223,7 +248,12 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
223
248
|
const reader = response.body.getReader();
|
|
224
249
|
const decoder = new TextDecoder();
|
|
225
250
|
let buffer = '';
|
|
226
|
-
let
|
|
251
|
+
let hasText = false;
|
|
252
|
+
let hasToolCall = false;
|
|
253
|
+
let accumulatedThoughts = '';
|
|
254
|
+
let nextBlockIndex = 0;
|
|
255
|
+
const reasoningBlockIndex = 0;
|
|
256
|
+
let textBlockIndex = 1;
|
|
227
257
|
|
|
228
258
|
try {
|
|
229
259
|
while (true) {
|
|
@@ -250,22 +280,26 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
250
280
|
|
|
251
281
|
for (const part of candidate.content?.parts || []) {
|
|
252
282
|
if (part.thought) {
|
|
283
|
+
accumulatedThoughts += part.text || '';
|
|
253
284
|
yield {
|
|
254
285
|
type: 'reasoning-delta',
|
|
255
|
-
index:
|
|
286
|
+
index: reasoningBlockIndex,
|
|
256
287
|
text: part.text || '',
|
|
257
288
|
};
|
|
258
289
|
} else if (part.text) {
|
|
290
|
+
hasText = true;
|
|
259
291
|
yield {
|
|
260
292
|
type: 'text-delta',
|
|
261
|
-
index:
|
|
293
|
+
index: textBlockIndex,
|
|
262
294
|
text: part.text || '',
|
|
263
295
|
};
|
|
264
296
|
} else if (part.functionCall) {
|
|
297
|
+
hasToolCall = true;
|
|
265
298
|
const callId = `call_${Math.random().toString(36).slice(2, 10)}`;
|
|
299
|
+
const callIndex = 2 + (nextBlockIndex++);
|
|
266
300
|
yield {
|
|
267
301
|
type: 'tool-call-delta',
|
|
268
|
-
index:
|
|
302
|
+
index: callIndex,
|
|
269
303
|
id: callId,
|
|
270
304
|
name: part.functionCall.name,
|
|
271
305
|
argumentsDelta: JSON.stringify(part.functionCall.args || {}),
|
|
@@ -274,6 +308,17 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
274
308
|
}
|
|
275
309
|
|
|
276
310
|
if (candidate.finishReason) {
|
|
311
|
+
// Fallback protection: If the model only thought and emitted 0 text and 0 tool calls,
|
|
312
|
+
// synthesize a completion text so the turn never cuts off silently!
|
|
313
|
+
if (!hasText && !hasToolCall && accumulatedThoughts.length > 0) {
|
|
314
|
+
hasText = true;
|
|
315
|
+
yield {
|
|
316
|
+
type: 'text-delta',
|
|
317
|
+
index: textBlockIndex,
|
|
318
|
+
text: '\n(已完成思考,请指示下一步)',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
277
322
|
yield {
|
|
278
323
|
type: 'finish',
|
|
279
324
|
reason: 'stop',
|
|
@@ -285,6 +330,19 @@ export async function* streamAntigravity(options, accessToken, projectId) {
|
|
|
285
330
|
}
|
|
286
331
|
}
|
|
287
332
|
}
|
|
333
|
+
|
|
334
|
+
// Final safety check
|
|
335
|
+
if (!hasText && !hasToolCall && accumulatedThoughts.length > 0) {
|
|
336
|
+
yield {
|
|
337
|
+
type: 'text-delta',
|
|
338
|
+
index: textBlockIndex,
|
|
339
|
+
text: '\n(已完成思考,请指示下一步)',
|
|
340
|
+
};
|
|
341
|
+
yield {
|
|
342
|
+
type: 'finish',
|
|
343
|
+
reason: 'stop',
|
|
344
|
+
};
|
|
345
|
+
}
|
|
288
346
|
} finally {
|
|
289
347
|
reader.releaseLock();
|
|
290
348
|
}
|
package/src/index.js
CHANGED
package/src/models.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
export const ANTIGRAVITY_MODELS = [
|
|
2
|
+
{
|
|
3
|
+
id: 'gemini-3.8-flash',
|
|
4
|
+
name: 'Gemini 3.8 Flash High (Thinking)',
|
|
5
|
+
wireId: 'gemini-3.8-flash-high',
|
|
6
|
+
contextWindow: 1048576,
|
|
7
|
+
maxTokens: 65536,
|
|
8
|
+
supportsThinking: true,
|
|
9
|
+
thinkingBudget: 10000,
|
|
10
|
+
description: 'Google flagship coding model with 10k thinking budget (Fast & Deep)',
|
|
11
|
+
},
|
|
2
12
|
{
|
|
3
13
|
id: 'gemini-3.7-flash',
|
|
4
14
|
name: 'Gemini 3.7 Flash High (Thinking)',
|