@bxb1337/windsurf-fast-context 1.0.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/dist/auth/api-key.d.ts +2 -0
  4. package/dist/auth/api-key.test.d.ts +1 -0
  5. package/dist/auth/jwt-manager.d.ts +18 -0
  6. package/dist/auth/jwt-manager.test.d.ts +1 -0
  7. package/dist/cjs/auth/api-key.js +10 -0
  8. package/dist/cjs/auth/api-key.test.js +29 -0
  9. package/dist/cjs/auth/jwt-manager.js +94 -0
  10. package/dist/cjs/auth/jwt-manager.test.js +99 -0
  11. package/dist/cjs/conversion/prompt-converter.js +57 -0
  12. package/dist/cjs/conversion/prompt-converter.test.js +95 -0
  13. package/dist/cjs/conversion/response-converter.js +233 -0
  14. package/dist/cjs/conversion/response-converter.test.js +65 -0
  15. package/dist/cjs/index.js +23 -0
  16. package/dist/cjs/model/devstral-language-model.js +399 -0
  17. package/dist/cjs/model/devstral-language-model.test.js +410 -0
  18. package/dist/cjs/package.json +3 -0
  19. package/dist/cjs/protocol/connect-frame.js +40 -0
  20. package/dist/cjs/protocol/connect-frame.test.js +36 -0
  21. package/dist/cjs/protocol/protobuf.js +114 -0
  22. package/dist/cjs/protocol/protobuf.test.js +58 -0
  23. package/dist/cjs/provider.js +13 -0
  24. package/dist/cjs/provider.test.js +61 -0
  25. package/dist/cjs/transport/http.js +83 -0
  26. package/dist/cjs/transport/http.test.js +196 -0
  27. package/dist/cjs/types/index.js +2 -0
  28. package/dist/conversion/prompt-converter.d.ts +49 -0
  29. package/dist/conversion/prompt-converter.test.d.ts +1 -0
  30. package/dist/conversion/response-converter.d.ts +12 -0
  31. package/dist/conversion/response-converter.test.d.ts +1 -0
  32. package/dist/esm/auth/api-key.js +7 -0
  33. package/dist/esm/auth/api-key.test.js +27 -0
  34. package/dist/esm/auth/jwt-manager.js +90 -0
  35. package/dist/esm/auth/jwt-manager.test.js +97 -0
  36. package/dist/esm/conversion/prompt-converter.js +54 -0
  37. package/dist/esm/conversion/prompt-converter.test.js +93 -0
  38. package/dist/esm/conversion/response-converter.js +230 -0
  39. package/dist/esm/conversion/response-converter.test.js +63 -0
  40. package/dist/esm/dist/cjs/index.js +3 -0
  41. package/dist/esm/index.js +3 -0
  42. package/dist/esm/model/devstral-language-model.js +395 -0
  43. package/dist/esm/model/devstral-language-model.test.js +408 -0
  44. package/dist/esm/protocol/connect-frame.js +36 -0
  45. package/dist/esm/protocol/connect-frame.test.js +34 -0
  46. package/dist/esm/protocol/protobuf.js +108 -0
  47. package/dist/esm/protocol/protobuf.test.js +56 -0
  48. package/dist/esm/provider.js +9 -0
  49. package/dist/esm/provider.test.js +59 -0
  50. package/dist/esm/scripts/postbuild.js +10 -0
  51. package/dist/esm/src/index.js +1 -0
  52. package/dist/esm/transport/http.js +78 -0
  53. package/dist/esm/transport/http.test.js +194 -0
  54. package/dist/esm/types/index.js +1 -0
  55. package/dist/esm/vitest.config.js +6 -0
  56. package/dist/index.cjs +2 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.js +1 -0
  59. package/dist/model/devstral-language-model.d.ts +118 -0
  60. package/dist/model/devstral-language-model.test.d.ts +1 -0
  61. package/dist/protocol/connect-frame.d.ts +10 -0
  62. package/dist/protocol/connect-frame.test.d.ts +1 -0
  63. package/dist/protocol/protobuf.d.ts +11 -0
  64. package/dist/protocol/protobuf.test.d.ts +1 -0
  65. package/dist/provider.d.ts +5 -0
  66. package/dist/provider.test.d.ts +1 -0
  67. package/dist/transport/http.d.ts +22 -0
  68. package/dist/transport/http.test.d.ts +1 -0
  69. package/dist/types/index.d.ts +37 -0
  70. package/package.json +51 -0
@@ -0,0 +1,410 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const protobuf_js_1 = require("../protocol/protobuf.js");
5
+ const connect_frame_js_1 = require("../protocol/connect-frame.js");
6
+ const devstral_language_model_js_1 = require("./devstral-language-model.js");
7
+ function bufferFromBody(body) {
8
+ if (body == null) {
9
+ return Buffer.alloc(0);
10
+ }
11
+ if (typeof body === 'string') {
12
+ return Buffer.from(body, 'utf8');
13
+ }
14
+ if (body instanceof ArrayBuffer) {
15
+ return Buffer.from(body);
16
+ }
17
+ if (ArrayBuffer.isView(body)) {
18
+ return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
19
+ }
20
+ throw new Error(`Unsupported request body type: ${typeof body}`);
21
+ }
22
+ function makeJwt(exp, tag) {
23
+ const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
24
+ const payload = Buffer.from(JSON.stringify({ exp, tag })).toString('base64url');
25
+ return `${header}.${payload}.signature`;
26
+ }
27
+ function chunkBuffer(buffer, chunkSize) {
28
+ const chunks = [];
29
+ for (let offset = 0; offset < buffer.length; offset += chunkSize) {
30
+ chunks.push(Uint8Array.from(buffer.subarray(offset, offset + chunkSize)));
31
+ }
32
+ return chunks;
33
+ }
34
+ function makeChunkedBody(chunks, options = {}) {
35
+ let index = 0;
36
+ return new ReadableStream({
37
+ async pull(controller) {
38
+ if (options.signal?.aborted) {
39
+ controller.close();
40
+ return;
41
+ }
42
+ if (index >= chunks.length) {
43
+ controller.close();
44
+ return;
45
+ }
46
+ if (options.pauseAtChunkIndex === index && options.waitForChunk) {
47
+ await options.waitForChunk;
48
+ }
49
+ if ((options.delayMs ?? 0) > 0) {
50
+ await new Promise((resolve) => setTimeout(resolve, options.delayMs));
51
+ }
52
+ if (options.signal?.aborted) {
53
+ controller.close();
54
+ return;
55
+ }
56
+ const chunk = chunks[index];
57
+ if (chunk) {
58
+ controller.enqueue(chunk);
59
+ }
60
+ index += 1;
61
+ },
62
+ });
63
+ }
64
+ function waitFor(ms) {
65
+ return new Promise((resolve) => setTimeout(resolve, ms));
66
+ }
67
+ function decodeRequestPayload(body) {
68
+ // Body is now a connect frame directly (gzip is inside the frame, not outside)
69
+ const decodedFrames = (0, connect_frame_js_1.connectFrameDecode)(body);
70
+ return decodedFrames[0] ?? Buffer.alloc(0);
71
+ }
72
+ async function collectStreamParts(stream) {
73
+ const reader = stream.getReader();
74
+ const parts = [];
75
+ while (true) {
76
+ const next = await reader.read();
77
+ if (next.done) {
78
+ break;
79
+ }
80
+ parts.push(next.value);
81
+ }
82
+ return parts;
83
+ }
84
+ (0, vitest_1.describe)('DevstralLanguageModel doGenerate', () => {
85
+ (0, vitest_1.it)('generate request uses connect endpoint and connect+proto gzip headers', async () => {
86
+ const calls = [];
87
+ const requestBodies = [];
88
+ const jwt = makeJwt(4_050_000_000, 'connect-gzip');
89
+ const fakeFetch = async (input, init) => {
90
+ const url = String(input);
91
+ calls.push({ url, init });
92
+ if (url.endsWith('/GetUserJwt')) {
93
+ return new Response(Uint8Array.from(Buffer.from(jwt, 'utf8')), { status: 200 });
94
+ }
95
+ requestBodies.push(bufferFromBody(init?.body));
96
+ return new Response(Uint8Array.from((0, connect_frame_js_1.connectFrameEncode)(Buffer.from('ok', 'utf8'))), { status: 200 });
97
+ };
98
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({ apiKey: 'test-api-key', fetch: fakeFetch, baseURL: 'https://windsurf.test' });
99
+ await model.doGenerate({
100
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Use connect route.' }] }],
101
+ });
102
+ const generateCall = calls[1];
103
+ (0, vitest_1.expect)(generateCall?.url).toBe('https://windsurf.test/exa.api_server_pb.ApiServerService/GetDevstralStream');
104
+ const headers = new Headers(generateCall?.init?.headers);
105
+ (0, vitest_1.expect)(headers.get('content-type')).toBe('application/connect+proto');
106
+ (0, vitest_1.expect)(headers.get('connect-protocol-version')).toBe('1');
107
+ (0, vitest_1.expect)(headers.get('connect-timeout-ms')).toBe('30000');
108
+ (0, vitest_1.expect)(headers.get('connect-accept-encoding')).toBe('gzip');
109
+ (0, vitest_1.expect)(headers.get('connect-content-encoding')).toBe('gzip');
110
+ (0, vitest_1.expect)(headers.get('accept-encoding')).toBe('identity');
111
+ const body = requestBodies[0];
112
+ (0, vitest_1.expect)(body?.readUInt8(0)).toBe(1);
113
+ const strings = (0, protobuf_js_1.extractStrings)(decodeRequestPayload(body ?? Buffer.alloc(0)));
114
+ const combined = strings.join('\n');
115
+ (0, vitest_1.expect)(combined).toContain('Use connect route.');
116
+ });
117
+ (0, vitest_1.it)('generate request returns plain text content', async () => {
118
+ const calls = [];
119
+ const requestBodies = [];
120
+ const jwt = makeJwt(4_100_000_000, 'generate');
121
+ const fakeFetch = async (input, init) => {
122
+ const url = String(input);
123
+ calls.push({ url, init });
124
+ if (url.endsWith('/GetUserJwt')) {
125
+ return new Response(Uint8Array.from(Buffer.from(`prefix:${jwt}:suffix`, 'utf8')), { status: 200 });
126
+ }
127
+ requestBodies.push(bufferFromBody(init?.body));
128
+ return new Response(Uint8Array.from((0, connect_frame_js_1.connectFrameEncode)(Buffer.from('generated answer', 'utf8'))), {
129
+ status: 200,
130
+ });
131
+ };
132
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({ apiKey: 'test-api-key', fetch: fakeFetch, baseURL: 'https://windsurf.test' });
133
+ (0, vitest_1.expect)(model.specificationVersion).toBe('v3');
134
+ (0, vitest_1.expect)(model.supportedUrls).toEqual({});
135
+ const result = await model.doGenerate({
136
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Find auth logic.' }] }],
137
+ });
138
+ (0, vitest_1.expect)(result.content).toEqual([{ type: 'text', text: 'generated answer' }]);
139
+ (0, vitest_1.expect)(result.finishReason).toEqual({ unified: 'stop', raw: 'stop' });
140
+ (0, vitest_1.expect)(result.usage).toEqual({
141
+ inputTokens: {
142
+ total: undefined,
143
+ noCache: undefined,
144
+ cacheRead: undefined,
145
+ cacheWrite: undefined,
146
+ },
147
+ outputTokens: {
148
+ total: undefined,
149
+ text: undefined,
150
+ reasoning: undefined,
151
+ },
152
+ });
153
+ (0, vitest_1.expect)(calls).toHaveLength(2);
154
+ (0, vitest_1.expect)(calls[0]?.url).toBe('https://windsurf.test/exa.auth_pb.AuthService/GetUserJwt');
155
+ (0, vitest_1.expect)(calls[1]?.url).toBe('https://windsurf.test/exa.api_server_pb.ApiServerService/GetDevstralStream');
156
+ const strings = (0, protobuf_js_1.extractStrings)(decodeRequestPayload(requestBodies[0] ?? Buffer.alloc(0)));
157
+ const combined = strings.join('\n');
158
+ (0, vitest_1.expect)(combined).toContain('test-api-key');
159
+ (0, vitest_1.expect)(combined).toContain(jwt);
160
+ (0, vitest_1.expect)(combined).toContain('Find auth logic.');
161
+ });
162
+ (0, vitest_1.it)('generate request with tool markers returns tool-call content parts', async () => {
163
+ const requestBodies = [];
164
+ const jwt = makeJwt(4_200_000_000, 'tools');
165
+ const fakeFetch = async (input, init) => {
166
+ const url = String(input);
167
+ if (url.endsWith('/GetUserJwt')) {
168
+ return new Response(Uint8Array.from(Buffer.from(jwt, 'utf8')), { status: 200 });
169
+ }
170
+ requestBodies.push(bufferFromBody(init?.body));
171
+ const payload = Buffer.from('[TOOL_CALLS]searchRepo[ARGS]{"query":"jwt manager"}', 'utf8');
172
+ return new Response(Uint8Array.from((0, connect_frame_js_1.connectFrameEncode)(payload)), { status: 200 });
173
+ };
174
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({ apiKey: 'tools-key', fetch: fakeFetch, baseURL: 'https://windsurf.test' });
175
+ const result = await model.doGenerate({
176
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Inspect jwt manager.' }] }],
177
+ tools: {
178
+ searchRepo: {
179
+ description: 'Search repository files',
180
+ parameters: {
181
+ type: 'object',
182
+ properties: {
183
+ query: { type: 'string' },
184
+ },
185
+ required: ['query'],
186
+ },
187
+ },
188
+ },
189
+ });
190
+ (0, vitest_1.expect)(result.content).toEqual([
191
+ {
192
+ type: 'tool-call',
193
+ toolCallType: 'function',
194
+ toolCallId: 'toolcall_1',
195
+ toolName: 'searchRepo',
196
+ args: '{"query":"jwt manager"}',
197
+ },
198
+ ]);
199
+ const strings = (0, protobuf_js_1.extractStrings)(decodeRequestPayload(requestBodies[0] ?? Buffer.alloc(0)));
200
+ const combined = strings.join('\n');
201
+ (0, vitest_1.expect)(combined).toContain('searchRepo');
202
+ (0, vitest_1.expect)(combined).toContain('Search repository files');
203
+ (0, vitest_1.expect)(combined).toContain('Inspect jwt manager.');
204
+ (0, vitest_1.expect)(combined).toContain('query');
205
+ });
206
+ });
207
+ (0, vitest_1.describe)('DevstralLanguageModel doStream', () => {
208
+ (0, vitest_1.it)('stream-text resolves before full body arrives and emits parts incrementally', async () => {
209
+ const jwt = makeJwt(4_300_000_000, 'stream-text');
210
+ const firstFrame = (0, connect_frame_js_1.connectFrameEncode)(Buffer.from('hello ', 'utf8'));
211
+ const secondFrame = (0, connect_frame_js_1.connectFrameEncode)(Buffer.from('world', 'utf8'));
212
+ let releaseSecondFrame;
213
+ const waitForSecondFrame = new Promise((resolve) => {
214
+ releaseSecondFrame = () => resolve();
215
+ });
216
+ const chunks = [
217
+ Uint8Array.from(firstFrame.subarray(0, 3)),
218
+ Uint8Array.from(firstFrame.subarray(3, 8)),
219
+ Uint8Array.from(firstFrame.subarray(8)),
220
+ Uint8Array.from(secondFrame.subarray(0, 4)),
221
+ Uint8Array.from(secondFrame.subarray(4)),
222
+ ];
223
+ const calls = [];
224
+ const fakeFetch = async (input, init) => {
225
+ const url = String(input);
226
+ calls.push({ url, init });
227
+ if (url.endsWith('/GetUserJwt')) {
228
+ return new Response(Uint8Array.from(Buffer.from(jwt, 'utf8')), { status: 200 });
229
+ }
230
+ return new Response(makeChunkedBody(chunks, {
231
+ pauseAtChunkIndex: 3,
232
+ waitForChunk: waitForSecondFrame,
233
+ }), { status: 200 });
234
+ };
235
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({
236
+ apiKey: 'stream-api-key',
237
+ fetch: fakeFetch,
238
+ baseURL: 'https://windsurf.test',
239
+ });
240
+ const resultPromise = model.doStream({
241
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Stream text.' }] }],
242
+ });
243
+ try {
244
+ const earlyResolution = await Promise.race([
245
+ resultPromise.then(() => 'resolved'),
246
+ waitFor(30).then(() => 'timed-out'),
247
+ ]);
248
+ (0, vitest_1.expect)(earlyResolution).toBe('resolved');
249
+ const result = await resultPromise;
250
+ const reader = result.stream.getReader();
251
+ const firstParts = [];
252
+ while (firstParts.length < 4) {
253
+ const next = await reader.read();
254
+ if (next.done) {
255
+ break;
256
+ }
257
+ firstParts.push(next.value);
258
+ if (next.value.type === 'text-delta') {
259
+ break;
260
+ }
261
+ }
262
+ (0, vitest_1.expect)(firstParts.map((part) => part.type)).toEqual([
263
+ 'stream-start',
264
+ 'response-metadata',
265
+ 'text-start',
266
+ 'text-delta',
267
+ ]);
268
+ (0, vitest_1.expect)(firstParts[3]).toMatchObject({ type: 'text-delta', delta: 'hello ' });
269
+ releaseSecondFrame?.();
270
+ const remainingParts = [];
271
+ while (true) {
272
+ const next = await reader.read();
273
+ if (next.done) {
274
+ break;
275
+ }
276
+ remainingParts.push(next.value);
277
+ }
278
+ const parts = [...firstParts, ...remainingParts];
279
+ (0, vitest_1.expect)(parts.map((part) => part.type)).toEqual([
280
+ 'stream-start',
281
+ 'response-metadata',
282
+ 'text-start',
283
+ 'text-delta',
284
+ 'text-delta',
285
+ 'text-end',
286
+ 'finish',
287
+ ]);
288
+ (0, vitest_1.expect)(parts[0]).toEqual({ type: 'stream-start', warnings: [] });
289
+ (0, vitest_1.expect)(parts[1]).toMatchObject({ type: 'response-metadata' });
290
+ (0, vitest_1.expect)(parts[4]).toMatchObject({ type: 'text-delta', delta: 'world' });
291
+ (0, vitest_1.expect)(parts[6]).toEqual({
292
+ type: 'finish',
293
+ finishReason: { unified: 'stop', raw: 'stop' },
294
+ usage: {
295
+ inputTokens: {
296
+ total: undefined,
297
+ noCache: undefined,
298
+ cacheRead: undefined,
299
+ cacheWrite: undefined,
300
+ },
301
+ outputTokens: {
302
+ total: undefined,
303
+ text: undefined,
304
+ reasoning: undefined,
305
+ },
306
+ },
307
+ });
308
+ }
309
+ finally {
310
+ releaseSecondFrame?.();
311
+ }
312
+ (0, vitest_1.expect)(calls).toHaveLength(2);
313
+ (0, vitest_1.expect)(calls[0]?.url).toBe('https://windsurf.test/exa.auth_pb.AuthService/GetUserJwt');
314
+ (0, vitest_1.expect)(calls[1]?.url).toBe('https://windsurf.test/exa.api_server_pb.ApiServerService/GetDevstralStream');
315
+ });
316
+ (0, vitest_1.it)('stream-tool emits tool-input deltas before final tool-call and finish', async () => {
317
+ const jwt = makeJwt(4_300_000_001, 'stream-tool');
318
+ const toolPayload = Buffer.from('[TOOL_CALLS]searchRepo[ARGS]{"query":"jwt manager"}', 'utf8');
319
+ const frames = Buffer.concat([(0, connect_frame_js_1.connectFrameEncode)(toolPayload)]);
320
+ const fakeFetch = async (input) => {
321
+ const url = String(input);
322
+ if (url.endsWith('/GetUserJwt')) {
323
+ return new Response(Uint8Array.from(Buffer.from(jwt, 'utf8')), { status: 200 });
324
+ }
325
+ return new Response(makeChunkedBody(chunkBuffer(frames, 6)), { status: 200 });
326
+ };
327
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({
328
+ apiKey: 'stream-tool-key',
329
+ fetch: fakeFetch,
330
+ baseURL: 'https://windsurf.test',
331
+ });
332
+ const result = await model.doStream({
333
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Call tools.' }] }],
334
+ tools: {
335
+ searchRepo: {
336
+ description: 'Search repository files',
337
+ parameters: {
338
+ type: 'object',
339
+ properties: {
340
+ query: { type: 'string' },
341
+ },
342
+ required: ['query'],
343
+ },
344
+ },
345
+ },
346
+ });
347
+ const parts = await collectStreamParts(result.stream);
348
+ (0, vitest_1.expect)(parts.map((part) => part.type)).toEqual([
349
+ 'stream-start',
350
+ 'response-metadata',
351
+ 'tool-input-start',
352
+ 'tool-input-delta',
353
+ 'tool-input-end',
354
+ 'tool-call',
355
+ 'finish',
356
+ ]);
357
+ (0, vitest_1.expect)(parts[3]).toMatchObject({ type: 'tool-input-delta', delta: '{"query":"jwt manager"}' });
358
+ (0, vitest_1.expect)(parts[5]).toEqual({
359
+ type: 'tool-call',
360
+ toolCallType: 'function',
361
+ toolCallId: 'toolcall_1',
362
+ toolName: 'searchRepo',
363
+ args: '{"query":"jwt manager"}',
364
+ });
365
+ });
366
+ (0, vitest_1.it)('abort stops stream mid-response', async () => {
367
+ const controller = new AbortController();
368
+ const jwt = makeJwt(4_300_000_002, 'abort');
369
+ const frames = Buffer.concat([
370
+ (0, connect_frame_js_1.connectFrameEncode)(Buffer.from('first ', 'utf8')),
371
+ (0, connect_frame_js_1.connectFrameEncode)(Buffer.from('second ', 'utf8')),
372
+ (0, connect_frame_js_1.connectFrameEncode)(Buffer.from('third', 'utf8')),
373
+ ]);
374
+ const fakeFetch = async (input, init) => {
375
+ const url = String(input);
376
+ if (url.endsWith('/GetUserJwt')) {
377
+ return new Response(Uint8Array.from(Buffer.from(jwt, 'utf8')), { status: 200 });
378
+ }
379
+ return new Response(makeChunkedBody(chunkBuffer(frames, 5), { delayMs: 10, signal: init?.signal ?? undefined }), {
380
+ status: 200,
381
+ });
382
+ };
383
+ const model = new devstral_language_model_js_1.DevstralLanguageModel({
384
+ apiKey: 'stream-abort-key',
385
+ fetch: fakeFetch,
386
+ baseURL: 'https://windsurf.test',
387
+ });
388
+ const result = await model.doStream({
389
+ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Abort stream.' }] }],
390
+ abortSignal: controller.signal,
391
+ });
392
+ const reader = result.stream.getReader();
393
+ const seen = [];
394
+ while (true) {
395
+ const next = await reader.read();
396
+ if (next.done) {
397
+ break;
398
+ }
399
+ const part = next.value;
400
+ seen.push(part);
401
+ if (part.type === 'text-delta') {
402
+ controller.abort();
403
+ }
404
+ }
405
+ const types = seen.map((part) => part.type);
406
+ (0, vitest_1.expect)(types).toContain('text-delta');
407
+ (0, vitest_1.expect)(types.filter((type) => type === 'text-delta')).toHaveLength(1);
408
+ (0, vitest_1.expect)(types).not.toContain('finish');
409
+ });
410
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connectFrameEncode = connectFrameEncode;
4
+ exports.connectFrameDecode = connectFrameDecode;
5
+ const node_zlib_1 = require("node:zlib");
6
+ const FRAME_HEADER_SIZE = 5;
7
+ const FLAG_COMPRESSED = 1;
8
+ /**
9
+ * Encode a protobuf payload into a Connect-RPC frame.
10
+ *
11
+ * @param payload - The raw protobuf bytes to encode
12
+ * @param compress - Whether to gzip-compress the payload (default: true)
13
+ * When true, the payload is gzipped and flags=1 is set
14
+ * @returns Buffer containing: [flags byte][4-byte length][payload (gzipped if compress=true)]
15
+ */
16
+ function connectFrameEncode(payload, compress = true) {
17
+ const payloadBytes = compress ? (0, node_zlib_1.gzipSync)(payload) : payload;
18
+ const frame = Buffer.allocUnsafe(FRAME_HEADER_SIZE + payloadBytes.length);
19
+ frame.writeUInt8(compress ? FLAG_COMPRESSED : 0, 0);
20
+ frame.writeUInt32BE(payloadBytes.length, 1);
21
+ payloadBytes.copy(frame, FRAME_HEADER_SIZE);
22
+ return frame;
23
+ }
24
+ function connectFrameDecode(buffer) {
25
+ const decoded = [];
26
+ let offset = 0;
27
+ while (offset + FRAME_HEADER_SIZE <= buffer.length) {
28
+ const flags = buffer.readUInt8(offset);
29
+ const payloadLength = buffer.readUInt32BE(offset + 1);
30
+ const payloadStart = offset + FRAME_HEADER_SIZE;
31
+ const payloadEnd = payloadStart + payloadLength;
32
+ if (payloadEnd > buffer.length) {
33
+ break;
34
+ }
35
+ const payload = buffer.subarray(payloadStart, payloadEnd);
36
+ decoded.push(flags === FLAG_COMPRESSED ? (0, node_zlib_1.gunzipSync)(payload) : Buffer.from(payload));
37
+ offset = payloadEnd;
38
+ }
39
+ return decoded;
40
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_fs_1 = require("node:fs");
4
+ const node_path_1 = require("node:path");
5
+ const vitest_1 = require("vitest");
6
+ const connect_frame_js_1 = require("./connect-frame.js");
7
+ const fixtureSimpleFrame = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'test/fixtures/connect/frame-simple.bin'));
8
+ const fixtureGzipFrame = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'test/fixtures/connect/frame-gzip.bin'));
9
+ const fixtureMultiFrame = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'test/fixtures/connect/frame-multi.bin'));
10
+ const payloadHello = Buffer.from('CONNECT\x01hello', 'utf8');
11
+ const payloadWorld = Buffer.from('CONNECT\x02world', 'utf8');
12
+ (0, vitest_1.describe)('connectFrameEncode', () => {
13
+ (0, vitest_1.it)('roundtrip encodes and decodes uncompressed payload', () => {
14
+ const encoded = (0, connect_frame_js_1.connectFrameEncode)(payloadHello, false);
15
+ (0, vitest_1.expect)(encoded.readUInt8(0)).toBe(0);
16
+ (0, vitest_1.expect)(encoded.readUInt32BE(1)).toBe(payloadHello.length);
17
+ (0, vitest_1.expect)(encoded.subarray(5)).toEqual(payloadHello);
18
+ (0, vitest_1.expect)((0, connect_frame_js_1.connectFrameDecode)(encoded)).toEqual([payloadHello]);
19
+ });
20
+ (0, vitest_1.it)('gzip roundtrip uses compressed frame and decodes back to source payload', () => {
21
+ const encoded = (0, connect_frame_js_1.connectFrameEncode)(payloadWorld, true);
22
+ (0, vitest_1.expect)(encoded.readUInt8(0)).toBe(1);
23
+ (0, vitest_1.expect)((0, connect_frame_js_1.connectFrameDecode)(encoded)).toEqual([payloadWorld]);
24
+ });
25
+ });
26
+ (0, vitest_1.describe)('connectFrameDecode fixtures', () => {
27
+ (0, vitest_1.it)('decodes frame-simple fixture payload', () => {
28
+ (0, vitest_1.expect)((0, connect_frame_js_1.connectFrameDecode)(fixtureSimpleFrame)).toEqual([payloadHello]);
29
+ });
30
+ (0, vitest_1.it)('decodes gzip fixture payload', () => {
31
+ (0, vitest_1.expect)((0, connect_frame_js_1.connectFrameDecode)(fixtureGzipFrame)).toEqual([payloadWorld]);
32
+ });
33
+ (0, vitest_1.it)('decodes multiple concatenated frames in order', () => {
34
+ (0, vitest_1.expect)((0, connect_frame_js_1.connectFrameDecode)(fixtureMultiFrame)).toEqual([payloadHello, payloadHello]);
35
+ });
36
+ });
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProtobufEncoder = void 0;
4
+ exports.decodeVarint = decodeVarint;
5
+ exports.extractStrings = extractStrings;
6
+ function encodeVarint(value) {
7
+ if (!Number.isInteger(value) || value < 0) {
8
+ throw new Error(`Varint value must be a non-negative integer: ${value}`);
9
+ }
10
+ const bytes = [];
11
+ let remaining = value;
12
+ while (remaining >= 0x80) {
13
+ bytes.push((remaining & 0x7f) | 0x80);
14
+ remaining = Math.floor(remaining / 0x80);
15
+ }
16
+ bytes.push(remaining);
17
+ return Buffer.from(bytes);
18
+ }
19
+ function decodeUtf8IfValid(value) {
20
+ if (value.length === 0) {
21
+ return '';
22
+ }
23
+ const decoded = value.toString('utf8');
24
+ const encoded = Buffer.from(decoded, 'utf8');
25
+ if (!encoded.equals(value)) {
26
+ return null;
27
+ }
28
+ return decoded;
29
+ }
30
+ class ProtobufEncoder {
31
+ chunks = [];
32
+ writeVarint(field, value) {
33
+ this.writeTag(field, 0);
34
+ this.chunks.push(encodeVarint(value));
35
+ }
36
+ writeString(field, value) {
37
+ this.writeBytes(field, Buffer.from(value, 'utf8'));
38
+ }
39
+ writeBytes(field, data) {
40
+ this.writeTag(field, 2);
41
+ this.chunks.push(encodeVarint(data.length));
42
+ this.chunks.push(data);
43
+ }
44
+ writeMessage(field, encoder) {
45
+ this.writeBytes(field, encoder.toBuffer());
46
+ }
47
+ toBuffer() {
48
+ return Buffer.concat(this.chunks);
49
+ }
50
+ writeTag(field, wireType) {
51
+ if (!Number.isInteger(field) || field <= 0) {
52
+ throw new Error(`Field number must be a positive integer: ${field}`);
53
+ }
54
+ this.chunks.push(encodeVarint((field << 3) | wireType));
55
+ }
56
+ }
57
+ exports.ProtobufEncoder = ProtobufEncoder;
58
+ function decodeVarint(buffer, offset) {
59
+ let value = 0;
60
+ let shift = 0;
61
+ let cursor = offset;
62
+ while (cursor < buffer.length) {
63
+ const byte = buffer.readUInt8(cursor);
64
+ value += (byte & 0x7f) * 2 ** shift;
65
+ cursor += 1;
66
+ if ((byte & 0x80) === 0) {
67
+ return [value, cursor];
68
+ }
69
+ shift += 7;
70
+ }
71
+ throw new Error('Unexpected end of buffer while decoding varint');
72
+ }
73
+ function extractStrings(buffer) {
74
+ const result = [];
75
+ let offset = 0;
76
+ while (offset < buffer.length) {
77
+ let key;
78
+ [key, offset] = decodeVarint(buffer, offset);
79
+ const wireType = key & 0x07;
80
+ if (wireType === 0) {
81
+ [, offset] = decodeVarint(buffer, offset);
82
+ continue;
83
+ }
84
+ if (wireType === 1) {
85
+ offset += 8;
86
+ continue;
87
+ }
88
+ if (wireType === 2) {
89
+ let length;
90
+ [length, offset] = decodeVarint(buffer, offset);
91
+ const end = offset + length;
92
+ if (end > buffer.length) {
93
+ break;
94
+ }
95
+ const slice = buffer.subarray(offset, end);
96
+ const candidate = decodeUtf8IfValid(slice);
97
+ if (candidate !== null) {
98
+ result.push(candidate);
99
+ }
100
+ else {
101
+ const nested = extractStrings(slice);
102
+ result.push(...nested);
103
+ }
104
+ offset = end;
105
+ continue;
106
+ }
107
+ if (wireType === 5) {
108
+ offset += 4;
109
+ continue;
110
+ }
111
+ break;
112
+ }
113
+ return result;
114
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_fs_1 = require("node:fs");
4
+ const node_path_1 = require("node:path");
5
+ const vitest_1 = require("vitest");
6
+ const protobuf_js_1 = require("./protobuf.js");
7
+ const fixtureMsg1 = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'test/fixtures/protobuf/msg-1.bin'));
8
+ const fixtureMsg2 = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'test/fixtures/protobuf/msg-2.bin'));
9
+ (0, vitest_1.describe)('ProtobufEncoder', () => {
10
+ (0, vitest_1.it)('matches fixture bytes for synthetic protobuf messages', () => {
11
+ const encoder1 = new protobuf_js_1.ProtobufEncoder();
12
+ encoder1.writeVarint(1, 150);
13
+ encoder1.writeString(2, 'alpha');
14
+ const encoder2 = new protobuf_js_1.ProtobufEncoder();
15
+ encoder2.writeVarint(1, 42);
16
+ encoder2.writeString(2, 'beta');
17
+ (0, vitest_1.expect)(encoder1.toBuffer()).toEqual(fixtureMsg1);
18
+ (0, vitest_1.expect)(encoder2.toBuffer()).toEqual(fixtureMsg2);
19
+ });
20
+ (0, vitest_1.it)('writes bytes and nested messages', () => {
21
+ const nested = new protobuf_js_1.ProtobufEncoder();
22
+ nested.writeString(1, 'xy');
23
+ const encoder = new protobuf_js_1.ProtobufEncoder();
24
+ encoder.writeBytes(3, Buffer.from([0xaa, 0xbb]));
25
+ encoder.writeMessage(4, nested);
26
+ (0, vitest_1.expect)(Array.from(encoder.toBuffer())).toEqual([
27
+ 0x1a,
28
+ 0x02,
29
+ 0xaa,
30
+ 0xbb,
31
+ 0x22,
32
+ 0x04,
33
+ 0x0a,
34
+ 0x02,
35
+ 0x78,
36
+ 0x79,
37
+ ]);
38
+ });
39
+ });
40
+ (0, vitest_1.describe)('decodeVarint', () => {
41
+ (0, vitest_1.it)('decodes varint value and returns new offset', () => {
42
+ const buffer = Buffer.from([0x96, 0x01, 0x2a]);
43
+ const [first, firstOffset] = (0, protobuf_js_1.decodeVarint)(buffer, 0);
44
+ const [second, secondOffset] = (0, protobuf_js_1.decodeVarint)(buffer, firstOffset);
45
+ (0, vitest_1.expect)(first).toBe(150);
46
+ (0, vitest_1.expect)(firstOffset).toBe(2);
47
+ (0, vitest_1.expect)(second).toBe(42);
48
+ (0, vitest_1.expect)(secondOffset).toBe(3);
49
+ });
50
+ });
51
+ (0, vitest_1.describe)('extractStrings', () => {
52
+ (0, vitest_1.it)('extractStrings returns all embedded strings from fixtures', () => {
53
+ const combined = Buffer.concat([fixtureMsg1, fixtureMsg2]);
54
+ (0, vitest_1.expect)((0, protobuf_js_1.extractStrings)(fixtureMsg1)).toEqual(['alpha']);
55
+ (0, vitest_1.expect)((0, protobuf_js_1.extractStrings)(fixtureMsg2)).toEqual(['beta']);
56
+ (0, vitest_1.expect)((0, protobuf_js_1.extractStrings)(combined)).toEqual(['alpha', 'beta']);
57
+ });
58
+ });
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.windsurf = void 0;
4
+ exports.createWindsurfProvider = createWindsurfProvider;
5
+ const devstral_language_model_js_1 = require("./model/devstral-language-model.js");
6
+ function createWindsurfProvider(options = {}) {
7
+ return (modelId) => {
8
+ const opts = { ...options, modelId };
9
+ return new devstral_language_model_js_1.DevstralLanguageModel(opts);
10
+ };
11
+ }
12
+ exports.windsurf = createWindsurfProvider();
13
+ exports.default = exports.windsurf;