@serii84/vertex-partner-provider 1.0.8 → 1.0.11
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 +58 -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.11 - Convert reasoning_content to content, emit all chunks
|
|
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,65 @@ 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
|
-
|
|
51
|
-
controller.enqueue(encoder.encode(line + '\n'));
|
|
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()) {
|
|
46
|
+
controller.enqueue(encoder.encode('\n'));
|
|
52
47
|
continue;
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
const
|
|
50
|
+
if (line.startsWith('data: ')) {
|
|
51
|
+
const data = line.slice(6).trim();
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
53
|
+
if (data === '[DONE]') {
|
|
54
|
+
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(data);
|
|
60
|
+
|
|
61
|
+
// Skip empty choices array (usage chunk at end)
|
|
62
|
+
if (parsed.choices && parsed.choices.length === 0) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Transform choices
|
|
67
|
+
if (parsed.choices) {
|
|
68
|
+
for (const choice of parsed.choices) {
|
|
69
|
+
if (choice.delta) {
|
|
70
|
+
// If content is null/empty but reasoning_content exists, use it
|
|
71
|
+
if (!choice.delta.content && choice.delta.reasoning_content) {
|
|
72
|
+
choice.delta.content = choice.delta.reasoning_content;
|
|
73
|
+
}
|
|
74
|
+
// Remove the non-standard field
|
|
75
|
+
delete choice.delta.reasoning_content;
|
|
65
76
|
}
|
|
66
|
-
// Remove reasoning_content to avoid confusion
|
|
67
|
-
delete choice.delta.reasoning_content;
|
|
68
77
|
}
|
|
69
78
|
}
|
|
79
|
+
|
|
80
|
+
controller.enqueue(encoder.encode('data: ' + JSON.stringify(parsed) + '\n\n'));
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// Pass through unparseable lines
|
|
83
|
+
controller.enqueue(encoder.encode(line + '\n'));
|
|
70
84
|
}
|
|
71
|
-
|
|
72
|
-
controller.enqueue(encoder.encode('data: ' + JSON.stringify(parsed) + '\n'));
|
|
73
|
-
} catch (e) {
|
|
74
|
-
// If JSON parse fails, pass through unchanged
|
|
85
|
+
} else {
|
|
75
86
|
controller.enqueue(encoder.encode(line + '\n'));
|
|
76
87
|
}
|
|
77
|
-
} else if (line.trim()) {
|
|
78
|
-
controller.enqueue(encoder.encode(line + '\n'));
|
|
79
88
|
}
|
|
89
|
+
} catch (err) {
|
|
90
|
+
controller.error(err);
|
|
80
91
|
}
|
|
81
92
|
}
|
|
82
93
|
});
|
|
@@ -110,11 +121,17 @@ function createVertexPartner(options = {}) {
|
|
|
110
121
|
const headers = new Headers(init?.headers);
|
|
111
122
|
headers.set('Authorization', `Bearer ${token}`);
|
|
112
123
|
|
|
124
|
+
let isStreaming = false;
|
|
125
|
+
if (init?.body) {
|
|
126
|
+
try {
|
|
127
|
+
const body = JSON.parse(init.body);
|
|
128
|
+
isStreaming = body.stream === true;
|
|
129
|
+
} catch (e) {}
|
|
130
|
+
}
|
|
131
|
+
|
|
113
132
|
const response = await fetch(url, { ...init, headers });
|
|
114
133
|
|
|
115
|
-
|
|
116
|
-
const contentType = response.headers.get('content-type') || '';
|
|
117
|
-
if (contentType.includes('text/event-stream')) {
|
|
134
|
+
if (isStreaming && response.ok) {
|
|
118
135
|
return transformStream(response);
|
|
119
136
|
}
|
|
120
137
|
|