@serii84/vertex-partner-provider 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.
Files changed (2) hide show
  1. package/index.js +109 -3
  2. 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.15 - No transform, pass through raw (debug)
3
+ * v1.0.17 - Skip usage-only chunk at end (empty choices)
4
4
  */
5
5
 
6
6
  const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');
@@ -20,6 +20,99 @@ async function getAuthToken(googleAuthOptions) {
20
20
  return token.token;
21
21
  }
22
22
 
23
+ function cleanChunk(parsed) {
24
+ if (parsed.choices) {
25
+ for (const choice of parsed.choices) {
26
+ delete choice.matched_stop;
27
+ delete choice.logprobs;
28
+
29
+ if (choice.delta) {
30
+ if (!choice.delta.content && choice.delta.reasoning_content) {
31
+ choice.delta.content = choice.delta.reasoning_content;
32
+ }
33
+ delete choice.delta.reasoning_content;
34
+ }
35
+ }
36
+ }
37
+
38
+ if (parsed.usage) {
39
+ // Keep only standard fields
40
+ const { prompt_tokens, completion_tokens, total_tokens } = parsed.usage;
41
+ parsed.usage = { prompt_tokens, completion_tokens, total_tokens };
42
+ }
43
+
44
+ delete parsed.metadata;
45
+
46
+ return parsed;
47
+ }
48
+
49
+ function transformStream(response) {
50
+ const reader = response.body.getReader();
51
+ const decoder = new TextDecoder();
52
+ const encoder = new TextEncoder();
53
+
54
+ let buffer = '';
55
+
56
+ const transformedStream = new ReadableStream({
57
+ async pull(controller) {
58
+ try {
59
+ const { done, value } = await reader.read();
60
+
61
+ if (done) {
62
+ controller.close();
63
+ return;
64
+ }
65
+
66
+ buffer += decoder.decode(value, { stream: true });
67
+
68
+ let boundary;
69
+ while ((boundary = buffer.indexOf('\n\n')) !== -1) {
70
+ const message = buffer.slice(0, boundary);
71
+ buffer = buffer.slice(boundary + 2);
72
+
73
+ if (!message.trim()) continue;
74
+
75
+ if (message.startsWith('data: ')) {
76
+ const data = message.slice(6);
77
+
78
+ if (data === '[DONE]') {
79
+ controller.enqueue(encoder.encode('data: [DONE]\n\n'));
80
+ continue;
81
+ }
82
+
83
+ try {
84
+ const parsed = JSON.parse(data);
85
+
86
+ // Skip the usage-only chunk (empty choices array)
87
+ // This chunk causes issues with some parsers
88
+ if (parsed.choices && parsed.choices.length === 0) {
89
+ continue;
90
+ }
91
+
92
+ const cleaned = cleanChunk(parsed);
93
+ controller.enqueue(encoder.encode('data: ' + JSON.stringify(cleaned) + '\n\n'));
94
+ } catch (e) {
95
+ // Skip invalid JSON
96
+ }
97
+ }
98
+ }
99
+ } catch (err) {
100
+ controller.error(err);
101
+ }
102
+ },
103
+
104
+ cancel() {
105
+ reader.cancel();
106
+ }
107
+ });
108
+
109
+ return new Response(transformedStream, {
110
+ headers: response.headers,
111
+ status: response.status,
112
+ statusText: response.statusText,
113
+ });
114
+ }
115
+
23
116
  function createVertexPartner(options = {}) {
24
117
  const {
25
118
  project = process.env.GOOGLE_VERTEX_PROJECT,
@@ -42,8 +135,21 @@ function createVertexPartner(options = {}) {
42
135
  const headers = new Headers(init?.headers);
43
136
  headers.set('Authorization', `Bearer ${token}`);
44
137
 
45
- // Just pass through - no transform
46
- return fetch(url, { ...init, headers });
138
+ let isStreaming = false;
139
+ if (init?.body) {
140
+ try {
141
+ const body = JSON.parse(init.body);
142
+ isStreaming = body.stream === true;
143
+ } catch (e) {}
144
+ }
145
+
146
+ const response = await fetch(url, { ...init, headers });
147
+
148
+ if (isStreaming && response.ok) {
149
+ return transformStream(response);
150
+ }
151
+
152
+ return response;
47
153
  };
48
154
 
49
155
  const provider = createOpenAICompatible({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serii84/vertex-partner-provider",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "Vertex AI partner models (GLM, Kimi, DeepSeek) for OpenCode",
5
5
  "main": "index.js",
6
6
  "scripts": {