git-coco 0.16.2 → 0.18.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.
- package/dist/index.d.ts +15 -6
- package/dist/index.esm.mjs +1409 -1286
- package/dist/index.js +1408 -1285
- package/package.json +3 -3
package/dist/index.esm.mjs
CHANGED
|
@@ -18,22 +18,22 @@ import prettyMilliseconds from 'pretty-ms';
|
|
|
18
18
|
import { ChatAnthropic } from '@langchain/anthropic';
|
|
19
19
|
import { ChatOllama } from '@langchain/ollama';
|
|
20
20
|
import { ChatOpenAI } from '@langchain/openai';
|
|
21
|
-
import { StructuredOutputParser, BaseOutputParser } from '@langchain/core/output_parsers';
|
|
21
|
+
import { StructuredOutputParser, BaseOutputParser, OutputParserException, StringOutputParser } from '@langchain/core/output_parsers';
|
|
22
22
|
import { simpleGit } from 'simple-git';
|
|
23
|
-
import
|
|
24
|
-
import {
|
|
23
|
+
import { BaseLangChain, BaseLanguageModel } from '@langchain/core/language_models/base';
|
|
24
|
+
import { ensureConfig, Runnable } from '@langchain/core/runnables';
|
|
25
25
|
import { RUN_KEY } from '@langchain/core/outputs';
|
|
26
26
|
import { CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager';
|
|
27
|
-
import
|
|
28
|
-
import
|
|
27
|
+
import '@langchain/core/utils/json_patch';
|
|
28
|
+
import pQueue from 'p-queue';
|
|
29
|
+
import { Document, BaseDocumentTransformer } from '@langchain/core/documents';
|
|
30
|
+
import { createTwoFilesPatch } from 'diff';
|
|
29
31
|
import '@langchain/core/messages';
|
|
30
32
|
import '@langchain/core/memory';
|
|
31
33
|
import '@langchain/core/chat_history';
|
|
32
34
|
import '@langchain/core/utils/tiktoken';
|
|
33
35
|
import '@langchain/core/utils/async_caller';
|
|
34
36
|
import '@langchain/core/utils/env';
|
|
35
|
-
import '@langchain/core/utils/json_patch';
|
|
36
|
-
import { createTwoFilesPatch } from 'diff';
|
|
37
37
|
import { minimatch } from 'minimatch';
|
|
38
38
|
import { encoding_for_model } from 'tiktoken';
|
|
39
39
|
import { exec } from 'child_process';
|
|
@@ -46,7 +46,7 @@ import * as readline from 'readline';
|
|
|
46
46
|
/**
|
|
47
47
|
* Current build version from package.json
|
|
48
48
|
*/
|
|
49
|
-
const BUILD_VERSION = "0.
|
|
49
|
+
const BUILD_VERSION = "0.18.0";
|
|
50
50
|
|
|
51
51
|
const isInteractive = (config) => {
|
|
52
52
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -173,51 +173,175 @@ const SUMMARIZE_PROMPT = new PromptTemplate({
|
|
|
173
173
|
template: template$5,
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Base class for all LangChain-related errors
|
|
178
|
+
*/
|
|
179
|
+
class LangChainError extends Error {
|
|
180
|
+
constructor(message, context) {
|
|
181
|
+
super(message);
|
|
182
|
+
this.context = context;
|
|
183
|
+
this.name = this.constructor.name;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Configuration-related errors (invalid service configs, missing settings, etc.)
|
|
188
|
+
*/
|
|
189
|
+
class LangChainConfigurationError extends LangChainError {
|
|
190
|
+
constructor(message, context) {
|
|
191
|
+
super(message, context);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Input validation errors (missing required parameters, invalid types, etc.)
|
|
196
|
+
*/
|
|
197
|
+
class LangChainValidationError extends LangChainError {
|
|
198
|
+
constructor(message, context) {
|
|
199
|
+
super(message, context);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Runtime execution errors (LLM failures, parsing errors, etc.)
|
|
204
|
+
*/
|
|
205
|
+
class LangChainExecutionError extends LangChainError {
|
|
206
|
+
constructor(message, context) {
|
|
207
|
+
super(message, context);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Authentication-related errors (missing API keys, invalid credentials, etc.)
|
|
212
|
+
*/
|
|
213
|
+
class LangChainAuthenticationError extends LangChainError {
|
|
214
|
+
constructor(message, context) {
|
|
215
|
+
super(message, context);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Validates that a required parameter is not null or undefined
|
|
221
|
+
*/
|
|
222
|
+
function validateRequired(value, paramName, functionName) {
|
|
223
|
+
if (value === null || value === undefined) {
|
|
224
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Required parameter '${paramName}' is missing`, { paramName, functionName, value });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Validates that a string parameter is not empty
|
|
229
|
+
*/
|
|
230
|
+
function validateNonEmptyString(value, paramName, functionName) {
|
|
231
|
+
validateRequired(value, paramName, functionName);
|
|
232
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
233
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Parameter '${paramName}' must be a non-empty string`, { paramName, functionName, value, type: typeof value });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Validates that an array parameter is not empty
|
|
238
|
+
*/
|
|
239
|
+
function validateNonEmptyArray(value, paramName, functionName) {
|
|
240
|
+
validateRequired(value, paramName, functionName);
|
|
241
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
242
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Parameter '${paramName}' must be a non-empty array`, { paramName, functionName, value, isArray: Array.isArray(value), length: Array.isArray(value) ? value.length : undefined });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Validates that a provider is supported
|
|
247
|
+
*/
|
|
248
|
+
function validateProvider(provider, functionName) {
|
|
249
|
+
const validProviders = ['openai', 'anthropic', 'ollama'];
|
|
250
|
+
if (!validProviders.includes(provider)) {
|
|
251
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Invalid provider '${provider}'. Supported providers: ${validProviders.join(', ')}`, { provider, validProviders, functionName });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Validates that a model is valid for the given provider
|
|
256
|
+
*/
|
|
257
|
+
function validateModel(model, provider, functionName) {
|
|
258
|
+
validateRequired(model, 'model', functionName);
|
|
259
|
+
if (typeof model !== 'string' || model.trim() === '') {
|
|
260
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Model must be a non-empty string`, { model, provider, functionName });
|
|
261
|
+
}
|
|
262
|
+
// Additional provider-specific validation could be added here
|
|
263
|
+
// For now, we trust the TypeScript types
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Validates that a service configuration is complete and valid
|
|
267
|
+
*/
|
|
268
|
+
function validateServiceConfig(service, functionName) {
|
|
269
|
+
validateRequired(service, 'service', functionName);
|
|
270
|
+
if (typeof service !== 'object') {
|
|
271
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Service configuration must be an object`, { service, functionName });
|
|
272
|
+
}
|
|
273
|
+
const serviceObj = service;
|
|
274
|
+
validateProvider(serviceObj.provider, functionName);
|
|
275
|
+
validateModel(serviceObj.model, serviceObj.provider, functionName);
|
|
276
|
+
// Validate authentication
|
|
277
|
+
if (!serviceObj.authentication || typeof serviceObj.authentication !== 'object') {
|
|
278
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Service configuration must include authentication`, { service, functionName });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
176
282
|
/**
|
|
177
283
|
* Retrieves the provider and model from the given configuration object.
|
|
178
284
|
* @param config The configuration object.
|
|
179
285
|
* @returns An object containing the provider and model.
|
|
180
|
-
* @throws
|
|
286
|
+
* @throws LangChainConfigurationError if the configuration is invalid or missing required properties.
|
|
181
287
|
*/
|
|
182
288
|
function getModelAndProviderFromConfig(config) {
|
|
289
|
+
validateRequired(config, 'config', 'getModelAndProviderFromConfig');
|
|
183
290
|
if (!config.service) {
|
|
184
|
-
throw new
|
|
291
|
+
throw new LangChainConfigurationError('getModelAndProviderFromConfig: Service configuration is missing', { config });
|
|
185
292
|
}
|
|
293
|
+
validateServiceConfig(config.service, 'getModelAndProviderFromConfig');
|
|
186
294
|
const { provider, model } = config.service;
|
|
187
|
-
if (!model || !provider) {
|
|
188
|
-
throw new Error(`Invalid service: ${config.service}`);
|
|
189
|
-
}
|
|
190
295
|
return { provider, model };
|
|
191
296
|
}
|
|
192
297
|
/**
|
|
193
298
|
* Retrieve appropriate API key based on selected model
|
|
194
|
-
* @param
|
|
195
|
-
* @
|
|
196
|
-
* @
|
|
299
|
+
* @param config The configuration object
|
|
300
|
+
* @returns API Key or empty string if no authentication required
|
|
301
|
+
* @throws LangChainAuthenticationError if authentication is required but missing
|
|
197
302
|
*/
|
|
198
303
|
function getApiKeyForModel(config) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
default:
|
|
204
|
-
return getDefaultServiceApiKey(config);
|
|
205
|
-
}
|
|
304
|
+
validateRequired(config, 'config', 'getApiKeyForModel');
|
|
305
|
+
// This function now simply delegates to getDefaultServiceApiKey
|
|
306
|
+
// The switch statement was unnecessary since all providers use the same logic
|
|
307
|
+
return getDefaultServiceApiKey(config);
|
|
206
308
|
}
|
|
207
309
|
/**
|
|
208
310
|
* Retrieves the default service API key from the given configuration.
|
|
209
311
|
* @param config The configuration object.
|
|
210
|
-
* @returns The default service API key.
|
|
312
|
+
* @returns The default service API key or empty string for services that don't require authentication.
|
|
313
|
+
* @throws LangChainAuthenticationError if authentication is required but invalid.
|
|
211
314
|
*/
|
|
212
315
|
function getDefaultServiceApiKey(config) {
|
|
316
|
+
validateRequired(config, 'config', 'getDefaultServiceApiKey');
|
|
317
|
+
validateServiceConfig(config.service, 'getDefaultServiceApiKey');
|
|
213
318
|
const service = config.service;
|
|
319
|
+
const { provider } = service;
|
|
320
|
+
// Check if authentication is required for this provider
|
|
321
|
+
const requiresAuth = provider === 'openai' || provider === 'anthropic';
|
|
214
322
|
if (service.authentication.type === 'APIKey') {
|
|
215
|
-
|
|
323
|
+
const apiKey = service.authentication.credentials?.apiKey;
|
|
324
|
+
if (requiresAuth && (!apiKey || apiKey.trim() === '')) {
|
|
325
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: API key is required for ${provider} provider but not provided`, { provider, authenticationType: service.authentication.type });
|
|
326
|
+
}
|
|
327
|
+
return apiKey || '';
|
|
328
|
+
}
|
|
329
|
+
if (service.authentication.type === 'OAuth') {
|
|
330
|
+
const token = service.authentication.credentials?.token;
|
|
331
|
+
if (requiresAuth && (!token || token.trim() === '')) {
|
|
332
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: OAuth token is required for ${provider} provider but not provided`, { provider, authenticationType: service.authentication.type });
|
|
333
|
+
}
|
|
334
|
+
return token || '';
|
|
216
335
|
}
|
|
217
|
-
|
|
218
|
-
|
|
336
|
+
if (service.authentication.type === 'None') {
|
|
337
|
+
if (requiresAuth) {
|
|
338
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: ${provider} provider requires authentication but 'None' was configured`, { provider, authenticationType: service.authentication.type });
|
|
339
|
+
}
|
|
340
|
+
return '';
|
|
219
341
|
}
|
|
220
|
-
|
|
342
|
+
// This should never be reached due to TypeScript type checking, but included for safety
|
|
343
|
+
const authType = service.authentication.type;
|
|
344
|
+
throw new LangChainConfigurationError(`getDefaultServiceApiKey: Unknown authentication type '${authType}'`, { provider, authentication: service.authentication });
|
|
221
345
|
}
|
|
222
346
|
const DEFAULT_OPENAI_LLM_SERVICE = {
|
|
223
347
|
provider: 'openai',
|
|
@@ -231,6 +355,17 @@ const DEFAULT_OPENAI_LLM_SERVICE = {
|
|
|
231
355
|
},
|
|
232
356
|
},
|
|
233
357
|
};
|
|
358
|
+
const DEFAULT_ANTHROPIC_LLM_SERVICE = {
|
|
359
|
+
provider: 'anthropic',
|
|
360
|
+
model: 'claude-3-5-sonnet-20240620',
|
|
361
|
+
temperature: 0.32,
|
|
362
|
+
authentication: {
|
|
363
|
+
type: 'APIKey',
|
|
364
|
+
credentials: {
|
|
365
|
+
apiKey: '',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
};
|
|
234
369
|
const DEFAULT_OLLAMA_LLM_SERVICE = {
|
|
235
370
|
provider: 'ollama',
|
|
236
371
|
model: 'llama3',
|
|
@@ -238,24 +373,33 @@ const DEFAULT_OLLAMA_LLM_SERVICE = {
|
|
|
238
373
|
maxConcurrent: 1,
|
|
239
374
|
tokenLimit: 2024,
|
|
240
375
|
temperature: 0.4,
|
|
376
|
+
maxParsingAttempts: 3,
|
|
241
377
|
authentication: {
|
|
242
378
|
type: 'None',
|
|
243
379
|
credentials: undefined,
|
|
244
380
|
},
|
|
245
381
|
};
|
|
246
382
|
/**
|
|
247
|
-
* Retrieves the default service configuration based on the provided
|
|
248
|
-
* @param provider - The
|
|
249
|
-
* @param model - The optional model to be used.
|
|
250
|
-
* @returns The default service configuration.
|
|
251
|
-
* @throws
|
|
383
|
+
* Retrieves the default service configuration based on the provided provider and optional model.
|
|
384
|
+
* @param provider - The LLM provider (openai, anthropic, ollama).
|
|
385
|
+
* @param model - The optional model to be used. If not provided, uses the default model for the provider.
|
|
386
|
+
* @returns The default service configuration for the specified provider.
|
|
387
|
+
* @throws LangChainConfigurationError if the provider is invalid or unsupported.
|
|
252
388
|
*/
|
|
253
389
|
function getDefaultServiceConfigFromAlias(provider, model) {
|
|
390
|
+
validateRequired(provider, 'provider', 'getDefaultServiceConfigFromAlias');
|
|
391
|
+
// Validate model if provided
|
|
392
|
+
if (model !== undefined) {
|
|
393
|
+
validateRequired(model, 'model', 'getDefaultServiceConfigFromAlias');
|
|
394
|
+
if (typeof model !== 'string' || model.trim() === '') {
|
|
395
|
+
throw new LangChainConfigurationError('getDefaultServiceConfigFromAlias: Model must be a non-empty string when provided', { provider, model });
|
|
396
|
+
}
|
|
397
|
+
}
|
|
254
398
|
switch (provider) {
|
|
255
399
|
case 'anthropic':
|
|
256
400
|
return {
|
|
257
|
-
...
|
|
258
|
-
model: model ||
|
|
401
|
+
...DEFAULT_ANTHROPIC_LLM_SERVICE,
|
|
402
|
+
model: model || DEFAULT_ANTHROPIC_LLM_SERVICE.model,
|
|
259
403
|
};
|
|
260
404
|
case 'ollama':
|
|
261
405
|
return {
|
|
@@ -263,11 +407,12 @@ function getDefaultServiceConfigFromAlias(provider, model) {
|
|
|
263
407
|
model: model || DEFAULT_OLLAMA_LLM_SERVICE.model,
|
|
264
408
|
};
|
|
265
409
|
case 'openai':
|
|
266
|
-
default:
|
|
267
410
|
return {
|
|
268
411
|
...DEFAULT_OPENAI_LLM_SERVICE,
|
|
269
412
|
model: model || DEFAULT_OPENAI_LLM_SERVICE.model,
|
|
270
413
|
};
|
|
414
|
+
default:
|
|
415
|
+
throw new LangChainConfigurationError(`getDefaultServiceConfigFromAlias: Unsupported provider '${provider}'. Supported providers: openai, anthropic, ollama`, { provider, supportedProviders: ['openai', 'anthropic', 'ollama'] });
|
|
271
416
|
}
|
|
272
417
|
}
|
|
273
418
|
|
|
@@ -309,14 +454,29 @@ const CONFIG_KEYS = Object.keys({
|
|
|
309
454
|
**/
|
|
310
455
|
function loadEnvConfig(config) {
|
|
311
456
|
const envConfig = {};
|
|
312
|
-
const envKeys = [
|
|
457
|
+
const envKeys = [
|
|
458
|
+
...CONFIG_KEYS,
|
|
459
|
+
'COCO_SERVICE_PROVIDER',
|
|
460
|
+
'COCO_SERVICE_MODEL',
|
|
461
|
+
'OPEN_AI_KEY',
|
|
462
|
+
'COCO_SERVICE_ENDPOINT',
|
|
463
|
+
'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT',
|
|
464
|
+
'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES',
|
|
465
|
+
'COCO_SERVICE_FIELDS',
|
|
466
|
+
];
|
|
313
467
|
envKeys.forEach((key) => {
|
|
314
468
|
const envVarName = toEnvVarName(key);
|
|
315
469
|
const envValue = parseEnvValue(key, process.env[envVarName]);
|
|
316
470
|
if (envValue === undefined) {
|
|
317
471
|
return;
|
|
318
472
|
}
|
|
319
|
-
if (key === 'COCO_SERVICE_PROVIDER' ||
|
|
473
|
+
if (key === 'COCO_SERVICE_PROVIDER' ||
|
|
474
|
+
key === 'COCO_SERVICE_MODEL' ||
|
|
475
|
+
key === 'OPEN_AI_KEY' ||
|
|
476
|
+
key === 'COCO_SERVICE_ENDPOINT' ||
|
|
477
|
+
key === 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT' ||
|
|
478
|
+
key === 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES' ||
|
|
479
|
+
key === 'COCO_SERVICE_FIELDS') {
|
|
320
480
|
// NOTE: We want to ensure that the service object is always defined
|
|
321
481
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
322
482
|
// @ts-ignore
|
|
@@ -343,9 +503,28 @@ function handleServiceEnvVar(service, key, value) {
|
|
|
343
503
|
break;
|
|
344
504
|
case 'OPEN_AI_KEY':
|
|
345
505
|
if (service.provider === 'openai') {
|
|
346
|
-
service.
|
|
506
|
+
service.authentication = {
|
|
507
|
+
type: 'APIKey',
|
|
508
|
+
credentials: {
|
|
509
|
+
apiKey: value,
|
|
510
|
+
},
|
|
511
|
+
};
|
|
347
512
|
}
|
|
348
513
|
break;
|
|
514
|
+
case 'COCO_SERVICE_ENDPOINT':
|
|
515
|
+
if (service.provider === 'ollama') {
|
|
516
|
+
service.endpoint = value;
|
|
517
|
+
}
|
|
518
|
+
break;
|
|
519
|
+
case 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT':
|
|
520
|
+
service.requestOptions = { ...service.requestOptions, timeout: value };
|
|
521
|
+
break;
|
|
522
|
+
case 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES':
|
|
523
|
+
service.requestOptions = { ...service.requestOptions, maxRetries: value };
|
|
524
|
+
break;
|
|
525
|
+
case 'COCO_SERVICE_FIELDS':
|
|
526
|
+
service.fields = value;
|
|
527
|
+
break;
|
|
349
528
|
}
|
|
350
529
|
}
|
|
351
530
|
function parseEnvValue(key, value) {
|
|
@@ -364,6 +543,9 @@ function parseEnvValue(key, value) {
|
|
|
364
543
|
// Handle number values
|
|
365
544
|
case typeof value === 'string' && !isNaN(Number(value)):
|
|
366
545
|
return Number(value);
|
|
546
|
+
// Handle JSON strings
|
|
547
|
+
case typeof value === 'string' && value.startsWith('{'):
|
|
548
|
+
return JSON.parse(value);
|
|
367
549
|
default:
|
|
368
550
|
return value;
|
|
369
551
|
}
|
|
@@ -377,32 +559,40 @@ function toEnvVarName(key) {
|
|
|
377
559
|
}
|
|
378
560
|
return `COCO_${key.replace(/([A-Z])/g, '_$1').toLocaleUpperCase()}`;
|
|
379
561
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
562
|
+
const flattenObject = (obj, prefix = '') => {
|
|
563
|
+
let flattened = {};
|
|
564
|
+
for (const key in obj) {
|
|
565
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
566
|
+
const propName = prefix ? `${prefix}_${key}` : key;
|
|
567
|
+
const value = obj[key];
|
|
568
|
+
// Skip undefined or null values
|
|
569
|
+
if (value === undefined || value === null) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
573
|
+
// Handle nested objects, but specifically handle 'fields' as JSON string
|
|
574
|
+
if (key === 'fields') {
|
|
575
|
+
flattened[propName.toUpperCase()] = JSON.stringify(value);
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
flattened = { ...flattened, ...flattenObject(value, propName) };
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
// For primitive types (string, number, boolean, symbol, bigint) and arrays
|
|
583
|
+
flattened[propName.toUpperCase()] = String(value);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
390
586
|
}
|
|
391
|
-
return
|
|
392
|
-
}
|
|
587
|
+
return flattened;
|
|
588
|
+
};
|
|
393
589
|
const appendToEnvFile = async (filePath, config) => {
|
|
394
590
|
const getNewContent = async () => {
|
|
395
|
-
|
|
591
|
+
const flattenedConfig = flattenObject(config);
|
|
592
|
+
return Object.entries(flattenedConfig)
|
|
396
593
|
.map(([key, value]) => {
|
|
397
|
-
if (key === 'service') {
|
|
398
|
-
const service = value;
|
|
399
|
-
return `${service.provider ? `COCO_SERVICE_PROVIDER=${service.provider}` : ''}\n${service.model ? `COCO_SERVICE_MODEL=${service.model}` : ''}\n${service.authentication.type === 'APIKey'
|
|
400
|
-
? `OPEN_AI_KEY=${service.authentication.credentials.apiKey}`
|
|
401
|
-
: ''}`;
|
|
402
|
-
}
|
|
403
594
|
const envVarName = toEnvVarName(key);
|
|
404
|
-
|
|
405
|
-
return `${envVarName}=${envValue}`;
|
|
595
|
+
return `${envVarName}=${value}`;
|
|
406
596
|
})
|
|
407
597
|
.join('\n');
|
|
408
598
|
};
|
|
@@ -426,22 +616,31 @@ function loadGitConfig(config) {
|
|
|
426
616
|
if (fs.existsSync(gitConfigPath)) {
|
|
427
617
|
const gitConfigRaw = fs.readFileSync(gitConfigPath, 'utf-8');
|
|
428
618
|
const gitConfigParsed = ini.parse(gitConfigRaw);
|
|
429
|
-
const gitConfigServiceObject = gitConfigParsed.coco?.service;
|
|
430
619
|
let service = config.service;
|
|
431
|
-
if (
|
|
432
|
-
|
|
433
|
-
|
|
620
|
+
if (gitConfigParsed.coco) {
|
|
621
|
+
service = {
|
|
622
|
+
provider: gitConfigParsed.coco?.['service.provider'],
|
|
623
|
+
model: gitConfigParsed.coco?.['service.model'],
|
|
624
|
+
authentication: {
|
|
625
|
+
type: 'APIKey',
|
|
626
|
+
credentials: {
|
|
627
|
+
apiKey: gitConfigParsed.coco?.['service.apiKey'],
|
|
628
|
+
},
|
|
629
|
+
},
|
|
630
|
+
requestOptions: {
|
|
631
|
+
timeout: Number(gitConfigParsed.coco?.['service.requestOptions.timeout']),
|
|
632
|
+
maxRetries: Number(gitConfigParsed.coco?.['service.requestOptions.maxRetries']),
|
|
633
|
+
},
|
|
634
|
+
endpoint: gitConfigParsed.coco?.['service.endpoint'],
|
|
635
|
+
fields: gitConfigParsed.coco?.['service.fields']
|
|
636
|
+
? JSON.parse(gitConfigParsed.coco?.['service.fields'])
|
|
637
|
+
: undefined,
|
|
638
|
+
};
|
|
434
639
|
}
|
|
435
640
|
config = {
|
|
436
641
|
...config,
|
|
642
|
+
...gitConfigParsed.coco,
|
|
437
643
|
service: service,
|
|
438
|
-
prompt: gitConfigParsed.coco?.prompt || config.prompt,
|
|
439
|
-
mode: gitConfigParsed.coco?.mode || config.mode,
|
|
440
|
-
summarizePrompt: gitConfigParsed.coco?.summarizePrompt || config.summarizePrompt,
|
|
441
|
-
ignoredFiles: gitConfigParsed.coco?.ignoredFiles || config.ignoredFiles,
|
|
442
|
-
ignoredExtensions: gitConfigParsed.coco?.ignoredExtensions || config.ignoredExtensions,
|
|
443
|
-
defaultBranch: gitConfigParsed.coco?.defaultBranch || config.defaultBranch,
|
|
444
|
-
verbose: gitConfigParsed.coco?.verbose || config.verbose,
|
|
445
644
|
};
|
|
446
645
|
}
|
|
447
646
|
return removeUndefined(config);
|
|
@@ -461,9 +660,28 @@ const appendToGitConfig = async (filePath, config) => {
|
|
|
461
660
|
const contentLines = [header];
|
|
462
661
|
for (const key in config) {
|
|
463
662
|
const value = config[key];
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
contentLines.push(`\
|
|
663
|
+
if (key === 'service') {
|
|
664
|
+
const service = value;
|
|
665
|
+
contentLines.push(`\tservice.provider = ${service.provider}`);
|
|
666
|
+
contentLines.push(`\tservice.model = ${service.model}`);
|
|
667
|
+
if (service.authentication.type === 'APIKey') {
|
|
668
|
+
contentLines.push(`\tservice.apiKey = ${service.authentication.credentials.apiKey}`);
|
|
669
|
+
}
|
|
670
|
+
if (service.requestOptions?.timeout) {
|
|
671
|
+
contentLines.push(`\tservice.requestOptions.timeout = ${service.requestOptions.timeout}`);
|
|
672
|
+
}
|
|
673
|
+
if (service.requestOptions?.maxRetries) {
|
|
674
|
+
contentLines.push(`\tservice.requestOptions.maxRetries = ${service.requestOptions.maxRetries}`);
|
|
675
|
+
}
|
|
676
|
+
if (service.provider === 'ollama') {
|
|
677
|
+
const ollamaService = service;
|
|
678
|
+
if (ollamaService.endpoint) {
|
|
679
|
+
contentLines.push(` service.endpoint = ${ollamaService.endpoint}`);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
if (service.fields) {
|
|
683
|
+
contentLines.push(`\tservice.fields = ${JSON.stringify(service.fields)}`);
|
|
684
|
+
}
|
|
467
685
|
}
|
|
468
686
|
else if (typeof value === 'string' && value.includes('\n')) {
|
|
469
687
|
// Wrap strings with new lines in quotes
|
|
@@ -893,6 +1111,11 @@ const schema$1 = {
|
|
|
893
1111
|
}
|
|
894
1112
|
},
|
|
895
1113
|
"additionalProperties": false
|
|
1114
|
+
},
|
|
1115
|
+
"maxParsingAttempts": {
|
|
1116
|
+
"type": "number",
|
|
1117
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1118
|
+
"default": 3
|
|
896
1119
|
}
|
|
897
1120
|
},
|
|
898
1121
|
"required": [
|
|
@@ -983,6 +1206,9 @@ const schema$1 = {
|
|
|
983
1206
|
"OllamaModel": {
|
|
984
1207
|
"type": "string",
|
|
985
1208
|
"enum": [
|
|
1209
|
+
"deepseek-r1:1.5b",
|
|
1210
|
+
"deepseek-r1:8b",
|
|
1211
|
+
"deepseek-r1:32b",
|
|
986
1212
|
"codegemma:2b",
|
|
987
1213
|
"codegemma:7b-code",
|
|
988
1214
|
"codegemma",
|
|
@@ -1014,9 +1240,11 @@ const schema$1 = {
|
|
|
1014
1240
|
"llama3.2:latest",
|
|
1015
1241
|
"llama3.2:1b",
|
|
1016
1242
|
"llama3.2:3b",
|
|
1017
|
-
"llama3.2:1b-instruct-fp16",
|
|
1018
|
-
"llama3.2:1b-instruct-q3_K_M",
|
|
1019
1243
|
"llama3",
|
|
1244
|
+
"llava-llama3:latest",
|
|
1245
|
+
"dolphin-llama3:latest",
|
|
1246
|
+
"dolphin-llama3:8b",
|
|
1247
|
+
"dolphin-llama3:70b",
|
|
1020
1248
|
"mistral:7b",
|
|
1021
1249
|
"mistral:latest",
|
|
1022
1250
|
"mistral:text",
|
|
@@ -1032,18 +1260,28 @@ const schema$1 = {
|
|
|
1032
1260
|
"qwen2:1.5b",
|
|
1033
1261
|
"qwen2:72b-text",
|
|
1034
1262
|
"qwen2:72b",
|
|
1035
|
-
"qwen2"
|
|
1263
|
+
"qwen2",
|
|
1264
|
+
"qwen2.5-coder:latest",
|
|
1265
|
+
"qwen2.5-coder:0.5b",
|
|
1266
|
+
"qwen2.5-coder:1.5b",
|
|
1267
|
+
"qwen2.5-coder:3b",
|
|
1268
|
+
"qwen2.5-coder:7b",
|
|
1269
|
+
"qwen2.5-coder:14b",
|
|
1270
|
+
"qwen2.5-coder:32b"
|
|
1036
1271
|
]
|
|
1037
1272
|
},
|
|
1038
1273
|
"AnthropicModel": {
|
|
1039
1274
|
"type": "string",
|
|
1040
1275
|
"enum": [
|
|
1276
|
+
"claude-sonnet-4-0",
|
|
1277
|
+
"claude-3-7-sonnet-latest",
|
|
1278
|
+
"claude-3-5-haiku-latest",
|
|
1279
|
+
"claude-3-5-sonnet-latest",
|
|
1280
|
+
"claude-3-5-sonnet-20241022",
|
|
1041
1281
|
"claude-3-5-sonnet-20240620",
|
|
1042
1282
|
"claude-3-opus-20240229",
|
|
1043
1283
|
"claude-3-sonnet-20240229",
|
|
1044
|
-
"claude-3-haiku-20240307"
|
|
1045
|
-
"claude-2.1",
|
|
1046
|
-
"claude-2.0"
|
|
1284
|
+
"claude-3-haiku-20240307"
|
|
1047
1285
|
]
|
|
1048
1286
|
},
|
|
1049
1287
|
"Callbacks": {
|
|
@@ -1488,6 +1726,11 @@ const schema$1 = {
|
|
|
1488
1726
|
}
|
|
1489
1727
|
},
|
|
1490
1728
|
"additionalProperties": false
|
|
1729
|
+
},
|
|
1730
|
+
"maxParsingAttempts": {
|
|
1731
|
+
"type": "number",
|
|
1732
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1733
|
+
"default": 3
|
|
1491
1734
|
}
|
|
1492
1735
|
},
|
|
1493
1736
|
"required": [
|
|
@@ -1634,6 +1877,11 @@ const schema$1 = {
|
|
|
1634
1877
|
}
|
|
1635
1878
|
},
|
|
1636
1879
|
"additionalProperties": false
|
|
1880
|
+
},
|
|
1881
|
+
"maxParsingAttempts": {
|
|
1882
|
+
"type": "number",
|
|
1883
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1884
|
+
"default": 3
|
|
1637
1885
|
}
|
|
1638
1886
|
},
|
|
1639
1887
|
"required": [
|
|
@@ -1853,7 +2101,7 @@ function commandExecutor(handler) {
|
|
|
1853
2101
|
|
|
1854
2102
|
var util;
|
|
1855
2103
|
(function (util) {
|
|
1856
|
-
util.assertEqual = (
|
|
2104
|
+
util.assertEqual = (_) => { };
|
|
1857
2105
|
function assertIs(_arg) { }
|
|
1858
2106
|
util.assertIs = assertIs;
|
|
1859
2107
|
function assertNever(_x) {
|
|
@@ -1900,11 +2148,9 @@ var util;
|
|
|
1900
2148
|
};
|
|
1901
2149
|
util.isInteger = typeof Number.isInteger === "function"
|
|
1902
2150
|
? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
|
|
1903
|
-
: (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val;
|
|
2151
|
+
: (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
|
|
1904
2152
|
function joinValues(array, separator = " | ") {
|
|
1905
|
-
return array
|
|
1906
|
-
.map((val) => (typeof val === "string" ? `'${val}'` : val))
|
|
1907
|
-
.join(separator);
|
|
2153
|
+
return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator);
|
|
1908
2154
|
}
|
|
1909
2155
|
util.joinValues = joinValues;
|
|
1910
2156
|
util.jsonStringifyReplacer = (_, value) => {
|
|
@@ -1953,7 +2199,7 @@ const getParsedType = (data) => {
|
|
|
1953
2199
|
case "string":
|
|
1954
2200
|
return ZodParsedType.string;
|
|
1955
2201
|
case "number":
|
|
1956
|
-
return isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
|
|
2202
|
+
return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
|
|
1957
2203
|
case "boolean":
|
|
1958
2204
|
return ZodParsedType.boolean;
|
|
1959
2205
|
case "function":
|
|
@@ -1969,10 +2215,7 @@ const getParsedType = (data) => {
|
|
|
1969
2215
|
if (data === null) {
|
|
1970
2216
|
return ZodParsedType.null;
|
|
1971
2217
|
}
|
|
1972
|
-
if (data.then &&
|
|
1973
|
-
typeof data.then === "function" &&
|
|
1974
|
-
data.catch &&
|
|
1975
|
-
typeof data.catch === "function") {
|
|
2218
|
+
if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
|
|
1976
2219
|
return ZodParsedType.promise;
|
|
1977
2220
|
}
|
|
1978
2221
|
if (typeof Map !== "undefined" && data instanceof Map) {
|
|
@@ -2008,10 +2251,6 @@ const ZodIssueCode = util.arrayToEnum([
|
|
|
2008
2251
|
"not_multiple_of",
|
|
2009
2252
|
"not_finite",
|
|
2010
2253
|
]);
|
|
2011
|
-
const quotelessJson = (obj) => {
|
|
2012
|
-
const json = JSON.stringify(obj, null, 2);
|
|
2013
|
-
return json.replace(/"([^"]+)":/g, "$1:");
|
|
2014
|
-
};
|
|
2015
2254
|
class ZodError extends Error {
|
|
2016
2255
|
get errors() {
|
|
2017
2256
|
return this.issues;
|
|
@@ -2104,8 +2343,9 @@ class ZodError extends Error {
|
|
|
2104
2343
|
const formErrors = [];
|
|
2105
2344
|
for (const sub of this.issues) {
|
|
2106
2345
|
if (sub.path.length > 0) {
|
|
2107
|
-
|
|
2108
|
-
fieldErrors[
|
|
2346
|
+
const firstEl = sub.path[0];
|
|
2347
|
+
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
|
|
2348
|
+
fieldErrors[firstEl].push(mapper(sub));
|
|
2109
2349
|
}
|
|
2110
2350
|
else {
|
|
2111
2351
|
formErrors.push(mapper(sub));
|
|
@@ -2188,17 +2428,11 @@ const errorMap = (issue, _ctx) => {
|
|
|
2188
2428
|
else if (issue.type === "string")
|
|
2189
2429
|
message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
|
|
2190
2430
|
else if (issue.type === "number")
|
|
2191
|
-
message = `Number must be ${issue.exact
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
? `greater than or equal to `
|
|
2195
|
-
: `greater than `}${issue.minimum}`;
|
|
2431
|
+
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
2432
|
+
else if (issue.type === "bigint")
|
|
2433
|
+
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
2196
2434
|
else if (issue.type === "date")
|
|
2197
|
-
message = `Date must be ${issue.exact
|
|
2198
|
-
? `exactly equal to `
|
|
2199
|
-
: issue.inclusive
|
|
2200
|
-
? `greater than or equal to `
|
|
2201
|
-
: `greater than `}${new Date(Number(issue.minimum))}`;
|
|
2435
|
+
message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
|
|
2202
2436
|
else
|
|
2203
2437
|
message = "Invalid input";
|
|
2204
2438
|
break;
|
|
@@ -2208,23 +2442,11 @@ const errorMap = (issue, _ctx) => {
|
|
|
2208
2442
|
else if (issue.type === "string")
|
|
2209
2443
|
message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
|
|
2210
2444
|
else if (issue.type === "number")
|
|
2211
|
-
message = `Number must be ${issue.exact
|
|
2212
|
-
? `exactly`
|
|
2213
|
-
: issue.inclusive
|
|
2214
|
-
? `less than or equal to`
|
|
2215
|
-
: `less than`} ${issue.maximum}`;
|
|
2445
|
+
message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
|
|
2216
2446
|
else if (issue.type === "bigint")
|
|
2217
|
-
message = `BigInt must be ${issue.exact
|
|
2218
|
-
? `exactly`
|
|
2219
|
-
: issue.inclusive
|
|
2220
|
-
? `less than or equal to`
|
|
2221
|
-
: `less than`} ${issue.maximum}`;
|
|
2447
|
+
message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
|
|
2222
2448
|
else if (issue.type === "date")
|
|
2223
|
-
message = `Date must be ${issue.exact
|
|
2224
|
-
? `exactly`
|
|
2225
|
-
: issue.inclusive
|
|
2226
|
-
? `smaller than or equal to`
|
|
2227
|
-
: `smaller than`} ${new Date(Number(issue.maximum))}`;
|
|
2449
|
+
message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
|
|
2228
2450
|
else
|
|
2229
2451
|
message = "Invalid input";
|
|
2230
2452
|
break;
|
|
@@ -2246,11 +2468,9 @@ const errorMap = (issue, _ctx) => {
|
|
|
2246
2468
|
}
|
|
2247
2469
|
return { message };
|
|
2248
2470
|
};
|
|
2471
|
+
var defaultErrorMap = errorMap;
|
|
2249
2472
|
|
|
2250
|
-
let overrideErrorMap =
|
|
2251
|
-
function setErrorMap(map) {
|
|
2252
|
-
overrideErrorMap = map;
|
|
2253
|
-
}
|
|
2473
|
+
let overrideErrorMap = defaultErrorMap;
|
|
2254
2474
|
function getErrorMap() {
|
|
2255
2475
|
return overrideErrorMap;
|
|
2256
2476
|
}
|
|
@@ -2283,7 +2503,6 @@ const makeIssue = (params) => {
|
|
|
2283
2503
|
message: errorMessage,
|
|
2284
2504
|
};
|
|
2285
2505
|
};
|
|
2286
|
-
const EMPTY_PATH = [];
|
|
2287
2506
|
function addIssueToContext(ctx, issueData) {
|
|
2288
2507
|
const overrideMap = getErrorMap();
|
|
2289
2508
|
const issue = makeIssue({
|
|
@@ -2294,7 +2513,7 @@ function addIssueToContext(ctx, issueData) {
|
|
|
2294
2513
|
ctx.common.contextualErrorMap, // contextual error map is first priority
|
|
2295
2514
|
ctx.schemaErrorMap, // then schema-bound map if available
|
|
2296
2515
|
overrideMap, // then global override map
|
|
2297
|
-
overrideMap ===
|
|
2516
|
+
overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map
|
|
2298
2517
|
].filter((x) => !!x),
|
|
2299
2518
|
});
|
|
2300
2519
|
ctx.common.issues.push(issue);
|
|
@@ -2346,8 +2565,7 @@ class ParseStatus {
|
|
|
2346
2565
|
status.dirty();
|
|
2347
2566
|
if (value.status === "dirty")
|
|
2348
2567
|
status.dirty();
|
|
2349
|
-
if (key.value !== "__proto__" &&
|
|
2350
|
-
(typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
2568
|
+
if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
2351
2569
|
finalObject[key.value] = value.value;
|
|
2352
2570
|
}
|
|
2353
2571
|
}
|
|
@@ -2364,46 +2582,13 @@ const isDirty = (x) => x.status === "dirty";
|
|
|
2364
2582
|
const isValid = (x) => x.status === "valid";
|
|
2365
2583
|
const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
2366
2584
|
|
|
2367
|
-
/******************************************************************************
|
|
2368
|
-
Copyright (c) Microsoft Corporation.
|
|
2369
|
-
|
|
2370
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
2371
|
-
purpose with or without fee is hereby granted.
|
|
2372
|
-
|
|
2373
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
2374
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
2375
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
2376
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
2377
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
2378
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2379
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
2380
|
-
***************************************************************************** */
|
|
2381
|
-
|
|
2382
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
2383
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
2384
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
2385
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
2386
|
-
}
|
|
2387
|
-
|
|
2388
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
2389
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
2390
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
2391
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
2392
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
2396
|
-
var e = new Error(message);
|
|
2397
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
2398
|
-
};
|
|
2399
|
-
|
|
2400
2585
|
var errorUtil;
|
|
2401
2586
|
(function (errorUtil) {
|
|
2402
2587
|
errorUtil.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
2403
|
-
|
|
2588
|
+
// biome-ignore lint:
|
|
2589
|
+
errorUtil.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
2404
2590
|
})(errorUtil || (errorUtil = {}));
|
|
2405
2591
|
|
|
2406
|
-
var _ZodEnum_cache, _ZodNativeEnum_cache;
|
|
2407
2592
|
class ParseInputLazyPath {
|
|
2408
2593
|
constructor(parent, value, path, key) {
|
|
2409
2594
|
this._cachedPath = [];
|
|
@@ -2414,7 +2599,7 @@ class ParseInputLazyPath {
|
|
|
2414
2599
|
}
|
|
2415
2600
|
get path() {
|
|
2416
2601
|
if (!this._cachedPath.length) {
|
|
2417
|
-
if (this._key
|
|
2602
|
+
if (Array.isArray(this._key)) {
|
|
2418
2603
|
this._cachedPath.push(...this._path, ...this._key);
|
|
2419
2604
|
}
|
|
2420
2605
|
else {
|
|
@@ -2454,17 +2639,16 @@ function processCreateParams(params) {
|
|
|
2454
2639
|
if (errorMap)
|
|
2455
2640
|
return { errorMap: errorMap, description };
|
|
2456
2641
|
const customMap = (iss, ctx) => {
|
|
2457
|
-
var _a, _b;
|
|
2458
2642
|
const { message } = params;
|
|
2459
2643
|
if (iss.code === "invalid_enum_value") {
|
|
2460
|
-
return { message: message
|
|
2644
|
+
return { message: message ?? ctx.defaultError };
|
|
2461
2645
|
}
|
|
2462
2646
|
if (typeof ctx.data === "undefined") {
|
|
2463
|
-
return { message:
|
|
2647
|
+
return { message: message ?? required_error ?? ctx.defaultError };
|
|
2464
2648
|
}
|
|
2465
2649
|
if (iss.code !== "invalid_type")
|
|
2466
2650
|
return { message: ctx.defaultError };
|
|
2467
|
-
return { message:
|
|
2651
|
+
return { message: message ?? invalid_type_error ?? ctx.defaultError };
|
|
2468
2652
|
};
|
|
2469
2653
|
return { errorMap: customMap, description };
|
|
2470
2654
|
}
|
|
@@ -2516,14 +2700,13 @@ class ZodType {
|
|
|
2516
2700
|
throw result.error;
|
|
2517
2701
|
}
|
|
2518
2702
|
safeParse(data, params) {
|
|
2519
|
-
var _a;
|
|
2520
2703
|
const ctx = {
|
|
2521
2704
|
common: {
|
|
2522
2705
|
issues: [],
|
|
2523
|
-
async:
|
|
2524
|
-
contextualErrorMap: params
|
|
2706
|
+
async: params?.async ?? false,
|
|
2707
|
+
contextualErrorMap: params?.errorMap,
|
|
2525
2708
|
},
|
|
2526
|
-
path:
|
|
2709
|
+
path: params?.path || [],
|
|
2527
2710
|
schemaErrorMap: this._def.errorMap,
|
|
2528
2711
|
parent: null,
|
|
2529
2712
|
data,
|
|
@@ -2533,7 +2716,6 @@ class ZodType {
|
|
|
2533
2716
|
return handleResult$1(ctx, result);
|
|
2534
2717
|
}
|
|
2535
2718
|
"~validate"(data) {
|
|
2536
|
-
var _a, _b;
|
|
2537
2719
|
const ctx = {
|
|
2538
2720
|
common: {
|
|
2539
2721
|
issues: [],
|
|
@@ -2557,7 +2739,7 @@ class ZodType {
|
|
|
2557
2739
|
};
|
|
2558
2740
|
}
|
|
2559
2741
|
catch (err) {
|
|
2560
|
-
if (
|
|
2742
|
+
if (err?.message?.toLowerCase()?.includes("encountered")) {
|
|
2561
2743
|
this["~standard"].async = true;
|
|
2562
2744
|
}
|
|
2563
2745
|
ctx.common = {
|
|
@@ -2584,19 +2766,17 @@ class ZodType {
|
|
|
2584
2766
|
const ctx = {
|
|
2585
2767
|
common: {
|
|
2586
2768
|
issues: [],
|
|
2587
|
-
contextualErrorMap: params
|
|
2769
|
+
contextualErrorMap: params?.errorMap,
|
|
2588
2770
|
async: true,
|
|
2589
2771
|
},
|
|
2590
|
-
path:
|
|
2772
|
+
path: params?.path || [],
|
|
2591
2773
|
schemaErrorMap: this._def.errorMap,
|
|
2592
2774
|
parent: null,
|
|
2593
2775
|
data,
|
|
2594
2776
|
parsedType: getParsedType(data),
|
|
2595
2777
|
};
|
|
2596
2778
|
const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });
|
|
2597
|
-
const result = await (isAsync(maybeAsyncResult)
|
|
2598
|
-
? maybeAsyncResult
|
|
2599
|
-
: Promise.resolve(maybeAsyncResult));
|
|
2779
|
+
const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
|
|
2600
2780
|
return handleResult$1(ctx, result);
|
|
2601
2781
|
}
|
|
2602
2782
|
refine(check, message) {
|
|
@@ -2640,9 +2820,7 @@ class ZodType {
|
|
|
2640
2820
|
refinement(check, refinementData) {
|
|
2641
2821
|
return this._refinement((val, ctx) => {
|
|
2642
2822
|
if (!check(val)) {
|
|
2643
|
-
ctx.addIssue(typeof refinementData === "function"
|
|
2644
|
-
? refinementData(val, ctx)
|
|
2645
|
-
: refinementData);
|
|
2823
|
+
ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData);
|
|
2646
2824
|
return false;
|
|
2647
2825
|
}
|
|
2648
2826
|
else {
|
|
@@ -2814,15 +2992,15 @@ const base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z
|
|
|
2814
2992
|
const dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
|
|
2815
2993
|
const dateRegex = new RegExp(`^${dateRegexSource}$`);
|
|
2816
2994
|
function timeRegexSource(args) {
|
|
2817
|
-
|
|
2818
|
-
let regex = `([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d`;
|
|
2995
|
+
let secondsRegexSource = `[0-5]\\d`;
|
|
2819
2996
|
if (args.precision) {
|
|
2820
|
-
|
|
2997
|
+
secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
|
|
2821
2998
|
}
|
|
2822
2999
|
else if (args.precision == null) {
|
|
2823
|
-
|
|
3000
|
+
secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
|
|
2824
3001
|
}
|
|
2825
|
-
|
|
3002
|
+
const secondsQuantifier = args.precision ? "+" : "?"; // require seconds if precision is nonzero
|
|
3003
|
+
return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
|
|
2826
3004
|
}
|
|
2827
3005
|
function timeRegex(args) {
|
|
2828
3006
|
return new RegExp(`^${timeRegexSource(args)}$`);
|
|
@@ -2851,6 +3029,8 @@ function isValidJWT(jwt, alg) {
|
|
|
2851
3029
|
return false;
|
|
2852
3030
|
try {
|
|
2853
3031
|
const [header] = jwt.split(".");
|
|
3032
|
+
if (!header)
|
|
3033
|
+
return false;
|
|
2854
3034
|
// Convert base64url to base64
|
|
2855
3035
|
const base64 = header
|
|
2856
3036
|
.replace(/-/g, "+")
|
|
@@ -2859,13 +3039,15 @@ function isValidJWT(jwt, alg) {
|
|
|
2859
3039
|
const decoded = JSON.parse(atob(base64));
|
|
2860
3040
|
if (typeof decoded !== "object" || decoded === null)
|
|
2861
3041
|
return false;
|
|
2862
|
-
if (
|
|
3042
|
+
if ("typ" in decoded && decoded?.typ !== "JWT")
|
|
3043
|
+
return false;
|
|
3044
|
+
if (!decoded.alg)
|
|
2863
3045
|
return false;
|
|
2864
3046
|
if (alg && decoded.alg !== alg)
|
|
2865
3047
|
return false;
|
|
2866
3048
|
return true;
|
|
2867
3049
|
}
|
|
2868
|
-
catch
|
|
3050
|
+
catch {
|
|
2869
3051
|
return false;
|
|
2870
3052
|
}
|
|
2871
3053
|
}
|
|
@@ -3036,7 +3218,7 @@ class ZodString extends ZodType {
|
|
|
3036
3218
|
try {
|
|
3037
3219
|
new URL(input.data);
|
|
3038
3220
|
}
|
|
3039
|
-
catch
|
|
3221
|
+
catch {
|
|
3040
3222
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3041
3223
|
addIssueToContext(ctx, {
|
|
3042
3224
|
validation: "url",
|
|
@@ -3266,7 +3448,6 @@ class ZodString extends ZodType {
|
|
|
3266
3448
|
return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) });
|
|
3267
3449
|
}
|
|
3268
3450
|
datetime(options) {
|
|
3269
|
-
var _a, _b;
|
|
3270
3451
|
if (typeof options === "string") {
|
|
3271
3452
|
return this._addCheck({
|
|
3272
3453
|
kind: "datetime",
|
|
@@ -3278,10 +3459,10 @@ class ZodString extends ZodType {
|
|
|
3278
3459
|
}
|
|
3279
3460
|
return this._addCheck({
|
|
3280
3461
|
kind: "datetime",
|
|
3281
|
-
precision: typeof
|
|
3282
|
-
offset:
|
|
3283
|
-
local:
|
|
3284
|
-
...errorUtil.errToObj(options
|
|
3462
|
+
precision: typeof options?.precision === "undefined" ? null : options?.precision,
|
|
3463
|
+
offset: options?.offset ?? false,
|
|
3464
|
+
local: options?.local ?? false,
|
|
3465
|
+
...errorUtil.errToObj(options?.message),
|
|
3285
3466
|
});
|
|
3286
3467
|
}
|
|
3287
3468
|
date(message) {
|
|
@@ -3297,8 +3478,8 @@ class ZodString extends ZodType {
|
|
|
3297
3478
|
}
|
|
3298
3479
|
return this._addCheck({
|
|
3299
3480
|
kind: "time",
|
|
3300
|
-
precision: typeof
|
|
3301
|
-
...errorUtil.errToObj(options
|
|
3481
|
+
precision: typeof options?.precision === "undefined" ? null : options?.precision,
|
|
3482
|
+
...errorUtil.errToObj(options?.message),
|
|
3302
3483
|
});
|
|
3303
3484
|
}
|
|
3304
3485
|
duration(message) {
|
|
@@ -3315,8 +3496,8 @@ class ZodString extends ZodType {
|
|
|
3315
3496
|
return this._addCheck({
|
|
3316
3497
|
kind: "includes",
|
|
3317
3498
|
value: value,
|
|
3318
|
-
position: options
|
|
3319
|
-
...errorUtil.errToObj(options
|
|
3499
|
+
position: options?.position,
|
|
3500
|
+
...errorUtil.errToObj(options?.message),
|
|
3320
3501
|
});
|
|
3321
3502
|
}
|
|
3322
3503
|
startsWith(value, message) {
|
|
@@ -3449,11 +3630,10 @@ class ZodString extends ZodType {
|
|
|
3449
3630
|
}
|
|
3450
3631
|
}
|
|
3451
3632
|
ZodString.create = (params) => {
|
|
3452
|
-
var _a;
|
|
3453
3633
|
return new ZodString({
|
|
3454
3634
|
checks: [],
|
|
3455
3635
|
typeName: ZodFirstPartyTypeKind.ZodString,
|
|
3456
|
-
coerce:
|
|
3636
|
+
coerce: params?.coerce ?? false,
|
|
3457
3637
|
...processCreateParams(params),
|
|
3458
3638
|
});
|
|
3459
3639
|
};
|
|
@@ -3462,9 +3642,9 @@ function floatSafeRemainder(val, step) {
|
|
|
3462
3642
|
const valDecCount = (val.toString().split(".")[1] || "").length;
|
|
3463
3643
|
const stepDecCount = (step.toString().split(".")[1] || "").length;
|
|
3464
3644
|
const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
|
|
3465
|
-
const valInt = parseInt(val.toFixed(decCount).replace(".", ""));
|
|
3466
|
-
const stepInt = parseInt(step.toFixed(decCount).replace(".", ""));
|
|
3467
|
-
return (valInt % stepInt) /
|
|
3645
|
+
const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
|
|
3646
|
+
const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
|
|
3647
|
+
return (valInt % stepInt) / 10 ** decCount;
|
|
3468
3648
|
}
|
|
3469
3649
|
class ZodNumber extends ZodType {
|
|
3470
3650
|
constructor() {
|
|
@@ -3503,9 +3683,7 @@ class ZodNumber extends ZodType {
|
|
|
3503
3683
|
}
|
|
3504
3684
|
}
|
|
3505
3685
|
else if (check.kind === "min") {
|
|
3506
|
-
const tooSmall = check.inclusive
|
|
3507
|
-
? input.data < check.value
|
|
3508
|
-
: input.data <= check.value;
|
|
3686
|
+
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
3509
3687
|
if (tooSmall) {
|
|
3510
3688
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3511
3689
|
addIssueToContext(ctx, {
|
|
@@ -3520,9 +3698,7 @@ class ZodNumber extends ZodType {
|
|
|
3520
3698
|
}
|
|
3521
3699
|
}
|
|
3522
3700
|
else if (check.kind === "max") {
|
|
3523
|
-
const tooBig = check.inclusive
|
|
3524
|
-
? input.data > check.value
|
|
3525
|
-
: input.data >= check.value;
|
|
3701
|
+
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
3526
3702
|
if (tooBig) {
|
|
3527
3703
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3528
3704
|
addIssueToContext(ctx, {
|
|
@@ -3680,15 +3856,13 @@ class ZodNumber extends ZodType {
|
|
|
3680
3856
|
return max;
|
|
3681
3857
|
}
|
|
3682
3858
|
get isInt() {
|
|
3683
|
-
return !!this._def.checks.find((ch) => ch.kind === "int" ||
|
|
3684
|
-
(ch.kind === "multipleOf" && util.isInteger(ch.value)));
|
|
3859
|
+
return !!this._def.checks.find((ch) => ch.kind === "int" || (ch.kind === "multipleOf" && util.isInteger(ch.value)));
|
|
3685
3860
|
}
|
|
3686
3861
|
get isFinite() {
|
|
3687
|
-
let max = null
|
|
3862
|
+
let max = null;
|
|
3863
|
+
let min = null;
|
|
3688
3864
|
for (const ch of this._def.checks) {
|
|
3689
|
-
if (ch.kind === "finite" ||
|
|
3690
|
-
ch.kind === "int" ||
|
|
3691
|
-
ch.kind === "multipleOf") {
|
|
3865
|
+
if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") {
|
|
3692
3866
|
return true;
|
|
3693
3867
|
}
|
|
3694
3868
|
else if (ch.kind === "min") {
|
|
@@ -3707,7 +3881,7 @@ ZodNumber.create = (params) => {
|
|
|
3707
3881
|
return new ZodNumber({
|
|
3708
3882
|
checks: [],
|
|
3709
3883
|
typeName: ZodFirstPartyTypeKind.ZodNumber,
|
|
3710
|
-
coerce:
|
|
3884
|
+
coerce: params?.coerce || false,
|
|
3711
3885
|
...processCreateParams(params),
|
|
3712
3886
|
});
|
|
3713
3887
|
};
|
|
@@ -3722,7 +3896,7 @@ class ZodBigInt extends ZodType {
|
|
|
3722
3896
|
try {
|
|
3723
3897
|
input.data = BigInt(input.data);
|
|
3724
3898
|
}
|
|
3725
|
-
catch
|
|
3899
|
+
catch {
|
|
3726
3900
|
return this._getInvalidInput(input);
|
|
3727
3901
|
}
|
|
3728
3902
|
}
|
|
@@ -3734,9 +3908,7 @@ class ZodBigInt extends ZodType {
|
|
|
3734
3908
|
const status = new ParseStatus();
|
|
3735
3909
|
for (const check of this._def.checks) {
|
|
3736
3910
|
if (check.kind === "min") {
|
|
3737
|
-
const tooSmall = check.inclusive
|
|
3738
|
-
? input.data < check.value
|
|
3739
|
-
: input.data <= check.value;
|
|
3911
|
+
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
3740
3912
|
if (tooSmall) {
|
|
3741
3913
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3742
3914
|
addIssueToContext(ctx, {
|
|
@@ -3750,9 +3922,7 @@ class ZodBigInt extends ZodType {
|
|
|
3750
3922
|
}
|
|
3751
3923
|
}
|
|
3752
3924
|
else if (check.kind === "max") {
|
|
3753
|
-
const tooBig = check.inclusive
|
|
3754
|
-
? input.data > check.value
|
|
3755
|
-
: input.data >= check.value;
|
|
3925
|
+
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
3756
3926
|
if (tooBig) {
|
|
3757
3927
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3758
3928
|
addIssueToContext(ctx, {
|
|
@@ -3884,11 +4054,10 @@ class ZodBigInt extends ZodType {
|
|
|
3884
4054
|
}
|
|
3885
4055
|
}
|
|
3886
4056
|
ZodBigInt.create = (params) => {
|
|
3887
|
-
var _a;
|
|
3888
4057
|
return new ZodBigInt({
|
|
3889
4058
|
checks: [],
|
|
3890
4059
|
typeName: ZodFirstPartyTypeKind.ZodBigInt,
|
|
3891
|
-
coerce:
|
|
4060
|
+
coerce: params?.coerce ?? false,
|
|
3892
4061
|
...processCreateParams(params),
|
|
3893
4062
|
});
|
|
3894
4063
|
};
|
|
@@ -3913,7 +4082,7 @@ class ZodBoolean extends ZodType {
|
|
|
3913
4082
|
ZodBoolean.create = (params) => {
|
|
3914
4083
|
return new ZodBoolean({
|
|
3915
4084
|
typeName: ZodFirstPartyTypeKind.ZodBoolean,
|
|
3916
|
-
coerce:
|
|
4085
|
+
coerce: params?.coerce || false,
|
|
3917
4086
|
...processCreateParams(params),
|
|
3918
4087
|
});
|
|
3919
4088
|
};
|
|
@@ -3932,7 +4101,7 @@ class ZodDate extends ZodType {
|
|
|
3932
4101
|
});
|
|
3933
4102
|
return INVALID;
|
|
3934
4103
|
}
|
|
3935
|
-
if (isNaN(input.data.getTime())) {
|
|
4104
|
+
if (Number.isNaN(input.data.getTime())) {
|
|
3936
4105
|
const ctx = this._getOrReturnCtx(input);
|
|
3937
4106
|
addIssueToContext(ctx, {
|
|
3938
4107
|
code: ZodIssueCode.invalid_date,
|
|
@@ -4023,7 +4192,7 @@ class ZodDate extends ZodType {
|
|
|
4023
4192
|
ZodDate.create = (params) => {
|
|
4024
4193
|
return new ZodDate({
|
|
4025
4194
|
checks: [],
|
|
4026
|
-
coerce:
|
|
4195
|
+
coerce: params?.coerce || false,
|
|
4027
4196
|
typeName: ZodFirstPartyTypeKind.ZodDate,
|
|
4028
4197
|
...processCreateParams(params),
|
|
4029
4198
|
});
|
|
@@ -4345,7 +4514,8 @@ class ZodObject extends ZodType {
|
|
|
4345
4514
|
return this._cached;
|
|
4346
4515
|
const shape = this._def.shape();
|
|
4347
4516
|
const keys = util.objectKeys(shape);
|
|
4348
|
-
|
|
4517
|
+
this._cached = { shape, keys };
|
|
4518
|
+
return this._cached;
|
|
4349
4519
|
}
|
|
4350
4520
|
_parse(input) {
|
|
4351
4521
|
const parsedType = this._getType(input);
|
|
@@ -4361,8 +4531,7 @@ class ZodObject extends ZodType {
|
|
|
4361
4531
|
const { status, ctx } = this._processInputParams(input);
|
|
4362
4532
|
const { shape, keys: shapeKeys } = this._getCached();
|
|
4363
4533
|
const extraKeys = [];
|
|
4364
|
-
if (!(this._def.catchall instanceof ZodNever &&
|
|
4365
|
-
this._def.unknownKeys === "strip")) {
|
|
4534
|
+
if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
|
|
4366
4535
|
for (const key in ctx.data) {
|
|
4367
4536
|
if (!shapeKeys.includes(key)) {
|
|
4368
4537
|
extraKeys.push(key);
|
|
@@ -4450,11 +4619,10 @@ class ZodObject extends ZodType {
|
|
|
4450
4619
|
...(message !== undefined
|
|
4451
4620
|
? {
|
|
4452
4621
|
errorMap: (issue, ctx) => {
|
|
4453
|
-
|
|
4454
|
-
const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError;
|
|
4622
|
+
const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;
|
|
4455
4623
|
if (issue.code === "unrecognized_keys")
|
|
4456
4624
|
return {
|
|
4457
|
-
message:
|
|
4625
|
+
message: errorUtil.errToObj(message).message ?? defaultError,
|
|
4458
4626
|
};
|
|
4459
4627
|
return {
|
|
4460
4628
|
message: defaultError,
|
|
@@ -4586,11 +4754,11 @@ class ZodObject extends ZodType {
|
|
|
4586
4754
|
}
|
|
4587
4755
|
pick(mask) {
|
|
4588
4756
|
const shape = {};
|
|
4589
|
-
util.objectKeys(mask)
|
|
4757
|
+
for (const key of util.objectKeys(mask)) {
|
|
4590
4758
|
if (mask[key] && this.shape[key]) {
|
|
4591
4759
|
shape[key] = this.shape[key];
|
|
4592
4760
|
}
|
|
4593
|
-
}
|
|
4761
|
+
}
|
|
4594
4762
|
return new ZodObject({
|
|
4595
4763
|
...this._def,
|
|
4596
4764
|
shape: () => shape,
|
|
@@ -4598,11 +4766,11 @@ class ZodObject extends ZodType {
|
|
|
4598
4766
|
}
|
|
4599
4767
|
omit(mask) {
|
|
4600
4768
|
const shape = {};
|
|
4601
|
-
util.objectKeys(this.shape)
|
|
4769
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4602
4770
|
if (!mask[key]) {
|
|
4603
4771
|
shape[key] = this.shape[key];
|
|
4604
4772
|
}
|
|
4605
|
-
}
|
|
4773
|
+
}
|
|
4606
4774
|
return new ZodObject({
|
|
4607
4775
|
...this._def,
|
|
4608
4776
|
shape: () => shape,
|
|
@@ -4616,7 +4784,7 @@ class ZodObject extends ZodType {
|
|
|
4616
4784
|
}
|
|
4617
4785
|
partial(mask) {
|
|
4618
4786
|
const newShape = {};
|
|
4619
|
-
util.objectKeys(this.shape)
|
|
4787
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4620
4788
|
const fieldSchema = this.shape[key];
|
|
4621
4789
|
if (mask && !mask[key]) {
|
|
4622
4790
|
newShape[key] = fieldSchema;
|
|
@@ -4624,7 +4792,7 @@ class ZodObject extends ZodType {
|
|
|
4624
4792
|
else {
|
|
4625
4793
|
newShape[key] = fieldSchema.optional();
|
|
4626
4794
|
}
|
|
4627
|
-
}
|
|
4795
|
+
}
|
|
4628
4796
|
return new ZodObject({
|
|
4629
4797
|
...this._def,
|
|
4630
4798
|
shape: () => newShape,
|
|
@@ -4632,7 +4800,7 @@ class ZodObject extends ZodType {
|
|
|
4632
4800
|
}
|
|
4633
4801
|
required(mask) {
|
|
4634
4802
|
const newShape = {};
|
|
4635
|
-
util.objectKeys(this.shape)
|
|
4803
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4636
4804
|
if (mask && !mask[key]) {
|
|
4637
4805
|
newShape[key] = this.shape[key];
|
|
4638
4806
|
}
|
|
@@ -4644,7 +4812,7 @@ class ZodObject extends ZodType {
|
|
|
4644
4812
|
}
|
|
4645
4813
|
newShape[key] = newField;
|
|
4646
4814
|
}
|
|
4647
|
-
}
|
|
4815
|
+
}
|
|
4648
4816
|
return new ZodObject({
|
|
4649
4817
|
...this._def,
|
|
4650
4818
|
shape: () => newShape,
|
|
@@ -4777,137 +4945,6 @@ ZodUnion.create = (types, params) => {
|
|
|
4777
4945
|
...processCreateParams(params),
|
|
4778
4946
|
});
|
|
4779
4947
|
};
|
|
4780
|
-
/////////////////////////////////////////////////////
|
|
4781
|
-
/////////////////////////////////////////////////////
|
|
4782
|
-
////////// //////////
|
|
4783
|
-
////////// ZodDiscriminatedUnion //////////
|
|
4784
|
-
////////// //////////
|
|
4785
|
-
/////////////////////////////////////////////////////
|
|
4786
|
-
/////////////////////////////////////////////////////
|
|
4787
|
-
const getDiscriminator = (type) => {
|
|
4788
|
-
if (type instanceof ZodLazy) {
|
|
4789
|
-
return getDiscriminator(type.schema);
|
|
4790
|
-
}
|
|
4791
|
-
else if (type instanceof ZodEffects) {
|
|
4792
|
-
return getDiscriminator(type.innerType());
|
|
4793
|
-
}
|
|
4794
|
-
else if (type instanceof ZodLiteral) {
|
|
4795
|
-
return [type.value];
|
|
4796
|
-
}
|
|
4797
|
-
else if (type instanceof ZodEnum) {
|
|
4798
|
-
return type.options;
|
|
4799
|
-
}
|
|
4800
|
-
else if (type instanceof ZodNativeEnum) {
|
|
4801
|
-
// eslint-disable-next-line ban/ban
|
|
4802
|
-
return util.objectValues(type.enum);
|
|
4803
|
-
}
|
|
4804
|
-
else if (type instanceof ZodDefault) {
|
|
4805
|
-
return getDiscriminator(type._def.innerType);
|
|
4806
|
-
}
|
|
4807
|
-
else if (type instanceof ZodUndefined) {
|
|
4808
|
-
return [undefined];
|
|
4809
|
-
}
|
|
4810
|
-
else if (type instanceof ZodNull) {
|
|
4811
|
-
return [null];
|
|
4812
|
-
}
|
|
4813
|
-
else if (type instanceof ZodOptional) {
|
|
4814
|
-
return [undefined, ...getDiscriminator(type.unwrap())];
|
|
4815
|
-
}
|
|
4816
|
-
else if (type instanceof ZodNullable) {
|
|
4817
|
-
return [null, ...getDiscriminator(type.unwrap())];
|
|
4818
|
-
}
|
|
4819
|
-
else if (type instanceof ZodBranded) {
|
|
4820
|
-
return getDiscriminator(type.unwrap());
|
|
4821
|
-
}
|
|
4822
|
-
else if (type instanceof ZodReadonly) {
|
|
4823
|
-
return getDiscriminator(type.unwrap());
|
|
4824
|
-
}
|
|
4825
|
-
else if (type instanceof ZodCatch) {
|
|
4826
|
-
return getDiscriminator(type._def.innerType);
|
|
4827
|
-
}
|
|
4828
|
-
else {
|
|
4829
|
-
return [];
|
|
4830
|
-
}
|
|
4831
|
-
};
|
|
4832
|
-
class ZodDiscriminatedUnion extends ZodType {
|
|
4833
|
-
_parse(input) {
|
|
4834
|
-
const { ctx } = this._processInputParams(input);
|
|
4835
|
-
if (ctx.parsedType !== ZodParsedType.object) {
|
|
4836
|
-
addIssueToContext(ctx, {
|
|
4837
|
-
code: ZodIssueCode.invalid_type,
|
|
4838
|
-
expected: ZodParsedType.object,
|
|
4839
|
-
received: ctx.parsedType,
|
|
4840
|
-
});
|
|
4841
|
-
return INVALID;
|
|
4842
|
-
}
|
|
4843
|
-
const discriminator = this.discriminator;
|
|
4844
|
-
const discriminatorValue = ctx.data[discriminator];
|
|
4845
|
-
const option = this.optionsMap.get(discriminatorValue);
|
|
4846
|
-
if (!option) {
|
|
4847
|
-
addIssueToContext(ctx, {
|
|
4848
|
-
code: ZodIssueCode.invalid_union_discriminator,
|
|
4849
|
-
options: Array.from(this.optionsMap.keys()),
|
|
4850
|
-
path: [discriminator],
|
|
4851
|
-
});
|
|
4852
|
-
return INVALID;
|
|
4853
|
-
}
|
|
4854
|
-
if (ctx.common.async) {
|
|
4855
|
-
return option._parseAsync({
|
|
4856
|
-
data: ctx.data,
|
|
4857
|
-
path: ctx.path,
|
|
4858
|
-
parent: ctx,
|
|
4859
|
-
});
|
|
4860
|
-
}
|
|
4861
|
-
else {
|
|
4862
|
-
return option._parseSync({
|
|
4863
|
-
data: ctx.data,
|
|
4864
|
-
path: ctx.path,
|
|
4865
|
-
parent: ctx,
|
|
4866
|
-
});
|
|
4867
|
-
}
|
|
4868
|
-
}
|
|
4869
|
-
get discriminator() {
|
|
4870
|
-
return this._def.discriminator;
|
|
4871
|
-
}
|
|
4872
|
-
get options() {
|
|
4873
|
-
return this._def.options;
|
|
4874
|
-
}
|
|
4875
|
-
get optionsMap() {
|
|
4876
|
-
return this._def.optionsMap;
|
|
4877
|
-
}
|
|
4878
|
-
/**
|
|
4879
|
-
* The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor.
|
|
4880
|
-
* However, it only allows a union of objects, all of which need to share a discriminator property. This property must
|
|
4881
|
-
* have a different value for each object in the union.
|
|
4882
|
-
* @param discriminator the name of the discriminator property
|
|
4883
|
-
* @param types an array of object schemas
|
|
4884
|
-
* @param params
|
|
4885
|
-
*/
|
|
4886
|
-
static create(discriminator, options, params) {
|
|
4887
|
-
// Get all the valid discriminator values
|
|
4888
|
-
const optionsMap = new Map();
|
|
4889
|
-
// try {
|
|
4890
|
-
for (const type of options) {
|
|
4891
|
-
const discriminatorValues = getDiscriminator(type.shape[discriminator]);
|
|
4892
|
-
if (!discriminatorValues.length) {
|
|
4893
|
-
throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
|
|
4894
|
-
}
|
|
4895
|
-
for (const value of discriminatorValues) {
|
|
4896
|
-
if (optionsMap.has(value)) {
|
|
4897
|
-
throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
|
|
4898
|
-
}
|
|
4899
|
-
optionsMap.set(value, type);
|
|
4900
|
-
}
|
|
4901
|
-
}
|
|
4902
|
-
return new ZodDiscriminatedUnion({
|
|
4903
|
-
typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,
|
|
4904
|
-
discriminator,
|
|
4905
|
-
options,
|
|
4906
|
-
optionsMap,
|
|
4907
|
-
...processCreateParams(params),
|
|
4908
|
-
});
|
|
4909
|
-
}
|
|
4910
|
-
}
|
|
4911
4948
|
function mergeValues(a, b) {
|
|
4912
4949
|
const aType = getParsedType(a);
|
|
4913
4950
|
const bType = getParsedType(b);
|
|
@@ -4916,9 +4953,7 @@ function mergeValues(a, b) {
|
|
|
4916
4953
|
}
|
|
4917
4954
|
else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
|
|
4918
4955
|
const bKeys = util.objectKeys(b);
|
|
4919
|
-
const sharedKeys = util
|
|
4920
|
-
.objectKeys(a)
|
|
4921
|
-
.filter((key) => bKeys.indexOf(key) !== -1);
|
|
4956
|
+
const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
4922
4957
|
const newObj = { ...a, ...b };
|
|
4923
4958
|
for (const key of sharedKeys) {
|
|
4924
4959
|
const sharedValue = mergeValues(a[key], b[key]);
|
|
@@ -4945,9 +4980,7 @@ function mergeValues(a, b) {
|
|
|
4945
4980
|
}
|
|
4946
4981
|
return { valid: true, data: newArray };
|
|
4947
4982
|
}
|
|
4948
|
-
else if (aType === ZodParsedType.date &&
|
|
4949
|
-
bType === ZodParsedType.date &&
|
|
4950
|
-
+a === +b) {
|
|
4983
|
+
else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) {
|
|
4951
4984
|
return { valid: true, data: a };
|
|
4952
4985
|
}
|
|
4953
4986
|
else {
|
|
@@ -5008,6 +5041,7 @@ ZodIntersection.create = (left, right, params) => {
|
|
|
5008
5041
|
...processCreateParams(params),
|
|
5009
5042
|
});
|
|
5010
5043
|
};
|
|
5044
|
+
// type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]];
|
|
5011
5045
|
class ZodTuple extends ZodType {
|
|
5012
5046
|
_parse(input) {
|
|
5013
5047
|
const { status, ctx } = this._processInputParams(input);
|
|
@@ -5078,7 +5112,7 @@ ZodTuple.create = (schemas, params) => {
|
|
|
5078
5112
|
...processCreateParams(params),
|
|
5079
5113
|
});
|
|
5080
5114
|
};
|
|
5081
|
-
class
|
|
5115
|
+
class ZodMap extends ZodType {
|
|
5082
5116
|
get keySchema() {
|
|
5083
5117
|
return this._def.keyType;
|
|
5084
5118
|
}
|
|
@@ -5087,75 +5121,21 @@ class ZodRecord extends ZodType {
|
|
|
5087
5121
|
}
|
|
5088
5122
|
_parse(input) {
|
|
5089
5123
|
const { status, ctx } = this._processInputParams(input);
|
|
5090
|
-
if (ctx.parsedType !== ZodParsedType.
|
|
5124
|
+
if (ctx.parsedType !== ZodParsedType.map) {
|
|
5091
5125
|
addIssueToContext(ctx, {
|
|
5092
5126
|
code: ZodIssueCode.invalid_type,
|
|
5093
|
-
expected: ZodParsedType.
|
|
5127
|
+
expected: ZodParsedType.map,
|
|
5094
5128
|
received: ctx.parsedType,
|
|
5095
5129
|
});
|
|
5096
5130
|
return INVALID;
|
|
5097
5131
|
}
|
|
5098
|
-
const pairs = [];
|
|
5099
5132
|
const keyType = this._def.keyType;
|
|
5100
5133
|
const valueType = this._def.valueType;
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
|
|
5104
|
-
value: valueType._parse(new ParseInputLazyPath(ctx,
|
|
5105
|
-
|
|
5106
|
-
});
|
|
5107
|
-
}
|
|
5108
|
-
if (ctx.common.async) {
|
|
5109
|
-
return ParseStatus.mergeObjectAsync(status, pairs);
|
|
5110
|
-
}
|
|
5111
|
-
else {
|
|
5112
|
-
return ParseStatus.mergeObjectSync(status, pairs);
|
|
5113
|
-
}
|
|
5114
|
-
}
|
|
5115
|
-
get element() {
|
|
5116
|
-
return this._def.valueType;
|
|
5117
|
-
}
|
|
5118
|
-
static create(first, second, third) {
|
|
5119
|
-
if (second instanceof ZodType) {
|
|
5120
|
-
return new ZodRecord({
|
|
5121
|
-
keyType: first,
|
|
5122
|
-
valueType: second,
|
|
5123
|
-
typeName: ZodFirstPartyTypeKind.ZodRecord,
|
|
5124
|
-
...processCreateParams(third),
|
|
5125
|
-
});
|
|
5126
|
-
}
|
|
5127
|
-
return new ZodRecord({
|
|
5128
|
-
keyType: ZodString.create(),
|
|
5129
|
-
valueType: first,
|
|
5130
|
-
typeName: ZodFirstPartyTypeKind.ZodRecord,
|
|
5131
|
-
...processCreateParams(second),
|
|
5132
|
-
});
|
|
5133
|
-
}
|
|
5134
|
-
}
|
|
5135
|
-
class ZodMap extends ZodType {
|
|
5136
|
-
get keySchema() {
|
|
5137
|
-
return this._def.keyType;
|
|
5138
|
-
}
|
|
5139
|
-
get valueSchema() {
|
|
5140
|
-
return this._def.valueType;
|
|
5141
|
-
}
|
|
5142
|
-
_parse(input) {
|
|
5143
|
-
const { status, ctx } = this._processInputParams(input);
|
|
5144
|
-
if (ctx.parsedType !== ZodParsedType.map) {
|
|
5145
|
-
addIssueToContext(ctx, {
|
|
5146
|
-
code: ZodIssueCode.invalid_type,
|
|
5147
|
-
expected: ZodParsedType.map,
|
|
5148
|
-
received: ctx.parsedType,
|
|
5149
|
-
});
|
|
5150
|
-
return INVALID;
|
|
5151
|
-
}
|
|
5152
|
-
const keyType = this._def.keyType;
|
|
5153
|
-
const valueType = this._def.valueType;
|
|
5154
|
-
const pairs = [...ctx.data.entries()].map(([key, value], index) => {
|
|
5155
|
-
return {
|
|
5156
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
|
|
5157
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])),
|
|
5158
|
-
};
|
|
5134
|
+
const pairs = [...ctx.data.entries()].map(([key, value], index) => {
|
|
5135
|
+
return {
|
|
5136
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
|
|
5137
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])),
|
|
5138
|
+
};
|
|
5159
5139
|
});
|
|
5160
5140
|
if (ctx.common.async) {
|
|
5161
5141
|
const finalMap = new Map();
|
|
@@ -5285,134 +5265,6 @@ ZodSet.create = (valueType, params) => {
|
|
|
5285
5265
|
...processCreateParams(params),
|
|
5286
5266
|
});
|
|
5287
5267
|
};
|
|
5288
|
-
class ZodFunction extends ZodType {
|
|
5289
|
-
constructor() {
|
|
5290
|
-
super(...arguments);
|
|
5291
|
-
this.validate = this.implement;
|
|
5292
|
-
}
|
|
5293
|
-
_parse(input) {
|
|
5294
|
-
const { ctx } = this._processInputParams(input);
|
|
5295
|
-
if (ctx.parsedType !== ZodParsedType.function) {
|
|
5296
|
-
addIssueToContext(ctx, {
|
|
5297
|
-
code: ZodIssueCode.invalid_type,
|
|
5298
|
-
expected: ZodParsedType.function,
|
|
5299
|
-
received: ctx.parsedType,
|
|
5300
|
-
});
|
|
5301
|
-
return INVALID;
|
|
5302
|
-
}
|
|
5303
|
-
function makeArgsIssue(args, error) {
|
|
5304
|
-
return makeIssue({
|
|
5305
|
-
data: args,
|
|
5306
|
-
path: ctx.path,
|
|
5307
|
-
errorMaps: [
|
|
5308
|
-
ctx.common.contextualErrorMap,
|
|
5309
|
-
ctx.schemaErrorMap,
|
|
5310
|
-
getErrorMap(),
|
|
5311
|
-
errorMap,
|
|
5312
|
-
].filter((x) => !!x),
|
|
5313
|
-
issueData: {
|
|
5314
|
-
code: ZodIssueCode.invalid_arguments,
|
|
5315
|
-
argumentsError: error,
|
|
5316
|
-
},
|
|
5317
|
-
});
|
|
5318
|
-
}
|
|
5319
|
-
function makeReturnsIssue(returns, error) {
|
|
5320
|
-
return makeIssue({
|
|
5321
|
-
data: returns,
|
|
5322
|
-
path: ctx.path,
|
|
5323
|
-
errorMaps: [
|
|
5324
|
-
ctx.common.contextualErrorMap,
|
|
5325
|
-
ctx.schemaErrorMap,
|
|
5326
|
-
getErrorMap(),
|
|
5327
|
-
errorMap,
|
|
5328
|
-
].filter((x) => !!x),
|
|
5329
|
-
issueData: {
|
|
5330
|
-
code: ZodIssueCode.invalid_return_type,
|
|
5331
|
-
returnTypeError: error,
|
|
5332
|
-
},
|
|
5333
|
-
});
|
|
5334
|
-
}
|
|
5335
|
-
const params = { errorMap: ctx.common.contextualErrorMap };
|
|
5336
|
-
const fn = ctx.data;
|
|
5337
|
-
if (this._def.returns instanceof ZodPromise) {
|
|
5338
|
-
// Would love a way to avoid disabling this rule, but we need
|
|
5339
|
-
// an alias (using an arrow function was what caused 2651).
|
|
5340
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
5341
|
-
const me = this;
|
|
5342
|
-
return OK(async function (...args) {
|
|
5343
|
-
const error = new ZodError([]);
|
|
5344
|
-
const parsedArgs = await me._def.args
|
|
5345
|
-
.parseAsync(args, params)
|
|
5346
|
-
.catch((e) => {
|
|
5347
|
-
error.addIssue(makeArgsIssue(args, e));
|
|
5348
|
-
throw error;
|
|
5349
|
-
});
|
|
5350
|
-
const result = await Reflect.apply(fn, this, parsedArgs);
|
|
5351
|
-
const parsedReturns = await me._def.returns._def.type
|
|
5352
|
-
.parseAsync(result, params)
|
|
5353
|
-
.catch((e) => {
|
|
5354
|
-
error.addIssue(makeReturnsIssue(result, e));
|
|
5355
|
-
throw error;
|
|
5356
|
-
});
|
|
5357
|
-
return parsedReturns;
|
|
5358
|
-
});
|
|
5359
|
-
}
|
|
5360
|
-
else {
|
|
5361
|
-
// Would love a way to avoid disabling this rule, but we need
|
|
5362
|
-
// an alias (using an arrow function was what caused 2651).
|
|
5363
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
5364
|
-
const me = this;
|
|
5365
|
-
return OK(function (...args) {
|
|
5366
|
-
const parsedArgs = me._def.args.safeParse(args, params);
|
|
5367
|
-
if (!parsedArgs.success) {
|
|
5368
|
-
throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
|
|
5369
|
-
}
|
|
5370
|
-
const result = Reflect.apply(fn, this, parsedArgs.data);
|
|
5371
|
-
const parsedReturns = me._def.returns.safeParse(result, params);
|
|
5372
|
-
if (!parsedReturns.success) {
|
|
5373
|
-
throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
|
|
5374
|
-
}
|
|
5375
|
-
return parsedReturns.data;
|
|
5376
|
-
});
|
|
5377
|
-
}
|
|
5378
|
-
}
|
|
5379
|
-
parameters() {
|
|
5380
|
-
return this._def.args;
|
|
5381
|
-
}
|
|
5382
|
-
returnType() {
|
|
5383
|
-
return this._def.returns;
|
|
5384
|
-
}
|
|
5385
|
-
args(...items) {
|
|
5386
|
-
return new ZodFunction({
|
|
5387
|
-
...this._def,
|
|
5388
|
-
args: ZodTuple.create(items).rest(ZodUnknown.create()),
|
|
5389
|
-
});
|
|
5390
|
-
}
|
|
5391
|
-
returns(returnType) {
|
|
5392
|
-
return new ZodFunction({
|
|
5393
|
-
...this._def,
|
|
5394
|
-
returns: returnType,
|
|
5395
|
-
});
|
|
5396
|
-
}
|
|
5397
|
-
implement(func) {
|
|
5398
|
-
const validatedFunc = this.parse(func);
|
|
5399
|
-
return validatedFunc;
|
|
5400
|
-
}
|
|
5401
|
-
strictImplement(func) {
|
|
5402
|
-
const validatedFunc = this.parse(func);
|
|
5403
|
-
return validatedFunc;
|
|
5404
|
-
}
|
|
5405
|
-
static create(args, returns, params) {
|
|
5406
|
-
return new ZodFunction({
|
|
5407
|
-
args: (args
|
|
5408
|
-
? args
|
|
5409
|
-
: ZodTuple.create([]).rest(ZodUnknown.create())),
|
|
5410
|
-
returns: returns || ZodUnknown.create(),
|
|
5411
|
-
typeName: ZodFirstPartyTypeKind.ZodFunction,
|
|
5412
|
-
...processCreateParams(params),
|
|
5413
|
-
});
|
|
5414
|
-
}
|
|
5415
|
-
}
|
|
5416
5268
|
class ZodLazy extends ZodType {
|
|
5417
5269
|
get schema() {
|
|
5418
5270
|
return this._def.getter();
|
|
@@ -5462,10 +5314,6 @@ function createZodEnum(values, params) {
|
|
|
5462
5314
|
});
|
|
5463
5315
|
}
|
|
5464
5316
|
class ZodEnum extends ZodType {
|
|
5465
|
-
constructor() {
|
|
5466
|
-
super(...arguments);
|
|
5467
|
-
_ZodEnum_cache.set(this, void 0);
|
|
5468
|
-
}
|
|
5469
5317
|
_parse(input) {
|
|
5470
5318
|
if (typeof input.data !== "string") {
|
|
5471
5319
|
const ctx = this._getOrReturnCtx(input);
|
|
@@ -5477,10 +5325,10 @@ class ZodEnum extends ZodType {
|
|
|
5477
5325
|
});
|
|
5478
5326
|
return INVALID;
|
|
5479
5327
|
}
|
|
5480
|
-
if (!
|
|
5481
|
-
|
|
5328
|
+
if (!this._cache) {
|
|
5329
|
+
this._cache = new Set(this._def.values);
|
|
5482
5330
|
}
|
|
5483
|
-
if (!
|
|
5331
|
+
if (!this._cache.has(input.data)) {
|
|
5484
5332
|
const ctx = this._getOrReturnCtx(input);
|
|
5485
5333
|
const expectedValues = this._def.values;
|
|
5486
5334
|
addIssueToContext(ctx, {
|
|
@@ -5529,18 +5377,12 @@ class ZodEnum extends ZodType {
|
|
|
5529
5377
|
});
|
|
5530
5378
|
}
|
|
5531
5379
|
}
|
|
5532
|
-
_ZodEnum_cache = new WeakMap();
|
|
5533
5380
|
ZodEnum.create = createZodEnum;
|
|
5534
5381
|
class ZodNativeEnum extends ZodType {
|
|
5535
|
-
constructor() {
|
|
5536
|
-
super(...arguments);
|
|
5537
|
-
_ZodNativeEnum_cache.set(this, void 0);
|
|
5538
|
-
}
|
|
5539
5382
|
_parse(input) {
|
|
5540
5383
|
const nativeEnumValues = util.getValidEnumValues(this._def.values);
|
|
5541
5384
|
const ctx = this._getOrReturnCtx(input);
|
|
5542
|
-
if (ctx.parsedType !== ZodParsedType.string &&
|
|
5543
|
-
ctx.parsedType !== ZodParsedType.number) {
|
|
5385
|
+
if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) {
|
|
5544
5386
|
const expectedValues = util.objectValues(nativeEnumValues);
|
|
5545
5387
|
addIssueToContext(ctx, {
|
|
5546
5388
|
expected: util.joinValues(expectedValues),
|
|
@@ -5549,10 +5391,10 @@ class ZodNativeEnum extends ZodType {
|
|
|
5549
5391
|
});
|
|
5550
5392
|
return INVALID;
|
|
5551
5393
|
}
|
|
5552
|
-
if (!
|
|
5553
|
-
|
|
5394
|
+
if (!this._cache) {
|
|
5395
|
+
this._cache = new Set(util.getValidEnumValues(this._def.values));
|
|
5554
5396
|
}
|
|
5555
|
-
if (!
|
|
5397
|
+
if (!this._cache.has(input.data)) {
|
|
5556
5398
|
const expectedValues = util.objectValues(nativeEnumValues);
|
|
5557
5399
|
addIssueToContext(ctx, {
|
|
5558
5400
|
received: ctx.data,
|
|
@@ -5567,7 +5409,6 @@ class ZodNativeEnum extends ZodType {
|
|
|
5567
5409
|
return this._def.values;
|
|
5568
5410
|
}
|
|
5569
5411
|
}
|
|
5570
|
-
_ZodNativeEnum_cache = new WeakMap();
|
|
5571
5412
|
ZodNativeEnum.create = (values, params) => {
|
|
5572
5413
|
return new ZodNativeEnum({
|
|
5573
5414
|
values: values,
|
|
@@ -5581,8 +5422,7 @@ class ZodPromise extends ZodType {
|
|
|
5581
5422
|
}
|
|
5582
5423
|
_parse(input) {
|
|
5583
5424
|
const { ctx } = this._processInputParams(input);
|
|
5584
|
-
if (ctx.parsedType !== ZodParsedType.promise &&
|
|
5585
|
-
ctx.common.async === false) {
|
|
5425
|
+
if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) {
|
|
5586
5426
|
addIssueToContext(ctx, {
|
|
5587
5427
|
code: ZodIssueCode.invalid_type,
|
|
5588
5428
|
expected: ZodParsedType.promise,
|
|
@@ -5590,9 +5430,7 @@ class ZodPromise extends ZodType {
|
|
|
5590
5430
|
});
|
|
5591
5431
|
return INVALID;
|
|
5592
5432
|
}
|
|
5593
|
-
const promisified = ctx.parsedType === ZodParsedType.promise
|
|
5594
|
-
? ctx.data
|
|
5595
|
-
: Promise.resolve(ctx.data);
|
|
5433
|
+
const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);
|
|
5596
5434
|
return OK(promisified.then((data) => {
|
|
5597
5435
|
return this._def.type.parseAsync(data, {
|
|
5598
5436
|
path: ctx.path,
|
|
@@ -5698,9 +5536,7 @@ class ZodEffects extends ZodType {
|
|
|
5698
5536
|
return { status: status.value, value: inner.value };
|
|
5699
5537
|
}
|
|
5700
5538
|
else {
|
|
5701
|
-
return this._def.schema
|
|
5702
|
-
._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
|
|
5703
|
-
.then((inner) => {
|
|
5539
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {
|
|
5704
5540
|
if (inner.status === "aborted")
|
|
5705
5541
|
return INVALID;
|
|
5706
5542
|
if (inner.status === "dirty")
|
|
@@ -5719,7 +5555,7 @@ class ZodEffects extends ZodType {
|
|
|
5719
5555
|
parent: ctx,
|
|
5720
5556
|
});
|
|
5721
5557
|
if (!isValid(base))
|
|
5722
|
-
return
|
|
5558
|
+
return INVALID;
|
|
5723
5559
|
const result = effect.transform(base.value, checkCtx);
|
|
5724
5560
|
if (result instanceof Promise) {
|
|
5725
5561
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
@@ -5727,12 +5563,13 @@ class ZodEffects extends ZodType {
|
|
|
5727
5563
|
return { status: status.value, value: result };
|
|
5728
5564
|
}
|
|
5729
5565
|
else {
|
|
5730
|
-
return this._def.schema
|
|
5731
|
-
._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
|
|
5732
|
-
.then((base) => {
|
|
5566
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
|
|
5733
5567
|
if (!isValid(base))
|
|
5734
|
-
return
|
|
5735
|
-
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
|
|
5568
|
+
return INVALID;
|
|
5569
|
+
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
|
|
5570
|
+
status: status.value,
|
|
5571
|
+
value: result,
|
|
5572
|
+
}));
|
|
5736
5573
|
});
|
|
5737
5574
|
}
|
|
5738
5575
|
}
|
|
@@ -5814,9 +5651,7 @@ ZodDefault.create = (type, params) => {
|
|
|
5814
5651
|
return new ZodDefault({
|
|
5815
5652
|
innerType: type,
|
|
5816
5653
|
typeName: ZodFirstPartyTypeKind.ZodDefault,
|
|
5817
|
-
defaultValue: typeof params.default === "function"
|
|
5818
|
-
? params.default
|
|
5819
|
-
: () => params.default,
|
|
5654
|
+
defaultValue: typeof params.default === "function" ? params.default : () => params.default,
|
|
5820
5655
|
...processCreateParams(params),
|
|
5821
5656
|
});
|
|
5822
5657
|
};
|
|
@@ -5900,7 +5735,6 @@ ZodNaN.create = (params) => {
|
|
|
5900
5735
|
...processCreateParams(params),
|
|
5901
5736
|
});
|
|
5902
5737
|
};
|
|
5903
|
-
const BRAND = Symbol("zod_brand");
|
|
5904
5738
|
class ZodBranded extends ZodType {
|
|
5905
5739
|
_parse(input) {
|
|
5906
5740
|
const { ctx } = this._processInputParams(input);
|
|
@@ -5982,9 +5816,7 @@ class ZodReadonly extends ZodType {
|
|
|
5982
5816
|
}
|
|
5983
5817
|
return data;
|
|
5984
5818
|
};
|
|
5985
|
-
return isAsync(result)
|
|
5986
|
-
? result.then((data) => freeze(data))
|
|
5987
|
-
: freeze(result);
|
|
5819
|
+
return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result);
|
|
5988
5820
|
}
|
|
5989
5821
|
unwrap() {
|
|
5990
5822
|
return this._def.innerType;
|
|
@@ -5997,60 +5829,9 @@ ZodReadonly.create = (type, params) => {
|
|
|
5997
5829
|
...processCreateParams(params),
|
|
5998
5830
|
});
|
|
5999
5831
|
};
|
|
6000
|
-
|
|
6001
|
-
////////////////////////////////////////
|
|
6002
|
-
////////// //////////
|
|
6003
|
-
////////// z.custom //////////
|
|
6004
|
-
////////// //////////
|
|
6005
|
-
////////////////////////////////////////
|
|
6006
|
-
////////////////////////////////////////
|
|
6007
|
-
function cleanParams(params, data) {
|
|
6008
|
-
const p = typeof params === "function"
|
|
6009
|
-
? params(data)
|
|
6010
|
-
: typeof params === "string"
|
|
6011
|
-
? { message: params }
|
|
6012
|
-
: params;
|
|
6013
|
-
const p2 = typeof p === "string" ? { message: p } : p;
|
|
6014
|
-
return p2;
|
|
6015
|
-
}
|
|
6016
|
-
function custom(check, _params = {},
|
|
6017
|
-
/**
|
|
6018
|
-
* @deprecated
|
|
6019
|
-
*
|
|
6020
|
-
* Pass `fatal` into the params object instead:
|
|
6021
|
-
*
|
|
6022
|
-
* ```ts
|
|
6023
|
-
* z.string().custom((val) => val.length > 5, { fatal: false })
|
|
6024
|
-
* ```
|
|
6025
|
-
*
|
|
6026
|
-
*/
|
|
6027
|
-
fatal) {
|
|
6028
|
-
if (check)
|
|
6029
|
-
return ZodAny.create().superRefine((data, ctx) => {
|
|
6030
|
-
var _a, _b;
|
|
6031
|
-
const r = check(data);
|
|
6032
|
-
if (r instanceof Promise) {
|
|
6033
|
-
return r.then((r) => {
|
|
6034
|
-
var _a, _b;
|
|
6035
|
-
if (!r) {
|
|
6036
|
-
const params = cleanParams(_params, data);
|
|
6037
|
-
const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
|
|
6038
|
-
ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
|
|
6039
|
-
}
|
|
6040
|
-
});
|
|
6041
|
-
}
|
|
6042
|
-
if (!r) {
|
|
6043
|
-
const params = cleanParams(_params, data);
|
|
6044
|
-
const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
|
|
6045
|
-
ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
|
|
6046
|
-
}
|
|
6047
|
-
return;
|
|
6048
|
-
});
|
|
6049
|
-
return ZodAny.create();
|
|
6050
|
-
}
|
|
6051
|
-
const late = {
|
|
5832
|
+
({
|
|
6052
5833
|
object: ZodObject.lazycreate,
|
|
6053
|
-
};
|
|
5834
|
+
});
|
|
6054
5835
|
var ZodFirstPartyTypeKind;
|
|
6055
5836
|
(function (ZodFirstPartyTypeKind) {
|
|
6056
5837
|
ZodFirstPartyTypeKind["ZodString"] = "ZodString";
|
|
@@ -6090,174 +5871,23 @@ var ZodFirstPartyTypeKind;
|
|
|
6090
5871
|
ZodFirstPartyTypeKind["ZodPipeline"] = "ZodPipeline";
|
|
6091
5872
|
ZodFirstPartyTypeKind["ZodReadonly"] = "ZodReadonly";
|
|
6092
5873
|
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
6093
|
-
const instanceOfType = (
|
|
6094
|
-
// const instanceOfType = <T extends new (...args: any[]) => any>(
|
|
6095
|
-
cls, params = {
|
|
6096
|
-
message: `Input not instance of ${cls.name}`,
|
|
6097
|
-
}) => custom((data) => data instanceof cls, params);
|
|
6098
5874
|
const stringType = ZodString.create;
|
|
6099
|
-
|
|
6100
|
-
const nanType = ZodNaN.create;
|
|
6101
|
-
const bigIntType = ZodBigInt.create;
|
|
6102
|
-
const booleanType = ZodBoolean.create;
|
|
6103
|
-
const dateType = ZodDate.create;
|
|
6104
|
-
const symbolType = ZodSymbol.create;
|
|
6105
|
-
const undefinedType = ZodUndefined.create;
|
|
6106
|
-
const nullType = ZodNull.create;
|
|
6107
|
-
const anyType = ZodAny.create;
|
|
6108
|
-
const unknownType = ZodUnknown.create;
|
|
6109
|
-
const neverType = ZodNever.create;
|
|
6110
|
-
const voidType = ZodVoid.create;
|
|
5875
|
+
ZodNever.create;
|
|
6111
5876
|
const arrayType = ZodArray.create;
|
|
6112
5877
|
const objectType = ZodObject.create;
|
|
6113
|
-
|
|
5878
|
+
ZodObject.strictCreate;
|
|
6114
5879
|
const unionType = ZodUnion.create;
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
const tupleType = ZodTuple.create;
|
|
6118
|
-
const recordType = ZodRecord.create;
|
|
6119
|
-
const mapType = ZodMap.create;
|
|
6120
|
-
const setType = ZodSet.create;
|
|
6121
|
-
const functionType = ZodFunction.create;
|
|
6122
|
-
const lazyType = ZodLazy.create;
|
|
5880
|
+
ZodIntersection.create;
|
|
5881
|
+
ZodTuple.create;
|
|
6123
5882
|
const literalType = ZodLiteral.create;
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
const
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
const ostring = () => stringType().optional();
|
|
6133
|
-
const onumber = () => numberType().optional();
|
|
6134
|
-
const oboolean = () => booleanType().optional();
|
|
6135
|
-
const coerce = {
|
|
6136
|
-
string: ((arg) => ZodString.create({ ...arg, coerce: true })),
|
|
6137
|
-
number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),
|
|
6138
|
-
boolean: ((arg) => ZodBoolean.create({
|
|
6139
|
-
...arg,
|
|
6140
|
-
coerce: true,
|
|
6141
|
-
})),
|
|
6142
|
-
bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),
|
|
6143
|
-
date: ((arg) => ZodDate.create({ ...arg, coerce: true })),
|
|
6144
|
-
};
|
|
6145
|
-
const NEVER = INVALID;
|
|
6146
|
-
|
|
6147
|
-
var z = /*#__PURE__*/Object.freeze({
|
|
6148
|
-
__proto__: null,
|
|
6149
|
-
defaultErrorMap: errorMap,
|
|
6150
|
-
setErrorMap: setErrorMap,
|
|
6151
|
-
getErrorMap: getErrorMap,
|
|
6152
|
-
makeIssue: makeIssue,
|
|
6153
|
-
EMPTY_PATH: EMPTY_PATH,
|
|
6154
|
-
addIssueToContext: addIssueToContext,
|
|
6155
|
-
ParseStatus: ParseStatus,
|
|
6156
|
-
INVALID: INVALID,
|
|
6157
|
-
DIRTY: DIRTY,
|
|
6158
|
-
OK: OK,
|
|
6159
|
-
isAborted: isAborted,
|
|
6160
|
-
isDirty: isDirty,
|
|
6161
|
-
isValid: isValid,
|
|
6162
|
-
isAsync: isAsync,
|
|
6163
|
-
get util () { return util; },
|
|
6164
|
-
get objectUtil () { return objectUtil; },
|
|
6165
|
-
ZodParsedType: ZodParsedType,
|
|
6166
|
-
getParsedType: getParsedType,
|
|
6167
|
-
ZodType: ZodType,
|
|
6168
|
-
datetimeRegex: datetimeRegex,
|
|
6169
|
-
ZodString: ZodString,
|
|
6170
|
-
ZodNumber: ZodNumber,
|
|
6171
|
-
ZodBigInt: ZodBigInt,
|
|
6172
|
-
ZodBoolean: ZodBoolean,
|
|
6173
|
-
ZodDate: ZodDate,
|
|
6174
|
-
ZodSymbol: ZodSymbol,
|
|
6175
|
-
ZodUndefined: ZodUndefined,
|
|
6176
|
-
ZodNull: ZodNull,
|
|
6177
|
-
ZodAny: ZodAny,
|
|
6178
|
-
ZodUnknown: ZodUnknown,
|
|
6179
|
-
ZodNever: ZodNever,
|
|
6180
|
-
ZodVoid: ZodVoid,
|
|
6181
|
-
ZodArray: ZodArray,
|
|
6182
|
-
ZodObject: ZodObject,
|
|
6183
|
-
ZodUnion: ZodUnion,
|
|
6184
|
-
ZodDiscriminatedUnion: ZodDiscriminatedUnion,
|
|
6185
|
-
ZodIntersection: ZodIntersection,
|
|
6186
|
-
ZodTuple: ZodTuple,
|
|
6187
|
-
ZodRecord: ZodRecord,
|
|
6188
|
-
ZodMap: ZodMap,
|
|
6189
|
-
ZodSet: ZodSet,
|
|
6190
|
-
ZodFunction: ZodFunction,
|
|
6191
|
-
ZodLazy: ZodLazy,
|
|
6192
|
-
ZodLiteral: ZodLiteral,
|
|
6193
|
-
ZodEnum: ZodEnum,
|
|
6194
|
-
ZodNativeEnum: ZodNativeEnum,
|
|
6195
|
-
ZodPromise: ZodPromise,
|
|
6196
|
-
ZodEffects: ZodEffects,
|
|
6197
|
-
ZodTransformer: ZodEffects,
|
|
6198
|
-
ZodOptional: ZodOptional,
|
|
6199
|
-
ZodNullable: ZodNullable,
|
|
6200
|
-
ZodDefault: ZodDefault,
|
|
6201
|
-
ZodCatch: ZodCatch,
|
|
6202
|
-
ZodNaN: ZodNaN,
|
|
6203
|
-
BRAND: BRAND,
|
|
6204
|
-
ZodBranded: ZodBranded,
|
|
6205
|
-
ZodPipeline: ZodPipeline,
|
|
6206
|
-
ZodReadonly: ZodReadonly,
|
|
6207
|
-
custom: custom,
|
|
6208
|
-
Schema: ZodType,
|
|
6209
|
-
ZodSchema: ZodType,
|
|
6210
|
-
late: late,
|
|
6211
|
-
get ZodFirstPartyTypeKind () { return ZodFirstPartyTypeKind; },
|
|
6212
|
-
coerce: coerce,
|
|
6213
|
-
any: anyType,
|
|
6214
|
-
array: arrayType,
|
|
6215
|
-
bigint: bigIntType,
|
|
6216
|
-
boolean: booleanType,
|
|
6217
|
-
date: dateType,
|
|
6218
|
-
discriminatedUnion: discriminatedUnionType,
|
|
6219
|
-
effect: effectsType,
|
|
6220
|
-
'enum': enumType,
|
|
6221
|
-
'function': functionType,
|
|
6222
|
-
'instanceof': instanceOfType,
|
|
6223
|
-
intersection: intersectionType,
|
|
6224
|
-
lazy: lazyType,
|
|
6225
|
-
literal: literalType,
|
|
6226
|
-
map: mapType,
|
|
6227
|
-
nan: nanType,
|
|
6228
|
-
nativeEnum: nativeEnumType,
|
|
6229
|
-
never: neverType,
|
|
6230
|
-
'null': nullType,
|
|
6231
|
-
nullable: nullableType,
|
|
6232
|
-
number: numberType,
|
|
6233
|
-
object: objectType,
|
|
6234
|
-
oboolean: oboolean,
|
|
6235
|
-
onumber: onumber,
|
|
6236
|
-
optional: optionalType,
|
|
6237
|
-
ostring: ostring,
|
|
6238
|
-
pipeline: pipelineType,
|
|
6239
|
-
preprocess: preprocessType,
|
|
6240
|
-
promise: promiseType,
|
|
6241
|
-
record: recordType,
|
|
6242
|
-
set: setType,
|
|
6243
|
-
strictObject: strictObjectType,
|
|
6244
|
-
string: stringType,
|
|
6245
|
-
symbol: symbolType,
|
|
6246
|
-
transformer: effectsType,
|
|
6247
|
-
tuple: tupleType,
|
|
6248
|
-
'undefined': undefinedType,
|
|
6249
|
-
union: unionType,
|
|
6250
|
-
unknown: unknownType,
|
|
6251
|
-
'void': voidType,
|
|
6252
|
-
NEVER: NEVER,
|
|
6253
|
-
ZodIssueCode: ZodIssueCode,
|
|
6254
|
-
quotelessJson: quotelessJson,
|
|
6255
|
-
ZodError: ZodError
|
|
6256
|
-
});
|
|
6257
|
-
|
|
6258
|
-
const ChangelogResponseSchema = z.object({
|
|
6259
|
-
title: z.string(),
|
|
6260
|
-
content: z.string(),
|
|
5883
|
+
ZodEnum.create;
|
|
5884
|
+
ZodPromise.create;
|
|
5885
|
+
ZodOptional.create;
|
|
5886
|
+
ZodNullable.create;
|
|
5887
|
+
|
|
5888
|
+
const ChangelogResponseSchema = objectType({
|
|
5889
|
+
title: stringType(),
|
|
5890
|
+
content: stringType(),
|
|
6261
5891
|
});
|
|
6262
5892
|
const command$4 = 'changelog';
|
|
6263
5893
|
/**
|
|
@@ -6291,70 +5921,233 @@ const builder$4 = (yargs) => {
|
|
|
6291
5921
|
};
|
|
6292
5922
|
|
|
6293
5923
|
/**
|
|
6294
|
-
*
|
|
5924
|
+
* Default retry predicate - retries on non-validation errors
|
|
5925
|
+
*/
|
|
5926
|
+
function defaultShouldRetry(error) {
|
|
5927
|
+
// Don't retry validation errors or configuration errors
|
|
5928
|
+
if (error.name.includes('Validation') || error.name.includes('Configuration')) {
|
|
5929
|
+
return false;
|
|
5930
|
+
}
|
|
5931
|
+
// Don't retry authentication errors
|
|
5932
|
+
if (error.name.includes('Authentication')) {
|
|
5933
|
+
return false;
|
|
5934
|
+
}
|
|
5935
|
+
// Retry execution errors and timeouts
|
|
5936
|
+
return true;
|
|
5937
|
+
}
|
|
5938
|
+
/**
|
|
5939
|
+
* Executes an operation with retry logic
|
|
5940
|
+
*/
|
|
5941
|
+
async function withRetry(operation, options = {}) {
|
|
5942
|
+
const { maxAttempts = 3, backoffMs = 1000, backoffMultiplier = 2, maxBackoffMs = 10000, onRetry, shouldRetry = defaultShouldRetry } = options;
|
|
5943
|
+
let lastError = new Error('No attempts made');
|
|
5944
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5945
|
+
try {
|
|
5946
|
+
return await operation();
|
|
5947
|
+
}
|
|
5948
|
+
catch (error) {
|
|
5949
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
5950
|
+
// If this is the last attempt or we shouldn't retry, throw the error
|
|
5951
|
+
if (attempt === maxAttempts || !shouldRetry(lastError)) {
|
|
5952
|
+
throw lastError;
|
|
5953
|
+
}
|
|
5954
|
+
// Calculate delay with exponential backoff
|
|
5955
|
+
const delay = Math.min(backoffMs * Math.pow(backoffMultiplier, attempt - 1), maxBackoffMs);
|
|
5956
|
+
// Call retry callback if provided
|
|
5957
|
+
if (onRetry) {
|
|
5958
|
+
onRetry(attempt, lastError, delay);
|
|
5959
|
+
}
|
|
5960
|
+
// Wait before retrying
|
|
5961
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
// This should never be reached, but TypeScript requires it
|
|
5965
|
+
throw new Error(`Operation failed after ${maxAttempts} attempts. Last error: ${lastError.message}`);
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5968
|
+
/**
|
|
5969
|
+
* Wraps errors with additional context and converts them to LangChain errors
|
|
5970
|
+
*/
|
|
5971
|
+
function handleLangChainError(error, context, additionalContext) {
|
|
5972
|
+
// If it's already a LangChain error, re-throw with additional context
|
|
5973
|
+
if (error instanceof LangChainError) {
|
|
5974
|
+
throw new LangChainExecutionError(`${context}: ${error.message}`, {
|
|
5975
|
+
...error.context,
|
|
5976
|
+
...additionalContext,
|
|
5977
|
+
originalError: error.name,
|
|
5978
|
+
context
|
|
5979
|
+
});
|
|
5980
|
+
}
|
|
5981
|
+
// If it's a regular Error, wrap it
|
|
5982
|
+
if (error instanceof Error) {
|
|
5983
|
+
throw new LangChainExecutionError(`${context}: ${error.message}`, {
|
|
5984
|
+
originalError: error.name,
|
|
5985
|
+
originalMessage: error.message,
|
|
5986
|
+
stack: error.stack,
|
|
5987
|
+
context,
|
|
5988
|
+
...additionalContext
|
|
5989
|
+
});
|
|
5990
|
+
}
|
|
5991
|
+
// For unknown error types
|
|
5992
|
+
throw new LangChainExecutionError(`${context}: Unknown error occurred`, {
|
|
5993
|
+
originalError: typeof error,
|
|
5994
|
+
originalValue: String(error),
|
|
5995
|
+
context,
|
|
5996
|
+
...additionalContext
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
|
|
6000
|
+
/**
|
|
6001
|
+
* Creates and configures an LLM instance based on the provider and configuration.
|
|
6295
6002
|
*
|
|
6296
|
-
* @param
|
|
6297
|
-
* @param
|
|
6298
|
-
* @
|
|
6003
|
+
* @param provider - The LLM provider (openai, anthropic, ollama)
|
|
6004
|
+
* @param model - The specific model to use
|
|
6005
|
+
* @param config - The configuration object containing service settings
|
|
6006
|
+
* @returns Configured LLM instance
|
|
6007
|
+
* @throws LangChainConfigurationError if the provider/model combination is invalid
|
|
6008
|
+
* @throws LangChainExecutionError if LLM instantiation fails
|
|
6299
6009
|
*/
|
|
6300
6010
|
function getLlm(provider, model, config) {
|
|
6301
|
-
|
|
6302
|
-
|
|
6011
|
+
// Validate input parameters
|
|
6012
|
+
validateProvider(provider, 'getLlm');
|
|
6013
|
+
validateModel(model, provider, 'getLlm');
|
|
6014
|
+
validateRequired(config, 'config', 'getLlm');
|
|
6015
|
+
// Get the API key once and validate it
|
|
6016
|
+
let apiKey;
|
|
6017
|
+
try {
|
|
6018
|
+
apiKey = getApiKeyForModel(config);
|
|
6303
6019
|
}
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6020
|
+
catch (error) {
|
|
6021
|
+
handleLangChainError(error, 'getLlm: Failed to retrieve API key', { provider, model });
|
|
6022
|
+
}
|
|
6023
|
+
try {
|
|
6024
|
+
switch (provider) {
|
|
6025
|
+
case 'anthropic':
|
|
6026
|
+
return new ChatAnthropic({
|
|
6027
|
+
anthropicApiKey: apiKey,
|
|
6028
|
+
maxConcurrency: config.service.maxConcurrent,
|
|
6029
|
+
model,
|
|
6030
|
+
});
|
|
6031
|
+
case 'ollama':
|
|
6032
|
+
// Use endpoint from service config if available, otherwise fall back to default
|
|
6033
|
+
const endpoint = 'endpoint' in config.service
|
|
6034
|
+
? config.service.endpoint
|
|
6035
|
+
: DEFAULT_OLLAMA_LLM_SERVICE.endpoint;
|
|
6036
|
+
return new ChatOllama({
|
|
6037
|
+
baseUrl: endpoint,
|
|
6038
|
+
maxConcurrency: config.service.maxConcurrent,
|
|
6039
|
+
model,
|
|
6040
|
+
});
|
|
6041
|
+
case 'openai':
|
|
6042
|
+
return new ChatOpenAI({
|
|
6043
|
+
openAIApiKey: apiKey,
|
|
6044
|
+
model,
|
|
6045
|
+
temperature: config.service.temperature || 0.2,
|
|
6046
|
+
});
|
|
6047
|
+
default:
|
|
6048
|
+
throw new LangChainConfigurationError(`getLlm: Unsupported provider '${provider}'`, { provider, model, supportedProviders: ['openai', 'anthropic', 'ollama'] });
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
6051
|
+
catch (error) {
|
|
6052
|
+
// If it's already a LangChain error, re-throw it
|
|
6053
|
+
if (error instanceof LangChainConfigurationError || error instanceof LangChainExecutionError) {
|
|
6054
|
+
throw error;
|
|
6055
|
+
}
|
|
6056
|
+
// Wrap other errors
|
|
6057
|
+
handleLangChainError(error, `getLlm: Failed to instantiate ${provider} LLM`, {
|
|
6058
|
+
provider,
|
|
6059
|
+
model,
|
|
6060
|
+
hasApiKey: !!apiKey,
|
|
6061
|
+
serviceConfig: {
|
|
6314
6062
|
maxConcurrency: config.service.maxConcurrent,
|
|
6315
|
-
|
|
6316
|
-
}
|
|
6317
|
-
|
|
6318
|
-
default:
|
|
6319
|
-
const openAiModel = new ChatOpenAI({
|
|
6320
|
-
openAIApiKey: getApiKeyForModel(config),
|
|
6321
|
-
model,
|
|
6322
|
-
temperature: config.service.temperature || 0.2,
|
|
6323
|
-
});
|
|
6324
|
-
return openAiModel;
|
|
6063
|
+
temperature: config.service.temperature
|
|
6064
|
+
}
|
|
6065
|
+
});
|
|
6325
6066
|
}
|
|
6326
6067
|
}
|
|
6327
6068
|
|
|
6069
|
+
/**
|
|
6070
|
+
* Creates a PromptTemplate from a template string or returns a fallback template.
|
|
6071
|
+
*
|
|
6072
|
+
* @param params - The prompt creation parameters
|
|
6073
|
+
* @returns A configured PromptTemplate instance
|
|
6074
|
+
* @throws LangChainValidationError if neither template nor fallback is provided or if parameters are invalid
|
|
6075
|
+
* @throws LangChainExecutionError if PromptTemplate instantiation fails
|
|
6076
|
+
*/
|
|
6328
6077
|
function getPrompt({ template, variables, fallback }) {
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6078
|
+
// Validate that we have either a template or fallback
|
|
6079
|
+
if (!template && !fallback) {
|
|
6080
|
+
throw new LangChainValidationError('getPrompt: Must provide either a template string or a fallback PromptTemplate', { hasTemplate: !!template, hasFallback: !!fallback, variables });
|
|
6081
|
+
}
|
|
6082
|
+
// Validate variables array
|
|
6083
|
+
validateRequired(variables, 'variables', 'getPrompt');
|
|
6084
|
+
validateNonEmptyArray(variables, 'variables', 'getPrompt');
|
|
6085
|
+
// If using template, validate it and create PromptTemplate
|
|
6086
|
+
if (template) {
|
|
6087
|
+
validateNonEmptyString(template, 'template', 'getPrompt');
|
|
6088
|
+
try {
|
|
6089
|
+
return new PromptTemplate({
|
|
6090
|
+
template,
|
|
6091
|
+
inputVariables: variables,
|
|
6092
|
+
templateFormat: 'mustache',
|
|
6093
|
+
});
|
|
6094
|
+
}
|
|
6095
|
+
catch (error) {
|
|
6096
|
+
handleLangChainError(error, 'getPrompt: Failed to create PromptTemplate', {
|
|
6097
|
+
template: template.substring(0, 100) + (template.length > 100 ? '...' : ''),
|
|
6098
|
+
variables,
|
|
6099
|
+
templateFormat: 'mustache'
|
|
6100
|
+
});
|
|
6101
|
+
}
|
|
6102
|
+
}
|
|
6103
|
+
// Validate fallback if using it
|
|
6104
|
+
if (fallback) {
|
|
6105
|
+
validateRequired(fallback, 'fallback', 'getPrompt');
|
|
6106
|
+
if (!(fallback instanceof PromptTemplate)) {
|
|
6107
|
+
throw new LangChainValidationError('getPrompt: Fallback must be a PromptTemplate instance', { fallbackType: typeof fallback, fallbackConstructor: fallback.constructor?.name });
|
|
6108
|
+
}
|
|
6109
|
+
return fallback;
|
|
6110
|
+
}
|
|
6111
|
+
// This should never be reached, but TypeScript requires it
|
|
6112
|
+
throw new LangChainExecutionError('getPrompt: Unexpected execution path - neither template nor fallback available', { template, fallback, variables });
|
|
6338
6113
|
}
|
|
6339
6114
|
|
|
6115
|
+
/**
|
|
6116
|
+
* Executes a LangChain pipeline with the provided LLM, prompt, variables, and parser.
|
|
6117
|
+
* @param params - The execution parameters
|
|
6118
|
+
* @returns The parsed result from the LLM chain
|
|
6119
|
+
* @throws LangChainExecutionError if the chain execution fails or returns empty results
|
|
6120
|
+
*/
|
|
6340
6121
|
const executeChain = async ({ llm, prompt, variables, parser }) => {
|
|
6341
|
-
|
|
6342
|
-
|
|
6122
|
+
// Validate all required parameters
|
|
6123
|
+
validateRequired(llm, 'llm', 'executeChain');
|
|
6124
|
+
validateRequired(prompt, 'prompt', 'executeChain');
|
|
6125
|
+
validateRequired(variables, 'variables', 'executeChain');
|
|
6126
|
+
validateRequired(parser, 'parser', 'executeChain');
|
|
6127
|
+
// Validate that variables is an object
|
|
6128
|
+
if (typeof variables !== 'object' || Array.isArray(variables)) {
|
|
6129
|
+
throw new LangChainExecutionError('executeChain: Variables must be a non-array object', { variables, type: typeof variables, isArray: Array.isArray(variables) });
|
|
6343
6130
|
}
|
|
6344
|
-
const chain = prompt.pipe(llm).pipe(parser);
|
|
6345
|
-
let res;
|
|
6346
6131
|
try {
|
|
6347
|
-
|
|
6132
|
+
const chain = prompt.pipe(llm).pipe(parser);
|
|
6133
|
+
const result = await chain.invoke(variables);
|
|
6134
|
+
if (result === null || result === undefined) {
|
|
6135
|
+
throw new LangChainExecutionError('executeChain: Chain execution returned null or undefined result', { variables, promptInputVariables: prompt.inputVariables });
|
|
6136
|
+
}
|
|
6137
|
+
return result;
|
|
6348
6138
|
}
|
|
6349
6139
|
catch (error) {
|
|
6350
|
-
|
|
6351
|
-
|
|
6140
|
+
// Re-throw LangChain errors as-is
|
|
6141
|
+
if (error instanceof LangChainExecutionError) {
|
|
6142
|
+
throw error;
|
|
6352
6143
|
}
|
|
6144
|
+
// Wrap other errors with context
|
|
6145
|
+
handleLangChainError(error, 'executeChain: Chain execution failed', {
|
|
6146
|
+
promptInputVariables: prompt.inputVariables,
|
|
6147
|
+
variableKeys: Object.keys(variables),
|
|
6148
|
+
parserType: parser.constructor.name
|
|
6149
|
+
});
|
|
6353
6150
|
}
|
|
6354
|
-
if (!res) {
|
|
6355
|
-
throw new Error('Empty response from LLMChain call');
|
|
6356
|
-
}
|
|
6357
|
-
return res;
|
|
6358
6151
|
};
|
|
6359
6152
|
|
|
6360
6153
|
function extractTicketIdFromBranchName(branchName) {
|
|
@@ -6393,19 +6186,20 @@ const getChangesSinceLastTag = async ({ git }) => {
|
|
|
6393
6186
|
};
|
|
6394
6187
|
|
|
6395
6188
|
/**
|
|
6396
|
-
* Retrieves the commit log range between two specified commits.
|
|
6189
|
+
* Retrieves the commit log range between two specified commits (inclusive of both commits).
|
|
6397
6190
|
*
|
|
6398
|
-
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name).
|
|
6399
|
-
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name).
|
|
6191
|
+
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6192
|
+
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6400
6193
|
* @param options - Additional options for retrieving the commit log range.
|
|
6401
|
-
* @returns A promise that resolves to an array of commit log messages.
|
|
6194
|
+
* @returns A promise that resolves to an array of commit log messages, including both the 'from' and 'to' commits.
|
|
6402
6195
|
* @throws If there is an error retrieving the commit log range.
|
|
6403
6196
|
*/
|
|
6404
6197
|
async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
6405
6198
|
try {
|
|
6406
|
-
// Use
|
|
6199
|
+
// Use from^..to to include the 'from' commit in the range
|
|
6200
|
+
// This works because from^..to means "commits reachable from 'to' but not from the parent of 'from'"
|
|
6407
6201
|
const logOptions = {
|
|
6408
|
-
from
|
|
6202
|
+
from: `${from}^`,
|
|
6409
6203
|
to,
|
|
6410
6204
|
'--no-merges': noMerges
|
|
6411
6205
|
};
|
|
@@ -6413,7 +6207,29 @@ async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
|
6413
6207
|
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6414
6208
|
}
|
|
6415
6209
|
catch (error) {
|
|
6416
|
-
// If
|
|
6210
|
+
// If from^ fails (e.g., 'from' is the first commit), fall back to using from..to and manually adding the 'from' commit
|
|
6211
|
+
if (error instanceof Error && error.message.includes('unknown revision')) {
|
|
6212
|
+
try {
|
|
6213
|
+
// Get the 'from' commit separately
|
|
6214
|
+
const fromCommitLog = await git.log({ from: from, maxCount: 1 });
|
|
6215
|
+
const fromCommit = fromCommitLog.latest;
|
|
6216
|
+
// Get the range from..to (excluding 'from')
|
|
6217
|
+
const rangeLogOptions = {
|
|
6218
|
+
from,
|
|
6219
|
+
to,
|
|
6220
|
+
'--no-merges': noMerges
|
|
6221
|
+
};
|
|
6222
|
+
const rangeCommitLog = await git.log(rangeLogOptions);
|
|
6223
|
+
// Combine the 'from' commit with the range commits
|
|
6224
|
+
const allCommits = fromCommit
|
|
6225
|
+
? [fromCommit, ...rangeCommitLog.all]
|
|
6226
|
+
: rangeCommitLog.all;
|
|
6227
|
+
return allCommits.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6228
|
+
}
|
|
6229
|
+
catch (fallbackError) {
|
|
6230
|
+
throw fallbackError;
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6417
6233
|
throw error;
|
|
6418
6234
|
}
|
|
6419
6235
|
}
|
|
@@ -6474,38 +6290,38 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
6474
6290
|
*/
|
|
6475
6291
|
async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main', comparisonRemote = 'origin', }) {
|
|
6476
6292
|
try {
|
|
6477
|
-
|
|
6478
|
-
const
|
|
6479
|
-
// Check if the current branch has any commits
|
|
6480
|
-
const hasCommits = (await git.raw(['rev-list', '--count', branch])) !== '0';
|
|
6293
|
+
const branchName = await getCurrentBranchName({ git });
|
|
6294
|
+
const hasCommits = (await git.raw(['rev-list', '--count', branchName])) !== '0';
|
|
6481
6295
|
if (!hasCommits) {
|
|
6482
6296
|
logger?.log('No commits on the current branch.');
|
|
6483
6297
|
return [];
|
|
6484
6298
|
}
|
|
6485
|
-
// Get the list of commits that are unique to the current branch
|
|
6486
6299
|
let uniqueCommits;
|
|
6487
|
-
if (comparisonBranch ===
|
|
6300
|
+
if (comparisonBranch === branchName) {
|
|
6488
6301
|
// If the comparison branch is the same as the current branch, we compare against the remote.
|
|
6489
|
-
uniqueCommits = (await git.raw(['rev-list', `${comparisonRemote}/${comparisonBranch}..${
|
|
6302
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonRemote}/${comparisonBranch}..${branchName}`]))
|
|
6490
6303
|
.split('\n')
|
|
6491
6304
|
.filter(Boolean)
|
|
6492
6305
|
.reverse();
|
|
6493
6306
|
}
|
|
6494
6307
|
else {
|
|
6495
6308
|
// Your existing code for different branches
|
|
6496
|
-
uniqueCommits = (await git.raw(['rev-list', `${comparisonBranch}..${
|
|
6309
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonBranch}..${branchName}`]))
|
|
6497
6310
|
.split('\n')
|
|
6498
6311
|
.filter(Boolean)
|
|
6499
6312
|
.reverse();
|
|
6500
6313
|
}
|
|
6501
|
-
logger?.verbose(`Found ${uniqueCommits.length} unique commits on "${
|
|
6314
|
+
logger?.verbose(`Found ${uniqueCommits.length} unique commits on "${branchName}"`, {
|
|
6315
|
+
color: 'blue',
|
|
6316
|
+
});
|
|
6502
6317
|
const firstCommit = uniqueCommits[0];
|
|
6503
6318
|
const lastCommit = uniqueCommits[uniqueCommits.length - 1];
|
|
6504
6319
|
if (!firstCommit || !lastCommit) {
|
|
6505
|
-
logger?.log('Unable to determine first and last commit on the current branch', {
|
|
6320
|
+
logger?.log('Unable to determine first and last commit on the current branch', {
|
|
6321
|
+
color: 'yellow',
|
|
6322
|
+
});
|
|
6506
6323
|
return [];
|
|
6507
6324
|
}
|
|
6508
|
-
// Retrieve commit log with messages
|
|
6509
6325
|
return await getCommitLogRange(firstCommit, lastCommit, { git, noMerges: true });
|
|
6510
6326
|
}
|
|
6511
6327
|
catch (error) {
|
|
@@ -6634,17 +6450,35 @@ const CONVENTIONAL_COMMIT_PROMPT = new PromptTemplate({
|
|
|
6634
6450
|
*
|
|
6635
6451
|
* @param text template string
|
|
6636
6452
|
* @param inputVariables template variables
|
|
6637
|
-
* @
|
|
6453
|
+
* @throws Error if validation fails
|
|
6638
6454
|
*/
|
|
6639
6455
|
function validatePromptTemplate(text, inputVariables) {
|
|
6640
|
-
if (!text) {
|
|
6641
|
-
|
|
6456
|
+
if (!text || text.trim() === '') {
|
|
6457
|
+
throw new Error('Prompt template cannot be empty');
|
|
6642
6458
|
}
|
|
6643
|
-
if (!inputVariables.
|
|
6644
|
-
return
|
|
6645
|
-
|
|
6459
|
+
if (!inputVariables || inputVariables.length === 0) {
|
|
6460
|
+
return; // No variables to validate
|
|
6461
|
+
}
|
|
6462
|
+
// Extract variables from template using regex to find {variable} patterns
|
|
6463
|
+
// This regex matches {variable_name} with no whitespace inside braces
|
|
6464
|
+
// Excludes JSON-like patterns with quotes, colons, or whitespace
|
|
6465
|
+
const templateVariableRegex = /\{([^}\s:"']+)\}/g;
|
|
6466
|
+
const foundVariables = new Set();
|
|
6467
|
+
let match;
|
|
6468
|
+
while ((match = templateVariableRegex.exec(text)) !== null) {
|
|
6469
|
+
foundVariables.add(match[1]);
|
|
6470
|
+
}
|
|
6471
|
+
// Check if all required variables are present in template
|
|
6472
|
+
const missingVariables = inputVariables.filter(variable => !foundVariables.has(variable));
|
|
6473
|
+
if (missingVariables.length > 0) {
|
|
6474
|
+
throw new Error(`Prompt template is missing required variables: ${missingVariables.map(v => `{${v}}`).join(', ')}. ` +
|
|
6475
|
+
`Found variables: ${Array.from(foundVariables).map(v => `{${v}}`).join(', ') || 'none'}`);
|
|
6476
|
+
}
|
|
6477
|
+
// Warn about unused variables in template (optional check)
|
|
6478
|
+
const unusedVariables = Array.from(foundVariables).filter(variable => !inputVariables.includes(variable));
|
|
6479
|
+
if (unusedVariables.length > 0) {
|
|
6480
|
+
console.warn(`Prompt template contains undefined variables: ${unusedVariables.map(v => `{${v}}`).join(', ')}`);
|
|
6646
6481
|
}
|
|
6647
|
-
return true;
|
|
6648
6482
|
}
|
|
6649
6483
|
|
|
6650
6484
|
async function editPrompt(options) {
|
|
@@ -6653,7 +6487,15 @@ async function editPrompt(options) {
|
|
|
6653
6487
|
default: options.prompt?.length ? options.prompt : COMMIT_PROMPT.template,
|
|
6654
6488
|
waitForUseInput: false,
|
|
6655
6489
|
postfix: 'Press ENTER to continue',
|
|
6656
|
-
validate: (text) =>
|
|
6490
|
+
validate: (text) => {
|
|
6491
|
+
try {
|
|
6492
|
+
validatePromptTemplate(text, COMMIT_PROMPT.inputVariables);
|
|
6493
|
+
return true;
|
|
6494
|
+
}
|
|
6495
|
+
catch (error) {
|
|
6496
|
+
return error instanceof Error ? error.message : 'Invalid prompt template';
|
|
6497
|
+
}
|
|
6498
|
+
},
|
|
6657
6499
|
});
|
|
6658
6500
|
}
|
|
6659
6501
|
|
|
@@ -6872,7 +6714,9 @@ const handler$4 = async (argv, logger) => {
|
|
|
6872
6714
|
const llm = getLlm(provider, model, config);
|
|
6873
6715
|
const INTERACTIVE = isInteractive(config);
|
|
6874
6716
|
if (INTERACTIVE) {
|
|
6875
|
-
|
|
6717
|
+
if (!config.hideCocoBanner) {
|
|
6718
|
+
logger.log(LOGO);
|
|
6719
|
+
}
|
|
6876
6720
|
}
|
|
6877
6721
|
async function factory() {
|
|
6878
6722
|
const branchName = await getCurrentBranchName({ git });
|
|
@@ -6904,9 +6748,10 @@ const handler$4 = async (argv, logger) => {
|
|
|
6904
6748
|
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
6905
6749
|
color: 'yellow',
|
|
6906
6750
|
});
|
|
6751
|
+
const commits = await getCommitLogCurrentBranch({ git, logger });
|
|
6907
6752
|
return {
|
|
6908
6753
|
branch: branchName,
|
|
6909
|
-
commits
|
|
6754
|
+
commits,
|
|
6910
6755
|
};
|
|
6911
6756
|
}
|
|
6912
6757
|
async function parser({ branch, commits }) {
|
|
@@ -6983,16 +6828,16 @@ var changelog = {
|
|
|
6983
6828
|
|
|
6984
6829
|
const conventionalTypeRegex = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?:/;
|
|
6985
6830
|
// Regular commit message schema with basic validation
|
|
6986
|
-
const CommitMessageResponseSchema =
|
|
6987
|
-
title:
|
|
6988
|
-
body:
|
|
6831
|
+
const CommitMessageResponseSchema = objectType({
|
|
6832
|
+
title: stringType(),
|
|
6833
|
+
body: stringType(),
|
|
6989
6834
|
});
|
|
6990
6835
|
// Conventional commit message schema with strict formatting rules
|
|
6991
|
-
const ConventionalCommitMessageResponseSchema =
|
|
6992
|
-
title:
|
|
6836
|
+
const ConventionalCommitMessageResponseSchema = objectType({
|
|
6837
|
+
title: stringType()
|
|
6993
6838
|
.max(50, "Title must be 50 characters or less")
|
|
6994
6839
|
.refine((title) => conventionalTypeRegex.test(title), "Title must follow Conventional Commits format (e.g., 'feat: add new feature' or 'fix(scope): fix bug')"),
|
|
6995
|
-
body:
|
|
6840
|
+
body: stringType()
|
|
6996
6841
|
// .max(280, "Body must be 280 characters or less"),
|
|
6997
6842
|
});
|
|
6998
6843
|
const command$3 = 'commit';
|
|
@@ -7049,133 +6894,14 @@ const builder$3 = (yargs) => {
|
|
|
7049
6894
|
return yargs.options(options$3).usage(getCommandUsageHeader(command$3));
|
|
7050
6895
|
};
|
|
7051
6896
|
|
|
7052
|
-
|
|
7053
|
-
* Extract the path from a file path string.
|
|
7054
|
-
* @param {string} filePath - The full file path.
|
|
7055
|
-
* @returns {string} The path portion of the file path.
|
|
7056
|
-
*/
|
|
7057
|
-
function getPathFromFilePath(filePath) {
|
|
7058
|
-
return filePath.split('/').slice(0, -1).join('/');
|
|
7059
|
-
}
|
|
7060
|
-
|
|
7061
|
-
async function summarize(documents, { chain, textSplitter, options }) {
|
|
7062
|
-
const { returnIntermediateSteps = false } = options || {};
|
|
7063
|
-
const docs = await textSplitter.splitDocuments(documents.map((doc) => new Document(doc)));
|
|
7064
|
-
const res = await chain.invoke({
|
|
7065
|
-
input_documents: docs,
|
|
7066
|
-
returnIntermediateSteps,
|
|
7067
|
-
});
|
|
7068
|
-
if (res.error)
|
|
7069
|
-
throw new Error(res.error);
|
|
7070
|
-
return res.text && res.text.trim();
|
|
7071
|
-
}
|
|
6897
|
+
new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
7072
6898
|
|
|
7073
6899
|
/**
|
|
7074
|
-
*
|
|
7075
|
-
* @param {DiffNode} node - The node info to start grouping.
|
|
7076
|
-
* @returns {DirectoryDiff[]} The groups created.
|
|
7077
|
-
*/
|
|
7078
|
-
function createDirectoryDiffs(node) {
|
|
7079
|
-
const groupByPath = {};
|
|
7080
|
-
function traverse(node) {
|
|
7081
|
-
node.diffs.forEach((diff) => {
|
|
7082
|
-
const path = getPathFromFilePath(diff.file);
|
|
7083
|
-
if (!groupByPath[path]) {
|
|
7084
|
-
groupByPath[path] = { diffs: [], path, tokenCount: 0 };
|
|
7085
|
-
}
|
|
7086
|
-
groupByPath[path].diffs.push(diff);
|
|
7087
|
-
groupByPath[path].tokenCount += diff.tokenCount;
|
|
7088
|
-
});
|
|
7089
|
-
node.children.forEach(traverse);
|
|
7090
|
-
}
|
|
7091
|
-
traverse(node);
|
|
7092
|
-
return Object.values(groupByPath);
|
|
7093
|
-
}
|
|
7094
|
-
/**
|
|
7095
|
-
* Summarize a directory diff asynchronously.
|
|
6900
|
+
* Base interface that all chains must implement.
|
|
7096
6901
|
*/
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
pageContent: diff.diff,
|
|
7101
|
-
metadata: {
|
|
7102
|
-
file: diff.file,
|
|
7103
|
-
summary: diff.summary,
|
|
7104
|
-
},
|
|
7105
|
-
})), {
|
|
7106
|
-
chain,
|
|
7107
|
-
textSplitter,
|
|
7108
|
-
options: {
|
|
7109
|
-
returnIntermediateSteps: true,
|
|
7110
|
-
},
|
|
7111
|
-
});
|
|
7112
|
-
const newTokenTotal = tokenizer(directorySummary);
|
|
7113
|
-
return {
|
|
7114
|
-
diffs: directory.diffs,
|
|
7115
|
-
path: directory.path,
|
|
7116
|
-
summary: directorySummary,
|
|
7117
|
-
tokenCount: newTokenTotal,
|
|
7118
|
-
};
|
|
7119
|
-
}
|
|
7120
|
-
catch (error) {
|
|
7121
|
-
console.error(error);
|
|
7122
|
-
return directory;
|
|
7123
|
-
}
|
|
7124
|
-
}
|
|
7125
|
-
const defaultOutputCallback = (group) => {
|
|
7126
|
-
let output = `
|
|
7127
|
-
-------\n* changes in "/${group.path}"\n\n`;
|
|
7128
|
-
if (group.summary) {
|
|
7129
|
-
output += `${group.diffs.map((diff) => ` • ${diff.summary}`).join('\n')}\n\nSummary:\n\n${group.summary}\n\n`;
|
|
7130
|
-
}
|
|
7131
|
-
else {
|
|
7132
|
-
output += `${group.diffs.map((diff) => ` • ${diff.summary}\n\n${diff.diff}`).join('\n\n')}\n\n`;
|
|
7133
|
-
}
|
|
7134
|
-
return output;
|
|
7135
|
-
};
|
|
7136
|
-
async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 2048, textSplitter, chain, handleOutput = defaultOutputCallback, }) {
|
|
7137
|
-
const queue = new pQueue({ concurrency: 8 });
|
|
7138
|
-
logger.startTimer().startSpinner(`Organizing Diffs...`, { color: 'blue' });
|
|
7139
|
-
const directoryDiffs = createDirectoryDiffs(rootDiffNode);
|
|
7140
|
-
// Sort by token count descending
|
|
7141
|
-
directoryDiffs.sort((a, b) => b.tokenCount - a.tokenCount);
|
|
7142
|
-
let totalTokenCount = directoryDiffs.reduce((sum, group) => sum + group.tokenCount, 0);
|
|
7143
|
-
logger.stopSpinner('Diffs Organized').stopTimer();
|
|
7144
|
-
logger.startSpinner(`Consolidating Diffs`, { color: 'blue' });
|
|
7145
|
-
const processingTasks = directoryDiffs.map((group, i) => {
|
|
7146
|
-
return queue.add(async () => {
|
|
7147
|
-
// If the diff token count is already less than the average req, we can skip summarizing.
|
|
7148
|
-
const isLessThanAvgTokenReq = group.tokenCount <= maxTokens / directoryDiffs.length;
|
|
7149
|
-
if (totalTokenCount <= maxTokens || isLessThanAvgTokenReq) {
|
|
7150
|
-
return group;
|
|
7151
|
-
}
|
|
7152
|
-
group = await summarizeDirectoryDiff(group, {
|
|
7153
|
-
chain,
|
|
7154
|
-
textSplitter,
|
|
7155
|
-
tokenizer,
|
|
7156
|
-
});
|
|
7157
|
-
// We need to subtract the old token count and add the new one
|
|
7158
|
-
totalTokenCount = totalTokenCount - directoryDiffs[i].tokenCount + group.tokenCount;
|
|
7159
|
-
directoryDiffs[i] = group;
|
|
7160
|
-
logger
|
|
7161
|
-
.verbose(`\n • Summarized diffs in "/${group.path}" `, { color: 'blue' })
|
|
7162
|
-
.verbose(`\nTotal token count: ${totalTokenCount}`, {
|
|
7163
|
-
color: totalTokenCount > maxTokens ? 'yellow' : 'green',
|
|
7164
|
-
});
|
|
7165
|
-
return group;
|
|
7166
|
-
}, { priority: group.tokenCount });
|
|
7167
|
-
});
|
|
7168
|
-
await Promise.all(processingTasks);
|
|
7169
|
-
logger.stopSpinner(`Summarized Diffs`);
|
|
7170
|
-
return directoryDiffs.map(handleOutput).join('');
|
|
7171
|
-
}
|
|
7172
|
-
|
|
7173
|
-
/**
|
|
7174
|
-
* Base interface that all chains must implement.
|
|
7175
|
-
*/
|
|
7176
|
-
class BaseChain extends BaseLangChain {
|
|
7177
|
-
get lc_namespace() {
|
|
7178
|
-
return ["langchain", "chains", this._chainType()];
|
|
6902
|
+
class BaseChain extends BaseLangChain {
|
|
6903
|
+
get lc_namespace() {
|
|
6904
|
+
return ["langchain", "chains", this._chainType()];
|
|
7179
6905
|
}
|
|
7180
6906
|
constructor(fields,
|
|
7181
6907
|
/** @deprecated */
|
|
@@ -7616,16 +7342,551 @@ class LLMChain extends BaseChain {
|
|
|
7616
7342
|
prompt: this.prompt.serialize(),
|
|
7617
7343
|
};
|
|
7618
7344
|
}
|
|
7619
|
-
_getNumTokens(text) {
|
|
7620
|
-
return _getLanguageModel(this.llm).getNumTokens(text);
|
|
7345
|
+
_getNumTokens(text) {
|
|
7346
|
+
return _getLanguageModel(this.llm).getNumTokens(text);
|
|
7347
|
+
}
|
|
7348
|
+
}
|
|
7349
|
+
|
|
7350
|
+
var llm_chain = /*#__PURE__*/Object.freeze({
|
|
7351
|
+
__proto__: null,
|
|
7352
|
+
LLMChain: LLMChain
|
|
7353
|
+
});
|
|
7354
|
+
|
|
7355
|
+
const NAIVE_FIX_TEMPLATE = `Instructions:
|
|
7356
|
+
--------------
|
|
7357
|
+
{instructions}
|
|
7358
|
+
--------------
|
|
7359
|
+
Completion:
|
|
7360
|
+
--------------
|
|
7361
|
+
{completion}
|
|
7362
|
+
--------------
|
|
7363
|
+
|
|
7364
|
+
Above, the Completion did not satisfy the constraints given in the Instructions.
|
|
7365
|
+
Error:
|
|
7366
|
+
--------------
|
|
7367
|
+
{error}
|
|
7368
|
+
--------------
|
|
7369
|
+
|
|
7370
|
+
Please try again. Please only respond with an answer that satisfies the constraints laid out in the Instructions:`;
|
|
7371
|
+
const NAIVE_FIX_PROMPT =
|
|
7372
|
+
/* #__PURE__ */ PromptTemplate.fromTemplate(NAIVE_FIX_TEMPLATE);
|
|
7373
|
+
|
|
7374
|
+
function isLLMChain(x) {
|
|
7375
|
+
return (x.prompt !== undefined && x.llm !== undefined);
|
|
7376
|
+
}
|
|
7377
|
+
/**
|
|
7378
|
+
* Class that extends the BaseOutputParser to handle situations where the
|
|
7379
|
+
* initial parsing attempt fails. It contains a retryChain for retrying
|
|
7380
|
+
* the parsing process in case of a failure.
|
|
7381
|
+
*/
|
|
7382
|
+
class OutputFixingParser extends BaseOutputParser {
|
|
7383
|
+
static lc_name() {
|
|
7384
|
+
return "OutputFixingParser";
|
|
7385
|
+
}
|
|
7386
|
+
/**
|
|
7387
|
+
* Static method to create a new instance of OutputFixingParser using a
|
|
7388
|
+
* given language model, parser, and optional fields.
|
|
7389
|
+
* @param llm The language model to be used.
|
|
7390
|
+
* @param parser The parser to be used.
|
|
7391
|
+
* @param fields Optional fields which may contain a prompt.
|
|
7392
|
+
* @returns A new instance of OutputFixingParser.
|
|
7393
|
+
*/
|
|
7394
|
+
static fromLLM(llm, parser, fields) {
|
|
7395
|
+
const prompt = fields?.prompt ?? NAIVE_FIX_PROMPT;
|
|
7396
|
+
const chain = new LLMChain({ llm, prompt });
|
|
7397
|
+
return new OutputFixingParser({ parser, retryChain: chain });
|
|
7398
|
+
}
|
|
7399
|
+
constructor({ parser, retryChain, }) {
|
|
7400
|
+
super(...arguments);
|
|
7401
|
+
Object.defineProperty(this, "lc_namespace", {
|
|
7402
|
+
enumerable: true,
|
|
7403
|
+
configurable: true,
|
|
7404
|
+
writable: true,
|
|
7405
|
+
value: ["langchain", "output_parsers", "fix"]
|
|
7406
|
+
});
|
|
7407
|
+
Object.defineProperty(this, "lc_serializable", {
|
|
7408
|
+
enumerable: true,
|
|
7409
|
+
configurable: true,
|
|
7410
|
+
writable: true,
|
|
7411
|
+
value: true
|
|
7412
|
+
});
|
|
7413
|
+
Object.defineProperty(this, "parser", {
|
|
7414
|
+
enumerable: true,
|
|
7415
|
+
configurable: true,
|
|
7416
|
+
writable: true,
|
|
7417
|
+
value: void 0
|
|
7418
|
+
});
|
|
7419
|
+
Object.defineProperty(this, "retryChain", {
|
|
7420
|
+
enumerable: true,
|
|
7421
|
+
configurable: true,
|
|
7422
|
+
writable: true,
|
|
7423
|
+
value: void 0
|
|
7424
|
+
});
|
|
7425
|
+
this.parser = parser;
|
|
7426
|
+
this.retryChain = retryChain;
|
|
7427
|
+
}
|
|
7428
|
+
/**
|
|
7429
|
+
* Method to parse the completion using the parser. If the initial parsing
|
|
7430
|
+
* fails, it uses the retryChain to attempt to fix the output and retry
|
|
7431
|
+
* the parsing process.
|
|
7432
|
+
* @param completion The completion to be parsed.
|
|
7433
|
+
* @param callbacks Optional callbacks to be used during parsing.
|
|
7434
|
+
* @returns The parsed output.
|
|
7435
|
+
*/
|
|
7436
|
+
async parse(completion, callbacks) {
|
|
7437
|
+
try {
|
|
7438
|
+
return await this.parser.parse(completion, callbacks);
|
|
7439
|
+
}
|
|
7440
|
+
catch (e) {
|
|
7441
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
7442
|
+
if (e instanceof OutputParserException) {
|
|
7443
|
+
const retryInput = {
|
|
7444
|
+
instructions: this.parser.getFormatInstructions(),
|
|
7445
|
+
completion,
|
|
7446
|
+
error: e,
|
|
7447
|
+
};
|
|
7448
|
+
if (isLLMChain(this.retryChain)) {
|
|
7449
|
+
const result = await this.retryChain.call(retryInput, callbacks);
|
|
7450
|
+
const newCompletion = result[this.retryChain.outputKey];
|
|
7451
|
+
return this.parser.parse(newCompletion, callbacks);
|
|
7452
|
+
}
|
|
7453
|
+
else {
|
|
7454
|
+
const result = await this.retryChain.invoke(retryInput, {
|
|
7455
|
+
callbacks,
|
|
7456
|
+
});
|
|
7457
|
+
return result;
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
throw e;
|
|
7461
|
+
}
|
|
7462
|
+
}
|
|
7463
|
+
/**
|
|
7464
|
+
* Method to get the format instructions for the parser.
|
|
7465
|
+
* @returns The format instructions for the parser.
|
|
7466
|
+
*/
|
|
7467
|
+
getFormatInstructions() {
|
|
7468
|
+
return this.parser.getFormatInstructions();
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
|
|
7472
|
+
/**
|
|
7473
|
+
* Creates a parser with built-in retry logic for schema-based generation
|
|
7474
|
+
* @param schema - Zod schema for the expected output structure
|
|
7475
|
+
* @param llm - LLM instance for retry attempts
|
|
7476
|
+
* @param options - Configuration options for retry behavior
|
|
7477
|
+
* @returns OutputFixingParser configured with retry logic
|
|
7478
|
+
* @throws LangChainExecutionError if parser creation fails
|
|
7479
|
+
*/
|
|
7480
|
+
function createSchemaParser(schema, llm, options = {}) {
|
|
7481
|
+
// Validate required parameters
|
|
7482
|
+
validateRequired(schema, 'schema', 'createSchemaParser');
|
|
7483
|
+
validateRequired(llm, 'llm', 'createSchemaParser');
|
|
7484
|
+
validateRequired(options, 'options', 'createSchemaParser');
|
|
7485
|
+
// Validate schema is actually a Zod schema
|
|
7486
|
+
if (typeof schema.parse !== 'function') {
|
|
7487
|
+
throw new LangChainExecutionError('createSchemaParser: Schema must be a valid Zod schema with a parse method', { schemaType: typeof schema, hasParseMethod: typeof schema.parse });
|
|
7488
|
+
}
|
|
7489
|
+
// Validate options structure
|
|
7490
|
+
if (typeof options !== 'object' || Array.isArray(options)) {
|
|
7491
|
+
throw new LangChainExecutionError('createSchemaParser: Options must be a non-array object', { options, type: typeof options, isArray: Array.isArray(options) });
|
|
7492
|
+
}
|
|
7493
|
+
const { retryTemplate } = options;
|
|
7494
|
+
// Validate retryTemplate if provided
|
|
7495
|
+
if (retryTemplate !== undefined && typeof retryTemplate !== 'string') {
|
|
7496
|
+
throw new LangChainExecutionError('createSchemaParser: retryTemplate must be a string when provided', { retryTemplate, type: typeof retryTemplate });
|
|
7497
|
+
}
|
|
7498
|
+
try {
|
|
7499
|
+
const baseParser = new StructuredOutputParser(schema);
|
|
7500
|
+
const defaultRetryTemplate = `The following text failed to parse as valid JSON. Please convert it into a valid JSON object that matches the required schema.
|
|
7501
|
+
|
|
7502
|
+
## Text to fix:
|
|
7503
|
+
{completion}
|
|
7504
|
+
|
|
7505
|
+
## Instructions:
|
|
7506
|
+
{instructions}
|
|
7507
|
+
|
|
7508
|
+
You must return ONLY valid JSON that matches the schema exactly. Do not include any additional text, explanations, or markdown formatting:`;
|
|
7509
|
+
const retryPromptTemplate = new PromptTemplate({
|
|
7510
|
+
template: retryTemplate || defaultRetryTemplate,
|
|
7511
|
+
inputVariables: ['completion', 'instructions'],
|
|
7512
|
+
});
|
|
7513
|
+
const retryChain = retryPromptTemplate.pipe(llm).pipe(baseParser);
|
|
7514
|
+
return new OutputFixingParser({
|
|
7515
|
+
parser: baseParser,
|
|
7516
|
+
retryChain: retryChain,
|
|
7517
|
+
});
|
|
7518
|
+
}
|
|
7519
|
+
catch (error) {
|
|
7520
|
+
handleLangChainError(error, 'createSchemaParser: Failed to create schema parser', {
|
|
7521
|
+
schemaName: schema.constructor.name,
|
|
7522
|
+
llmType: llm.constructor.name,
|
|
7523
|
+
hasRetryTemplate: !!retryTemplate
|
|
7524
|
+
});
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
|
|
7528
|
+
/**
|
|
7529
|
+
* High-level function that combines chain execution with schema-based parsing
|
|
7530
|
+
* Includes automatic retry logic and graceful degradation
|
|
7531
|
+
* @param schema - Zod schema for the expected output structure
|
|
7532
|
+
* @param llm - LLM instance
|
|
7533
|
+
* @param prompt - Prompt template
|
|
7534
|
+
* @param variables - Variables for the prompt
|
|
7535
|
+
* @param options - Configuration options
|
|
7536
|
+
* @returns Parsed result matching the schema type
|
|
7537
|
+
*/
|
|
7538
|
+
async function executeChainWithSchema(schema, llm, prompt, variables, options = {}) {
|
|
7539
|
+
const { retryOptions = { maxAttempts: 3 }, fallbackParser, onFallback, ...parserOptions } = options;
|
|
7540
|
+
const parser = createSchemaParser(schema, llm, parserOptions);
|
|
7541
|
+
// Define the operation to retry
|
|
7542
|
+
const operation = async () => {
|
|
7543
|
+
const result = await executeChain({
|
|
7544
|
+
llm,
|
|
7545
|
+
prompt,
|
|
7546
|
+
variables,
|
|
7547
|
+
parser,
|
|
7548
|
+
});
|
|
7549
|
+
return result;
|
|
7550
|
+
};
|
|
7551
|
+
try {
|
|
7552
|
+
// Use the general retry utility
|
|
7553
|
+
return await withRetry(operation, retryOptions);
|
|
7554
|
+
}
|
|
7555
|
+
catch (error) {
|
|
7556
|
+
// If all retries failed and we have a fallback parser, use it
|
|
7557
|
+
if (fallbackParser) {
|
|
7558
|
+
if (onFallback) {
|
|
7559
|
+
onFallback();
|
|
7560
|
+
}
|
|
7561
|
+
// Generate without structured parsing as fallback
|
|
7562
|
+
const fallbackResult = await executeChain({
|
|
7563
|
+
llm,
|
|
7564
|
+
prompt,
|
|
7565
|
+
variables,
|
|
7566
|
+
parser: new StringOutputParser(),
|
|
7567
|
+
});
|
|
7568
|
+
const fallbackText = typeof fallbackResult === 'string' ? fallbackResult : String(fallbackResult);
|
|
7569
|
+
return fallbackParser(fallbackText);
|
|
7570
|
+
}
|
|
7571
|
+
// No fallback available, re-throw the error
|
|
7572
|
+
throw error;
|
|
7573
|
+
}
|
|
7574
|
+
}
|
|
7575
|
+
|
|
7576
|
+
/**
|
|
7577
|
+
* Extract the path from a file path string.
|
|
7578
|
+
* @param {string} filePath - The full file path.
|
|
7579
|
+
* @returns {string} The path portion of the file path.
|
|
7580
|
+
*/
|
|
7581
|
+
function getPathFromFilePath(filePath) {
|
|
7582
|
+
return filePath.split('/').slice(0, -1).join('/');
|
|
7583
|
+
}
|
|
7584
|
+
|
|
7585
|
+
async function summarize(documents, { chain, textSplitter, options }) {
|
|
7586
|
+
const { returnIntermediateSteps = false } = options || {};
|
|
7587
|
+
const docs = await textSplitter.splitDocuments(documents.map((doc) => new Document(doc)));
|
|
7588
|
+
const res = await chain.invoke({
|
|
7589
|
+
input_documents: docs,
|
|
7590
|
+
returnIntermediateSteps,
|
|
7591
|
+
});
|
|
7592
|
+
if (res.error)
|
|
7593
|
+
throw new Error(res.error);
|
|
7594
|
+
return res.text && res.text.trim();
|
|
7595
|
+
}
|
|
7596
|
+
|
|
7597
|
+
/**
|
|
7598
|
+
* Create groups from a given node info.
|
|
7599
|
+
* @param {DiffNode} node - The node info to start grouping.
|
|
7600
|
+
* @returns {DirectoryDiff[]} The groups created.
|
|
7601
|
+
*/
|
|
7602
|
+
function createDirectoryDiffs(node) {
|
|
7603
|
+
const groupByPath = {};
|
|
7604
|
+
function traverse(node) {
|
|
7605
|
+
node.diffs.forEach((diff) => {
|
|
7606
|
+
const path = getPathFromFilePath(diff.file);
|
|
7607
|
+
if (!groupByPath[path]) {
|
|
7608
|
+
groupByPath[path] = { diffs: [], path, tokenCount: 0 };
|
|
7609
|
+
}
|
|
7610
|
+
groupByPath[path].diffs.push(diff);
|
|
7611
|
+
groupByPath[path].tokenCount += diff.tokenCount;
|
|
7612
|
+
});
|
|
7613
|
+
node.children.forEach(traverse);
|
|
7614
|
+
}
|
|
7615
|
+
traverse(node);
|
|
7616
|
+
return Object.values(groupByPath);
|
|
7617
|
+
}
|
|
7618
|
+
/**
|
|
7619
|
+
* Summarize a directory diff asynchronously.
|
|
7620
|
+
*/
|
|
7621
|
+
async function summarizeDirectoryDiff(directory, { chain, textSplitter, tokenizer }) {
|
|
7622
|
+
try {
|
|
7623
|
+
const directorySummary = await summarize(directory.diffs.map((diff) => ({
|
|
7624
|
+
pageContent: diff.diff,
|
|
7625
|
+
metadata: {
|
|
7626
|
+
file: diff.file,
|
|
7627
|
+
summary: diff.summary,
|
|
7628
|
+
},
|
|
7629
|
+
})), {
|
|
7630
|
+
chain,
|
|
7631
|
+
textSplitter,
|
|
7632
|
+
options: {
|
|
7633
|
+
returnIntermediateSteps: true,
|
|
7634
|
+
},
|
|
7635
|
+
});
|
|
7636
|
+
const newTokenTotal = tokenizer(directorySummary);
|
|
7637
|
+
return {
|
|
7638
|
+
diffs: directory.diffs,
|
|
7639
|
+
path: directory.path,
|
|
7640
|
+
summary: directorySummary,
|
|
7641
|
+
tokenCount: newTokenTotal,
|
|
7642
|
+
};
|
|
7643
|
+
}
|
|
7644
|
+
catch (error) {
|
|
7645
|
+
console.error(error);
|
|
7646
|
+
return directory;
|
|
7647
|
+
}
|
|
7648
|
+
}
|
|
7649
|
+
const defaultOutputCallback = (group) => {
|
|
7650
|
+
let output = `
|
|
7651
|
+
-------\n* changes in "/${group.path}"\n\n`;
|
|
7652
|
+
if (group.summary) {
|
|
7653
|
+
output += `${group.diffs.map((diff) => ` • ${diff.summary}`).join('\n')}\n\nSummary:\n\n${group.summary}\n\n`;
|
|
7654
|
+
}
|
|
7655
|
+
else {
|
|
7656
|
+
output += `${group.diffs.map((diff) => ` • ${diff.summary}\n\n${diff.diff}`).join('\n\n')}\n\n`;
|
|
7657
|
+
}
|
|
7658
|
+
return output;
|
|
7659
|
+
};
|
|
7660
|
+
async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 2048, textSplitter, chain, handleOutput = defaultOutputCallback, }) {
|
|
7661
|
+
const queue = new pQueue({ concurrency: 8 });
|
|
7662
|
+
logger.startTimer().startSpinner(`Organizing Diffs...`, { color: 'blue' });
|
|
7663
|
+
const directoryDiffs = createDirectoryDiffs(rootDiffNode);
|
|
7664
|
+
// Sort by token count descending
|
|
7665
|
+
directoryDiffs.sort((a, b) => b.tokenCount - a.tokenCount);
|
|
7666
|
+
let totalTokenCount = directoryDiffs.reduce((sum, group) => sum + group.tokenCount, 0);
|
|
7667
|
+
logger.stopSpinner('Diffs Organized').stopTimer();
|
|
7668
|
+
logger.startSpinner(`Consolidating Diffs`, { color: 'blue' });
|
|
7669
|
+
const processingTasks = directoryDiffs.map((group, i) => {
|
|
7670
|
+
return queue.add(async () => {
|
|
7671
|
+
// If the diff token count is already less than the average req, we can skip summarizing.
|
|
7672
|
+
const isLessThanAvgTokenReq = group.tokenCount <= maxTokens / directoryDiffs.length;
|
|
7673
|
+
if (totalTokenCount <= maxTokens || isLessThanAvgTokenReq) {
|
|
7674
|
+
return group;
|
|
7675
|
+
}
|
|
7676
|
+
group = await summarizeDirectoryDiff(group, {
|
|
7677
|
+
chain,
|
|
7678
|
+
textSplitter,
|
|
7679
|
+
tokenizer,
|
|
7680
|
+
});
|
|
7681
|
+
// We need to subtract the old token count and add the new one
|
|
7682
|
+
totalTokenCount = totalTokenCount - directoryDiffs[i].tokenCount + group.tokenCount;
|
|
7683
|
+
directoryDiffs[i] = group;
|
|
7684
|
+
logger
|
|
7685
|
+
.verbose(`\n • Summarized diffs in "/${group.path}" `, { color: 'blue' })
|
|
7686
|
+
.verbose(`\nTotal token count: ${totalTokenCount}`, {
|
|
7687
|
+
color: totalTokenCount > maxTokens ? 'yellow' : 'green',
|
|
7688
|
+
});
|
|
7689
|
+
return group;
|
|
7690
|
+
}, { priority: group.tokenCount });
|
|
7691
|
+
});
|
|
7692
|
+
await Promise.all(processingTasks);
|
|
7693
|
+
logger.stopSpinner(`Summarized Diffs`);
|
|
7694
|
+
return directoryDiffs.map(handleOutput).join('');
|
|
7695
|
+
}
|
|
7696
|
+
|
|
7697
|
+
/**
|
|
7698
|
+
* Asynchronously collect diffs for a given node and its children.
|
|
7699
|
+
*/
|
|
7700
|
+
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
7701
|
+
// Collect diffs for the files of the current node
|
|
7702
|
+
const diffPromises = node.files.map(async (nodeFile) => {
|
|
7703
|
+
const diff = await getFileDiff(nodeFile);
|
|
7704
|
+
const tokenCount = tokenizer(diff);
|
|
7705
|
+
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
7706
|
+
color: 'magenta',
|
|
7707
|
+
});
|
|
7708
|
+
return {
|
|
7709
|
+
file: nodeFile.filePath,
|
|
7710
|
+
summary: nodeFile.summary,
|
|
7711
|
+
diff,
|
|
7712
|
+
tokenCount,
|
|
7713
|
+
};
|
|
7714
|
+
});
|
|
7715
|
+
// Collect diffs for the children of the current node
|
|
7716
|
+
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
7717
|
+
const [diffs, children] = await Promise.all([
|
|
7718
|
+
Promise.all(diffPromises),
|
|
7719
|
+
Promise.all(childrenPromises),
|
|
7720
|
+
]);
|
|
7721
|
+
return {
|
|
7722
|
+
path: node.getPath(),
|
|
7723
|
+
diffs,
|
|
7724
|
+
children,
|
|
7725
|
+
};
|
|
7726
|
+
}
|
|
7727
|
+
|
|
7728
|
+
class DiffTreeNode {
|
|
7729
|
+
constructor(path) {
|
|
7730
|
+
this.path = [];
|
|
7731
|
+
this.files = [];
|
|
7732
|
+
this.children = new Map();
|
|
7733
|
+
if (path)
|
|
7734
|
+
this.path = path;
|
|
7735
|
+
}
|
|
7736
|
+
addFile(file) {
|
|
7737
|
+
this.files.push(file);
|
|
7738
|
+
}
|
|
7739
|
+
addChild(part, node) {
|
|
7740
|
+
this.children.set(part, node);
|
|
7741
|
+
}
|
|
7742
|
+
getChild(part) {
|
|
7743
|
+
return this.children.get(part);
|
|
7744
|
+
}
|
|
7745
|
+
getPath() {
|
|
7746
|
+
return this.path.join('/');
|
|
7747
|
+
}
|
|
7748
|
+
print(indentation = 0) {
|
|
7749
|
+
const indent = ' '.repeat(indentation);
|
|
7750
|
+
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
7751
|
+
if (this.files.length > 0) {
|
|
7752
|
+
output += `${indent} Files:\n`;
|
|
7753
|
+
for (const file of this.files) {
|
|
7754
|
+
output += `${indent} - ${file.summary}\n`;
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
if (this.children.size > 0) {
|
|
7758
|
+
output += `${indent} Children:\n`;
|
|
7759
|
+
for (const [, child] of this.children) {
|
|
7760
|
+
output += child.print(indentation + 4);
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
return output;
|
|
7764
|
+
}
|
|
7765
|
+
}
|
|
7766
|
+
const createDiffTree = (changes) => {
|
|
7767
|
+
const root = new DiffTreeNode();
|
|
7768
|
+
for (const change of changes) {
|
|
7769
|
+
let currentParent = root;
|
|
7770
|
+
const parts = change.filePath.split('/');
|
|
7771
|
+
parts.pop();
|
|
7772
|
+
for (const part of parts) {
|
|
7773
|
+
let childNode = currentParent.getChild(part);
|
|
7774
|
+
if (!childNode) {
|
|
7775
|
+
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
7776
|
+
currentParent.addChild(part, childNode);
|
|
7777
|
+
}
|
|
7778
|
+
currentParent = childNode;
|
|
7779
|
+
}
|
|
7780
|
+
// Create a NodeFile object and add it to the parent
|
|
7781
|
+
currentParent.addFile({
|
|
7782
|
+
filePath: change.filePath,
|
|
7783
|
+
oldFilePath: change.oldFilePath,
|
|
7784
|
+
summary: change.summary,
|
|
7785
|
+
status: change.status,
|
|
7786
|
+
});
|
|
7787
|
+
}
|
|
7788
|
+
return root;
|
|
7789
|
+
};
|
|
7790
|
+
|
|
7791
|
+
/**
|
|
7792
|
+
* Parses the default file diff for a given nodeFile.
|
|
7793
|
+
*
|
|
7794
|
+
* @param nodeFile - The file change object.
|
|
7795
|
+
* @param commit - The commit to diff against. Defaults to '--staged'.
|
|
7796
|
+
* @param git - The SimpleGit instance.
|
|
7797
|
+
* @returns A Promise that resolves to the file diff as a string.
|
|
7798
|
+
*/
|
|
7799
|
+
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
7800
|
+
if (commit === '--staged') {
|
|
7801
|
+
return await git.diff(['--staged', nodeFile.filePath]);
|
|
7802
|
+
}
|
|
7803
|
+
else if (commit === '--unstaged') {
|
|
7804
|
+
return await git.diff([nodeFile.filePath]);
|
|
7805
|
+
}
|
|
7806
|
+
else if (commit === '--untracked') {
|
|
7807
|
+
// For untracked files, read the file content directly from the filesystem
|
|
7808
|
+
try {
|
|
7809
|
+
const fileContent = await promises.readFile(nodeFile.filePath, 'utf-8');
|
|
7810
|
+
return fileContent;
|
|
7811
|
+
}
|
|
7812
|
+
catch (error) {
|
|
7813
|
+
throw new Error(`Error reading untracked file: ${error?.message || 'Unknown error'}`);
|
|
7814
|
+
}
|
|
7815
|
+
}
|
|
7816
|
+
return await git.diff([commit, nodeFile.filePath]);
|
|
7817
|
+
}
|
|
7818
|
+
/**
|
|
7819
|
+
* Parses the diff for a renamed file.
|
|
7820
|
+
*
|
|
7821
|
+
* @param nodeFile - The file change object.
|
|
7822
|
+
* @param commit - The commit hash or '--staged'.
|
|
7823
|
+
* @param git - The SimpleGit instance.
|
|
7824
|
+
* @param logger - The logger instance.
|
|
7825
|
+
* @returns A Promise that resolves to the diff string.
|
|
7826
|
+
*/
|
|
7827
|
+
async function parseRenamedFileDiff(nodeFile, commit, git, logger) {
|
|
7828
|
+
let result = '';
|
|
7829
|
+
const oldFilePath = nodeFile?.oldFilePath || nodeFile.filePath;
|
|
7830
|
+
let previousCommitHash = 'HEAD';
|
|
7831
|
+
let newCommitHash = '';
|
|
7832
|
+
if (commit !== '--staged') {
|
|
7833
|
+
try {
|
|
7834
|
+
previousCommitHash = await git.revparse([`${commit}~1`]);
|
|
7835
|
+
}
|
|
7836
|
+
catch (err) {
|
|
7837
|
+
logger.verbose(`Error getting previous commit hash for ${nodeFile.filePath}`, {
|
|
7838
|
+
color: 'red',
|
|
7839
|
+
});
|
|
7840
|
+
}
|
|
7841
|
+
newCommitHash = commit;
|
|
7842
|
+
}
|
|
7843
|
+
try {
|
|
7844
|
+
const [previousContent, newContent] = await Promise.all([
|
|
7845
|
+
git.show([`${previousCommitHash}:${oldFilePath}`]),
|
|
7846
|
+
git.show([`${newCommitHash}:${nodeFile.filePath}`]),
|
|
7847
|
+
]);
|
|
7848
|
+
if (previousContent !== newContent) {
|
|
7849
|
+
result = createTwoFilesPatch(oldFilePath, nodeFile.filePath, previousContent, newContent, '', '', {
|
|
7850
|
+
context: 3,
|
|
7851
|
+
});
|
|
7852
|
+
// remove the first 4 lines of the patch (they contain the old and new file names)
|
|
7853
|
+
result = result.split('\n').slice(4).join('\n');
|
|
7854
|
+
}
|
|
7855
|
+
else {
|
|
7856
|
+
result = 'File contents are unchanged.';
|
|
7857
|
+
}
|
|
7858
|
+
}
|
|
7859
|
+
catch (err) {
|
|
7860
|
+
logger.verbose(`Error comparing file contents for ${nodeFile.filePath}`, { color: 'red' });
|
|
7861
|
+
result = 'Error comparing file contents.';
|
|
7862
|
+
}
|
|
7863
|
+
return result;
|
|
7864
|
+
}
|
|
7865
|
+
/**
|
|
7866
|
+
* Retrieves the diff for a given file change in a specific commit.
|
|
7867
|
+
* If the file is deleted, it returns a message indicating that the file has been deleted.
|
|
7868
|
+
* If the file is renamed, it parses the renamed file diff and returns it.
|
|
7869
|
+
* Otherwise, it retrieves the default diff from the index and returns it.
|
|
7870
|
+
*
|
|
7871
|
+
* @param nodeFile - The file change object.
|
|
7872
|
+
* @param commit - The commit hash.
|
|
7873
|
+
* @param git - The SimpleGit instance.
|
|
7874
|
+
* @param logger - The logger instance.
|
|
7875
|
+
* @returns A promise that resolves to the diff as a string.
|
|
7876
|
+
*/
|
|
7877
|
+
async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
7878
|
+
if (nodeFile.status === 'deleted') {
|
|
7879
|
+
return 'This file has been deleted.';
|
|
7880
|
+
}
|
|
7881
|
+
if (nodeFile.status === 'renamed' && nodeFile.oldFilePath) {
|
|
7882
|
+
const renamedDiff = await parseRenamedFileDiff(nodeFile, commit, git, logger);
|
|
7883
|
+
return renamedDiff;
|
|
7621
7884
|
}
|
|
7885
|
+
// If not deleted or renamed, get the diff from the index
|
|
7886
|
+
const defaultDiff = await parseDefaultFileDiff(nodeFile, commit, git);
|
|
7887
|
+
return defaultDiff;
|
|
7622
7888
|
}
|
|
7623
7889
|
|
|
7624
|
-
var llm_chain = /*#__PURE__*/Object.freeze({
|
|
7625
|
-
__proto__: null,
|
|
7626
|
-
LLMChain: LLMChain
|
|
7627
|
-
});
|
|
7628
|
-
|
|
7629
7890
|
/* eslint-disable spaced-comment */
|
|
7630
7891
|
const API_URL_RAW_PROMPT_TEMPLATE = `You are given the below API Documentation:
|
|
7631
7892
|
{api_docs}
|
|
@@ -9374,8 +9635,6 @@ const loadSummarizationChain = (llm, params = { type: "map_reduce" }) => {
|
|
|
9374
9635
|
throw new Error(`Invalid _type: ${params.type}`);
|
|
9375
9636
|
};
|
|
9376
9637
|
|
|
9377
|
-
new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
9378
|
-
|
|
9379
9638
|
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
|
|
9380
9639
|
function isNothing(subject) {
|
|
9381
9640
|
return (typeof subject === 'undefined') || (subject === null);
|
|
@@ -10400,225 +10659,12 @@ for (var i = 0; i < 256; i++) {
|
|
|
10400
10659
|
simpleEscapeMap[i] = simpleEscapeSequence(i);
|
|
10401
10660
|
}
|
|
10402
10661
|
|
|
10403
|
-
/**
|
|
10404
|
-
* Get Summarization Chain
|
|
10405
|
-
* @param model
|
|
10406
|
-
* @param options
|
|
10407
|
-
* @returns
|
|
10408
|
-
*/
|
|
10409
|
-
function getSummarizationChain(model, options = { type: 'map_reduce' }) {
|
|
10410
|
-
return loadSummarizationChain(model, options);
|
|
10411
|
-
}
|
|
10412
|
-
|
|
10413
|
-
/**
|
|
10414
|
-
* Get Recursive Character Text Splitter
|
|
10415
|
-
*
|
|
10416
|
-
* @param options
|
|
10417
|
-
* @returns
|
|
10418
|
-
*/
|
|
10419
|
-
function getTextSplitter(options = {}) {
|
|
10420
|
-
return new RecursiveCharacterTextSplitter(options);
|
|
10421
|
-
}
|
|
10422
|
-
|
|
10423
|
-
/**
|
|
10424
|
-
* Asynchronously collect diffs for a given node and its children.
|
|
10425
|
-
*/
|
|
10426
|
-
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
10427
|
-
// Collect diffs for the files of the current node
|
|
10428
|
-
const diffPromises = node.files.map(async (nodeFile) => {
|
|
10429
|
-
const diff = await getFileDiff(nodeFile);
|
|
10430
|
-
const tokenCount = tokenizer(diff);
|
|
10431
|
-
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
10432
|
-
color: 'magenta',
|
|
10433
|
-
});
|
|
10434
|
-
return {
|
|
10435
|
-
file: nodeFile.filePath,
|
|
10436
|
-
summary: nodeFile.summary,
|
|
10437
|
-
diff,
|
|
10438
|
-
tokenCount,
|
|
10439
|
-
};
|
|
10440
|
-
});
|
|
10441
|
-
// Collect diffs for the children of the current node
|
|
10442
|
-
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
10443
|
-
const [diffs, children] = await Promise.all([
|
|
10444
|
-
Promise.all(diffPromises),
|
|
10445
|
-
Promise.all(childrenPromises),
|
|
10446
|
-
]);
|
|
10447
|
-
return {
|
|
10448
|
-
path: node.getPath(),
|
|
10449
|
-
diffs,
|
|
10450
|
-
children,
|
|
10451
|
-
};
|
|
10452
|
-
}
|
|
10453
|
-
|
|
10454
|
-
class DiffTreeNode {
|
|
10455
|
-
constructor(path) {
|
|
10456
|
-
this.path = [];
|
|
10457
|
-
this.files = [];
|
|
10458
|
-
this.children = new Map();
|
|
10459
|
-
if (path)
|
|
10460
|
-
this.path = path;
|
|
10461
|
-
}
|
|
10462
|
-
addFile(file) {
|
|
10463
|
-
this.files.push(file);
|
|
10464
|
-
}
|
|
10465
|
-
addChild(part, node) {
|
|
10466
|
-
this.children.set(part, node);
|
|
10467
|
-
}
|
|
10468
|
-
getChild(part) {
|
|
10469
|
-
return this.children.get(part);
|
|
10470
|
-
}
|
|
10471
|
-
getPath() {
|
|
10472
|
-
return this.path.join('/');
|
|
10473
|
-
}
|
|
10474
|
-
print(indentation = 0) {
|
|
10475
|
-
const indent = ' '.repeat(indentation);
|
|
10476
|
-
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
10477
|
-
if (this.files.length > 0) {
|
|
10478
|
-
output += `${indent} Files:\n`;
|
|
10479
|
-
for (const file of this.files) {
|
|
10480
|
-
output += `${indent} - ${file.summary}\n`;
|
|
10481
|
-
}
|
|
10482
|
-
}
|
|
10483
|
-
if (this.children.size > 0) {
|
|
10484
|
-
output += `${indent} Children:\n`;
|
|
10485
|
-
for (const [, child] of this.children) {
|
|
10486
|
-
output += child.print(indentation + 4);
|
|
10487
|
-
}
|
|
10488
|
-
}
|
|
10489
|
-
return output;
|
|
10490
|
-
}
|
|
10491
|
-
}
|
|
10492
|
-
const createDiffTree = (changes) => {
|
|
10493
|
-
const root = new DiffTreeNode();
|
|
10494
|
-
for (const change of changes) {
|
|
10495
|
-
let currentParent = root;
|
|
10496
|
-
const parts = change.filePath.split('/');
|
|
10497
|
-
parts.pop();
|
|
10498
|
-
for (const part of parts) {
|
|
10499
|
-
let childNode = currentParent.getChild(part);
|
|
10500
|
-
if (!childNode) {
|
|
10501
|
-
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
10502
|
-
currentParent.addChild(part, childNode);
|
|
10503
|
-
}
|
|
10504
|
-
currentParent = childNode;
|
|
10505
|
-
}
|
|
10506
|
-
// Create a NodeFile object and add it to the parent
|
|
10507
|
-
currentParent.addFile({
|
|
10508
|
-
filePath: change.filePath,
|
|
10509
|
-
oldFilePath: change.oldFilePath,
|
|
10510
|
-
summary: change.summary,
|
|
10511
|
-
status: change.status,
|
|
10512
|
-
});
|
|
10513
|
-
}
|
|
10514
|
-
return root;
|
|
10515
|
-
};
|
|
10516
|
-
|
|
10517
|
-
/**
|
|
10518
|
-
* Parses the default file diff for a given nodeFile.
|
|
10519
|
-
*
|
|
10520
|
-
* @param nodeFile - The file change object.
|
|
10521
|
-
* @param commit - The commit to diff against. Defaults to '--staged'.
|
|
10522
|
-
* @param git - The SimpleGit instance.
|
|
10523
|
-
* @returns A Promise that resolves to the file diff as a string.
|
|
10524
|
-
*/
|
|
10525
|
-
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
10526
|
-
if (commit === '--staged') {
|
|
10527
|
-
return await git.diff(['--staged', nodeFile.filePath]);
|
|
10528
|
-
}
|
|
10529
|
-
else if (commit === '--unstaged') {
|
|
10530
|
-
return await git.diff([nodeFile.filePath]);
|
|
10531
|
-
}
|
|
10532
|
-
else if (commit === '--untracked') {
|
|
10533
|
-
// For untracked files, read the file content directly from the filesystem
|
|
10534
|
-
try {
|
|
10535
|
-
const fileContent = await promises.readFile(nodeFile.filePath, 'utf-8');
|
|
10536
|
-
return fileContent;
|
|
10537
|
-
}
|
|
10538
|
-
catch (error) {
|
|
10539
|
-
throw new Error(`Error reading untracked file: ${error?.message || 'Unknown error'}`);
|
|
10540
|
-
}
|
|
10541
|
-
}
|
|
10542
|
-
return await git.diff([commit, nodeFile.filePath]);
|
|
10543
|
-
}
|
|
10544
|
-
/**
|
|
10545
|
-
* Parses the diff for a renamed file.
|
|
10546
|
-
*
|
|
10547
|
-
* @param nodeFile - The file change object.
|
|
10548
|
-
* @param commit - The commit hash or '--staged'.
|
|
10549
|
-
* @param git - The SimpleGit instance.
|
|
10550
|
-
* @param logger - The logger instance.
|
|
10551
|
-
* @returns A Promise that resolves to the diff string.
|
|
10552
|
-
*/
|
|
10553
|
-
async function parseRenamedFileDiff(nodeFile, commit, git, logger) {
|
|
10554
|
-
let result = '';
|
|
10555
|
-
const oldFilePath = nodeFile?.oldFilePath || nodeFile.filePath;
|
|
10556
|
-
let previousCommitHash = 'HEAD';
|
|
10557
|
-
let newCommitHash = '';
|
|
10558
|
-
if (commit !== '--staged') {
|
|
10559
|
-
try {
|
|
10560
|
-
previousCommitHash = await git.revparse([`${commit}~1`]);
|
|
10561
|
-
}
|
|
10562
|
-
catch (err) {
|
|
10563
|
-
logger.verbose(`Error getting previous commit hash for ${nodeFile.filePath}`, {
|
|
10564
|
-
color: 'red',
|
|
10565
|
-
});
|
|
10566
|
-
}
|
|
10567
|
-
newCommitHash = commit;
|
|
10568
|
-
}
|
|
10569
|
-
try {
|
|
10570
|
-
const [previousContent, newContent] = await Promise.all([
|
|
10571
|
-
git.show([`${previousCommitHash}:${oldFilePath}`]),
|
|
10572
|
-
git.show([`${newCommitHash}:${nodeFile.filePath}`]),
|
|
10573
|
-
]);
|
|
10574
|
-
if (previousContent !== newContent) {
|
|
10575
|
-
result = createTwoFilesPatch(oldFilePath, nodeFile.filePath, previousContent, newContent, '', '', {
|
|
10576
|
-
context: 3,
|
|
10577
|
-
});
|
|
10578
|
-
// remove the first 4 lines of the patch (they contain the old and new file names)
|
|
10579
|
-
result = result.split('\n').slice(4).join('\n');
|
|
10580
|
-
}
|
|
10581
|
-
else {
|
|
10582
|
-
result = 'File contents are unchanged.';
|
|
10583
|
-
}
|
|
10584
|
-
}
|
|
10585
|
-
catch (err) {
|
|
10586
|
-
logger.verbose(`Error comparing file contents for ${nodeFile.filePath}`, { color: 'red' });
|
|
10587
|
-
result = 'Error comparing file contents.';
|
|
10588
|
-
}
|
|
10589
|
-
return result;
|
|
10590
|
-
}
|
|
10591
|
-
/**
|
|
10592
|
-
* Retrieves the diff for a given file change in a specific commit.
|
|
10593
|
-
* If the file is deleted, it returns a message indicating that the file has been deleted.
|
|
10594
|
-
* If the file is renamed, it parses the renamed file diff and returns it.
|
|
10595
|
-
* Otherwise, it retrieves the default diff from the index and returns it.
|
|
10596
|
-
*
|
|
10597
|
-
* @param nodeFile - The file change object.
|
|
10598
|
-
* @param commit - The commit hash.
|
|
10599
|
-
* @param git - The SimpleGit instance.
|
|
10600
|
-
* @param logger - The logger instance.
|
|
10601
|
-
* @returns A promise that resolves to the diff as a string.
|
|
10602
|
-
*/
|
|
10603
|
-
async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
10604
|
-
if (nodeFile.status === 'deleted') {
|
|
10605
|
-
return 'This file has been deleted.';
|
|
10606
|
-
}
|
|
10607
|
-
if (nodeFile.status === 'renamed' && nodeFile.oldFilePath) {
|
|
10608
|
-
const renamedDiff = await parseRenamedFileDiff(nodeFile, commit, git, logger);
|
|
10609
|
-
return renamedDiff;
|
|
10610
|
-
}
|
|
10611
|
-
// If not deleted or renamed, get the diff from the index
|
|
10612
|
-
const defaultDiff = await parseDefaultFileDiff(nodeFile, commit, git);
|
|
10613
|
-
return defaultDiff;
|
|
10614
|
-
}
|
|
10615
|
-
|
|
10616
10662
|
// Max tokens for GPT-3 is 4096
|
|
10617
10663
|
// const MAX_TOKENS_PER_SUMMARY = 4096
|
|
10618
10664
|
const MAX_TOKENS_PER_SUMMARY = 12288;
|
|
10619
10665
|
async function fileChangeParser({ changes, commit, options: { tokenizer, git, llm: model, logger }, }) {
|
|
10620
|
-
const textSplitter =
|
|
10621
|
-
const summarizationChain =
|
|
10666
|
+
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 10000, chunkOverlap: 250 });
|
|
10667
|
+
const summarizationChain = loadSummarizationChain(model, {
|
|
10622
10668
|
type: 'map_reduce',
|
|
10623
10669
|
combineMapPrompt: SUMMARIZE_PROMPT,
|
|
10624
10670
|
combinePrompt: SUMMARIZE_PROMPT,
|
|
@@ -10889,11 +10935,18 @@ const handler$3 = async (argv, logger) => {
|
|
|
10889
10935
|
const llm = getLlm(provider, model, config);
|
|
10890
10936
|
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
10891
10937
|
if (INTERACTIVE) {
|
|
10892
|
-
|
|
10938
|
+
if (!config.hideCocoBanner) {
|
|
10939
|
+
logger.log(LOGO);
|
|
10940
|
+
}
|
|
10893
10941
|
}
|
|
10894
10942
|
else {
|
|
10895
10943
|
logger.setConfig({ silent: true });
|
|
10896
10944
|
}
|
|
10945
|
+
if (config.service.provider === 'ollama') {
|
|
10946
|
+
logger.verbose('⚠️ Ollama models may not strictly adhere to the output format instructions.', {
|
|
10947
|
+
color: 'yellow',
|
|
10948
|
+
});
|
|
10949
|
+
}
|
|
10897
10950
|
async function factory() {
|
|
10898
10951
|
const changes = await getChanges({
|
|
10899
10952
|
git,
|
|
@@ -10940,7 +10993,8 @@ const handler$3 = async (argv, logger) => {
|
|
|
10940
10993
|
const schema = useConventional
|
|
10941
10994
|
? ConventionalCommitMessageResponseSchema
|
|
10942
10995
|
: CommitMessageResponseSchema;
|
|
10943
|
-
const
|
|
10996
|
+
const formatInstructions = `You must always return valid JSON fenced by a markdown code block. Do not return any additional text. The JSON object you return should match the following schema:
|
|
10997
|
+
{{ body: string, title: string }}`;
|
|
10944
10998
|
// Use conventional commit prompt if enabled
|
|
10945
10999
|
const promptTemplate = useConventional ? CONVENTIONAL_COMMIT_PROMPT : COMMIT_PROMPT;
|
|
10946
11000
|
const prompt = getPrompt({
|
|
@@ -10948,7 +11002,6 @@ const handler$3 = async (argv, logger) => {
|
|
|
10948
11002
|
variables: promptTemplate.inputVariables,
|
|
10949
11003
|
fallback: promptTemplate,
|
|
10950
11004
|
});
|
|
10951
|
-
const formatInstructions = "Respond with a valid JSON object, containing two fields: 'title' and 'body', both strings.";
|
|
10952
11005
|
// Get additional context if provided
|
|
10953
11006
|
let additional_context = '';
|
|
10954
11007
|
if (argv.additional) {
|
|
@@ -10981,11 +11034,25 @@ const handler$3 = async (argv, logger) => {
|
|
|
10981
11034
|
commit_history: commit_history,
|
|
10982
11035
|
branch_name_context: branchNameContext,
|
|
10983
11036
|
};
|
|
10984
|
-
const
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
11037
|
+
const maxAttempts = config.service.provider === 'ollama' && 'maxParsingAttempts' in config.service
|
|
11038
|
+
? config.service.maxParsingAttempts || 3
|
|
11039
|
+
: 3;
|
|
11040
|
+
const commitMsg = await executeChainWithSchema(schema, llm, prompt, variables, {
|
|
11041
|
+
retryOptions: {
|
|
11042
|
+
maxAttempts,
|
|
11043
|
+
onRetry: (attempt, error) => {
|
|
11044
|
+
logger.verbose(`Failed to parse commit message (attempt ${attempt}/${maxAttempts}): ${error.message}`, { color: 'yellow' });
|
|
11045
|
+
},
|
|
11046
|
+
},
|
|
11047
|
+
fallbackParser: (text) => ({
|
|
11048
|
+
title: text.split('\n')[0] || 'Auto-generated commit',
|
|
11049
|
+
body: text.split('\n').slice(1).join('\n') || 'Generated commit message',
|
|
11050
|
+
}),
|
|
11051
|
+
onFallback: () => {
|
|
11052
|
+
logger.verbose('Max retry attempts reached. Falling back to simple text output.', {
|
|
11053
|
+
color: 'red',
|
|
11054
|
+
});
|
|
11055
|
+
},
|
|
10989
11056
|
});
|
|
10990
11057
|
// Construct the full commit message
|
|
10991
11058
|
const appendedText = argv.append ? `\n\n${argv.append}` : '';
|
|
@@ -11203,12 +11270,15 @@ const OPEN_AI_MODELS = [
|
|
|
11203
11270
|
'gpt-3.5-turbo',
|
|
11204
11271
|
];
|
|
11205
11272
|
const ANTHROPIC_MODELS = [
|
|
11273
|
+
'claude-sonnet-4-0',
|
|
11274
|
+
'claude-3-7-sonnet-latest',
|
|
11275
|
+
'claude-3-5-haiku-latest',
|
|
11276
|
+
'claude-3-5-sonnet-latest',
|
|
11277
|
+
'claude-3-5-sonnet-20241022',
|
|
11206
11278
|
'claude-3-5-sonnet-20240620',
|
|
11207
11279
|
'claude-3-opus-20240229',
|
|
11208
11280
|
'claude-3-sonnet-20240229',
|
|
11209
11281
|
'claude-3-haiku-20240307',
|
|
11210
|
-
'claude-2.1',
|
|
11211
|
-
'claude-2.0',
|
|
11212
11282
|
];
|
|
11213
11283
|
|
|
11214
11284
|
const questions = {
|
|
@@ -11342,6 +11412,32 @@ const questions = {
|
|
|
11342
11412
|
});
|
|
11343
11413
|
return parseFloat(temperature);
|
|
11344
11414
|
},
|
|
11415
|
+
inputOllamaEndpoint: async () => {
|
|
11416
|
+
return await input({
|
|
11417
|
+
message: 'Ollama endpoint (e.g., http://localhost:11434):',
|
|
11418
|
+
default: 'http://localhost:11434',
|
|
11419
|
+
});
|
|
11420
|
+
},
|
|
11421
|
+
inputRequestTimeout: async () => {
|
|
11422
|
+
const timeout = await input({
|
|
11423
|
+
message: 'Request timeout in milliseconds:',
|
|
11424
|
+
default: '30000',
|
|
11425
|
+
});
|
|
11426
|
+
return parseInt(timeout);
|
|
11427
|
+
},
|
|
11428
|
+
inputRequestMaxRetries: async () => {
|
|
11429
|
+
const maxRetries = await input({
|
|
11430
|
+
message: 'Maximum number of request retries:',
|
|
11431
|
+
default: '3',
|
|
11432
|
+
});
|
|
11433
|
+
return parseInt(maxRetries);
|
|
11434
|
+
},
|
|
11435
|
+
inputServiceFields: async () => {
|
|
11436
|
+
return await editor({
|
|
11437
|
+
message: 'Enter additional service fields as a JSON string (optional):',
|
|
11438
|
+
default: '{}',
|
|
11439
|
+
});
|
|
11440
|
+
},
|
|
11345
11441
|
selectDefaultGitBranch: async () => (await input({
|
|
11346
11442
|
message: 'default branch for the repository:',
|
|
11347
11443
|
default: 'main',
|
|
@@ -11435,6 +11531,29 @@ const handler$2 = async (argv, logger) => {
|
|
|
11435
11531
|
tokenLimit: await questions.inputTokenLimit(),
|
|
11436
11532
|
};
|
|
11437
11533
|
config.verbose = await questions.enableVerboseMode();
|
|
11534
|
+
if (llmProvider === 'ollama') {
|
|
11535
|
+
config.service.endpoint = await questions.inputOllamaEndpoint();
|
|
11536
|
+
}
|
|
11537
|
+
config.service.requestOptions = {
|
|
11538
|
+
timeout: await questions.inputRequestTimeout(),
|
|
11539
|
+
maxRetries: await questions.inputRequestMaxRetries(),
|
|
11540
|
+
};
|
|
11541
|
+
const promptForServiceFields = await confirm({
|
|
11542
|
+
message: 'would you like to configure additional service fields (advanced)?',
|
|
11543
|
+
default: false,
|
|
11544
|
+
});
|
|
11545
|
+
if (promptForServiceFields) {
|
|
11546
|
+
const fieldsJson = await questions.inputServiceFields();
|
|
11547
|
+
try {
|
|
11548
|
+
config.service.fields = JSON.parse(fieldsJson);
|
|
11549
|
+
}
|
|
11550
|
+
catch (e) {
|
|
11551
|
+
logger.log('Invalid JSON for service fields. Skipping.', { color: 'red' });
|
|
11552
|
+
logger.verbose(`Error parsing service fields: ${e.message}`, {
|
|
11553
|
+
color: 'red',
|
|
11554
|
+
});
|
|
11555
|
+
}
|
|
11556
|
+
}
|
|
11438
11557
|
const promptForIgnores = await confirm({
|
|
11439
11558
|
message: 'would you like to configure ignored files and extensions?',
|
|
11440
11559
|
default: false,
|
|
@@ -11500,9 +11619,9 @@ var init = {
|
|
|
11500
11619
|
options: options$2,
|
|
11501
11620
|
};
|
|
11502
11621
|
|
|
11503
|
-
const RecapLlmResponseSchema =
|
|
11504
|
-
title:
|
|
11505
|
-
summary:
|
|
11622
|
+
const RecapLlmResponseSchema = objectType({
|
|
11623
|
+
title: stringType().optional(),
|
|
11624
|
+
summary: stringType().optional(),
|
|
11506
11625
|
});
|
|
11507
11626
|
const command$1 = 'recap';
|
|
11508
11627
|
/**
|
|
@@ -11576,7 +11695,9 @@ const handler$1 = async (argv, logger) => {
|
|
|
11576
11695
|
const llm = getLlm(provider, model, config);
|
|
11577
11696
|
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
11578
11697
|
if (INTERACTIVE) {
|
|
11579
|
-
|
|
11698
|
+
if (!config.hideCocoBanner) {
|
|
11699
|
+
logger.log(LOGO);
|
|
11700
|
+
}
|
|
11580
11701
|
}
|
|
11581
11702
|
else {
|
|
11582
11703
|
logger.setConfig({ silent: true });
|
|
@@ -11725,26 +11846,26 @@ var recap = {
|
|
|
11725
11846
|
options: options$1,
|
|
11726
11847
|
};
|
|
11727
11848
|
|
|
11728
|
-
const ReviewFeedbackItemSchema =
|
|
11729
|
-
title:
|
|
11730
|
-
summary:
|
|
11731
|
-
severity:
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11849
|
+
const ReviewFeedbackItemSchema = objectType({
|
|
11850
|
+
title: stringType(),
|
|
11851
|
+
summary: stringType(),
|
|
11852
|
+
severity: unionType([
|
|
11853
|
+
literalType(1),
|
|
11854
|
+
literalType(2),
|
|
11855
|
+
literalType(3),
|
|
11856
|
+
literalType(4),
|
|
11857
|
+
literalType(5),
|
|
11858
|
+
literalType(6),
|
|
11859
|
+
literalType(7),
|
|
11860
|
+
literalType(8),
|
|
11861
|
+
literalType(9),
|
|
11862
|
+
literalType(10),
|
|
11742
11863
|
]),
|
|
11743
|
-
category:
|
|
11744
|
-
filePath:
|
|
11864
|
+
category: stringType(),
|
|
11865
|
+
filePath: stringType(),
|
|
11745
11866
|
});
|
|
11746
11867
|
// Array schema for review feedback items
|
|
11747
|
-
const ReviewFeedbackItemArraySchema =
|
|
11868
|
+
const ReviewFeedbackItemArraySchema = arrayType(ReviewFeedbackItemSchema);
|
|
11748
11869
|
const command = 'review';
|
|
11749
11870
|
/**
|
|
11750
11871
|
* Command line options via yargs
|
|
@@ -14014,7 +14135,9 @@ const handler = async (argv, logger) => {
|
|
|
14014
14135
|
const llm = getLlm(provider, model, config);
|
|
14015
14136
|
const INTERACTIVE = isInteractive(config);
|
|
14016
14137
|
if (INTERACTIVE) {
|
|
14017
|
-
|
|
14138
|
+
if (!config.hideCocoBanner) {
|
|
14139
|
+
logger.log(LOGO);
|
|
14140
|
+
}
|
|
14018
14141
|
}
|
|
14019
14142
|
async function factory() {
|
|
14020
14143
|
if (argv.branch) {
|