@serii84/vertex-partner-provider 1.0.8 → 1.0.10
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 +64 -41
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vertex Partner Provider for OpenCode
|
|
3
|
-
*
|
|
3
|
+
* v1.0.10 - Skip reasoning_content, only pass actual content
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');
|
|
@@ -20,10 +20,6 @@ async function getAuthToken(googleAuthOptions) {
|
|
|
20
20
|
return token.token;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
* Transform SSE stream to handle reasoning_content
|
|
25
|
-
* Converts reasoning_content to content so SDK can parse it
|
|
26
|
-
*/
|
|
27
23
|
function transformStream(response) {
|
|
28
24
|
const reader = response.body.getReader();
|
|
29
25
|
const decoder = new TextDecoder();
|
|
@@ -33,50 +29,71 @@ function transformStream(response) {
|
|
|
33
29
|
|
|
34
30
|
const transformedStream = new ReadableStream({
|
|
35
31
|
async pull(controller) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (data === '[DONE]') {
|
|
51
|
-
controller.enqueue(encoder.encode(line + '\n'));
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
32
|
+
try {
|
|
33
|
+
const { done, value } = await reader.read();
|
|
34
|
+
|
|
35
|
+
if (done) {
|
|
36
|
+
controller.close();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
buffer += decoder.decode(value, { stream: true });
|
|
41
|
+
const lines = buffer.split('\n');
|
|
42
|
+
buffer = lines.pop() || '';
|
|
43
|
+
|
|
44
|
+
for (const line of lines) {
|
|
45
|
+
if (!line.trim()) continue;
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
const
|
|
47
|
+
if (line.startsWith('data: ')) {
|
|
48
|
+
const data = line.slice(6).trim();
|
|
49
|
+
|
|
50
|
+
if (data === '[DONE]') {
|
|
51
|
+
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
57
54
|
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(data);
|
|
57
|
+
|
|
58
|
+
// Skip empty choices
|
|
59
|
+
if (!parsed.choices || parsed.choices.length === 0) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let hasContent = false;
|
|
64
|
+
|
|
60
65
|
for (const choice of parsed.choices) {
|
|
61
66
|
if (choice.delta) {
|
|
62
|
-
//
|
|
63
|
-
if (choice.delta.content
|
|
64
|
-
|
|
67
|
+
// Only keep chunks that have actual content (not reasoning)
|
|
68
|
+
if (choice.delta.content && choice.delta.content !== null) {
|
|
69
|
+
hasContent = true;
|
|
65
70
|
}
|
|
66
|
-
// Remove reasoning_content
|
|
71
|
+
// Remove reasoning_content entirely
|
|
67
72
|
delete choice.delta.reasoning_content;
|
|
73
|
+
|
|
74
|
+
// If only reasoning was present, set empty content
|
|
75
|
+
if (!choice.delta.content) {
|
|
76
|
+
choice.delta.content = '';
|
|
77
|
+
}
|
|
68
78
|
}
|
|
79
|
+
|
|
80
|
+
// Pass through finish_reason chunks
|
|
81
|
+
if (choice.finish_reason) {
|
|
82
|
+
hasContent = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Only emit if there's actual content or it's a finish chunk
|
|
87
|
+
if (hasContent || parsed.choices.some(c => c.finish_reason)) {
|
|
88
|
+
controller.enqueue(encoder.encode('data: ' + JSON.stringify(parsed) + '\n\n'));
|
|
69
89
|
}
|
|
90
|
+
} catch (e) {
|
|
91
|
+
controller.enqueue(encoder.encode(line + '\n'));
|
|
70
92
|
}
|
|
71
|
-
|
|
72
|
-
controller.enqueue(encoder.encode('data: ' + JSON.stringify(parsed) + '\n'));
|
|
73
|
-
} catch (e) {
|
|
74
|
-
// If JSON parse fails, pass through unchanged
|
|
75
|
-
controller.enqueue(encoder.encode(line + '\n'));
|
|
76
93
|
}
|
|
77
|
-
} else if (line.trim()) {
|
|
78
|
-
controller.enqueue(encoder.encode(line + '\n'));
|
|
79
94
|
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
controller.error(err);
|
|
80
97
|
}
|
|
81
98
|
}
|
|
82
99
|
});
|
|
@@ -110,11 +127,17 @@ function createVertexPartner(options = {}) {
|
|
|
110
127
|
const headers = new Headers(init?.headers);
|
|
111
128
|
headers.set('Authorization', `Bearer ${token}`);
|
|
112
129
|
|
|
130
|
+
let isStreaming = false;
|
|
131
|
+
if (init?.body) {
|
|
132
|
+
try {
|
|
133
|
+
const body = JSON.parse(init.body);
|
|
134
|
+
isStreaming = body.stream === true;
|
|
135
|
+
} catch (e) {}
|
|
136
|
+
}
|
|
137
|
+
|
|
113
138
|
const response = await fetch(url, { ...init, headers });
|
|
114
139
|
|
|
115
|
-
|
|
116
|
-
const contentType = response.headers.get('content-type') || '';
|
|
117
|
-
if (contentType.includes('text/event-stream')) {
|
|
140
|
+
if (isStreaming && response.ok) {
|
|
118
141
|
return transformStream(response);
|
|
119
142
|
}
|
|
120
143
|
|