@bxb1337/windsurf-fast-context 1.0.9 → 1.1.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.
@@ -36,7 +36,7 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
36
36
  },
37
37
  });
38
38
  });
39
- (0, vitest_1.it)('multi-turn preserves ordering across mixed roles (V3 output shape)', () => {
39
+ (0, vitest_1.it)('multi-turn preserves ordering across mixed roles (V2 output shape)', () => {
40
40
  const prompt = [
41
41
  { role: 'system', content: 'System instruction' },
42
42
  {
@@ -161,7 +161,7 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
161
161
  },
162
162
  ]);
163
163
  });
164
- (0, vitest_1.it)('tool-result with execution-denied output includes reason', () => {
164
+ (0, vitest_1.it)('tool-result with error-text output includes denial reason', () => {
165
165
  const prompt = [
166
166
  {
167
167
  role: 'tool',
@@ -170,7 +170,7 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
170
170
  type: 'tool-result',
171
171
  toolCallId: 'call_denied',
172
172
  toolName: 'dangerousAction',
173
- output: { type: 'execution-denied', reason: 'User rejected tool execution' },
173
+ output: { type: 'error-text', value: 'User rejected tool execution' },
174
174
  },
175
175
  ],
176
176
  },
@@ -179,12 +179,12 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
179
179
  (0, vitest_1.expect)(result).toEqual([
180
180
  {
181
181
  role: 4,
182
- content: '{"type":"execution-denied","reason":"User rejected tool execution"}',
182
+ content: 'User rejected tool execution',
183
183
  metadata: { refCallId: 'call_denied' },
184
184
  },
185
185
  ]);
186
186
  });
187
- (0, vitest_1.it)('tool-result with execution-denied output handles missing reason', () => {
187
+ (0, vitest_1.it)('tool-result with error-text output handles fallback denial text', () => {
188
188
  const prompt = [
189
189
  {
190
190
  role: 'tool',
@@ -193,7 +193,7 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
193
193
  type: 'tool-result',
194
194
  toolCallId: 'call_denied_no_reason',
195
195
  toolName: 'someTool',
196
- output: { type: 'execution-denied' },
196
+ output: { type: 'error-text', value: 'Tool execution denied' },
197
197
  },
198
198
  ],
199
199
  },
@@ -202,7 +202,7 @@ const prompt_converter_js_1 = require("./prompt-converter.js");
202
202
  (0, vitest_1.expect)(result).toEqual([
203
203
  {
204
204
  role: 4,
205
- content: '{"type":"execution-denied"}',
205
+ content: 'Tool execution denied',
206
206
  metadata: { refCallId: 'call_denied_no_reason' },
207
207
  },
208
208
  ]);
@@ -21,7 +21,7 @@ const WS_LS_VER = process.env.WS_LS_VER ?? '1.9544.35';
21
21
  const SENTRY_PUBLIC_KEY = 'b813f73488da69eedec534dba1029111';
22
22
  const CONNECT_USER_AGENT = 'connect-go/1.18.1 (go1.25.5)';
23
23
  class DevstralLanguageModel {
24
- specificationVersion = 'v3';
24
+ specificationVersion = 'v2';
25
25
  provider = 'windsurf';
26
26
  modelId;
27
27
  supportedUrls = {};
@@ -58,16 +58,13 @@ class DevstralLanguageModel {
58
58
  const responseFrame = await this.transport.postUnary(`${this.baseURL}${API_SERVICE_PATH}${DEVSTRAL_STREAM_PATH}`, requestFrame, headers);
59
59
  const { payloads: responsePayloads } = (0, connect_frame_js_1.connectFrameDecode)(responseFrame);
60
60
  const payloads = responsePayloads.length > 0 ? responsePayloads : [responseFrame];
61
- const content = payloads.flatMap((payload) => toV3Content((0, response_converter_js_1.convertResponse)(payload)));
61
+ const content = payloads.flatMap((payload) => toV2Content((0, response_converter_js_1.convertResponse)(payload)));
62
62
  const unified = content.some((part) => part.type === 'tool-call')
63
63
  ? 'tool-calls'
64
64
  : 'stop';
65
65
  return {
66
66
  content,
67
- finishReason: {
68
- unified,
69
- raw: undefined,
70
- },
67
+ finishReason: unified,
71
68
  usage: emptyUsage(),
72
69
  warnings: [],
73
70
  };
@@ -125,7 +122,7 @@ class DevstralLanguageModel {
125
122
  break;
126
123
  }
127
124
  pending = frameResult.rest;
128
- const contentParts = toV3Content((0, response_converter_js_1.convertResponse)(frameResult.payload));
125
+ const contentParts = toV2Content((0, response_converter_js_1.convertResponse)(frameResult.payload));
129
126
  for (const part of contentParts) {
130
127
  if (isAborted(options.abortSignal)) {
131
128
  safeClose(controller);
@@ -175,10 +172,7 @@ class DevstralLanguageModel {
175
172
  const unified = hasToolCalls ? 'tool-calls' : 'stop';
176
173
  safeEnqueue(controller, {
177
174
  type: 'finish',
178
- finishReason: {
179
- unified,
180
- raw: undefined,
181
- },
175
+ finishReason: unified,
182
176
  usage: emptyUsage(),
183
177
  });
184
178
  safeClose(controller);
@@ -192,10 +186,7 @@ class DevstralLanguageModel {
192
186
  });
193
187
  safeEnqueue(controller, {
194
188
  type: 'finish',
195
- finishReason: {
196
- unified: 'error',
197
- raw: undefined,
198
- },
189
+ finishReason: 'error',
199
190
  usage: emptyUsage(),
200
191
  });
201
192
  }
@@ -255,20 +246,12 @@ function isAborted(signal) {
255
246
  }
256
247
  function emptyUsage() {
257
248
  return {
258
- inputTokens: {
259
- total: undefined,
260
- noCache: undefined,
261
- cacheRead: undefined,
262
- cacheWrite: undefined,
263
- },
264
- outputTokens: {
265
- total: undefined,
266
- text: undefined,
267
- reasoning: undefined,
268
- },
249
+ inputTokens: undefined,
250
+ outputTokens: undefined,
251
+ totalTokens: undefined,
269
252
  };
270
253
  }
271
- function toV3Content(parts) {
254
+ function toV2Content(parts) {
272
255
  return parts.map((part) => {
273
256
  if (part.type !== 'tool-call') {
274
257
  return part;
@@ -133,25 +133,17 @@ async function collectStreamParts(stream) {
133
133
  });
134
134
  };
135
135
  const model = new devstral_language_model_js_1.DevstralLanguageModel({ apiKey: 'test-api-key', fetch: fakeFetch, baseURL: 'https://windsurf.test' });
136
- (0, vitest_1.expect)(model.specificationVersion).toBe('v3');
136
+ (0, vitest_1.expect)(model.specificationVersion).toBe('v2');
137
137
  (0, vitest_1.expect)(model.supportedUrls).toEqual({});
138
138
  const result = await model.doGenerate({
139
139
  prompt: [{ role: 'user', content: [{ type: 'text', text: 'Find auth logic.' }] }],
140
140
  });
141
141
  (0, vitest_1.expect)(result.content).toEqual([{ type: 'text', text: 'generated answer' }]);
142
- (0, vitest_1.expect)(result.finishReason).toEqual({ unified: 'stop', raw: undefined });
142
+ (0, vitest_1.expect)(result.finishReason).toBe('stop');
143
143
  (0, vitest_1.expect)(result.usage).toEqual({
144
- inputTokens: {
145
- total: undefined,
146
- noCache: undefined,
147
- cacheRead: undefined,
148
- cacheWrite: undefined,
149
- },
150
- outputTokens: {
151
- total: undefined,
152
- text: undefined,
153
- reasoning: undefined,
154
- },
144
+ inputTokens: undefined,
145
+ outputTokens: undefined,
146
+ totalTokens: undefined,
155
147
  });
156
148
  (0, vitest_1.expect)(calls).toHaveLength(2);
157
149
  (0, vitest_1.expect)(calls[0]?.url).toBe('https://windsurf.test/exa.auth_pb.AuthService/GetUserJwt');
@@ -200,7 +192,7 @@ async function collectStreamParts(stream) {
200
192
  input: '{"query":"jwt manager"}',
201
193
  },
202
194
  ]);
203
- (0, vitest_1.expect)(result.finishReason).toEqual({ unified: 'tool-calls', raw: undefined });
195
+ (0, vitest_1.expect)(result.finishReason).toBe('tool-calls');
204
196
  const strings = (0, protobuf_js_1.extractStrings)(decodeRequestPayload(requestBodies[0] ?? Buffer.alloc(0)));
205
197
  const toolsPayload = extractToolsPayload(strings);
206
198
  (0, vitest_1.expect)(toolsPayload).toBeDefined();
@@ -250,7 +242,7 @@ async function collectStreamParts(stream) {
250
242
  },
251
243
  },
252
244
  {
253
- type: 'provider',
245
+ type: 'provider-defined',
254
246
  id: 'windsurf.restricted_exec',
255
247
  name: 'restricted_exec',
256
248
  args: { mode: 'read-only' },
@@ -370,22 +362,11 @@ async function collectStreamParts(stream) {
370
362
  (0, vitest_1.expect)(parts[4]).toMatchObject({ type: 'text-delta', delta: 'world' });
371
363
  (0, vitest_1.expect)(parts[6]).toEqual({
372
364
  type: 'finish',
373
- finishReason: {
374
- unified: 'stop',
375
- raw: undefined,
376
- },
365
+ finishReason: 'stop',
377
366
  usage: {
378
- inputTokens: {
379
- total: undefined,
380
- noCache: undefined,
381
- cacheRead: undefined,
382
- cacheWrite: undefined,
383
- },
384
- outputTokens: {
385
- total: undefined,
386
- text: undefined,
387
- reasoning: undefined,
388
- },
367
+ inputTokens: undefined,
368
+ outputTokens: undefined,
369
+ totalTokens: undefined,
389
370
  },
390
371
  });
391
372
  }
@@ -448,22 +429,11 @@ async function collectStreamParts(stream) {
448
429
  });
449
430
  (0, vitest_1.expect)(parts[6]).toEqual({
450
431
  type: 'finish',
451
- finishReason: {
452
- unified: 'tool-calls',
453
- raw: undefined,
454
- },
432
+ finishReason: 'tool-calls',
455
433
  usage: {
456
- inputTokens: {
457
- total: undefined,
458
- noCache: undefined,
459
- cacheRead: undefined,
460
- cacheWrite: undefined,
461
- },
462
- outputTokens: {
463
- total: undefined,
464
- text: undefined,
465
- reasoning: undefined,
466
- },
434
+ inputTokens: undefined,
435
+ outputTokens: undefined,
436
+ totalTokens: undefined,
467
437
  },
468
438
  });
469
439
  });
@@ -1,3 +1,3 @@
1
- import type { LanguageModelV3Prompt } from '@ai-sdk/provider';
1
+ import type { LanguageModelV2Prompt } from '@ai-sdk/provider';
2
2
  import type { DevstralMessage } from '../types/index.js';
3
- export declare function convertPrompt(prompt: LanguageModelV3Prompt): DevstralMessage[];
3
+ export declare function convertPrompt(prompt: LanguageModelV2Prompt): DevstralMessage[];
@@ -8,5 +8,5 @@ export interface ToolCallPart {
8
8
  toolName: string;
9
9
  input: unknown;
10
10
  }
11
- export type LanguageModelV3Content = TextPart | ToolCallPart;
12
- export declare function convertResponse(buffer: Buffer): LanguageModelV3Content[];
11
+ export type LanguageModelV2Content = TextPart | ToolCallPart;
12
+ export declare function convertResponse(buffer: Buffer): LanguageModelV2Content[];
@@ -34,7 +34,7 @@ describe('convertPrompt', () => {
34
34
  },
35
35
  });
36
36
  });
37
- it('multi-turn preserves ordering across mixed roles (V3 output shape)', () => {
37
+ it('multi-turn preserves ordering across mixed roles (V2 output shape)', () => {
38
38
  const prompt = [
39
39
  { role: 'system', content: 'System instruction' },
40
40
  {
@@ -159,7 +159,7 @@ describe('convertPrompt', () => {
159
159
  },
160
160
  ]);
161
161
  });
162
- it('tool-result with execution-denied output includes reason', () => {
162
+ it('tool-result with error-text output includes denial reason', () => {
163
163
  const prompt = [
164
164
  {
165
165
  role: 'tool',
@@ -168,7 +168,7 @@ describe('convertPrompt', () => {
168
168
  type: 'tool-result',
169
169
  toolCallId: 'call_denied',
170
170
  toolName: 'dangerousAction',
171
- output: { type: 'execution-denied', reason: 'User rejected tool execution' },
171
+ output: { type: 'error-text', value: 'User rejected tool execution' },
172
172
  },
173
173
  ],
174
174
  },
@@ -177,12 +177,12 @@ describe('convertPrompt', () => {
177
177
  expect(result).toEqual([
178
178
  {
179
179
  role: 4,
180
- content: '{"type":"execution-denied","reason":"User rejected tool execution"}',
180
+ content: 'User rejected tool execution',
181
181
  metadata: { refCallId: 'call_denied' },
182
182
  },
183
183
  ]);
184
184
  });
185
- it('tool-result with execution-denied output handles missing reason', () => {
185
+ it('tool-result with error-text output handles fallback denial text', () => {
186
186
  const prompt = [
187
187
  {
188
188
  role: 'tool',
@@ -191,7 +191,7 @@ describe('convertPrompt', () => {
191
191
  type: 'tool-result',
192
192
  toolCallId: 'call_denied_no_reason',
193
193
  toolName: 'someTool',
194
- output: { type: 'execution-denied' },
194
+ output: { type: 'error-text', value: 'Tool execution denied' },
195
195
  },
196
196
  ],
197
197
  },
@@ -200,7 +200,7 @@ describe('convertPrompt', () => {
200
200
  expect(result).toEqual([
201
201
  {
202
202
  role: 4,
203
- content: '{"type":"execution-denied"}',
203
+ content: 'Tool execution denied',
204
204
  metadata: { refCallId: 'call_denied_no_reason' },
205
205
  },
206
206
  ]);
@@ -18,7 +18,7 @@ const WS_LS_VER = process.env.WS_LS_VER ?? '1.9544.35';
18
18
  const SENTRY_PUBLIC_KEY = 'b813f73488da69eedec534dba1029111';
19
19
  const CONNECT_USER_AGENT = 'connect-go/1.18.1 (go1.25.5)';
20
20
  export class DevstralLanguageModel {
21
- specificationVersion = 'v3';
21
+ specificationVersion = 'v2';
22
22
  provider = 'windsurf';
23
23
  modelId;
24
24
  supportedUrls = {};
@@ -55,16 +55,13 @@ export class DevstralLanguageModel {
55
55
  const responseFrame = await this.transport.postUnary(`${this.baseURL}${API_SERVICE_PATH}${DEVSTRAL_STREAM_PATH}`, requestFrame, headers);
56
56
  const { payloads: responsePayloads } = connectFrameDecode(responseFrame);
57
57
  const payloads = responsePayloads.length > 0 ? responsePayloads : [responseFrame];
58
- const content = payloads.flatMap((payload) => toV3Content(convertResponse(payload)));
58
+ const content = payloads.flatMap((payload) => toV2Content(convertResponse(payload)));
59
59
  const unified = content.some((part) => part.type === 'tool-call')
60
60
  ? 'tool-calls'
61
61
  : 'stop';
62
62
  return {
63
63
  content,
64
- finishReason: {
65
- unified,
66
- raw: undefined,
67
- },
64
+ finishReason: unified,
68
65
  usage: emptyUsage(),
69
66
  warnings: [],
70
67
  };
@@ -122,7 +119,7 @@ export class DevstralLanguageModel {
122
119
  break;
123
120
  }
124
121
  pending = frameResult.rest;
125
- const contentParts = toV3Content(convertResponse(frameResult.payload));
122
+ const contentParts = toV2Content(convertResponse(frameResult.payload));
126
123
  for (const part of contentParts) {
127
124
  if (isAborted(options.abortSignal)) {
128
125
  safeClose(controller);
@@ -172,10 +169,7 @@ export class DevstralLanguageModel {
172
169
  const unified = hasToolCalls ? 'tool-calls' : 'stop';
173
170
  safeEnqueue(controller, {
174
171
  type: 'finish',
175
- finishReason: {
176
- unified,
177
- raw: undefined,
178
- },
172
+ finishReason: unified,
179
173
  usage: emptyUsage(),
180
174
  });
181
175
  safeClose(controller);
@@ -189,10 +183,7 @@ export class DevstralLanguageModel {
189
183
  });
190
184
  safeEnqueue(controller, {
191
185
  type: 'finish',
192
- finishReason: {
193
- unified: 'error',
194
- raw: undefined,
195
- },
186
+ finishReason: 'error',
196
187
  usage: emptyUsage(),
197
188
  });
198
189
  }
@@ -251,20 +242,12 @@ function isAborted(signal) {
251
242
  }
252
243
  function emptyUsage() {
253
244
  return {
254
- inputTokens: {
255
- total: undefined,
256
- noCache: undefined,
257
- cacheRead: undefined,
258
- cacheWrite: undefined,
259
- },
260
- outputTokens: {
261
- total: undefined,
262
- text: undefined,
263
- reasoning: undefined,
264
- },
245
+ inputTokens: undefined,
246
+ outputTokens: undefined,
247
+ totalTokens: undefined,
265
248
  };
266
249
  }
267
- function toV3Content(parts) {
250
+ function toV2Content(parts) {
268
251
  return parts.map((part) => {
269
252
  if (part.type !== 'tool-call') {
270
253
  return part;
@@ -131,25 +131,17 @@ describe('DevstralLanguageModel doGenerate', () => {
131
131
  });
132
132
  };
133
133
  const model = new DevstralLanguageModel({ apiKey: 'test-api-key', fetch: fakeFetch, baseURL: 'https://windsurf.test' });
134
- expect(model.specificationVersion).toBe('v3');
134
+ expect(model.specificationVersion).toBe('v2');
135
135
  expect(model.supportedUrls).toEqual({});
136
136
  const result = await model.doGenerate({
137
137
  prompt: [{ role: 'user', content: [{ type: 'text', text: 'Find auth logic.' }] }],
138
138
  });
139
139
  expect(result.content).toEqual([{ type: 'text', text: 'generated answer' }]);
140
- expect(result.finishReason).toEqual({ unified: 'stop', raw: undefined });
140
+ expect(result.finishReason).toBe('stop');
141
141
  expect(result.usage).toEqual({
142
- inputTokens: {
143
- total: undefined,
144
- noCache: undefined,
145
- cacheRead: undefined,
146
- cacheWrite: undefined,
147
- },
148
- outputTokens: {
149
- total: undefined,
150
- text: undefined,
151
- reasoning: undefined,
152
- },
142
+ inputTokens: undefined,
143
+ outputTokens: undefined,
144
+ totalTokens: undefined,
153
145
  });
154
146
  expect(calls).toHaveLength(2);
155
147
  expect(calls[0]?.url).toBe('https://windsurf.test/exa.auth_pb.AuthService/GetUserJwt');
@@ -198,7 +190,7 @@ describe('DevstralLanguageModel doGenerate', () => {
198
190
  input: '{"query":"jwt manager"}',
199
191
  },
200
192
  ]);
201
- expect(result.finishReason).toEqual({ unified: 'tool-calls', raw: undefined });
193
+ expect(result.finishReason).toBe('tool-calls');
202
194
  const strings = extractStrings(decodeRequestPayload(requestBodies[0] ?? Buffer.alloc(0)));
203
195
  const toolsPayload = extractToolsPayload(strings);
204
196
  expect(toolsPayload).toBeDefined();
@@ -248,7 +240,7 @@ describe('DevstralLanguageModel doGenerate', () => {
248
240
  },
249
241
  },
250
242
  {
251
- type: 'provider',
243
+ type: 'provider-defined',
252
244
  id: 'windsurf.restricted_exec',
253
245
  name: 'restricted_exec',
254
246
  args: { mode: 'read-only' },
@@ -368,22 +360,11 @@ describe('DevstralLanguageModel doStream', () => {
368
360
  expect(parts[4]).toMatchObject({ type: 'text-delta', delta: 'world' });
369
361
  expect(parts[6]).toEqual({
370
362
  type: 'finish',
371
- finishReason: {
372
- unified: 'stop',
373
- raw: undefined,
374
- },
363
+ finishReason: 'stop',
375
364
  usage: {
376
- inputTokens: {
377
- total: undefined,
378
- noCache: undefined,
379
- cacheRead: undefined,
380
- cacheWrite: undefined,
381
- },
382
- outputTokens: {
383
- total: undefined,
384
- text: undefined,
385
- reasoning: undefined,
386
- },
365
+ inputTokens: undefined,
366
+ outputTokens: undefined,
367
+ totalTokens: undefined,
387
368
  },
388
369
  });
389
370
  }
@@ -446,22 +427,11 @@ describe('DevstralLanguageModel doStream', () => {
446
427
  });
447
428
  expect(parts[6]).toEqual({
448
429
  type: 'finish',
449
- finishReason: {
450
- unified: 'tool-calls',
451
- raw: undefined,
452
- },
430
+ finishReason: 'tool-calls',
453
431
  usage: {
454
- inputTokens: {
455
- total: undefined,
456
- noCache: undefined,
457
- cacheRead: undefined,
458
- cacheWrite: undefined,
459
- },
460
- outputTokens: {
461
- total: undefined,
462
- text: undefined,
463
- reasoning: undefined,
464
- },
432
+ inputTokens: undefined,
433
+ outputTokens: undefined,
434
+ totalTokens: undefined,
465
435
  },
466
436
  });
467
437
  });
@@ -1,4 +1,4 @@
1
- import type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult } from '@ai-sdk/provider';
1
+ import type { LanguageModelV2, LanguageModelV2CallOptions } from '@ai-sdk/provider';
2
2
  import { JwtManager } from '../auth/jwt-manager.js';
3
3
  import { DevstralTransport } from '../transport/http.js';
4
4
  import type { WindsurfProviderOptions } from '../types/index.js';
@@ -7,8 +7,10 @@ export interface DevstralLanguageModelOptions extends WindsurfProviderOptions {
7
7
  transport?: DevstralTransport;
8
8
  jwtManager?: JwtManager;
9
9
  }
10
- export declare class DevstralLanguageModel implements LanguageModelV3 {
11
- readonly specificationVersion = "v3";
10
+ type LanguageModelV2GenerateResult = Awaited<ReturnType<LanguageModelV2['doGenerate']>>;
11
+ type LanguageModelV2StreamResult = Awaited<ReturnType<LanguageModelV2['doStream']>>;
12
+ export declare class DevstralLanguageModel implements LanguageModelV2 {
13
+ readonly specificationVersion = "v2";
12
14
  readonly provider = "windsurf";
13
15
  readonly modelId: string;
14
16
  readonly supportedUrls: Record<string, RegExp[]>;
@@ -18,6 +20,7 @@ export declare class DevstralLanguageModel implements LanguageModelV3 {
18
20
  private readonly transport;
19
21
  private readonly jwtManager;
20
22
  constructor(options?: DevstralLanguageModelOptions);
21
- doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
22
- doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
23
+ doGenerate(options: LanguageModelV2CallOptions): Promise<LanguageModelV2GenerateResult>;
24
+ doStream(options: LanguageModelV2CallOptions): Promise<LanguageModelV2StreamResult>;
23
25
  }
26
+ export {};
@@ -6,7 +6,7 @@ export interface WindsurfProviderOptions {
6
6
  generateId?: () => string;
7
7
  }
8
8
  /**
9
- * Windsurf provider interface extending AI SDK V3 ProviderV3 pattern.
9
+ * Windsurf provider interface extending AI SDK V2 ProviderV2 pattern.
10
10
  * The provider is callable as a function and has a languageModel method.
11
11
  */
12
12
  export interface WindsurfProvider {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bxb1337/windsurf-fast-context",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "description": "AI SDK V3 provider for Windsurf's Devstral code search API",
5
5
  "type": "module",
6
6
  "scripts": {