@juspay/neurolink 1.0.0 → 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.
@@ -1,6 +1,6 @@
1
1
  import type { ZodType, ZodTypeDef } from 'zod';
2
2
  import { type StreamTextResult, type ToolSet, type Schema, type GenerateTextResult } from 'ai';
3
- import type { AIProvider } from '../core/types.js';
3
+ import type { AIProvider, TextGenerationOptions, StreamTextOptions } from '../core/types.js';
4
4
  export declare class GoogleVertexAI implements AIProvider {
5
5
  private modelName;
6
6
  /**
@@ -19,12 +19,12 @@ export declare class GoogleVertexAI implements AIProvider {
19
19
  * @param analysisSchema - Optional Zod schema or Schema object for output validation
20
20
  * @returns Promise resolving to StreamTextResult or null if operation fails
21
21
  */
22
- streamText(prompt: string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamTextResult<ToolSet, unknown> | null>;
22
+ streamText(optionsOrPrompt: StreamTextOptions | string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamTextResult<ToolSet, unknown> | null>;
23
23
  /**
24
24
  * Processes text using non-streaming approach with optional schema validation
25
25
  * @param prompt - The input text prompt to analyze
26
26
  * @param analysisSchema - Optional Zod schema or Schema object for output validation
27
27
  * @returns Promise resolving to GenerateTextResult or null if operation fails
28
28
  */
29
- generateText(prompt: string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<GenerateTextResult<ToolSet, unknown> | null>;
29
+ generateText(optionsOrPrompt: TextGenerationOptions | string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<GenerateTextResult<ToolSet, unknown> | null>;
30
30
  }
@@ -40,37 +40,143 @@ const getGCPVertexBreezeLocation = () => {
40
40
  const getGoogleApplicationCredentials = () => {
41
41
  return process.env.GOOGLE_APPLICATION_CREDENTIALS;
42
42
  };
43
+ const getGoogleServiceAccountKey = () => {
44
+ return process.env.GOOGLE_SERVICE_ACCOUNT_KEY;
45
+ };
46
+ const getGoogleClientEmail = () => {
47
+ return process.env.GOOGLE_AUTH_CLIENT_EMAIL;
48
+ };
49
+ const getGooglePrivateKey = () => {
50
+ return process.env.GOOGLE_AUTH_PRIVATE_KEY;
51
+ };
43
52
  const getVertexModelId = () => {
44
53
  return process.env.VERTEX_MODEL_ID || 'claude-sonnet-4@20250514';
45
54
  };
46
55
  const hasPrincipalAccountAuth = () => {
47
56
  return !!getGoogleApplicationCredentials();
48
57
  };
49
- // Vertex AI setup with Principal Account Authentication support
50
- const createVertexSettings = () => {
58
+ const hasServiceAccountKeyAuth = () => {
59
+ return !!getGoogleServiceAccountKey();
60
+ };
61
+ const hasServiceAccountEnvAuth = () => {
62
+ return !!(getGoogleClientEmail() && getGooglePrivateKey());
63
+ };
64
+ const hasValidAuth = () => {
65
+ return hasPrincipalAccountAuth() || hasServiceAccountKeyAuth() || hasServiceAccountEnvAuth();
66
+ };
67
+ // Setup environment for Google authentication
68
+ const setupGoogleAuth = async () => {
69
+ const functionTag = 'setupGoogleAuth';
70
+ // Method 2: Service Account Key (JSON string) - Create temporary file
71
+ if (hasServiceAccountKeyAuth() && !hasPrincipalAccountAuth()) {
72
+ const serviceAccountKey = getGoogleServiceAccountKey();
73
+ console.log(`[${functionTag}] Service account key auth (JSON string)`, {
74
+ hasServiceAccountKey: !!serviceAccountKey,
75
+ authMethod: 'service_account_key'
76
+ });
77
+ try {
78
+ // Parse to validate JSON
79
+ JSON.parse(serviceAccountKey);
80
+ // Write to temporary file and set environment variable using dynamic imports
81
+ const { writeFileSync } = await import('fs');
82
+ const { join } = await import('path');
83
+ const { tmpdir } = await import('os');
84
+ const tempFile = join(tmpdir(), `gcp-credentials-${Date.now()}.json`);
85
+ writeFileSync(tempFile, serviceAccountKey);
86
+ process.env.GOOGLE_APPLICATION_CREDENTIALS = tempFile;
87
+ console.log(`[${functionTag}] Created temporary credentials file`, {
88
+ tempFile: '[CREATED]',
89
+ authMethod: 'service_account_key_temp_file'
90
+ });
91
+ }
92
+ catch (error) {
93
+ console.error(`[${functionTag}] Failed to parse service account key`, {
94
+ error: error instanceof Error ? error.message : String(error)
95
+ });
96
+ throw new Error('Invalid GOOGLE_SERVICE_ACCOUNT_KEY format. Must be valid JSON.');
97
+ }
98
+ }
99
+ // Method 3: Service Account Environment Variables - Set as individual env vars
100
+ if (hasServiceAccountEnvAuth() && !hasPrincipalAccountAuth() && !hasServiceAccountKeyAuth()) {
101
+ const clientEmail = getGoogleClientEmail();
102
+ const privateKey = getGooglePrivateKey();
103
+ console.log(`[${functionTag}] Service account env auth (separate variables)`, {
104
+ hasClientEmail: !!clientEmail,
105
+ hasPrivateKey: !!privateKey,
106
+ authMethod: 'service_account_env'
107
+ });
108
+ // Create service account object and write to temporary file
109
+ const serviceAccount = {
110
+ type: 'service_account',
111
+ project_id: getGCPVertexBreezeProjectId(),
112
+ client_email: clientEmail,
113
+ private_key: privateKey.replace(/\\n/g, '\n'),
114
+ auth_uri: 'https://accounts.google.com/o/oauth2/auth',
115
+ token_uri: 'https://oauth2.googleapis.com/token'
116
+ };
117
+ try {
118
+ // Use dynamic imports for ESM compatibility
119
+ const { writeFileSync } = await import('fs');
120
+ const { join } = await import('path');
121
+ const { tmpdir } = await import('os');
122
+ const tempFile = join(tmpdir(), `gcp-credentials-env-${Date.now()}.json`);
123
+ writeFileSync(tempFile, JSON.stringify(serviceAccount, null, 2));
124
+ process.env.GOOGLE_APPLICATION_CREDENTIALS = tempFile;
125
+ console.log(`[${functionTag}] Created temporary credentials file from env vars`, {
126
+ tempFile: '[CREATED]',
127
+ authMethod: 'service_account_env_temp_file'
128
+ });
129
+ }
130
+ catch (error) {
131
+ console.error(`[${functionTag}] Failed to create service account file from env vars`, {
132
+ error: error instanceof Error ? error.message : String(error)
133
+ });
134
+ throw new Error('Failed to create temporary service account file from environment variables.');
135
+ }
136
+ }
137
+ };
138
+ // Vertex AI setup with multiple authentication support
139
+ const createVertexSettings = async () => {
51
140
  const functionTag = 'createVertexSettings';
141
+ // Setup authentication first
142
+ await setupGoogleAuth();
52
143
  const baseSettings = {
53
144
  project: getGCPVertexBreezeProjectId(),
54
145
  location: getGCPVertexBreezeLocation()
55
146
  };
56
- // Check for principal account authentication first (recommended for production)
147
+ // Method 1: Principal Account Authentication (file path) - Recommended for production
57
148
  if (hasPrincipalAccountAuth()) {
58
149
  const credentialsPath = getGoogleApplicationCredentials();
59
- console.log(`[${functionTag}] Principal account auth`, {
150
+ console.log(`[${functionTag}] Principal account auth (file path)`, {
60
151
  credentialsPath: credentialsPath ? '[PROVIDED]' : '[NOT_PROVIDED]',
61
- authMethod: 'principal_account'
152
+ authMethod: 'principal_account_file'
153
+ });
154
+ return baseSettings;
155
+ }
156
+ // Method 2 & 3: Other methods now set GOOGLE_APPLICATION_CREDENTIALS in setupGoogleAuth()
157
+ if (hasServiceAccountKeyAuth() || hasServiceAccountEnvAuth()) {
158
+ console.log(`[${functionTag}] Alternative auth method configured`, {
159
+ authMethod: hasServiceAccountKeyAuth() ? 'service_account_key' : 'service_account_env',
160
+ credentialsSet: !!process.env.GOOGLE_APPLICATION_CREDENTIALS
62
161
  });
63
- // For principal account auth, we don't need to provide explicit credentials
64
- // The google-auth-library will use GOOGLE_APPLICATION_CREDENTIALS automatically
65
162
  return baseSettings;
66
163
  }
67
- // Log warning if no valid authentication is available
68
- console.warn(`[${functionTag}] No valid auth`, {
164
+ // No valid authentication found
165
+ console.error(`[${functionTag}] No valid authentication method found`, {
69
166
  authMethod: 'none',
70
- hasPrincipalAccount: hasPrincipalAccountAuth()
167
+ hasPrincipalAccount: hasPrincipalAccountAuth(),
168
+ hasServiceAccountKey: hasServiceAccountKeyAuth(),
169
+ hasServiceAccountEnv: hasServiceAccountEnvAuth(),
170
+ availableMethods: [
171
+ 'GOOGLE_APPLICATION_CREDENTIALS (file path)',
172
+ 'GOOGLE_SERVICE_ACCOUNT_KEY (JSON string)',
173
+ 'GOOGLE_AUTH_CLIENT_EMAIL + GOOGLE_AUTH_PRIVATE_KEY (env vars)'
174
+ ]
71
175
  });
72
- // Return base settings and let it fail if no auth is available
73
- return baseSettings;
176
+ throw new Error('No valid Google Vertex AI authentication found. Please provide one of:\n' +
177
+ '1. GOOGLE_APPLICATION_CREDENTIALS (path to service account file)\n' +
178
+ '2. GOOGLE_SERVICE_ACCOUNT_KEY (JSON string of service account)\n' +
179
+ '3. GOOGLE_AUTH_CLIENT_EMAIL + GOOGLE_AUTH_PRIVATE_KEY (environment variables)');
74
180
  };
75
181
  // Helper function to determine if a model is an Anthropic model
76
182
  const isAnthropicModel = (modelName) => {
@@ -79,9 +185,10 @@ const isAnthropicModel = (modelName) => {
79
185
  };
80
186
  // Lazy initialization cache
81
187
  let _vertex = null;
82
- function getVertexInstance() {
188
+ async function getVertexInstance() {
83
189
  if (!_vertex) {
84
- _vertex = createVertex(createVertexSettings());
190
+ const settings = await createVertexSettings();
191
+ _vertex = createVertex(settings);
85
192
  }
86
193
  return _vertex;
87
194
  }
@@ -149,10 +256,11 @@ export class GoogleVertexAI {
149
256
  throw new Error(`Anthropic model "${this.modelName}" requested but @ai-sdk/google-vertex/anthropic is not available. ` +
150
257
  'Please install @ai-sdk/google-vertex ^2.2.0 or use a Google model instead.');
151
258
  }
152
- const vertexAnthropic = createVertexAnthropic(createVertexSettings());
259
+ const settings = await createVertexSettings();
260
+ const vertexAnthropic = createVertexAnthropic(settings);
153
261
  return vertexAnthropic(this.modelName);
154
262
  }
155
- const vertex = getVertexInstance();
263
+ const vertex = await getVertexInstance();
156
264
  return vertex(this.modelName);
157
265
  }
158
266
  /**
@@ -161,23 +269,34 @@ export class GoogleVertexAI {
161
269
  * @param analysisSchema - Optional Zod schema or Schema object for output validation
162
270
  * @returns Promise resolving to StreamTextResult or null if operation fails
163
271
  */
164
- async streamText(prompt, analysisSchema) {
272
+ async streamText(optionsOrPrompt, analysisSchema) {
165
273
  const functionTag = 'GoogleVertexAI.streamText';
166
274
  const provider = 'vertex';
167
275
  let chunkCount = 0;
168
276
  try {
277
+ // Parse parameters - support both string and options object
278
+ const options = typeof optionsOrPrompt === 'string'
279
+ ? { prompt: optionsOrPrompt }
280
+ : optionsOrPrompt;
281
+ const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options;
282
+ // Use schema from options or fallback parameter
283
+ const finalSchema = schema || analysisSchema;
169
284
  console.log(`[${functionTag}] Stream request started`, {
170
285
  provider,
171
286
  modelName: this.modelName,
172
287
  isAnthropic: isAnthropicModel(this.modelName),
173
288
  promptLength: prompt.length,
174
- hasSchema: !!analysisSchema
289
+ temperature,
290
+ maxTokens,
291
+ hasSchema: !!finalSchema
175
292
  });
176
293
  const model = await this.getModel();
177
294
  const streamOptions = {
178
295
  model: model,
179
296
  prompt: prompt,
180
- system: DEFAULT_SYSTEM_CONTEXT.systemPrompt,
297
+ system: systemPrompt,
298
+ temperature,
299
+ maxTokens,
181
300
  onError: (event) => {
182
301
  const error = event.error;
183
302
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -236,37 +355,43 @@ export class GoogleVertexAI {
236
355
  * @param analysisSchema - Optional Zod schema or Schema object for output validation
237
356
  * @returns Promise resolving to GenerateTextResult or null if operation fails
238
357
  */
239
- async generateText(prompt, analysisSchema) {
358
+ async generateText(optionsOrPrompt, analysisSchema) {
240
359
  const functionTag = 'GoogleVertexAI.generateText';
241
360
  const provider = 'vertex';
242
361
  try {
362
+ // Parse parameters - support both string and options object
363
+ const options = typeof optionsOrPrompt === 'string'
364
+ ? { prompt: optionsOrPrompt }
365
+ : optionsOrPrompt;
366
+ const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options;
367
+ // Use schema from options or fallback parameter
368
+ const finalSchema = schema || analysisSchema;
243
369
  console.log(`[${functionTag}] Generate request started`, {
244
370
  provider,
245
371
  modelName: this.modelName,
246
372
  isAnthropic: isAnthropicModel(this.modelName),
247
- promptLength: prompt.length
373
+ promptLength: prompt.length,
374
+ temperature,
375
+ maxTokens
248
376
  });
249
377
  const model = await this.getModel();
250
378
  const generateOptions = {
251
379
  model: model,
252
380
  prompt: prompt,
253
- system: DEFAULT_SYSTEM_CONTEXT.systemPrompt
381
+ system: systemPrompt,
382
+ temperature,
383
+ maxTokens
254
384
  };
255
- if (analysisSchema) {
256
- generateOptions.experimental_output = Output.object({ schema: analysisSchema });
385
+ if (finalSchema) {
386
+ generateOptions.experimental_output = Output.object({ schema: finalSchema });
257
387
  }
258
- console.log(`[${functionTag}] Generate text started`, {
259
- provider,
260
- modelName: this.modelName,
261
- isAnthropic: isAnthropicModel(this.modelName),
262
- promptLength: prompt.length
263
- });
264
388
  const result = await generateText(generateOptions);
265
389
  console.log(`[${functionTag}] Generate text completed`, {
266
390
  provider,
267
391
  modelName: this.modelName,
268
392
  usage: result.usage,
269
- finishReason: result.finishReason
393
+ finishReason: result.finishReason,
394
+ responseLength: result.text?.length || 0
270
395
  });
271
396
  return result;
272
397
  }
@@ -1,10 +1,10 @@
1
1
  import type { ZodType, ZodTypeDef } from 'zod';
2
2
  import { type StreamTextResult, type ToolSet, type Schema, type GenerateTextResult } from 'ai';
3
- import type { AIProvider } from '../core/types.js';
3
+ import type { AIProvider, TextGenerationOptions, StreamTextOptions } from '../core/types.js';
4
4
  export declare class OpenAI implements AIProvider {
5
5
  private modelName;
6
6
  private model;
7
7
  constructor(modelName?: string | null);
8
- streamText(prompt: string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamTextResult<ToolSet, unknown> | null>;
9
- generateText(prompt: string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<GenerateTextResult<ToolSet, unknown> | null>;
8
+ streamText(optionsOrPrompt: StreamTextOptions | string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamTextResult<ToolSet, unknown> | null>;
9
+ generateText(optionsOrPrompt: TextGenerationOptions | string, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<GenerateTextResult<ToolSet, unknown> | null>;
10
10
  }
@@ -41,15 +41,31 @@ export class OpenAI {
41
41
  throw err;
42
42
  }
43
43
  }
44
- async streamText(prompt, analysisSchema) {
44
+ async streamText(optionsOrPrompt, analysisSchema) {
45
45
  const functionTag = 'OpenAI.streamText';
46
46
  const provider = 'openai';
47
47
  let chunkCount = 0;
48
48
  try {
49
+ // Parse parameters - support both string and options object
50
+ const options = typeof optionsOrPrompt === 'string'
51
+ ? { prompt: optionsOrPrompt }
52
+ : optionsOrPrompt;
53
+ const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options;
54
+ // Use schema from options or fallback parameter
55
+ const finalSchema = schema || analysisSchema;
56
+ console.log(`[${functionTag}] Stream text started`, {
57
+ provider,
58
+ modelName: this.modelName,
59
+ promptLength: prompt.length,
60
+ temperature,
61
+ maxTokens
62
+ });
49
63
  const streamOptions = {
50
64
  model: this.model,
51
65
  prompt: prompt,
52
- system: DEFAULT_SYSTEM_CONTEXT.systemPrompt,
66
+ system: systemPrompt,
67
+ temperature,
68
+ maxTokens,
53
69
  onError: (event) => {
54
70
  const error = event.error;
55
71
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -85,14 +101,9 @@ export class OpenAI {
85
101
  });
86
102
  }
87
103
  };
88
- if (analysisSchema) {
89
- streamOptions.experimental_output = Output.object({ schema: analysisSchema });
104
+ if (finalSchema) {
105
+ streamOptions.experimental_output = Output.object({ schema: finalSchema });
90
106
  }
91
- console.log(`[${functionTag}] Stream text started`, {
92
- provider,
93
- modelName: this.modelName,
94
- promptLength: prompt.length
95
- });
96
107
  const result = streamText(streamOptions);
97
108
  return result;
98
109
  }
@@ -106,29 +117,41 @@ export class OpenAI {
106
117
  return null;
107
118
  }
108
119
  }
109
- async generateText(prompt, analysisSchema) {
120
+ async generateText(optionsOrPrompt, analysisSchema) {
110
121
  const functionTag = 'OpenAI.generateText';
111
122
  const provider = 'openai';
112
123
  try {
124
+ // Parse parameters - support both string and options object
125
+ const options = typeof optionsOrPrompt === 'string'
126
+ ? { prompt: optionsOrPrompt }
127
+ : optionsOrPrompt;
128
+ const { prompt, temperature = 0.7, maxTokens = 500, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema } = options;
129
+ // Use schema from options or fallback parameter
130
+ const finalSchema = schema || analysisSchema;
131
+ console.log(`[${functionTag}] Generate text started`, {
132
+ provider,
133
+ modelName: this.modelName,
134
+ promptLength: prompt.length,
135
+ temperature,
136
+ maxTokens
137
+ });
113
138
  const generateOptions = {
114
139
  model: this.model,
115
140
  prompt: prompt,
116
- system: DEFAULT_SYSTEM_CONTEXT.systemPrompt
141
+ system: systemPrompt,
142
+ temperature,
143
+ maxTokens
117
144
  };
118
- if (analysisSchema) {
119
- generateOptions.experimental_output = Output.object({ schema: analysisSchema });
145
+ if (finalSchema) {
146
+ generateOptions.experimental_output = Output.object({ schema: finalSchema });
120
147
  }
121
- console.log(`[${functionTag}] Generate text started`, {
122
- provider,
123
- modelName: this.modelName,
124
- promptLength: prompt.length
125
- });
126
148
  const result = await generateText(generateOptions);
127
149
  console.log(`[${functionTag}] Generate text completed`, {
128
150
  provider,
129
151
  modelName: this.modelName,
130
152
  usage: result.usage,
131
- finishReason: result.finishReason
153
+ finishReason: result.finishReason,
154
+ responseLength: result.text?.length || 0
132
155
  });
133
156
  return result;
134
157
  }
@@ -11,8 +11,8 @@ export function getBestProvider(requestedProvider) {
11
11
  if (requestedProvider) {
12
12
  return requestedProvider;
13
13
  }
14
- // Default fallback order based on environment variables
15
- const providers = ['bedrock', 'vertex', 'openai'];
14
+ // Default fallback order based on environment variables - OpenAI first since it's most reliable
15
+ const providers = ['openai', 'vertex', 'bedrock'];
16
16
  // Check which providers have their required environment variables
17
17
  for (const provider of providers) {
18
18
  if (isProviderConfigured(provider)) {
package/package.json CHANGED
@@ -1,21 +1,26 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI toolkit with multi-provider support for OpenAI, Amazon Bedrock, and Google Vertex AI",
5
5
  "author": "Juspay Technologies",
6
6
  "license": "MIT",
7
7
  "scripts": {
8
8
  "dev": "vite dev",
9
9
  "build": "vite build && npm run prepack",
10
+ "build:cli": "tsc src/cli/index.ts --outDir dist/cli --target es2022 --module esnext --moduleResolution bundler --allowImportingTsExtensions false --resolveJsonModule --esModuleInterop --allowSyntheticDefaultImports --strict --rootDir src/cli",
11
+ "cli": "node dist/cli/index.js",
10
12
  "preview": "vite preview",
11
13
  "prepare": "svelte-kit sync || echo ''",
12
- "prepack": "svelte-kit sync && svelte-package && publint",
14
+ "prepack": "svelte-kit sync && svelte-package && npm run build:cli && publint",
13
15
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
14
16
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
15
17
  "test": "vitest",
16
18
  "test:run": "vitest run",
17
19
  "lint": "prettier --check . && eslint .",
18
- "format": "prettier --write ."
20
+ "format": "prettier --write .",
21
+ "changeset": "changeset",
22
+ "changeset:version": "changeset version && git add --all",
23
+ "publish": "npm run build && npm publish --access public"
19
24
  },
20
25
  "files": [
21
26
  "dist",
@@ -29,6 +34,9 @@
29
34
  "types": "./dist/index.d.ts",
30
35
  "type": "module",
31
36
  "main": "./dist/index.js",
37
+ "bin": {
38
+ "neurolink": "./dist/cli/index.js"
39
+ },
32
40
  "exports": {
33
41
  ".": {
34
42
  "types": "./dist/index.d.ts",
@@ -38,18 +46,26 @@
38
46
  }
39
47
  },
40
48
  "peerDependencies": {
41
- "ai": "^4.0.0",
42
49
  "@ai-sdk/amazon-bedrock": "^1.0.0",
43
- "@ai-sdk/openai": "^1.0.0",
44
50
  "@ai-sdk/google-vertex": "^2.2.0",
51
+ "@ai-sdk/openai": "^1.0.0",
52
+ "ai": "^4.0.0",
45
53
  "zod": "^3.22.0"
46
54
  },
55
+ "dependencies": {
56
+ "chalk": "^5.3.0",
57
+ "ora": "^7.0.1",
58
+ "playwright": "^1.52.0",
59
+ "yargs": "^17.7.2"
60
+ },
47
61
  "devDependencies": {
62
+ "@changesets/cli": "^2.26.2",
48
63
  "@sveltejs/adapter-auto": "^6.0.0",
49
64
  "@sveltejs/kit": "^2.16.0",
50
65
  "@sveltejs/package": "^2.0.0",
51
66
  "@sveltejs/vite-plugin-svelte": "^5.0.0",
52
67
  "@types/node": "^20.0.0",
68
+ "@types/yargs": "^17.0.33",
53
69
  "eslint": "^9.0.0",
54
70
  "prettier": "^3.0.0",
55
71
  "publint": "^0.3.2",