@serii84/vertex-partner-provider 1.0.17 → 1.0.19
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/index.js +59 -9
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vertex Partner Provider for OpenCode
|
|
3
|
-
* v1.0.
|
|
3
|
+
* v1.0.19 - Fix response body consumption issue
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');
|
|
@@ -20,7 +20,7 @@ async function getAuthToken(googleAuthOptions) {
|
|
|
20
20
|
return token.token;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function
|
|
23
|
+
function cleanResponse(parsed) {
|
|
24
24
|
if (parsed.choices) {
|
|
25
25
|
for (const choice of parsed.choices) {
|
|
26
26
|
delete choice.matched_stop;
|
|
@@ -32,11 +32,17 @@ function cleanChunk(parsed) {
|
|
|
32
32
|
}
|
|
33
33
|
delete choice.delta.reasoning_content;
|
|
34
34
|
}
|
|
35
|
+
|
|
36
|
+
if (choice.message) {
|
|
37
|
+
if (!choice.message.content && choice.message.reasoning_content) {
|
|
38
|
+
choice.message.content = choice.message.reasoning_content;
|
|
39
|
+
}
|
|
40
|
+
delete choice.message.reasoning_content;
|
|
41
|
+
}
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
if (parsed.usage) {
|
|
39
|
-
// Keep only standard fields
|
|
40
46
|
const { prompt_tokens, completion_tokens, total_tokens } = parsed.usage;
|
|
41
47
|
parsed.usage = { prompt_tokens, completion_tokens, total_tokens };
|
|
42
48
|
}
|
|
@@ -83,13 +89,12 @@ function transformStream(response) {
|
|
|
83
89
|
try {
|
|
84
90
|
const parsed = JSON.parse(data);
|
|
85
91
|
|
|
86
|
-
// Skip
|
|
87
|
-
// This chunk causes issues with some parsers
|
|
92
|
+
// Skip empty choices (usage-only chunk)
|
|
88
93
|
if (parsed.choices && parsed.choices.length === 0) {
|
|
89
94
|
continue;
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
const cleaned =
|
|
97
|
+
const cleaned = cleanResponse(parsed);
|
|
93
98
|
controller.enqueue(encoder.encode('data: ' + JSON.stringify(cleaned) + '\n\n'));
|
|
94
99
|
} catch (e) {
|
|
95
100
|
// Skip invalid JSON
|
|
@@ -113,6 +118,46 @@ function transformStream(response) {
|
|
|
113
118
|
});
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
async function transformNonStreamingResponse(response) {
|
|
122
|
+
const text = await response.text();
|
|
123
|
+
|
|
124
|
+
// Handle empty response
|
|
125
|
+
if (!text || text.trim() === '') {
|
|
126
|
+
return new Response(JSON.stringify({
|
|
127
|
+
id: 'empty',
|
|
128
|
+
object: 'chat.completion',
|
|
129
|
+
choices: [{
|
|
130
|
+
index: 0,
|
|
131
|
+
message: { role: 'assistant', content: '' },
|
|
132
|
+
finish_reason: 'stop'
|
|
133
|
+
}],
|
|
134
|
+
usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
135
|
+
}), {
|
|
136
|
+
headers: { 'content-type': 'application/json' },
|
|
137
|
+
status: response.status,
|
|
138
|
+
statusText: response.statusText,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const data = JSON.parse(text);
|
|
144
|
+
const cleaned = cleanResponse(data);
|
|
145
|
+
|
|
146
|
+
return new Response(JSON.stringify(cleaned), {
|
|
147
|
+
headers: { 'content-type': 'application/json' },
|
|
148
|
+
status: response.status,
|
|
149
|
+
statusText: response.statusText,
|
|
150
|
+
});
|
|
151
|
+
} catch (e) {
|
|
152
|
+
// If JSON parse fails, return original text as-is
|
|
153
|
+
return new Response(text, {
|
|
154
|
+
headers: response.headers,
|
|
155
|
+
status: response.status,
|
|
156
|
+
statusText: response.statusText,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
116
161
|
function createVertexPartner(options = {}) {
|
|
117
162
|
const {
|
|
118
163
|
project = process.env.GOOGLE_VERTEX_PROJECT,
|
|
@@ -145,11 +190,16 @@ function createVertexPartner(options = {}) {
|
|
|
145
190
|
|
|
146
191
|
const response = await fetch(url, { ...init, headers });
|
|
147
192
|
|
|
148
|
-
if (
|
|
149
|
-
return
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
// Clone and return error responses as-is
|
|
195
|
+
return response;
|
|
150
196
|
}
|
|
151
197
|
|
|
152
|
-
|
|
198
|
+
if (isStreaming) {
|
|
199
|
+
return transformStream(response);
|
|
200
|
+
} else {
|
|
201
|
+
return transformNonStreamingResponse(response);
|
|
202
|
+
}
|
|
153
203
|
};
|
|
154
204
|
|
|
155
205
|
const provider = createOpenAICompatible({
|