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.js
CHANGED
|
@@ -19,20 +19,20 @@ var ollama = require('@langchain/ollama');
|
|
|
19
19
|
var openai = require('@langchain/openai');
|
|
20
20
|
var output_parsers = require('@langchain/core/output_parsers');
|
|
21
21
|
var simpleGit = require('simple-git');
|
|
22
|
-
var
|
|
23
|
-
var
|
|
22
|
+
var base = require('@langchain/core/language_models/base');
|
|
23
|
+
var runnables = require('@langchain/core/runnables');
|
|
24
24
|
var outputs = require('@langchain/core/outputs');
|
|
25
25
|
var manager = require('@langchain/core/callbacks/manager');
|
|
26
|
-
|
|
27
|
-
var
|
|
26
|
+
require('@langchain/core/utils/json_patch');
|
|
27
|
+
var pQueue = require('p-queue');
|
|
28
|
+
var documents = require('@langchain/core/documents');
|
|
29
|
+
var diff = require('diff');
|
|
28
30
|
require('@langchain/core/messages');
|
|
29
31
|
require('@langchain/core/memory');
|
|
30
32
|
require('@langchain/core/chat_history');
|
|
31
33
|
require('@langchain/core/utils/tiktoken');
|
|
32
34
|
require('@langchain/core/utils/async_caller');
|
|
33
35
|
require('@langchain/core/utils/env');
|
|
34
|
-
require('@langchain/core/utils/json_patch');
|
|
35
|
-
var diff = require('diff');
|
|
36
36
|
var minimatch = require('minimatch');
|
|
37
37
|
var tiktoken = require('tiktoken');
|
|
38
38
|
var child_process = require('child_process');
|
|
@@ -68,7 +68,7 @@ var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline$1);
|
|
|
68
68
|
/**
|
|
69
69
|
* Current build version from package.json
|
|
70
70
|
*/
|
|
71
|
-
const BUILD_VERSION = "0.
|
|
71
|
+
const BUILD_VERSION = "0.18.0";
|
|
72
72
|
|
|
73
73
|
const isInteractive = (config) => {
|
|
74
74
|
return config?.mode === 'interactive' || !!config?.interactive;
|
|
@@ -195,51 +195,175 @@ const SUMMARIZE_PROMPT = new prompts$1.PromptTemplate({
|
|
|
195
195
|
template: template$5,
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Base class for all LangChain-related errors
|
|
200
|
+
*/
|
|
201
|
+
class LangChainError extends Error {
|
|
202
|
+
constructor(message, context) {
|
|
203
|
+
super(message);
|
|
204
|
+
this.context = context;
|
|
205
|
+
this.name = this.constructor.name;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Configuration-related errors (invalid service configs, missing settings, etc.)
|
|
210
|
+
*/
|
|
211
|
+
class LangChainConfigurationError extends LangChainError {
|
|
212
|
+
constructor(message, context) {
|
|
213
|
+
super(message, context);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Input validation errors (missing required parameters, invalid types, etc.)
|
|
218
|
+
*/
|
|
219
|
+
class LangChainValidationError extends LangChainError {
|
|
220
|
+
constructor(message, context) {
|
|
221
|
+
super(message, context);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Runtime execution errors (LLM failures, parsing errors, etc.)
|
|
226
|
+
*/
|
|
227
|
+
class LangChainExecutionError extends LangChainError {
|
|
228
|
+
constructor(message, context) {
|
|
229
|
+
super(message, context);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Authentication-related errors (missing API keys, invalid credentials, etc.)
|
|
234
|
+
*/
|
|
235
|
+
class LangChainAuthenticationError extends LangChainError {
|
|
236
|
+
constructor(message, context) {
|
|
237
|
+
super(message, context);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Validates that a required parameter is not null or undefined
|
|
243
|
+
*/
|
|
244
|
+
function validateRequired(value, paramName, functionName) {
|
|
245
|
+
if (value === null || value === undefined) {
|
|
246
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Required parameter '${paramName}' is missing`, { paramName, functionName, value });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Validates that a string parameter is not empty
|
|
251
|
+
*/
|
|
252
|
+
function validateNonEmptyString(value, paramName, functionName) {
|
|
253
|
+
validateRequired(value, paramName, functionName);
|
|
254
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
255
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Parameter '${paramName}' must be a non-empty string`, { paramName, functionName, value, type: typeof value });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Validates that an array parameter is not empty
|
|
260
|
+
*/
|
|
261
|
+
function validateNonEmptyArray(value, paramName, functionName) {
|
|
262
|
+
validateRequired(value, paramName, functionName);
|
|
263
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
264
|
+
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 });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Validates that a provider is supported
|
|
269
|
+
*/
|
|
270
|
+
function validateProvider(provider, functionName) {
|
|
271
|
+
const validProviders = ['openai', 'anthropic', 'ollama'];
|
|
272
|
+
if (!validProviders.includes(provider)) {
|
|
273
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Invalid provider '${provider}'. Supported providers: ${validProviders.join(', ')}`, { provider, validProviders, functionName });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Validates that a model is valid for the given provider
|
|
278
|
+
*/
|
|
279
|
+
function validateModel(model, provider, functionName) {
|
|
280
|
+
validateRequired(model, 'model', functionName);
|
|
281
|
+
if (typeof model !== 'string' || model.trim() === '') {
|
|
282
|
+
throw new LangChainValidationError(`${functionName ? `${functionName}: ` : ''}Model must be a non-empty string`, { model, provider, functionName });
|
|
283
|
+
}
|
|
284
|
+
// Additional provider-specific validation could be added here
|
|
285
|
+
// For now, we trust the TypeScript types
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Validates that a service configuration is complete and valid
|
|
289
|
+
*/
|
|
290
|
+
function validateServiceConfig(service, functionName) {
|
|
291
|
+
validateRequired(service, 'service', functionName);
|
|
292
|
+
if (typeof service !== 'object') {
|
|
293
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Service configuration must be an object`, { service, functionName });
|
|
294
|
+
}
|
|
295
|
+
const serviceObj = service;
|
|
296
|
+
validateProvider(serviceObj.provider, functionName);
|
|
297
|
+
validateModel(serviceObj.model, serviceObj.provider, functionName);
|
|
298
|
+
// Validate authentication
|
|
299
|
+
if (!serviceObj.authentication || typeof serviceObj.authentication !== 'object') {
|
|
300
|
+
throw new LangChainConfigurationError(`${functionName ? `${functionName}: ` : ''}Service configuration must include authentication`, { service, functionName });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
198
304
|
/**
|
|
199
305
|
* Retrieves the provider and model from the given configuration object.
|
|
200
306
|
* @param config The configuration object.
|
|
201
307
|
* @returns An object containing the provider and model.
|
|
202
|
-
* @throws
|
|
308
|
+
* @throws LangChainConfigurationError if the configuration is invalid or missing required properties.
|
|
203
309
|
*/
|
|
204
310
|
function getModelAndProviderFromConfig(config) {
|
|
311
|
+
validateRequired(config, 'config', 'getModelAndProviderFromConfig');
|
|
205
312
|
if (!config.service) {
|
|
206
|
-
throw new
|
|
313
|
+
throw new LangChainConfigurationError('getModelAndProviderFromConfig: Service configuration is missing', { config });
|
|
207
314
|
}
|
|
315
|
+
validateServiceConfig(config.service, 'getModelAndProviderFromConfig');
|
|
208
316
|
const { provider, model } = config.service;
|
|
209
|
-
if (!model || !provider) {
|
|
210
|
-
throw new Error(`Invalid service: ${config.service}`);
|
|
211
|
-
}
|
|
212
317
|
return { provider, model };
|
|
213
318
|
}
|
|
214
319
|
/**
|
|
215
320
|
* Retrieve appropriate API key based on selected model
|
|
216
|
-
* @param
|
|
217
|
-
* @
|
|
218
|
-
* @
|
|
321
|
+
* @param config The configuration object
|
|
322
|
+
* @returns API Key or empty string if no authentication required
|
|
323
|
+
* @throws LangChainAuthenticationError if authentication is required but missing
|
|
219
324
|
*/
|
|
220
325
|
function getApiKeyForModel(config) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
default:
|
|
226
|
-
return getDefaultServiceApiKey(config);
|
|
227
|
-
}
|
|
326
|
+
validateRequired(config, 'config', 'getApiKeyForModel');
|
|
327
|
+
// This function now simply delegates to getDefaultServiceApiKey
|
|
328
|
+
// The switch statement was unnecessary since all providers use the same logic
|
|
329
|
+
return getDefaultServiceApiKey(config);
|
|
228
330
|
}
|
|
229
331
|
/**
|
|
230
332
|
* Retrieves the default service API key from the given configuration.
|
|
231
333
|
* @param config The configuration object.
|
|
232
|
-
* @returns The default service API key.
|
|
334
|
+
* @returns The default service API key or empty string for services that don't require authentication.
|
|
335
|
+
* @throws LangChainAuthenticationError if authentication is required but invalid.
|
|
233
336
|
*/
|
|
234
337
|
function getDefaultServiceApiKey(config) {
|
|
338
|
+
validateRequired(config, 'config', 'getDefaultServiceApiKey');
|
|
339
|
+
validateServiceConfig(config.service, 'getDefaultServiceApiKey');
|
|
235
340
|
const service = config.service;
|
|
341
|
+
const { provider } = service;
|
|
342
|
+
// Check if authentication is required for this provider
|
|
343
|
+
const requiresAuth = provider === 'openai' || provider === 'anthropic';
|
|
236
344
|
if (service.authentication.type === 'APIKey') {
|
|
237
|
-
|
|
345
|
+
const apiKey = service.authentication.credentials?.apiKey;
|
|
346
|
+
if (requiresAuth && (!apiKey || apiKey.trim() === '')) {
|
|
347
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: API key is required for ${provider} provider but not provided`, { provider, authenticationType: service.authentication.type });
|
|
348
|
+
}
|
|
349
|
+
return apiKey || '';
|
|
350
|
+
}
|
|
351
|
+
if (service.authentication.type === 'OAuth') {
|
|
352
|
+
const token = service.authentication.credentials?.token;
|
|
353
|
+
if (requiresAuth && (!token || token.trim() === '')) {
|
|
354
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: OAuth token is required for ${provider} provider but not provided`, { provider, authenticationType: service.authentication.type });
|
|
355
|
+
}
|
|
356
|
+
return token || '';
|
|
238
357
|
}
|
|
239
|
-
|
|
240
|
-
|
|
358
|
+
if (service.authentication.type === 'None') {
|
|
359
|
+
if (requiresAuth) {
|
|
360
|
+
throw new LangChainAuthenticationError(`getDefaultServiceApiKey: ${provider} provider requires authentication but 'None' was configured`, { provider, authenticationType: service.authentication.type });
|
|
361
|
+
}
|
|
362
|
+
return '';
|
|
241
363
|
}
|
|
242
|
-
|
|
364
|
+
// This should never be reached due to TypeScript type checking, but included for safety
|
|
365
|
+
const authType = service.authentication.type;
|
|
366
|
+
throw new LangChainConfigurationError(`getDefaultServiceApiKey: Unknown authentication type '${authType}'`, { provider, authentication: service.authentication });
|
|
243
367
|
}
|
|
244
368
|
const DEFAULT_OPENAI_LLM_SERVICE = {
|
|
245
369
|
provider: 'openai',
|
|
@@ -253,6 +377,17 @@ const DEFAULT_OPENAI_LLM_SERVICE = {
|
|
|
253
377
|
},
|
|
254
378
|
},
|
|
255
379
|
};
|
|
380
|
+
const DEFAULT_ANTHROPIC_LLM_SERVICE = {
|
|
381
|
+
provider: 'anthropic',
|
|
382
|
+
model: 'claude-3-5-sonnet-20240620',
|
|
383
|
+
temperature: 0.32,
|
|
384
|
+
authentication: {
|
|
385
|
+
type: 'APIKey',
|
|
386
|
+
credentials: {
|
|
387
|
+
apiKey: '',
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
};
|
|
256
391
|
const DEFAULT_OLLAMA_LLM_SERVICE = {
|
|
257
392
|
provider: 'ollama',
|
|
258
393
|
model: 'llama3',
|
|
@@ -260,24 +395,33 @@ const DEFAULT_OLLAMA_LLM_SERVICE = {
|
|
|
260
395
|
maxConcurrent: 1,
|
|
261
396
|
tokenLimit: 2024,
|
|
262
397
|
temperature: 0.4,
|
|
398
|
+
maxParsingAttempts: 3,
|
|
263
399
|
authentication: {
|
|
264
400
|
type: 'None',
|
|
265
401
|
credentials: undefined,
|
|
266
402
|
},
|
|
267
403
|
};
|
|
268
404
|
/**
|
|
269
|
-
* Retrieves the default service configuration based on the provided
|
|
270
|
-
* @param provider - The
|
|
271
|
-
* @param model - The optional model to be used.
|
|
272
|
-
* @returns The default service configuration.
|
|
273
|
-
* @throws
|
|
405
|
+
* Retrieves the default service configuration based on the provided provider and optional model.
|
|
406
|
+
* @param provider - The LLM provider (openai, anthropic, ollama).
|
|
407
|
+
* @param model - The optional model to be used. If not provided, uses the default model for the provider.
|
|
408
|
+
* @returns The default service configuration for the specified provider.
|
|
409
|
+
* @throws LangChainConfigurationError if the provider is invalid or unsupported.
|
|
274
410
|
*/
|
|
275
411
|
function getDefaultServiceConfigFromAlias(provider, model) {
|
|
412
|
+
validateRequired(provider, 'provider', 'getDefaultServiceConfigFromAlias');
|
|
413
|
+
// Validate model if provided
|
|
414
|
+
if (model !== undefined) {
|
|
415
|
+
validateRequired(model, 'model', 'getDefaultServiceConfigFromAlias');
|
|
416
|
+
if (typeof model !== 'string' || model.trim() === '') {
|
|
417
|
+
throw new LangChainConfigurationError('getDefaultServiceConfigFromAlias: Model must be a non-empty string when provided', { provider, model });
|
|
418
|
+
}
|
|
419
|
+
}
|
|
276
420
|
switch (provider) {
|
|
277
421
|
case 'anthropic':
|
|
278
422
|
return {
|
|
279
|
-
...
|
|
280
|
-
model: model ||
|
|
423
|
+
...DEFAULT_ANTHROPIC_LLM_SERVICE,
|
|
424
|
+
model: model || DEFAULT_ANTHROPIC_LLM_SERVICE.model,
|
|
281
425
|
};
|
|
282
426
|
case 'ollama':
|
|
283
427
|
return {
|
|
@@ -285,11 +429,12 @@ function getDefaultServiceConfigFromAlias(provider, model) {
|
|
|
285
429
|
model: model || DEFAULT_OLLAMA_LLM_SERVICE.model,
|
|
286
430
|
};
|
|
287
431
|
case 'openai':
|
|
288
|
-
default:
|
|
289
432
|
return {
|
|
290
433
|
...DEFAULT_OPENAI_LLM_SERVICE,
|
|
291
434
|
model: model || DEFAULT_OPENAI_LLM_SERVICE.model,
|
|
292
435
|
};
|
|
436
|
+
default:
|
|
437
|
+
throw new LangChainConfigurationError(`getDefaultServiceConfigFromAlias: Unsupported provider '${provider}'. Supported providers: openai, anthropic, ollama`, { provider, supportedProviders: ['openai', 'anthropic', 'ollama'] });
|
|
293
438
|
}
|
|
294
439
|
}
|
|
295
440
|
|
|
@@ -331,14 +476,29 @@ const CONFIG_KEYS = Object.keys({
|
|
|
331
476
|
**/
|
|
332
477
|
function loadEnvConfig(config) {
|
|
333
478
|
const envConfig = {};
|
|
334
|
-
const envKeys = [
|
|
479
|
+
const envKeys = [
|
|
480
|
+
...CONFIG_KEYS,
|
|
481
|
+
'COCO_SERVICE_PROVIDER',
|
|
482
|
+
'COCO_SERVICE_MODEL',
|
|
483
|
+
'OPEN_AI_KEY',
|
|
484
|
+
'COCO_SERVICE_ENDPOINT',
|
|
485
|
+
'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT',
|
|
486
|
+
'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES',
|
|
487
|
+
'COCO_SERVICE_FIELDS',
|
|
488
|
+
];
|
|
335
489
|
envKeys.forEach((key) => {
|
|
336
490
|
const envVarName = toEnvVarName(key);
|
|
337
491
|
const envValue = parseEnvValue(key, process.env[envVarName]);
|
|
338
492
|
if (envValue === undefined) {
|
|
339
493
|
return;
|
|
340
494
|
}
|
|
341
|
-
if (key === 'COCO_SERVICE_PROVIDER' ||
|
|
495
|
+
if (key === 'COCO_SERVICE_PROVIDER' ||
|
|
496
|
+
key === 'COCO_SERVICE_MODEL' ||
|
|
497
|
+
key === 'OPEN_AI_KEY' ||
|
|
498
|
+
key === 'COCO_SERVICE_ENDPOINT' ||
|
|
499
|
+
key === 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT' ||
|
|
500
|
+
key === 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES' ||
|
|
501
|
+
key === 'COCO_SERVICE_FIELDS') {
|
|
342
502
|
// NOTE: We want to ensure that the service object is always defined
|
|
343
503
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
344
504
|
// @ts-ignore
|
|
@@ -365,9 +525,28 @@ function handleServiceEnvVar(service, key, value) {
|
|
|
365
525
|
break;
|
|
366
526
|
case 'OPEN_AI_KEY':
|
|
367
527
|
if (service.provider === 'openai') {
|
|
368
|
-
service.
|
|
528
|
+
service.authentication = {
|
|
529
|
+
type: 'APIKey',
|
|
530
|
+
credentials: {
|
|
531
|
+
apiKey: value,
|
|
532
|
+
},
|
|
533
|
+
};
|
|
369
534
|
}
|
|
370
535
|
break;
|
|
536
|
+
case 'COCO_SERVICE_ENDPOINT':
|
|
537
|
+
if (service.provider === 'ollama') {
|
|
538
|
+
service.endpoint = value;
|
|
539
|
+
}
|
|
540
|
+
break;
|
|
541
|
+
case 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT':
|
|
542
|
+
service.requestOptions = { ...service.requestOptions, timeout: value };
|
|
543
|
+
break;
|
|
544
|
+
case 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES':
|
|
545
|
+
service.requestOptions = { ...service.requestOptions, maxRetries: value };
|
|
546
|
+
break;
|
|
547
|
+
case 'COCO_SERVICE_FIELDS':
|
|
548
|
+
service.fields = value;
|
|
549
|
+
break;
|
|
371
550
|
}
|
|
372
551
|
}
|
|
373
552
|
function parseEnvValue(key, value) {
|
|
@@ -386,6 +565,9 @@ function parseEnvValue(key, value) {
|
|
|
386
565
|
// Handle number values
|
|
387
566
|
case typeof value === 'string' && !isNaN(Number(value)):
|
|
388
567
|
return Number(value);
|
|
568
|
+
// Handle JSON strings
|
|
569
|
+
case typeof value === 'string' && value.startsWith('{'):
|
|
570
|
+
return JSON.parse(value);
|
|
389
571
|
default:
|
|
390
572
|
return value;
|
|
391
573
|
}
|
|
@@ -399,32 +581,40 @@ function toEnvVarName(key) {
|
|
|
399
581
|
}
|
|
400
582
|
return `COCO_${key.replace(/([A-Z])/g, '_$1').toLocaleUpperCase()}`;
|
|
401
583
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
584
|
+
const flattenObject = (obj, prefix = '') => {
|
|
585
|
+
let flattened = {};
|
|
586
|
+
for (const key in obj) {
|
|
587
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
588
|
+
const propName = prefix ? `${prefix}_${key}` : key;
|
|
589
|
+
const value = obj[key];
|
|
590
|
+
// Skip undefined or null values
|
|
591
|
+
if (value === undefined || value === null) {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
595
|
+
// Handle nested objects, but specifically handle 'fields' as JSON string
|
|
596
|
+
if (key === 'fields') {
|
|
597
|
+
flattened[propName.toUpperCase()] = JSON.stringify(value);
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
flattened = { ...flattened, ...flattenObject(value, propName) };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
// For primitive types (string, number, boolean, symbol, bigint) and arrays
|
|
605
|
+
flattened[propName.toUpperCase()] = String(value);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
412
608
|
}
|
|
413
|
-
return
|
|
414
|
-
}
|
|
609
|
+
return flattened;
|
|
610
|
+
};
|
|
415
611
|
const appendToEnvFile = async (filePath, config) => {
|
|
416
612
|
const getNewContent = async () => {
|
|
417
|
-
|
|
613
|
+
const flattenedConfig = flattenObject(config);
|
|
614
|
+
return Object.entries(flattenedConfig)
|
|
418
615
|
.map(([key, value]) => {
|
|
419
|
-
if (key === 'service') {
|
|
420
|
-
const service = value;
|
|
421
|
-
return `${service.provider ? `COCO_SERVICE_PROVIDER=${service.provider}` : ''}\n${service.model ? `COCO_SERVICE_MODEL=${service.model}` : ''}\n${service.authentication.type === 'APIKey'
|
|
422
|
-
? `OPEN_AI_KEY=${service.authentication.credentials.apiKey}`
|
|
423
|
-
: ''}`;
|
|
424
|
-
}
|
|
425
616
|
const envVarName = toEnvVarName(key);
|
|
426
|
-
|
|
427
|
-
return `${envVarName}=${envValue}`;
|
|
617
|
+
return `${envVarName}=${value}`;
|
|
428
618
|
})
|
|
429
619
|
.join('\n');
|
|
430
620
|
};
|
|
@@ -448,22 +638,31 @@ function loadGitConfig(config) {
|
|
|
448
638
|
if (fs__namespace.existsSync(gitConfigPath)) {
|
|
449
639
|
const gitConfigRaw = fs__namespace.readFileSync(gitConfigPath, 'utf-8');
|
|
450
640
|
const gitConfigParsed = ini__namespace.parse(gitConfigRaw);
|
|
451
|
-
const gitConfigServiceObject = gitConfigParsed.coco?.service;
|
|
452
641
|
let service = config.service;
|
|
453
|
-
if (
|
|
454
|
-
|
|
455
|
-
|
|
642
|
+
if (gitConfigParsed.coco) {
|
|
643
|
+
service = {
|
|
644
|
+
provider: gitConfigParsed.coco?.['service.provider'],
|
|
645
|
+
model: gitConfigParsed.coco?.['service.model'],
|
|
646
|
+
authentication: {
|
|
647
|
+
type: 'APIKey',
|
|
648
|
+
credentials: {
|
|
649
|
+
apiKey: gitConfigParsed.coco?.['service.apiKey'],
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
requestOptions: {
|
|
653
|
+
timeout: Number(gitConfigParsed.coco?.['service.requestOptions.timeout']),
|
|
654
|
+
maxRetries: Number(gitConfigParsed.coco?.['service.requestOptions.maxRetries']),
|
|
655
|
+
},
|
|
656
|
+
endpoint: gitConfigParsed.coco?.['service.endpoint'],
|
|
657
|
+
fields: gitConfigParsed.coco?.['service.fields']
|
|
658
|
+
? JSON.parse(gitConfigParsed.coco?.['service.fields'])
|
|
659
|
+
: undefined,
|
|
660
|
+
};
|
|
456
661
|
}
|
|
457
662
|
config = {
|
|
458
663
|
...config,
|
|
664
|
+
...gitConfigParsed.coco,
|
|
459
665
|
service: service,
|
|
460
|
-
prompt: gitConfigParsed.coco?.prompt || config.prompt,
|
|
461
|
-
mode: gitConfigParsed.coco?.mode || config.mode,
|
|
462
|
-
summarizePrompt: gitConfigParsed.coco?.summarizePrompt || config.summarizePrompt,
|
|
463
|
-
ignoredFiles: gitConfigParsed.coco?.ignoredFiles || config.ignoredFiles,
|
|
464
|
-
ignoredExtensions: gitConfigParsed.coco?.ignoredExtensions || config.ignoredExtensions,
|
|
465
|
-
defaultBranch: gitConfigParsed.coco?.defaultBranch || config.defaultBranch,
|
|
466
|
-
verbose: gitConfigParsed.coco?.verbose || config.verbose,
|
|
467
666
|
};
|
|
468
667
|
}
|
|
469
668
|
return removeUndefined(config);
|
|
@@ -483,9 +682,28 @@ const appendToGitConfig = async (filePath, config) => {
|
|
|
483
682
|
const contentLines = [header];
|
|
484
683
|
for (const key in config) {
|
|
485
684
|
const value = config[key];
|
|
486
|
-
if (
|
|
487
|
-
|
|
488
|
-
contentLines.push(`\
|
|
685
|
+
if (key === 'service') {
|
|
686
|
+
const service = value;
|
|
687
|
+
contentLines.push(`\tservice.provider = ${service.provider}`);
|
|
688
|
+
contentLines.push(`\tservice.model = ${service.model}`);
|
|
689
|
+
if (service.authentication.type === 'APIKey') {
|
|
690
|
+
contentLines.push(`\tservice.apiKey = ${service.authentication.credentials.apiKey}`);
|
|
691
|
+
}
|
|
692
|
+
if (service.requestOptions?.timeout) {
|
|
693
|
+
contentLines.push(`\tservice.requestOptions.timeout = ${service.requestOptions.timeout}`);
|
|
694
|
+
}
|
|
695
|
+
if (service.requestOptions?.maxRetries) {
|
|
696
|
+
contentLines.push(`\tservice.requestOptions.maxRetries = ${service.requestOptions.maxRetries}`);
|
|
697
|
+
}
|
|
698
|
+
if (service.provider === 'ollama') {
|
|
699
|
+
const ollamaService = service;
|
|
700
|
+
if (ollamaService.endpoint) {
|
|
701
|
+
contentLines.push(` service.endpoint = ${ollamaService.endpoint}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (service.fields) {
|
|
705
|
+
contentLines.push(`\tservice.fields = ${JSON.stringify(service.fields)}`);
|
|
706
|
+
}
|
|
489
707
|
}
|
|
490
708
|
else if (typeof value === 'string' && value.includes('\n')) {
|
|
491
709
|
// Wrap strings with new lines in quotes
|
|
@@ -915,6 +1133,11 @@ const schema$1 = {
|
|
|
915
1133
|
}
|
|
916
1134
|
},
|
|
917
1135
|
"additionalProperties": false
|
|
1136
|
+
},
|
|
1137
|
+
"maxParsingAttempts": {
|
|
1138
|
+
"type": "number",
|
|
1139
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1140
|
+
"default": 3
|
|
918
1141
|
}
|
|
919
1142
|
},
|
|
920
1143
|
"required": [
|
|
@@ -1005,6 +1228,9 @@ const schema$1 = {
|
|
|
1005
1228
|
"OllamaModel": {
|
|
1006
1229
|
"type": "string",
|
|
1007
1230
|
"enum": [
|
|
1231
|
+
"deepseek-r1:1.5b",
|
|
1232
|
+
"deepseek-r1:8b",
|
|
1233
|
+
"deepseek-r1:32b",
|
|
1008
1234
|
"codegemma:2b",
|
|
1009
1235
|
"codegemma:7b-code",
|
|
1010
1236
|
"codegemma",
|
|
@@ -1036,9 +1262,11 @@ const schema$1 = {
|
|
|
1036
1262
|
"llama3.2:latest",
|
|
1037
1263
|
"llama3.2:1b",
|
|
1038
1264
|
"llama3.2:3b",
|
|
1039
|
-
"llama3.2:1b-instruct-fp16",
|
|
1040
|
-
"llama3.2:1b-instruct-q3_K_M",
|
|
1041
1265
|
"llama3",
|
|
1266
|
+
"llava-llama3:latest",
|
|
1267
|
+
"dolphin-llama3:latest",
|
|
1268
|
+
"dolphin-llama3:8b",
|
|
1269
|
+
"dolphin-llama3:70b",
|
|
1042
1270
|
"mistral:7b",
|
|
1043
1271
|
"mistral:latest",
|
|
1044
1272
|
"mistral:text",
|
|
@@ -1054,18 +1282,28 @@ const schema$1 = {
|
|
|
1054
1282
|
"qwen2:1.5b",
|
|
1055
1283
|
"qwen2:72b-text",
|
|
1056
1284
|
"qwen2:72b",
|
|
1057
|
-
"qwen2"
|
|
1285
|
+
"qwen2",
|
|
1286
|
+
"qwen2.5-coder:latest",
|
|
1287
|
+
"qwen2.5-coder:0.5b",
|
|
1288
|
+
"qwen2.5-coder:1.5b",
|
|
1289
|
+
"qwen2.5-coder:3b",
|
|
1290
|
+
"qwen2.5-coder:7b",
|
|
1291
|
+
"qwen2.5-coder:14b",
|
|
1292
|
+
"qwen2.5-coder:32b"
|
|
1058
1293
|
]
|
|
1059
1294
|
},
|
|
1060
1295
|
"AnthropicModel": {
|
|
1061
1296
|
"type": "string",
|
|
1062
1297
|
"enum": [
|
|
1298
|
+
"claude-sonnet-4-0",
|
|
1299
|
+
"claude-3-7-sonnet-latest",
|
|
1300
|
+
"claude-3-5-haiku-latest",
|
|
1301
|
+
"claude-3-5-sonnet-latest",
|
|
1302
|
+
"claude-3-5-sonnet-20241022",
|
|
1063
1303
|
"claude-3-5-sonnet-20240620",
|
|
1064
1304
|
"claude-3-opus-20240229",
|
|
1065
1305
|
"claude-3-sonnet-20240229",
|
|
1066
|
-
"claude-3-haiku-20240307"
|
|
1067
|
-
"claude-2.1",
|
|
1068
|
-
"claude-2.0"
|
|
1306
|
+
"claude-3-haiku-20240307"
|
|
1069
1307
|
]
|
|
1070
1308
|
},
|
|
1071
1309
|
"Callbacks": {
|
|
@@ -1510,6 +1748,11 @@ const schema$1 = {
|
|
|
1510
1748
|
}
|
|
1511
1749
|
},
|
|
1512
1750
|
"additionalProperties": false
|
|
1751
|
+
},
|
|
1752
|
+
"maxParsingAttempts": {
|
|
1753
|
+
"type": "number",
|
|
1754
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1755
|
+
"default": 3
|
|
1513
1756
|
}
|
|
1514
1757
|
},
|
|
1515
1758
|
"required": [
|
|
@@ -1656,6 +1899,11 @@ const schema$1 = {
|
|
|
1656
1899
|
}
|
|
1657
1900
|
},
|
|
1658
1901
|
"additionalProperties": false
|
|
1902
|
+
},
|
|
1903
|
+
"maxParsingAttempts": {
|
|
1904
|
+
"type": "number",
|
|
1905
|
+
"description": "The maximum number of attempts for schema parsing with retry logic.",
|
|
1906
|
+
"default": 3
|
|
1659
1907
|
}
|
|
1660
1908
|
},
|
|
1661
1909
|
"required": [
|
|
@@ -1875,7 +2123,7 @@ function commandExecutor(handler) {
|
|
|
1875
2123
|
|
|
1876
2124
|
var util;
|
|
1877
2125
|
(function (util) {
|
|
1878
|
-
util.assertEqual = (
|
|
2126
|
+
util.assertEqual = (_) => { };
|
|
1879
2127
|
function assertIs(_arg) { }
|
|
1880
2128
|
util.assertIs = assertIs;
|
|
1881
2129
|
function assertNever(_x) {
|
|
@@ -1922,11 +2170,9 @@ var util;
|
|
|
1922
2170
|
};
|
|
1923
2171
|
util.isInteger = typeof Number.isInteger === "function"
|
|
1924
2172
|
? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
|
|
1925
|
-
: (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val;
|
|
2173
|
+
: (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
|
|
1926
2174
|
function joinValues(array, separator = " | ") {
|
|
1927
|
-
return array
|
|
1928
|
-
.map((val) => (typeof val === "string" ? `'${val}'` : val))
|
|
1929
|
-
.join(separator);
|
|
2175
|
+
return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator);
|
|
1930
2176
|
}
|
|
1931
2177
|
util.joinValues = joinValues;
|
|
1932
2178
|
util.jsonStringifyReplacer = (_, value) => {
|
|
@@ -1975,7 +2221,7 @@ const getParsedType = (data) => {
|
|
|
1975
2221
|
case "string":
|
|
1976
2222
|
return ZodParsedType.string;
|
|
1977
2223
|
case "number":
|
|
1978
|
-
return isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
|
|
2224
|
+
return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
|
|
1979
2225
|
case "boolean":
|
|
1980
2226
|
return ZodParsedType.boolean;
|
|
1981
2227
|
case "function":
|
|
@@ -1991,10 +2237,7 @@ const getParsedType = (data) => {
|
|
|
1991
2237
|
if (data === null) {
|
|
1992
2238
|
return ZodParsedType.null;
|
|
1993
2239
|
}
|
|
1994
|
-
if (data.then &&
|
|
1995
|
-
typeof data.then === "function" &&
|
|
1996
|
-
data.catch &&
|
|
1997
|
-
typeof data.catch === "function") {
|
|
2240
|
+
if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
|
|
1998
2241
|
return ZodParsedType.promise;
|
|
1999
2242
|
}
|
|
2000
2243
|
if (typeof Map !== "undefined" && data instanceof Map) {
|
|
@@ -2030,10 +2273,6 @@ const ZodIssueCode = util.arrayToEnum([
|
|
|
2030
2273
|
"not_multiple_of",
|
|
2031
2274
|
"not_finite",
|
|
2032
2275
|
]);
|
|
2033
|
-
const quotelessJson = (obj) => {
|
|
2034
|
-
const json = JSON.stringify(obj, null, 2);
|
|
2035
|
-
return json.replace(/"([^"]+)":/g, "$1:");
|
|
2036
|
-
};
|
|
2037
2276
|
class ZodError extends Error {
|
|
2038
2277
|
get errors() {
|
|
2039
2278
|
return this.issues;
|
|
@@ -2126,8 +2365,9 @@ class ZodError extends Error {
|
|
|
2126
2365
|
const formErrors = [];
|
|
2127
2366
|
for (const sub of this.issues) {
|
|
2128
2367
|
if (sub.path.length > 0) {
|
|
2129
|
-
|
|
2130
|
-
fieldErrors[
|
|
2368
|
+
const firstEl = sub.path[0];
|
|
2369
|
+
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
|
|
2370
|
+
fieldErrors[firstEl].push(mapper(sub));
|
|
2131
2371
|
}
|
|
2132
2372
|
else {
|
|
2133
2373
|
formErrors.push(mapper(sub));
|
|
@@ -2210,17 +2450,11 @@ const errorMap = (issue, _ctx) => {
|
|
|
2210
2450
|
else if (issue.type === "string")
|
|
2211
2451
|
message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
|
|
2212
2452
|
else if (issue.type === "number")
|
|
2213
|
-
message = `Number must be ${issue.exact
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
? `greater than or equal to `
|
|
2217
|
-
: `greater than `}${issue.minimum}`;
|
|
2453
|
+
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
2454
|
+
else if (issue.type === "bigint")
|
|
2455
|
+
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
2218
2456
|
else if (issue.type === "date")
|
|
2219
|
-
message = `Date must be ${issue.exact
|
|
2220
|
-
? `exactly equal to `
|
|
2221
|
-
: issue.inclusive
|
|
2222
|
-
? `greater than or equal to `
|
|
2223
|
-
: `greater than `}${new Date(Number(issue.minimum))}`;
|
|
2457
|
+
message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
|
|
2224
2458
|
else
|
|
2225
2459
|
message = "Invalid input";
|
|
2226
2460
|
break;
|
|
@@ -2230,23 +2464,11 @@ const errorMap = (issue, _ctx) => {
|
|
|
2230
2464
|
else if (issue.type === "string")
|
|
2231
2465
|
message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
|
|
2232
2466
|
else if (issue.type === "number")
|
|
2233
|
-
message = `Number must be ${issue.exact
|
|
2234
|
-
? `exactly`
|
|
2235
|
-
: issue.inclusive
|
|
2236
|
-
? `less than or equal to`
|
|
2237
|
-
: `less than`} ${issue.maximum}`;
|
|
2467
|
+
message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
|
|
2238
2468
|
else if (issue.type === "bigint")
|
|
2239
|
-
message = `BigInt must be ${issue.exact
|
|
2240
|
-
? `exactly`
|
|
2241
|
-
: issue.inclusive
|
|
2242
|
-
? `less than or equal to`
|
|
2243
|
-
: `less than`} ${issue.maximum}`;
|
|
2469
|
+
message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
|
|
2244
2470
|
else if (issue.type === "date")
|
|
2245
|
-
message = `Date must be ${issue.exact
|
|
2246
|
-
? `exactly`
|
|
2247
|
-
: issue.inclusive
|
|
2248
|
-
? `smaller than or equal to`
|
|
2249
|
-
: `smaller than`} ${new Date(Number(issue.maximum))}`;
|
|
2471
|
+
message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
|
|
2250
2472
|
else
|
|
2251
2473
|
message = "Invalid input";
|
|
2252
2474
|
break;
|
|
@@ -2268,11 +2490,9 @@ const errorMap = (issue, _ctx) => {
|
|
|
2268
2490
|
}
|
|
2269
2491
|
return { message };
|
|
2270
2492
|
};
|
|
2493
|
+
var defaultErrorMap = errorMap;
|
|
2271
2494
|
|
|
2272
|
-
let overrideErrorMap =
|
|
2273
|
-
function setErrorMap(map) {
|
|
2274
|
-
overrideErrorMap = map;
|
|
2275
|
-
}
|
|
2495
|
+
let overrideErrorMap = defaultErrorMap;
|
|
2276
2496
|
function getErrorMap() {
|
|
2277
2497
|
return overrideErrorMap;
|
|
2278
2498
|
}
|
|
@@ -2305,7 +2525,6 @@ const makeIssue = (params) => {
|
|
|
2305
2525
|
message: errorMessage,
|
|
2306
2526
|
};
|
|
2307
2527
|
};
|
|
2308
|
-
const EMPTY_PATH = [];
|
|
2309
2528
|
function addIssueToContext(ctx, issueData) {
|
|
2310
2529
|
const overrideMap = getErrorMap();
|
|
2311
2530
|
const issue = makeIssue({
|
|
@@ -2316,7 +2535,7 @@ function addIssueToContext(ctx, issueData) {
|
|
|
2316
2535
|
ctx.common.contextualErrorMap, // contextual error map is first priority
|
|
2317
2536
|
ctx.schemaErrorMap, // then schema-bound map if available
|
|
2318
2537
|
overrideMap, // then global override map
|
|
2319
|
-
overrideMap ===
|
|
2538
|
+
overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map
|
|
2320
2539
|
].filter((x) => !!x),
|
|
2321
2540
|
});
|
|
2322
2541
|
ctx.common.issues.push(issue);
|
|
@@ -2368,8 +2587,7 @@ class ParseStatus {
|
|
|
2368
2587
|
status.dirty();
|
|
2369
2588
|
if (value.status === "dirty")
|
|
2370
2589
|
status.dirty();
|
|
2371
|
-
if (key.value !== "__proto__" &&
|
|
2372
|
-
(typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
2590
|
+
if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
2373
2591
|
finalObject[key.value] = value.value;
|
|
2374
2592
|
}
|
|
2375
2593
|
}
|
|
@@ -2386,46 +2604,13 @@ const isDirty = (x) => x.status === "dirty";
|
|
|
2386
2604
|
const isValid = (x) => x.status === "valid";
|
|
2387
2605
|
const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
2388
2606
|
|
|
2389
|
-
/******************************************************************************
|
|
2390
|
-
Copyright (c) Microsoft Corporation.
|
|
2391
|
-
|
|
2392
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
2393
|
-
purpose with or without fee is hereby granted.
|
|
2394
|
-
|
|
2395
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
2396
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
2397
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
2398
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
2399
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
2400
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2401
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
2402
|
-
***************************************************************************** */
|
|
2403
|
-
|
|
2404
|
-
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
2405
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
2406
|
-
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");
|
|
2407
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
2411
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
2412
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
2413
|
-
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");
|
|
2414
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
2415
|
-
}
|
|
2416
|
-
|
|
2417
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
2418
|
-
var e = new Error(message);
|
|
2419
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
2420
|
-
};
|
|
2421
|
-
|
|
2422
2607
|
var errorUtil;
|
|
2423
2608
|
(function (errorUtil) {
|
|
2424
2609
|
errorUtil.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
2425
|
-
|
|
2610
|
+
// biome-ignore lint:
|
|
2611
|
+
errorUtil.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
2426
2612
|
})(errorUtil || (errorUtil = {}));
|
|
2427
2613
|
|
|
2428
|
-
var _ZodEnum_cache, _ZodNativeEnum_cache;
|
|
2429
2614
|
class ParseInputLazyPath {
|
|
2430
2615
|
constructor(parent, value, path, key) {
|
|
2431
2616
|
this._cachedPath = [];
|
|
@@ -2436,7 +2621,7 @@ class ParseInputLazyPath {
|
|
|
2436
2621
|
}
|
|
2437
2622
|
get path() {
|
|
2438
2623
|
if (!this._cachedPath.length) {
|
|
2439
|
-
if (this._key
|
|
2624
|
+
if (Array.isArray(this._key)) {
|
|
2440
2625
|
this._cachedPath.push(...this._path, ...this._key);
|
|
2441
2626
|
}
|
|
2442
2627
|
else {
|
|
@@ -2476,17 +2661,16 @@ function processCreateParams(params) {
|
|
|
2476
2661
|
if (errorMap)
|
|
2477
2662
|
return { errorMap: errorMap, description };
|
|
2478
2663
|
const customMap = (iss, ctx) => {
|
|
2479
|
-
var _a, _b;
|
|
2480
2664
|
const { message } = params;
|
|
2481
2665
|
if (iss.code === "invalid_enum_value") {
|
|
2482
|
-
return { message: message
|
|
2666
|
+
return { message: message ?? ctx.defaultError };
|
|
2483
2667
|
}
|
|
2484
2668
|
if (typeof ctx.data === "undefined") {
|
|
2485
|
-
return { message:
|
|
2669
|
+
return { message: message ?? required_error ?? ctx.defaultError };
|
|
2486
2670
|
}
|
|
2487
2671
|
if (iss.code !== "invalid_type")
|
|
2488
2672
|
return { message: ctx.defaultError };
|
|
2489
|
-
return { message:
|
|
2673
|
+
return { message: message ?? invalid_type_error ?? ctx.defaultError };
|
|
2490
2674
|
};
|
|
2491
2675
|
return { errorMap: customMap, description };
|
|
2492
2676
|
}
|
|
@@ -2538,14 +2722,13 @@ class ZodType {
|
|
|
2538
2722
|
throw result.error;
|
|
2539
2723
|
}
|
|
2540
2724
|
safeParse(data, params) {
|
|
2541
|
-
var _a;
|
|
2542
2725
|
const ctx = {
|
|
2543
2726
|
common: {
|
|
2544
2727
|
issues: [],
|
|
2545
|
-
async:
|
|
2546
|
-
contextualErrorMap: params
|
|
2728
|
+
async: params?.async ?? false,
|
|
2729
|
+
contextualErrorMap: params?.errorMap,
|
|
2547
2730
|
},
|
|
2548
|
-
path:
|
|
2731
|
+
path: params?.path || [],
|
|
2549
2732
|
schemaErrorMap: this._def.errorMap,
|
|
2550
2733
|
parent: null,
|
|
2551
2734
|
data,
|
|
@@ -2555,7 +2738,6 @@ class ZodType {
|
|
|
2555
2738
|
return handleResult$1(ctx, result);
|
|
2556
2739
|
}
|
|
2557
2740
|
"~validate"(data) {
|
|
2558
|
-
var _a, _b;
|
|
2559
2741
|
const ctx = {
|
|
2560
2742
|
common: {
|
|
2561
2743
|
issues: [],
|
|
@@ -2579,7 +2761,7 @@ class ZodType {
|
|
|
2579
2761
|
};
|
|
2580
2762
|
}
|
|
2581
2763
|
catch (err) {
|
|
2582
|
-
if (
|
|
2764
|
+
if (err?.message?.toLowerCase()?.includes("encountered")) {
|
|
2583
2765
|
this["~standard"].async = true;
|
|
2584
2766
|
}
|
|
2585
2767
|
ctx.common = {
|
|
@@ -2606,19 +2788,17 @@ class ZodType {
|
|
|
2606
2788
|
const ctx = {
|
|
2607
2789
|
common: {
|
|
2608
2790
|
issues: [],
|
|
2609
|
-
contextualErrorMap: params
|
|
2791
|
+
contextualErrorMap: params?.errorMap,
|
|
2610
2792
|
async: true,
|
|
2611
2793
|
},
|
|
2612
|
-
path:
|
|
2794
|
+
path: params?.path || [],
|
|
2613
2795
|
schemaErrorMap: this._def.errorMap,
|
|
2614
2796
|
parent: null,
|
|
2615
2797
|
data,
|
|
2616
2798
|
parsedType: getParsedType(data),
|
|
2617
2799
|
};
|
|
2618
2800
|
const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });
|
|
2619
|
-
const result = await (isAsync(maybeAsyncResult)
|
|
2620
|
-
? maybeAsyncResult
|
|
2621
|
-
: Promise.resolve(maybeAsyncResult));
|
|
2801
|
+
const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
|
|
2622
2802
|
return handleResult$1(ctx, result);
|
|
2623
2803
|
}
|
|
2624
2804
|
refine(check, message) {
|
|
@@ -2662,9 +2842,7 @@ class ZodType {
|
|
|
2662
2842
|
refinement(check, refinementData) {
|
|
2663
2843
|
return this._refinement((val, ctx) => {
|
|
2664
2844
|
if (!check(val)) {
|
|
2665
|
-
ctx.addIssue(typeof refinementData === "function"
|
|
2666
|
-
? refinementData(val, ctx)
|
|
2667
|
-
: refinementData);
|
|
2845
|
+
ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData);
|
|
2668
2846
|
return false;
|
|
2669
2847
|
}
|
|
2670
2848
|
else {
|
|
@@ -2836,15 +3014,15 @@ const base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z
|
|
|
2836
3014
|
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])))`;
|
|
2837
3015
|
const dateRegex = new RegExp(`^${dateRegexSource}$`);
|
|
2838
3016
|
function timeRegexSource(args) {
|
|
2839
|
-
|
|
2840
|
-
let regex = `([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d`;
|
|
3017
|
+
let secondsRegexSource = `[0-5]\\d`;
|
|
2841
3018
|
if (args.precision) {
|
|
2842
|
-
|
|
3019
|
+
secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
|
|
2843
3020
|
}
|
|
2844
3021
|
else if (args.precision == null) {
|
|
2845
|
-
|
|
3022
|
+
secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
|
|
2846
3023
|
}
|
|
2847
|
-
|
|
3024
|
+
const secondsQuantifier = args.precision ? "+" : "?"; // require seconds if precision is nonzero
|
|
3025
|
+
return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
|
|
2848
3026
|
}
|
|
2849
3027
|
function timeRegex(args) {
|
|
2850
3028
|
return new RegExp(`^${timeRegexSource(args)}$`);
|
|
@@ -2873,6 +3051,8 @@ function isValidJWT(jwt, alg) {
|
|
|
2873
3051
|
return false;
|
|
2874
3052
|
try {
|
|
2875
3053
|
const [header] = jwt.split(".");
|
|
3054
|
+
if (!header)
|
|
3055
|
+
return false;
|
|
2876
3056
|
// Convert base64url to base64
|
|
2877
3057
|
const base64 = header
|
|
2878
3058
|
.replace(/-/g, "+")
|
|
@@ -2881,13 +3061,15 @@ function isValidJWT(jwt, alg) {
|
|
|
2881
3061
|
const decoded = JSON.parse(atob(base64));
|
|
2882
3062
|
if (typeof decoded !== "object" || decoded === null)
|
|
2883
3063
|
return false;
|
|
2884
|
-
if (
|
|
3064
|
+
if ("typ" in decoded && decoded?.typ !== "JWT")
|
|
3065
|
+
return false;
|
|
3066
|
+
if (!decoded.alg)
|
|
2885
3067
|
return false;
|
|
2886
3068
|
if (alg && decoded.alg !== alg)
|
|
2887
3069
|
return false;
|
|
2888
3070
|
return true;
|
|
2889
3071
|
}
|
|
2890
|
-
catch
|
|
3072
|
+
catch {
|
|
2891
3073
|
return false;
|
|
2892
3074
|
}
|
|
2893
3075
|
}
|
|
@@ -3058,7 +3240,7 @@ class ZodString extends ZodType {
|
|
|
3058
3240
|
try {
|
|
3059
3241
|
new URL(input.data);
|
|
3060
3242
|
}
|
|
3061
|
-
catch
|
|
3243
|
+
catch {
|
|
3062
3244
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3063
3245
|
addIssueToContext(ctx, {
|
|
3064
3246
|
validation: "url",
|
|
@@ -3288,7 +3470,6 @@ class ZodString extends ZodType {
|
|
|
3288
3470
|
return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) });
|
|
3289
3471
|
}
|
|
3290
3472
|
datetime(options) {
|
|
3291
|
-
var _a, _b;
|
|
3292
3473
|
if (typeof options === "string") {
|
|
3293
3474
|
return this._addCheck({
|
|
3294
3475
|
kind: "datetime",
|
|
@@ -3300,10 +3481,10 @@ class ZodString extends ZodType {
|
|
|
3300
3481
|
}
|
|
3301
3482
|
return this._addCheck({
|
|
3302
3483
|
kind: "datetime",
|
|
3303
|
-
precision: typeof
|
|
3304
|
-
offset:
|
|
3305
|
-
local:
|
|
3306
|
-
...errorUtil.errToObj(options
|
|
3484
|
+
precision: typeof options?.precision === "undefined" ? null : options?.precision,
|
|
3485
|
+
offset: options?.offset ?? false,
|
|
3486
|
+
local: options?.local ?? false,
|
|
3487
|
+
...errorUtil.errToObj(options?.message),
|
|
3307
3488
|
});
|
|
3308
3489
|
}
|
|
3309
3490
|
date(message) {
|
|
@@ -3319,8 +3500,8 @@ class ZodString extends ZodType {
|
|
|
3319
3500
|
}
|
|
3320
3501
|
return this._addCheck({
|
|
3321
3502
|
kind: "time",
|
|
3322
|
-
precision: typeof
|
|
3323
|
-
...errorUtil.errToObj(options
|
|
3503
|
+
precision: typeof options?.precision === "undefined" ? null : options?.precision,
|
|
3504
|
+
...errorUtil.errToObj(options?.message),
|
|
3324
3505
|
});
|
|
3325
3506
|
}
|
|
3326
3507
|
duration(message) {
|
|
@@ -3337,8 +3518,8 @@ class ZodString extends ZodType {
|
|
|
3337
3518
|
return this._addCheck({
|
|
3338
3519
|
kind: "includes",
|
|
3339
3520
|
value: value,
|
|
3340
|
-
position: options
|
|
3341
|
-
...errorUtil.errToObj(options
|
|
3521
|
+
position: options?.position,
|
|
3522
|
+
...errorUtil.errToObj(options?.message),
|
|
3342
3523
|
});
|
|
3343
3524
|
}
|
|
3344
3525
|
startsWith(value, message) {
|
|
@@ -3471,11 +3652,10 @@ class ZodString extends ZodType {
|
|
|
3471
3652
|
}
|
|
3472
3653
|
}
|
|
3473
3654
|
ZodString.create = (params) => {
|
|
3474
|
-
var _a;
|
|
3475
3655
|
return new ZodString({
|
|
3476
3656
|
checks: [],
|
|
3477
3657
|
typeName: ZodFirstPartyTypeKind.ZodString,
|
|
3478
|
-
coerce:
|
|
3658
|
+
coerce: params?.coerce ?? false,
|
|
3479
3659
|
...processCreateParams(params),
|
|
3480
3660
|
});
|
|
3481
3661
|
};
|
|
@@ -3484,9 +3664,9 @@ function floatSafeRemainder(val, step) {
|
|
|
3484
3664
|
const valDecCount = (val.toString().split(".")[1] || "").length;
|
|
3485
3665
|
const stepDecCount = (step.toString().split(".")[1] || "").length;
|
|
3486
3666
|
const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
|
|
3487
|
-
const valInt = parseInt(val.toFixed(decCount).replace(".", ""));
|
|
3488
|
-
const stepInt = parseInt(step.toFixed(decCount).replace(".", ""));
|
|
3489
|
-
return (valInt % stepInt) /
|
|
3667
|
+
const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
|
|
3668
|
+
const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
|
|
3669
|
+
return (valInt % stepInt) / 10 ** decCount;
|
|
3490
3670
|
}
|
|
3491
3671
|
class ZodNumber extends ZodType {
|
|
3492
3672
|
constructor() {
|
|
@@ -3525,9 +3705,7 @@ class ZodNumber extends ZodType {
|
|
|
3525
3705
|
}
|
|
3526
3706
|
}
|
|
3527
3707
|
else if (check.kind === "min") {
|
|
3528
|
-
const tooSmall = check.inclusive
|
|
3529
|
-
? input.data < check.value
|
|
3530
|
-
: input.data <= check.value;
|
|
3708
|
+
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
3531
3709
|
if (tooSmall) {
|
|
3532
3710
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3533
3711
|
addIssueToContext(ctx, {
|
|
@@ -3542,9 +3720,7 @@ class ZodNumber extends ZodType {
|
|
|
3542
3720
|
}
|
|
3543
3721
|
}
|
|
3544
3722
|
else if (check.kind === "max") {
|
|
3545
|
-
const tooBig = check.inclusive
|
|
3546
|
-
? input.data > check.value
|
|
3547
|
-
: input.data >= check.value;
|
|
3723
|
+
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
3548
3724
|
if (tooBig) {
|
|
3549
3725
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3550
3726
|
addIssueToContext(ctx, {
|
|
@@ -3702,15 +3878,13 @@ class ZodNumber extends ZodType {
|
|
|
3702
3878
|
return max;
|
|
3703
3879
|
}
|
|
3704
3880
|
get isInt() {
|
|
3705
|
-
return !!this._def.checks.find((ch) => ch.kind === "int" ||
|
|
3706
|
-
(ch.kind === "multipleOf" && util.isInteger(ch.value)));
|
|
3881
|
+
return !!this._def.checks.find((ch) => ch.kind === "int" || (ch.kind === "multipleOf" && util.isInteger(ch.value)));
|
|
3707
3882
|
}
|
|
3708
3883
|
get isFinite() {
|
|
3709
|
-
let max = null
|
|
3884
|
+
let max = null;
|
|
3885
|
+
let min = null;
|
|
3710
3886
|
for (const ch of this._def.checks) {
|
|
3711
|
-
if (ch.kind === "finite" ||
|
|
3712
|
-
ch.kind === "int" ||
|
|
3713
|
-
ch.kind === "multipleOf") {
|
|
3887
|
+
if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") {
|
|
3714
3888
|
return true;
|
|
3715
3889
|
}
|
|
3716
3890
|
else if (ch.kind === "min") {
|
|
@@ -3729,7 +3903,7 @@ ZodNumber.create = (params) => {
|
|
|
3729
3903
|
return new ZodNumber({
|
|
3730
3904
|
checks: [],
|
|
3731
3905
|
typeName: ZodFirstPartyTypeKind.ZodNumber,
|
|
3732
|
-
coerce:
|
|
3906
|
+
coerce: params?.coerce || false,
|
|
3733
3907
|
...processCreateParams(params),
|
|
3734
3908
|
});
|
|
3735
3909
|
};
|
|
@@ -3744,7 +3918,7 @@ class ZodBigInt extends ZodType {
|
|
|
3744
3918
|
try {
|
|
3745
3919
|
input.data = BigInt(input.data);
|
|
3746
3920
|
}
|
|
3747
|
-
catch
|
|
3921
|
+
catch {
|
|
3748
3922
|
return this._getInvalidInput(input);
|
|
3749
3923
|
}
|
|
3750
3924
|
}
|
|
@@ -3756,9 +3930,7 @@ class ZodBigInt extends ZodType {
|
|
|
3756
3930
|
const status = new ParseStatus();
|
|
3757
3931
|
for (const check of this._def.checks) {
|
|
3758
3932
|
if (check.kind === "min") {
|
|
3759
|
-
const tooSmall = check.inclusive
|
|
3760
|
-
? input.data < check.value
|
|
3761
|
-
: input.data <= check.value;
|
|
3933
|
+
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
3762
3934
|
if (tooSmall) {
|
|
3763
3935
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3764
3936
|
addIssueToContext(ctx, {
|
|
@@ -3772,9 +3944,7 @@ class ZodBigInt extends ZodType {
|
|
|
3772
3944
|
}
|
|
3773
3945
|
}
|
|
3774
3946
|
else if (check.kind === "max") {
|
|
3775
|
-
const tooBig = check.inclusive
|
|
3776
|
-
? input.data > check.value
|
|
3777
|
-
: input.data >= check.value;
|
|
3947
|
+
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
3778
3948
|
if (tooBig) {
|
|
3779
3949
|
ctx = this._getOrReturnCtx(input, ctx);
|
|
3780
3950
|
addIssueToContext(ctx, {
|
|
@@ -3906,11 +4076,10 @@ class ZodBigInt extends ZodType {
|
|
|
3906
4076
|
}
|
|
3907
4077
|
}
|
|
3908
4078
|
ZodBigInt.create = (params) => {
|
|
3909
|
-
var _a;
|
|
3910
4079
|
return new ZodBigInt({
|
|
3911
4080
|
checks: [],
|
|
3912
4081
|
typeName: ZodFirstPartyTypeKind.ZodBigInt,
|
|
3913
|
-
coerce:
|
|
4082
|
+
coerce: params?.coerce ?? false,
|
|
3914
4083
|
...processCreateParams(params),
|
|
3915
4084
|
});
|
|
3916
4085
|
};
|
|
@@ -3935,7 +4104,7 @@ class ZodBoolean extends ZodType {
|
|
|
3935
4104
|
ZodBoolean.create = (params) => {
|
|
3936
4105
|
return new ZodBoolean({
|
|
3937
4106
|
typeName: ZodFirstPartyTypeKind.ZodBoolean,
|
|
3938
|
-
coerce:
|
|
4107
|
+
coerce: params?.coerce || false,
|
|
3939
4108
|
...processCreateParams(params),
|
|
3940
4109
|
});
|
|
3941
4110
|
};
|
|
@@ -3954,7 +4123,7 @@ class ZodDate extends ZodType {
|
|
|
3954
4123
|
});
|
|
3955
4124
|
return INVALID;
|
|
3956
4125
|
}
|
|
3957
|
-
if (isNaN(input.data.getTime())) {
|
|
4126
|
+
if (Number.isNaN(input.data.getTime())) {
|
|
3958
4127
|
const ctx = this._getOrReturnCtx(input);
|
|
3959
4128
|
addIssueToContext(ctx, {
|
|
3960
4129
|
code: ZodIssueCode.invalid_date,
|
|
@@ -4045,7 +4214,7 @@ class ZodDate extends ZodType {
|
|
|
4045
4214
|
ZodDate.create = (params) => {
|
|
4046
4215
|
return new ZodDate({
|
|
4047
4216
|
checks: [],
|
|
4048
|
-
coerce:
|
|
4217
|
+
coerce: params?.coerce || false,
|
|
4049
4218
|
typeName: ZodFirstPartyTypeKind.ZodDate,
|
|
4050
4219
|
...processCreateParams(params),
|
|
4051
4220
|
});
|
|
@@ -4367,7 +4536,8 @@ class ZodObject extends ZodType {
|
|
|
4367
4536
|
return this._cached;
|
|
4368
4537
|
const shape = this._def.shape();
|
|
4369
4538
|
const keys = util.objectKeys(shape);
|
|
4370
|
-
|
|
4539
|
+
this._cached = { shape, keys };
|
|
4540
|
+
return this._cached;
|
|
4371
4541
|
}
|
|
4372
4542
|
_parse(input) {
|
|
4373
4543
|
const parsedType = this._getType(input);
|
|
@@ -4383,8 +4553,7 @@ class ZodObject extends ZodType {
|
|
|
4383
4553
|
const { status, ctx } = this._processInputParams(input);
|
|
4384
4554
|
const { shape, keys: shapeKeys } = this._getCached();
|
|
4385
4555
|
const extraKeys = [];
|
|
4386
|
-
if (!(this._def.catchall instanceof ZodNever &&
|
|
4387
|
-
this._def.unknownKeys === "strip")) {
|
|
4556
|
+
if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
|
|
4388
4557
|
for (const key in ctx.data) {
|
|
4389
4558
|
if (!shapeKeys.includes(key)) {
|
|
4390
4559
|
extraKeys.push(key);
|
|
@@ -4472,11 +4641,10 @@ class ZodObject extends ZodType {
|
|
|
4472
4641
|
...(message !== undefined
|
|
4473
4642
|
? {
|
|
4474
4643
|
errorMap: (issue, ctx) => {
|
|
4475
|
-
|
|
4476
|
-
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;
|
|
4644
|
+
const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;
|
|
4477
4645
|
if (issue.code === "unrecognized_keys")
|
|
4478
4646
|
return {
|
|
4479
|
-
message:
|
|
4647
|
+
message: errorUtil.errToObj(message).message ?? defaultError,
|
|
4480
4648
|
};
|
|
4481
4649
|
return {
|
|
4482
4650
|
message: defaultError,
|
|
@@ -4608,11 +4776,11 @@ class ZodObject extends ZodType {
|
|
|
4608
4776
|
}
|
|
4609
4777
|
pick(mask) {
|
|
4610
4778
|
const shape = {};
|
|
4611
|
-
util.objectKeys(mask)
|
|
4779
|
+
for (const key of util.objectKeys(mask)) {
|
|
4612
4780
|
if (mask[key] && this.shape[key]) {
|
|
4613
4781
|
shape[key] = this.shape[key];
|
|
4614
4782
|
}
|
|
4615
|
-
}
|
|
4783
|
+
}
|
|
4616
4784
|
return new ZodObject({
|
|
4617
4785
|
...this._def,
|
|
4618
4786
|
shape: () => shape,
|
|
@@ -4620,11 +4788,11 @@ class ZodObject extends ZodType {
|
|
|
4620
4788
|
}
|
|
4621
4789
|
omit(mask) {
|
|
4622
4790
|
const shape = {};
|
|
4623
|
-
util.objectKeys(this.shape)
|
|
4791
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4624
4792
|
if (!mask[key]) {
|
|
4625
4793
|
shape[key] = this.shape[key];
|
|
4626
4794
|
}
|
|
4627
|
-
}
|
|
4795
|
+
}
|
|
4628
4796
|
return new ZodObject({
|
|
4629
4797
|
...this._def,
|
|
4630
4798
|
shape: () => shape,
|
|
@@ -4638,7 +4806,7 @@ class ZodObject extends ZodType {
|
|
|
4638
4806
|
}
|
|
4639
4807
|
partial(mask) {
|
|
4640
4808
|
const newShape = {};
|
|
4641
|
-
util.objectKeys(this.shape)
|
|
4809
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4642
4810
|
const fieldSchema = this.shape[key];
|
|
4643
4811
|
if (mask && !mask[key]) {
|
|
4644
4812
|
newShape[key] = fieldSchema;
|
|
@@ -4646,7 +4814,7 @@ class ZodObject extends ZodType {
|
|
|
4646
4814
|
else {
|
|
4647
4815
|
newShape[key] = fieldSchema.optional();
|
|
4648
4816
|
}
|
|
4649
|
-
}
|
|
4817
|
+
}
|
|
4650
4818
|
return new ZodObject({
|
|
4651
4819
|
...this._def,
|
|
4652
4820
|
shape: () => newShape,
|
|
@@ -4654,7 +4822,7 @@ class ZodObject extends ZodType {
|
|
|
4654
4822
|
}
|
|
4655
4823
|
required(mask) {
|
|
4656
4824
|
const newShape = {};
|
|
4657
|
-
util.objectKeys(this.shape)
|
|
4825
|
+
for (const key of util.objectKeys(this.shape)) {
|
|
4658
4826
|
if (mask && !mask[key]) {
|
|
4659
4827
|
newShape[key] = this.shape[key];
|
|
4660
4828
|
}
|
|
@@ -4666,7 +4834,7 @@ class ZodObject extends ZodType {
|
|
|
4666
4834
|
}
|
|
4667
4835
|
newShape[key] = newField;
|
|
4668
4836
|
}
|
|
4669
|
-
}
|
|
4837
|
+
}
|
|
4670
4838
|
return new ZodObject({
|
|
4671
4839
|
...this._def,
|
|
4672
4840
|
shape: () => newShape,
|
|
@@ -4799,137 +4967,6 @@ ZodUnion.create = (types, params) => {
|
|
|
4799
4967
|
...processCreateParams(params),
|
|
4800
4968
|
});
|
|
4801
4969
|
};
|
|
4802
|
-
/////////////////////////////////////////////////////
|
|
4803
|
-
/////////////////////////////////////////////////////
|
|
4804
|
-
////////// //////////
|
|
4805
|
-
////////// ZodDiscriminatedUnion //////////
|
|
4806
|
-
////////// //////////
|
|
4807
|
-
/////////////////////////////////////////////////////
|
|
4808
|
-
/////////////////////////////////////////////////////
|
|
4809
|
-
const getDiscriminator = (type) => {
|
|
4810
|
-
if (type instanceof ZodLazy) {
|
|
4811
|
-
return getDiscriminator(type.schema);
|
|
4812
|
-
}
|
|
4813
|
-
else if (type instanceof ZodEffects) {
|
|
4814
|
-
return getDiscriminator(type.innerType());
|
|
4815
|
-
}
|
|
4816
|
-
else if (type instanceof ZodLiteral) {
|
|
4817
|
-
return [type.value];
|
|
4818
|
-
}
|
|
4819
|
-
else if (type instanceof ZodEnum) {
|
|
4820
|
-
return type.options;
|
|
4821
|
-
}
|
|
4822
|
-
else if (type instanceof ZodNativeEnum) {
|
|
4823
|
-
// eslint-disable-next-line ban/ban
|
|
4824
|
-
return util.objectValues(type.enum);
|
|
4825
|
-
}
|
|
4826
|
-
else if (type instanceof ZodDefault) {
|
|
4827
|
-
return getDiscriminator(type._def.innerType);
|
|
4828
|
-
}
|
|
4829
|
-
else if (type instanceof ZodUndefined) {
|
|
4830
|
-
return [undefined];
|
|
4831
|
-
}
|
|
4832
|
-
else if (type instanceof ZodNull) {
|
|
4833
|
-
return [null];
|
|
4834
|
-
}
|
|
4835
|
-
else if (type instanceof ZodOptional) {
|
|
4836
|
-
return [undefined, ...getDiscriminator(type.unwrap())];
|
|
4837
|
-
}
|
|
4838
|
-
else if (type instanceof ZodNullable) {
|
|
4839
|
-
return [null, ...getDiscriminator(type.unwrap())];
|
|
4840
|
-
}
|
|
4841
|
-
else if (type instanceof ZodBranded) {
|
|
4842
|
-
return getDiscriminator(type.unwrap());
|
|
4843
|
-
}
|
|
4844
|
-
else if (type instanceof ZodReadonly) {
|
|
4845
|
-
return getDiscriminator(type.unwrap());
|
|
4846
|
-
}
|
|
4847
|
-
else if (type instanceof ZodCatch) {
|
|
4848
|
-
return getDiscriminator(type._def.innerType);
|
|
4849
|
-
}
|
|
4850
|
-
else {
|
|
4851
|
-
return [];
|
|
4852
|
-
}
|
|
4853
|
-
};
|
|
4854
|
-
class ZodDiscriminatedUnion extends ZodType {
|
|
4855
|
-
_parse(input) {
|
|
4856
|
-
const { ctx } = this._processInputParams(input);
|
|
4857
|
-
if (ctx.parsedType !== ZodParsedType.object) {
|
|
4858
|
-
addIssueToContext(ctx, {
|
|
4859
|
-
code: ZodIssueCode.invalid_type,
|
|
4860
|
-
expected: ZodParsedType.object,
|
|
4861
|
-
received: ctx.parsedType,
|
|
4862
|
-
});
|
|
4863
|
-
return INVALID;
|
|
4864
|
-
}
|
|
4865
|
-
const discriminator = this.discriminator;
|
|
4866
|
-
const discriminatorValue = ctx.data[discriminator];
|
|
4867
|
-
const option = this.optionsMap.get(discriminatorValue);
|
|
4868
|
-
if (!option) {
|
|
4869
|
-
addIssueToContext(ctx, {
|
|
4870
|
-
code: ZodIssueCode.invalid_union_discriminator,
|
|
4871
|
-
options: Array.from(this.optionsMap.keys()),
|
|
4872
|
-
path: [discriminator],
|
|
4873
|
-
});
|
|
4874
|
-
return INVALID;
|
|
4875
|
-
}
|
|
4876
|
-
if (ctx.common.async) {
|
|
4877
|
-
return option._parseAsync({
|
|
4878
|
-
data: ctx.data,
|
|
4879
|
-
path: ctx.path,
|
|
4880
|
-
parent: ctx,
|
|
4881
|
-
});
|
|
4882
|
-
}
|
|
4883
|
-
else {
|
|
4884
|
-
return option._parseSync({
|
|
4885
|
-
data: ctx.data,
|
|
4886
|
-
path: ctx.path,
|
|
4887
|
-
parent: ctx,
|
|
4888
|
-
});
|
|
4889
|
-
}
|
|
4890
|
-
}
|
|
4891
|
-
get discriminator() {
|
|
4892
|
-
return this._def.discriminator;
|
|
4893
|
-
}
|
|
4894
|
-
get options() {
|
|
4895
|
-
return this._def.options;
|
|
4896
|
-
}
|
|
4897
|
-
get optionsMap() {
|
|
4898
|
-
return this._def.optionsMap;
|
|
4899
|
-
}
|
|
4900
|
-
/**
|
|
4901
|
-
* The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor.
|
|
4902
|
-
* However, it only allows a union of objects, all of which need to share a discriminator property. This property must
|
|
4903
|
-
* have a different value for each object in the union.
|
|
4904
|
-
* @param discriminator the name of the discriminator property
|
|
4905
|
-
* @param types an array of object schemas
|
|
4906
|
-
* @param params
|
|
4907
|
-
*/
|
|
4908
|
-
static create(discriminator, options, params) {
|
|
4909
|
-
// Get all the valid discriminator values
|
|
4910
|
-
const optionsMap = new Map();
|
|
4911
|
-
// try {
|
|
4912
|
-
for (const type of options) {
|
|
4913
|
-
const discriminatorValues = getDiscriminator(type.shape[discriminator]);
|
|
4914
|
-
if (!discriminatorValues.length) {
|
|
4915
|
-
throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
|
|
4916
|
-
}
|
|
4917
|
-
for (const value of discriminatorValues) {
|
|
4918
|
-
if (optionsMap.has(value)) {
|
|
4919
|
-
throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
|
|
4920
|
-
}
|
|
4921
|
-
optionsMap.set(value, type);
|
|
4922
|
-
}
|
|
4923
|
-
}
|
|
4924
|
-
return new ZodDiscriminatedUnion({
|
|
4925
|
-
typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,
|
|
4926
|
-
discriminator,
|
|
4927
|
-
options,
|
|
4928
|
-
optionsMap,
|
|
4929
|
-
...processCreateParams(params),
|
|
4930
|
-
});
|
|
4931
|
-
}
|
|
4932
|
-
}
|
|
4933
4970
|
function mergeValues(a, b) {
|
|
4934
4971
|
const aType = getParsedType(a);
|
|
4935
4972
|
const bType = getParsedType(b);
|
|
@@ -4938,9 +4975,7 @@ function mergeValues(a, b) {
|
|
|
4938
4975
|
}
|
|
4939
4976
|
else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
|
|
4940
4977
|
const bKeys = util.objectKeys(b);
|
|
4941
|
-
const sharedKeys = util
|
|
4942
|
-
.objectKeys(a)
|
|
4943
|
-
.filter((key) => bKeys.indexOf(key) !== -1);
|
|
4978
|
+
const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
4944
4979
|
const newObj = { ...a, ...b };
|
|
4945
4980
|
for (const key of sharedKeys) {
|
|
4946
4981
|
const sharedValue = mergeValues(a[key], b[key]);
|
|
@@ -4967,9 +5002,7 @@ function mergeValues(a, b) {
|
|
|
4967
5002
|
}
|
|
4968
5003
|
return { valid: true, data: newArray };
|
|
4969
5004
|
}
|
|
4970
|
-
else if (aType === ZodParsedType.date &&
|
|
4971
|
-
bType === ZodParsedType.date &&
|
|
4972
|
-
+a === +b) {
|
|
5005
|
+
else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) {
|
|
4973
5006
|
return { valid: true, data: a };
|
|
4974
5007
|
}
|
|
4975
5008
|
else {
|
|
@@ -5030,6 +5063,7 @@ ZodIntersection.create = (left, right, params) => {
|
|
|
5030
5063
|
...processCreateParams(params),
|
|
5031
5064
|
});
|
|
5032
5065
|
};
|
|
5066
|
+
// type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]];
|
|
5033
5067
|
class ZodTuple extends ZodType {
|
|
5034
5068
|
_parse(input) {
|
|
5035
5069
|
const { status, ctx } = this._processInputParams(input);
|
|
@@ -5100,7 +5134,7 @@ ZodTuple.create = (schemas, params) => {
|
|
|
5100
5134
|
...processCreateParams(params),
|
|
5101
5135
|
});
|
|
5102
5136
|
};
|
|
5103
|
-
class
|
|
5137
|
+
class ZodMap extends ZodType {
|
|
5104
5138
|
get keySchema() {
|
|
5105
5139
|
return this._def.keyType;
|
|
5106
5140
|
}
|
|
@@ -5109,75 +5143,21 @@ class ZodRecord extends ZodType {
|
|
|
5109
5143
|
}
|
|
5110
5144
|
_parse(input) {
|
|
5111
5145
|
const { status, ctx } = this._processInputParams(input);
|
|
5112
|
-
if (ctx.parsedType !== ZodParsedType.
|
|
5146
|
+
if (ctx.parsedType !== ZodParsedType.map) {
|
|
5113
5147
|
addIssueToContext(ctx, {
|
|
5114
5148
|
code: ZodIssueCode.invalid_type,
|
|
5115
|
-
expected: ZodParsedType.
|
|
5149
|
+
expected: ZodParsedType.map,
|
|
5116
5150
|
received: ctx.parsedType,
|
|
5117
5151
|
});
|
|
5118
5152
|
return INVALID;
|
|
5119
5153
|
}
|
|
5120
|
-
const pairs = [];
|
|
5121
5154
|
const keyType = this._def.keyType;
|
|
5122
5155
|
const valueType = this._def.valueType;
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
|
|
5126
|
-
value: valueType._parse(new ParseInputLazyPath(ctx,
|
|
5127
|
-
|
|
5128
|
-
});
|
|
5129
|
-
}
|
|
5130
|
-
if (ctx.common.async) {
|
|
5131
|
-
return ParseStatus.mergeObjectAsync(status, pairs);
|
|
5132
|
-
}
|
|
5133
|
-
else {
|
|
5134
|
-
return ParseStatus.mergeObjectSync(status, pairs);
|
|
5135
|
-
}
|
|
5136
|
-
}
|
|
5137
|
-
get element() {
|
|
5138
|
-
return this._def.valueType;
|
|
5139
|
-
}
|
|
5140
|
-
static create(first, second, third) {
|
|
5141
|
-
if (second instanceof ZodType) {
|
|
5142
|
-
return new ZodRecord({
|
|
5143
|
-
keyType: first,
|
|
5144
|
-
valueType: second,
|
|
5145
|
-
typeName: ZodFirstPartyTypeKind.ZodRecord,
|
|
5146
|
-
...processCreateParams(third),
|
|
5147
|
-
});
|
|
5148
|
-
}
|
|
5149
|
-
return new ZodRecord({
|
|
5150
|
-
keyType: ZodString.create(),
|
|
5151
|
-
valueType: first,
|
|
5152
|
-
typeName: ZodFirstPartyTypeKind.ZodRecord,
|
|
5153
|
-
...processCreateParams(second),
|
|
5154
|
-
});
|
|
5155
|
-
}
|
|
5156
|
-
}
|
|
5157
|
-
class ZodMap extends ZodType {
|
|
5158
|
-
get keySchema() {
|
|
5159
|
-
return this._def.keyType;
|
|
5160
|
-
}
|
|
5161
|
-
get valueSchema() {
|
|
5162
|
-
return this._def.valueType;
|
|
5163
|
-
}
|
|
5164
|
-
_parse(input) {
|
|
5165
|
-
const { status, ctx } = this._processInputParams(input);
|
|
5166
|
-
if (ctx.parsedType !== ZodParsedType.map) {
|
|
5167
|
-
addIssueToContext(ctx, {
|
|
5168
|
-
code: ZodIssueCode.invalid_type,
|
|
5169
|
-
expected: ZodParsedType.map,
|
|
5170
|
-
received: ctx.parsedType,
|
|
5171
|
-
});
|
|
5172
|
-
return INVALID;
|
|
5173
|
-
}
|
|
5174
|
-
const keyType = this._def.keyType;
|
|
5175
|
-
const valueType = this._def.valueType;
|
|
5176
|
-
const pairs = [...ctx.data.entries()].map(([key, value], index) => {
|
|
5177
|
-
return {
|
|
5178
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
|
|
5179
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])),
|
|
5180
|
-
};
|
|
5156
|
+
const pairs = [...ctx.data.entries()].map(([key, value], index) => {
|
|
5157
|
+
return {
|
|
5158
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
|
|
5159
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])),
|
|
5160
|
+
};
|
|
5181
5161
|
});
|
|
5182
5162
|
if (ctx.common.async) {
|
|
5183
5163
|
const finalMap = new Map();
|
|
@@ -5307,134 +5287,6 @@ ZodSet.create = (valueType, params) => {
|
|
|
5307
5287
|
...processCreateParams(params),
|
|
5308
5288
|
});
|
|
5309
5289
|
};
|
|
5310
|
-
class ZodFunction extends ZodType {
|
|
5311
|
-
constructor() {
|
|
5312
|
-
super(...arguments);
|
|
5313
|
-
this.validate = this.implement;
|
|
5314
|
-
}
|
|
5315
|
-
_parse(input) {
|
|
5316
|
-
const { ctx } = this._processInputParams(input);
|
|
5317
|
-
if (ctx.parsedType !== ZodParsedType.function) {
|
|
5318
|
-
addIssueToContext(ctx, {
|
|
5319
|
-
code: ZodIssueCode.invalid_type,
|
|
5320
|
-
expected: ZodParsedType.function,
|
|
5321
|
-
received: ctx.parsedType,
|
|
5322
|
-
});
|
|
5323
|
-
return INVALID;
|
|
5324
|
-
}
|
|
5325
|
-
function makeArgsIssue(args, error) {
|
|
5326
|
-
return makeIssue({
|
|
5327
|
-
data: args,
|
|
5328
|
-
path: ctx.path,
|
|
5329
|
-
errorMaps: [
|
|
5330
|
-
ctx.common.contextualErrorMap,
|
|
5331
|
-
ctx.schemaErrorMap,
|
|
5332
|
-
getErrorMap(),
|
|
5333
|
-
errorMap,
|
|
5334
|
-
].filter((x) => !!x),
|
|
5335
|
-
issueData: {
|
|
5336
|
-
code: ZodIssueCode.invalid_arguments,
|
|
5337
|
-
argumentsError: error,
|
|
5338
|
-
},
|
|
5339
|
-
});
|
|
5340
|
-
}
|
|
5341
|
-
function makeReturnsIssue(returns, error) {
|
|
5342
|
-
return makeIssue({
|
|
5343
|
-
data: returns,
|
|
5344
|
-
path: ctx.path,
|
|
5345
|
-
errorMaps: [
|
|
5346
|
-
ctx.common.contextualErrorMap,
|
|
5347
|
-
ctx.schemaErrorMap,
|
|
5348
|
-
getErrorMap(),
|
|
5349
|
-
errorMap,
|
|
5350
|
-
].filter((x) => !!x),
|
|
5351
|
-
issueData: {
|
|
5352
|
-
code: ZodIssueCode.invalid_return_type,
|
|
5353
|
-
returnTypeError: error,
|
|
5354
|
-
},
|
|
5355
|
-
});
|
|
5356
|
-
}
|
|
5357
|
-
const params = { errorMap: ctx.common.contextualErrorMap };
|
|
5358
|
-
const fn = ctx.data;
|
|
5359
|
-
if (this._def.returns instanceof ZodPromise) {
|
|
5360
|
-
// Would love a way to avoid disabling this rule, but we need
|
|
5361
|
-
// an alias (using an arrow function was what caused 2651).
|
|
5362
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
5363
|
-
const me = this;
|
|
5364
|
-
return OK(async function (...args) {
|
|
5365
|
-
const error = new ZodError([]);
|
|
5366
|
-
const parsedArgs = await me._def.args
|
|
5367
|
-
.parseAsync(args, params)
|
|
5368
|
-
.catch((e) => {
|
|
5369
|
-
error.addIssue(makeArgsIssue(args, e));
|
|
5370
|
-
throw error;
|
|
5371
|
-
});
|
|
5372
|
-
const result = await Reflect.apply(fn, this, parsedArgs);
|
|
5373
|
-
const parsedReturns = await me._def.returns._def.type
|
|
5374
|
-
.parseAsync(result, params)
|
|
5375
|
-
.catch((e) => {
|
|
5376
|
-
error.addIssue(makeReturnsIssue(result, e));
|
|
5377
|
-
throw error;
|
|
5378
|
-
});
|
|
5379
|
-
return parsedReturns;
|
|
5380
|
-
});
|
|
5381
|
-
}
|
|
5382
|
-
else {
|
|
5383
|
-
// Would love a way to avoid disabling this rule, but we need
|
|
5384
|
-
// an alias (using an arrow function was what caused 2651).
|
|
5385
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
5386
|
-
const me = this;
|
|
5387
|
-
return OK(function (...args) {
|
|
5388
|
-
const parsedArgs = me._def.args.safeParse(args, params);
|
|
5389
|
-
if (!parsedArgs.success) {
|
|
5390
|
-
throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
|
|
5391
|
-
}
|
|
5392
|
-
const result = Reflect.apply(fn, this, parsedArgs.data);
|
|
5393
|
-
const parsedReturns = me._def.returns.safeParse(result, params);
|
|
5394
|
-
if (!parsedReturns.success) {
|
|
5395
|
-
throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
|
|
5396
|
-
}
|
|
5397
|
-
return parsedReturns.data;
|
|
5398
|
-
});
|
|
5399
|
-
}
|
|
5400
|
-
}
|
|
5401
|
-
parameters() {
|
|
5402
|
-
return this._def.args;
|
|
5403
|
-
}
|
|
5404
|
-
returnType() {
|
|
5405
|
-
return this._def.returns;
|
|
5406
|
-
}
|
|
5407
|
-
args(...items) {
|
|
5408
|
-
return new ZodFunction({
|
|
5409
|
-
...this._def,
|
|
5410
|
-
args: ZodTuple.create(items).rest(ZodUnknown.create()),
|
|
5411
|
-
});
|
|
5412
|
-
}
|
|
5413
|
-
returns(returnType) {
|
|
5414
|
-
return new ZodFunction({
|
|
5415
|
-
...this._def,
|
|
5416
|
-
returns: returnType,
|
|
5417
|
-
});
|
|
5418
|
-
}
|
|
5419
|
-
implement(func) {
|
|
5420
|
-
const validatedFunc = this.parse(func);
|
|
5421
|
-
return validatedFunc;
|
|
5422
|
-
}
|
|
5423
|
-
strictImplement(func) {
|
|
5424
|
-
const validatedFunc = this.parse(func);
|
|
5425
|
-
return validatedFunc;
|
|
5426
|
-
}
|
|
5427
|
-
static create(args, returns, params) {
|
|
5428
|
-
return new ZodFunction({
|
|
5429
|
-
args: (args
|
|
5430
|
-
? args
|
|
5431
|
-
: ZodTuple.create([]).rest(ZodUnknown.create())),
|
|
5432
|
-
returns: returns || ZodUnknown.create(),
|
|
5433
|
-
typeName: ZodFirstPartyTypeKind.ZodFunction,
|
|
5434
|
-
...processCreateParams(params),
|
|
5435
|
-
});
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
5290
|
class ZodLazy extends ZodType {
|
|
5439
5291
|
get schema() {
|
|
5440
5292
|
return this._def.getter();
|
|
@@ -5484,10 +5336,6 @@ function createZodEnum(values, params) {
|
|
|
5484
5336
|
});
|
|
5485
5337
|
}
|
|
5486
5338
|
class ZodEnum extends ZodType {
|
|
5487
|
-
constructor() {
|
|
5488
|
-
super(...arguments);
|
|
5489
|
-
_ZodEnum_cache.set(this, void 0);
|
|
5490
|
-
}
|
|
5491
5339
|
_parse(input) {
|
|
5492
5340
|
if (typeof input.data !== "string") {
|
|
5493
5341
|
const ctx = this._getOrReturnCtx(input);
|
|
@@ -5499,10 +5347,10 @@ class ZodEnum extends ZodType {
|
|
|
5499
5347
|
});
|
|
5500
5348
|
return INVALID;
|
|
5501
5349
|
}
|
|
5502
|
-
if (!
|
|
5503
|
-
|
|
5350
|
+
if (!this._cache) {
|
|
5351
|
+
this._cache = new Set(this._def.values);
|
|
5504
5352
|
}
|
|
5505
|
-
if (!
|
|
5353
|
+
if (!this._cache.has(input.data)) {
|
|
5506
5354
|
const ctx = this._getOrReturnCtx(input);
|
|
5507
5355
|
const expectedValues = this._def.values;
|
|
5508
5356
|
addIssueToContext(ctx, {
|
|
@@ -5551,18 +5399,12 @@ class ZodEnum extends ZodType {
|
|
|
5551
5399
|
});
|
|
5552
5400
|
}
|
|
5553
5401
|
}
|
|
5554
|
-
_ZodEnum_cache = new WeakMap();
|
|
5555
5402
|
ZodEnum.create = createZodEnum;
|
|
5556
5403
|
class ZodNativeEnum extends ZodType {
|
|
5557
|
-
constructor() {
|
|
5558
|
-
super(...arguments);
|
|
5559
|
-
_ZodNativeEnum_cache.set(this, void 0);
|
|
5560
|
-
}
|
|
5561
5404
|
_parse(input) {
|
|
5562
5405
|
const nativeEnumValues = util.getValidEnumValues(this._def.values);
|
|
5563
5406
|
const ctx = this._getOrReturnCtx(input);
|
|
5564
|
-
if (ctx.parsedType !== ZodParsedType.string &&
|
|
5565
|
-
ctx.parsedType !== ZodParsedType.number) {
|
|
5407
|
+
if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) {
|
|
5566
5408
|
const expectedValues = util.objectValues(nativeEnumValues);
|
|
5567
5409
|
addIssueToContext(ctx, {
|
|
5568
5410
|
expected: util.joinValues(expectedValues),
|
|
@@ -5571,10 +5413,10 @@ class ZodNativeEnum extends ZodType {
|
|
|
5571
5413
|
});
|
|
5572
5414
|
return INVALID;
|
|
5573
5415
|
}
|
|
5574
|
-
if (!
|
|
5575
|
-
|
|
5416
|
+
if (!this._cache) {
|
|
5417
|
+
this._cache = new Set(util.getValidEnumValues(this._def.values));
|
|
5576
5418
|
}
|
|
5577
|
-
if (!
|
|
5419
|
+
if (!this._cache.has(input.data)) {
|
|
5578
5420
|
const expectedValues = util.objectValues(nativeEnumValues);
|
|
5579
5421
|
addIssueToContext(ctx, {
|
|
5580
5422
|
received: ctx.data,
|
|
@@ -5589,7 +5431,6 @@ class ZodNativeEnum extends ZodType {
|
|
|
5589
5431
|
return this._def.values;
|
|
5590
5432
|
}
|
|
5591
5433
|
}
|
|
5592
|
-
_ZodNativeEnum_cache = new WeakMap();
|
|
5593
5434
|
ZodNativeEnum.create = (values, params) => {
|
|
5594
5435
|
return new ZodNativeEnum({
|
|
5595
5436
|
values: values,
|
|
@@ -5603,8 +5444,7 @@ class ZodPromise extends ZodType {
|
|
|
5603
5444
|
}
|
|
5604
5445
|
_parse(input) {
|
|
5605
5446
|
const { ctx } = this._processInputParams(input);
|
|
5606
|
-
if (ctx.parsedType !== ZodParsedType.promise &&
|
|
5607
|
-
ctx.common.async === false) {
|
|
5447
|
+
if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) {
|
|
5608
5448
|
addIssueToContext(ctx, {
|
|
5609
5449
|
code: ZodIssueCode.invalid_type,
|
|
5610
5450
|
expected: ZodParsedType.promise,
|
|
@@ -5612,9 +5452,7 @@ class ZodPromise extends ZodType {
|
|
|
5612
5452
|
});
|
|
5613
5453
|
return INVALID;
|
|
5614
5454
|
}
|
|
5615
|
-
const promisified = ctx.parsedType === ZodParsedType.promise
|
|
5616
|
-
? ctx.data
|
|
5617
|
-
: Promise.resolve(ctx.data);
|
|
5455
|
+
const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);
|
|
5618
5456
|
return OK(promisified.then((data) => {
|
|
5619
5457
|
return this._def.type.parseAsync(data, {
|
|
5620
5458
|
path: ctx.path,
|
|
@@ -5720,9 +5558,7 @@ class ZodEffects extends ZodType {
|
|
|
5720
5558
|
return { status: status.value, value: inner.value };
|
|
5721
5559
|
}
|
|
5722
5560
|
else {
|
|
5723
|
-
return this._def.schema
|
|
5724
|
-
._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
|
|
5725
|
-
.then((inner) => {
|
|
5561
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {
|
|
5726
5562
|
if (inner.status === "aborted")
|
|
5727
5563
|
return INVALID;
|
|
5728
5564
|
if (inner.status === "dirty")
|
|
@@ -5741,7 +5577,7 @@ class ZodEffects extends ZodType {
|
|
|
5741
5577
|
parent: ctx,
|
|
5742
5578
|
});
|
|
5743
5579
|
if (!isValid(base))
|
|
5744
|
-
return
|
|
5580
|
+
return INVALID;
|
|
5745
5581
|
const result = effect.transform(base.value, checkCtx);
|
|
5746
5582
|
if (result instanceof Promise) {
|
|
5747
5583
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
@@ -5749,12 +5585,13 @@ class ZodEffects extends ZodType {
|
|
|
5749
5585
|
return { status: status.value, value: result };
|
|
5750
5586
|
}
|
|
5751
5587
|
else {
|
|
5752
|
-
return this._def.schema
|
|
5753
|
-
._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
|
|
5754
|
-
.then((base) => {
|
|
5588
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
|
|
5755
5589
|
if (!isValid(base))
|
|
5756
|
-
return
|
|
5757
|
-
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
|
|
5590
|
+
return INVALID;
|
|
5591
|
+
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
|
|
5592
|
+
status: status.value,
|
|
5593
|
+
value: result,
|
|
5594
|
+
}));
|
|
5758
5595
|
});
|
|
5759
5596
|
}
|
|
5760
5597
|
}
|
|
@@ -5836,9 +5673,7 @@ ZodDefault.create = (type, params) => {
|
|
|
5836
5673
|
return new ZodDefault({
|
|
5837
5674
|
innerType: type,
|
|
5838
5675
|
typeName: ZodFirstPartyTypeKind.ZodDefault,
|
|
5839
|
-
defaultValue: typeof params.default === "function"
|
|
5840
|
-
? params.default
|
|
5841
|
-
: () => params.default,
|
|
5676
|
+
defaultValue: typeof params.default === "function" ? params.default : () => params.default,
|
|
5842
5677
|
...processCreateParams(params),
|
|
5843
5678
|
});
|
|
5844
5679
|
};
|
|
@@ -5922,7 +5757,6 @@ ZodNaN.create = (params) => {
|
|
|
5922
5757
|
...processCreateParams(params),
|
|
5923
5758
|
});
|
|
5924
5759
|
};
|
|
5925
|
-
const BRAND = Symbol("zod_brand");
|
|
5926
5760
|
class ZodBranded extends ZodType {
|
|
5927
5761
|
_parse(input) {
|
|
5928
5762
|
const { ctx } = this._processInputParams(input);
|
|
@@ -6004,9 +5838,7 @@ class ZodReadonly extends ZodType {
|
|
|
6004
5838
|
}
|
|
6005
5839
|
return data;
|
|
6006
5840
|
};
|
|
6007
|
-
return isAsync(result)
|
|
6008
|
-
? result.then((data) => freeze(data))
|
|
6009
|
-
: freeze(result);
|
|
5841
|
+
return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result);
|
|
6010
5842
|
}
|
|
6011
5843
|
unwrap() {
|
|
6012
5844
|
return this._def.innerType;
|
|
@@ -6019,60 +5851,9 @@ ZodReadonly.create = (type, params) => {
|
|
|
6019
5851
|
...processCreateParams(params),
|
|
6020
5852
|
});
|
|
6021
5853
|
};
|
|
6022
|
-
|
|
6023
|
-
////////////////////////////////////////
|
|
6024
|
-
////////// //////////
|
|
6025
|
-
////////// z.custom //////////
|
|
6026
|
-
////////// //////////
|
|
6027
|
-
////////////////////////////////////////
|
|
6028
|
-
////////////////////////////////////////
|
|
6029
|
-
function cleanParams(params, data) {
|
|
6030
|
-
const p = typeof params === "function"
|
|
6031
|
-
? params(data)
|
|
6032
|
-
: typeof params === "string"
|
|
6033
|
-
? { message: params }
|
|
6034
|
-
: params;
|
|
6035
|
-
const p2 = typeof p === "string" ? { message: p } : p;
|
|
6036
|
-
return p2;
|
|
6037
|
-
}
|
|
6038
|
-
function custom(check, _params = {},
|
|
6039
|
-
/**
|
|
6040
|
-
* @deprecated
|
|
6041
|
-
*
|
|
6042
|
-
* Pass `fatal` into the params object instead:
|
|
6043
|
-
*
|
|
6044
|
-
* ```ts
|
|
6045
|
-
* z.string().custom((val) => val.length > 5, { fatal: false })
|
|
6046
|
-
* ```
|
|
6047
|
-
*
|
|
6048
|
-
*/
|
|
6049
|
-
fatal) {
|
|
6050
|
-
if (check)
|
|
6051
|
-
return ZodAny.create().superRefine((data, ctx) => {
|
|
6052
|
-
var _a, _b;
|
|
6053
|
-
const r = check(data);
|
|
6054
|
-
if (r instanceof Promise) {
|
|
6055
|
-
return r.then((r) => {
|
|
6056
|
-
var _a, _b;
|
|
6057
|
-
if (!r) {
|
|
6058
|
-
const params = cleanParams(_params, data);
|
|
6059
|
-
const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
|
|
6060
|
-
ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
|
|
6061
|
-
}
|
|
6062
|
-
});
|
|
6063
|
-
}
|
|
6064
|
-
if (!r) {
|
|
6065
|
-
const params = cleanParams(_params, data);
|
|
6066
|
-
const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
|
|
6067
|
-
ctx.addIssue({ code: "custom", ...params, fatal: _fatal });
|
|
6068
|
-
}
|
|
6069
|
-
return;
|
|
6070
|
-
});
|
|
6071
|
-
return ZodAny.create();
|
|
6072
|
-
}
|
|
6073
|
-
const late = {
|
|
5854
|
+
({
|
|
6074
5855
|
object: ZodObject.lazycreate,
|
|
6075
|
-
};
|
|
5856
|
+
});
|
|
6076
5857
|
var ZodFirstPartyTypeKind;
|
|
6077
5858
|
(function (ZodFirstPartyTypeKind) {
|
|
6078
5859
|
ZodFirstPartyTypeKind["ZodString"] = "ZodString";
|
|
@@ -6112,174 +5893,23 @@ var ZodFirstPartyTypeKind;
|
|
|
6112
5893
|
ZodFirstPartyTypeKind["ZodPipeline"] = "ZodPipeline";
|
|
6113
5894
|
ZodFirstPartyTypeKind["ZodReadonly"] = "ZodReadonly";
|
|
6114
5895
|
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
6115
|
-
const instanceOfType = (
|
|
6116
|
-
// const instanceOfType = <T extends new (...args: any[]) => any>(
|
|
6117
|
-
cls, params = {
|
|
6118
|
-
message: `Input not instance of ${cls.name}`,
|
|
6119
|
-
}) => custom((data) => data instanceof cls, params);
|
|
6120
5896
|
const stringType = ZodString.create;
|
|
6121
|
-
|
|
6122
|
-
const nanType = ZodNaN.create;
|
|
6123
|
-
const bigIntType = ZodBigInt.create;
|
|
6124
|
-
const booleanType = ZodBoolean.create;
|
|
6125
|
-
const dateType = ZodDate.create;
|
|
6126
|
-
const symbolType = ZodSymbol.create;
|
|
6127
|
-
const undefinedType = ZodUndefined.create;
|
|
6128
|
-
const nullType = ZodNull.create;
|
|
6129
|
-
const anyType = ZodAny.create;
|
|
6130
|
-
const unknownType = ZodUnknown.create;
|
|
6131
|
-
const neverType = ZodNever.create;
|
|
6132
|
-
const voidType = ZodVoid.create;
|
|
5897
|
+
ZodNever.create;
|
|
6133
5898
|
const arrayType = ZodArray.create;
|
|
6134
5899
|
const objectType = ZodObject.create;
|
|
6135
|
-
|
|
5900
|
+
ZodObject.strictCreate;
|
|
6136
5901
|
const unionType = ZodUnion.create;
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
const tupleType = ZodTuple.create;
|
|
6140
|
-
const recordType = ZodRecord.create;
|
|
6141
|
-
const mapType = ZodMap.create;
|
|
6142
|
-
const setType = ZodSet.create;
|
|
6143
|
-
const functionType = ZodFunction.create;
|
|
6144
|
-
const lazyType = ZodLazy.create;
|
|
5902
|
+
ZodIntersection.create;
|
|
5903
|
+
ZodTuple.create;
|
|
6145
5904
|
const literalType = ZodLiteral.create;
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
const
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
const ostring = () => stringType().optional();
|
|
6155
|
-
const onumber = () => numberType().optional();
|
|
6156
|
-
const oboolean = () => booleanType().optional();
|
|
6157
|
-
const coerce = {
|
|
6158
|
-
string: ((arg) => ZodString.create({ ...arg, coerce: true })),
|
|
6159
|
-
number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),
|
|
6160
|
-
boolean: ((arg) => ZodBoolean.create({
|
|
6161
|
-
...arg,
|
|
6162
|
-
coerce: true,
|
|
6163
|
-
})),
|
|
6164
|
-
bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),
|
|
6165
|
-
date: ((arg) => ZodDate.create({ ...arg, coerce: true })),
|
|
6166
|
-
};
|
|
6167
|
-
const NEVER = INVALID;
|
|
6168
|
-
|
|
6169
|
-
var z = /*#__PURE__*/Object.freeze({
|
|
6170
|
-
__proto__: null,
|
|
6171
|
-
defaultErrorMap: errorMap,
|
|
6172
|
-
setErrorMap: setErrorMap,
|
|
6173
|
-
getErrorMap: getErrorMap,
|
|
6174
|
-
makeIssue: makeIssue,
|
|
6175
|
-
EMPTY_PATH: EMPTY_PATH,
|
|
6176
|
-
addIssueToContext: addIssueToContext,
|
|
6177
|
-
ParseStatus: ParseStatus,
|
|
6178
|
-
INVALID: INVALID,
|
|
6179
|
-
DIRTY: DIRTY,
|
|
6180
|
-
OK: OK,
|
|
6181
|
-
isAborted: isAborted,
|
|
6182
|
-
isDirty: isDirty,
|
|
6183
|
-
isValid: isValid,
|
|
6184
|
-
isAsync: isAsync,
|
|
6185
|
-
get util () { return util; },
|
|
6186
|
-
get objectUtil () { return objectUtil; },
|
|
6187
|
-
ZodParsedType: ZodParsedType,
|
|
6188
|
-
getParsedType: getParsedType,
|
|
6189
|
-
ZodType: ZodType,
|
|
6190
|
-
datetimeRegex: datetimeRegex,
|
|
6191
|
-
ZodString: ZodString,
|
|
6192
|
-
ZodNumber: ZodNumber,
|
|
6193
|
-
ZodBigInt: ZodBigInt,
|
|
6194
|
-
ZodBoolean: ZodBoolean,
|
|
6195
|
-
ZodDate: ZodDate,
|
|
6196
|
-
ZodSymbol: ZodSymbol,
|
|
6197
|
-
ZodUndefined: ZodUndefined,
|
|
6198
|
-
ZodNull: ZodNull,
|
|
6199
|
-
ZodAny: ZodAny,
|
|
6200
|
-
ZodUnknown: ZodUnknown,
|
|
6201
|
-
ZodNever: ZodNever,
|
|
6202
|
-
ZodVoid: ZodVoid,
|
|
6203
|
-
ZodArray: ZodArray,
|
|
6204
|
-
ZodObject: ZodObject,
|
|
6205
|
-
ZodUnion: ZodUnion,
|
|
6206
|
-
ZodDiscriminatedUnion: ZodDiscriminatedUnion,
|
|
6207
|
-
ZodIntersection: ZodIntersection,
|
|
6208
|
-
ZodTuple: ZodTuple,
|
|
6209
|
-
ZodRecord: ZodRecord,
|
|
6210
|
-
ZodMap: ZodMap,
|
|
6211
|
-
ZodSet: ZodSet,
|
|
6212
|
-
ZodFunction: ZodFunction,
|
|
6213
|
-
ZodLazy: ZodLazy,
|
|
6214
|
-
ZodLiteral: ZodLiteral,
|
|
6215
|
-
ZodEnum: ZodEnum,
|
|
6216
|
-
ZodNativeEnum: ZodNativeEnum,
|
|
6217
|
-
ZodPromise: ZodPromise,
|
|
6218
|
-
ZodEffects: ZodEffects,
|
|
6219
|
-
ZodTransformer: ZodEffects,
|
|
6220
|
-
ZodOptional: ZodOptional,
|
|
6221
|
-
ZodNullable: ZodNullable,
|
|
6222
|
-
ZodDefault: ZodDefault,
|
|
6223
|
-
ZodCatch: ZodCatch,
|
|
6224
|
-
ZodNaN: ZodNaN,
|
|
6225
|
-
BRAND: BRAND,
|
|
6226
|
-
ZodBranded: ZodBranded,
|
|
6227
|
-
ZodPipeline: ZodPipeline,
|
|
6228
|
-
ZodReadonly: ZodReadonly,
|
|
6229
|
-
custom: custom,
|
|
6230
|
-
Schema: ZodType,
|
|
6231
|
-
ZodSchema: ZodType,
|
|
6232
|
-
late: late,
|
|
6233
|
-
get ZodFirstPartyTypeKind () { return ZodFirstPartyTypeKind; },
|
|
6234
|
-
coerce: coerce,
|
|
6235
|
-
any: anyType,
|
|
6236
|
-
array: arrayType,
|
|
6237
|
-
bigint: bigIntType,
|
|
6238
|
-
boolean: booleanType,
|
|
6239
|
-
date: dateType,
|
|
6240
|
-
discriminatedUnion: discriminatedUnionType,
|
|
6241
|
-
effect: effectsType,
|
|
6242
|
-
'enum': enumType,
|
|
6243
|
-
'function': functionType,
|
|
6244
|
-
'instanceof': instanceOfType,
|
|
6245
|
-
intersection: intersectionType,
|
|
6246
|
-
lazy: lazyType,
|
|
6247
|
-
literal: literalType,
|
|
6248
|
-
map: mapType,
|
|
6249
|
-
nan: nanType,
|
|
6250
|
-
nativeEnum: nativeEnumType,
|
|
6251
|
-
never: neverType,
|
|
6252
|
-
'null': nullType,
|
|
6253
|
-
nullable: nullableType,
|
|
6254
|
-
number: numberType,
|
|
6255
|
-
object: objectType,
|
|
6256
|
-
oboolean: oboolean,
|
|
6257
|
-
onumber: onumber,
|
|
6258
|
-
optional: optionalType,
|
|
6259
|
-
ostring: ostring,
|
|
6260
|
-
pipeline: pipelineType,
|
|
6261
|
-
preprocess: preprocessType,
|
|
6262
|
-
promise: promiseType,
|
|
6263
|
-
record: recordType,
|
|
6264
|
-
set: setType,
|
|
6265
|
-
strictObject: strictObjectType,
|
|
6266
|
-
string: stringType,
|
|
6267
|
-
symbol: symbolType,
|
|
6268
|
-
transformer: effectsType,
|
|
6269
|
-
tuple: tupleType,
|
|
6270
|
-
'undefined': undefinedType,
|
|
6271
|
-
union: unionType,
|
|
6272
|
-
unknown: unknownType,
|
|
6273
|
-
'void': voidType,
|
|
6274
|
-
NEVER: NEVER,
|
|
6275
|
-
ZodIssueCode: ZodIssueCode,
|
|
6276
|
-
quotelessJson: quotelessJson,
|
|
6277
|
-
ZodError: ZodError
|
|
6278
|
-
});
|
|
6279
|
-
|
|
6280
|
-
const ChangelogResponseSchema = z.object({
|
|
6281
|
-
title: z.string(),
|
|
6282
|
-
content: z.string(),
|
|
5905
|
+
ZodEnum.create;
|
|
5906
|
+
ZodPromise.create;
|
|
5907
|
+
ZodOptional.create;
|
|
5908
|
+
ZodNullable.create;
|
|
5909
|
+
|
|
5910
|
+
const ChangelogResponseSchema = objectType({
|
|
5911
|
+
title: stringType(),
|
|
5912
|
+
content: stringType(),
|
|
6283
5913
|
});
|
|
6284
5914
|
const command$4 = 'changelog';
|
|
6285
5915
|
/**
|
|
@@ -6313,70 +5943,233 @@ const builder$4 = (yargs) => {
|
|
|
6313
5943
|
};
|
|
6314
5944
|
|
|
6315
5945
|
/**
|
|
6316
|
-
*
|
|
5946
|
+
* Default retry predicate - retries on non-validation errors
|
|
5947
|
+
*/
|
|
5948
|
+
function defaultShouldRetry(error) {
|
|
5949
|
+
// Don't retry validation errors or configuration errors
|
|
5950
|
+
if (error.name.includes('Validation') || error.name.includes('Configuration')) {
|
|
5951
|
+
return false;
|
|
5952
|
+
}
|
|
5953
|
+
// Don't retry authentication errors
|
|
5954
|
+
if (error.name.includes('Authentication')) {
|
|
5955
|
+
return false;
|
|
5956
|
+
}
|
|
5957
|
+
// Retry execution errors and timeouts
|
|
5958
|
+
return true;
|
|
5959
|
+
}
|
|
5960
|
+
/**
|
|
5961
|
+
* Executes an operation with retry logic
|
|
5962
|
+
*/
|
|
5963
|
+
async function withRetry(operation, options = {}) {
|
|
5964
|
+
const { maxAttempts = 3, backoffMs = 1000, backoffMultiplier = 2, maxBackoffMs = 10000, onRetry, shouldRetry = defaultShouldRetry } = options;
|
|
5965
|
+
let lastError = new Error('No attempts made');
|
|
5966
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5967
|
+
try {
|
|
5968
|
+
return await operation();
|
|
5969
|
+
}
|
|
5970
|
+
catch (error) {
|
|
5971
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
5972
|
+
// If this is the last attempt or we shouldn't retry, throw the error
|
|
5973
|
+
if (attempt === maxAttempts || !shouldRetry(lastError)) {
|
|
5974
|
+
throw lastError;
|
|
5975
|
+
}
|
|
5976
|
+
// Calculate delay with exponential backoff
|
|
5977
|
+
const delay = Math.min(backoffMs * Math.pow(backoffMultiplier, attempt - 1), maxBackoffMs);
|
|
5978
|
+
// Call retry callback if provided
|
|
5979
|
+
if (onRetry) {
|
|
5980
|
+
onRetry(attempt, lastError, delay);
|
|
5981
|
+
}
|
|
5982
|
+
// Wait before retrying
|
|
5983
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
5984
|
+
}
|
|
5985
|
+
}
|
|
5986
|
+
// This should never be reached, but TypeScript requires it
|
|
5987
|
+
throw new Error(`Operation failed after ${maxAttempts} attempts. Last error: ${lastError.message}`);
|
|
5988
|
+
}
|
|
5989
|
+
|
|
5990
|
+
/**
|
|
5991
|
+
* Wraps errors with additional context and converts them to LangChain errors
|
|
5992
|
+
*/
|
|
5993
|
+
function handleLangChainError(error, context, additionalContext) {
|
|
5994
|
+
// If it's already a LangChain error, re-throw with additional context
|
|
5995
|
+
if (error instanceof LangChainError) {
|
|
5996
|
+
throw new LangChainExecutionError(`${context}: ${error.message}`, {
|
|
5997
|
+
...error.context,
|
|
5998
|
+
...additionalContext,
|
|
5999
|
+
originalError: error.name,
|
|
6000
|
+
context
|
|
6001
|
+
});
|
|
6002
|
+
}
|
|
6003
|
+
// If it's a regular Error, wrap it
|
|
6004
|
+
if (error instanceof Error) {
|
|
6005
|
+
throw new LangChainExecutionError(`${context}: ${error.message}`, {
|
|
6006
|
+
originalError: error.name,
|
|
6007
|
+
originalMessage: error.message,
|
|
6008
|
+
stack: error.stack,
|
|
6009
|
+
context,
|
|
6010
|
+
...additionalContext
|
|
6011
|
+
});
|
|
6012
|
+
}
|
|
6013
|
+
// For unknown error types
|
|
6014
|
+
throw new LangChainExecutionError(`${context}: Unknown error occurred`, {
|
|
6015
|
+
originalError: typeof error,
|
|
6016
|
+
originalValue: String(error),
|
|
6017
|
+
context,
|
|
6018
|
+
...additionalContext
|
|
6019
|
+
});
|
|
6020
|
+
}
|
|
6021
|
+
|
|
6022
|
+
/**
|
|
6023
|
+
* Creates and configures an LLM instance based on the provider and configuration.
|
|
6317
6024
|
*
|
|
6318
|
-
* @param
|
|
6319
|
-
* @param
|
|
6320
|
-
* @
|
|
6025
|
+
* @param provider - The LLM provider (openai, anthropic, ollama)
|
|
6026
|
+
* @param model - The specific model to use
|
|
6027
|
+
* @param config - The configuration object containing service settings
|
|
6028
|
+
* @returns Configured LLM instance
|
|
6029
|
+
* @throws LangChainConfigurationError if the provider/model combination is invalid
|
|
6030
|
+
* @throws LangChainExecutionError if LLM instantiation fails
|
|
6321
6031
|
*/
|
|
6322
6032
|
function getLlm(provider, model, config) {
|
|
6323
|
-
|
|
6324
|
-
|
|
6033
|
+
// Validate input parameters
|
|
6034
|
+
validateProvider(provider, 'getLlm');
|
|
6035
|
+
validateModel(model, provider, 'getLlm');
|
|
6036
|
+
validateRequired(config, 'config', 'getLlm');
|
|
6037
|
+
// Get the API key once and validate it
|
|
6038
|
+
let apiKey;
|
|
6039
|
+
try {
|
|
6040
|
+
apiKey = getApiKeyForModel(config);
|
|
6325
6041
|
}
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6042
|
+
catch (error) {
|
|
6043
|
+
handleLangChainError(error, 'getLlm: Failed to retrieve API key', { provider, model });
|
|
6044
|
+
}
|
|
6045
|
+
try {
|
|
6046
|
+
switch (provider) {
|
|
6047
|
+
case 'anthropic':
|
|
6048
|
+
return new anthropic.ChatAnthropic({
|
|
6049
|
+
anthropicApiKey: apiKey,
|
|
6050
|
+
maxConcurrency: config.service.maxConcurrent,
|
|
6051
|
+
model,
|
|
6052
|
+
});
|
|
6053
|
+
case 'ollama':
|
|
6054
|
+
// Use endpoint from service config if available, otherwise fall back to default
|
|
6055
|
+
const endpoint = 'endpoint' in config.service
|
|
6056
|
+
? config.service.endpoint
|
|
6057
|
+
: DEFAULT_OLLAMA_LLM_SERVICE.endpoint;
|
|
6058
|
+
return new ollama.ChatOllama({
|
|
6059
|
+
baseUrl: endpoint,
|
|
6060
|
+
maxConcurrency: config.service.maxConcurrent,
|
|
6061
|
+
model,
|
|
6062
|
+
});
|
|
6063
|
+
case 'openai':
|
|
6064
|
+
return new openai.ChatOpenAI({
|
|
6065
|
+
openAIApiKey: apiKey,
|
|
6066
|
+
model,
|
|
6067
|
+
temperature: config.service.temperature || 0.2,
|
|
6068
|
+
});
|
|
6069
|
+
default:
|
|
6070
|
+
throw new LangChainConfigurationError(`getLlm: Unsupported provider '${provider}'`, { provider, model, supportedProviders: ['openai', 'anthropic', 'ollama'] });
|
|
6071
|
+
}
|
|
6072
|
+
}
|
|
6073
|
+
catch (error) {
|
|
6074
|
+
// If it's already a LangChain error, re-throw it
|
|
6075
|
+
if (error instanceof LangChainConfigurationError || error instanceof LangChainExecutionError) {
|
|
6076
|
+
throw error;
|
|
6077
|
+
}
|
|
6078
|
+
// Wrap other errors
|
|
6079
|
+
handleLangChainError(error, `getLlm: Failed to instantiate ${provider} LLM`, {
|
|
6080
|
+
provider,
|
|
6081
|
+
model,
|
|
6082
|
+
hasApiKey: !!apiKey,
|
|
6083
|
+
serviceConfig: {
|
|
6336
6084
|
maxConcurrency: config.service.maxConcurrent,
|
|
6337
|
-
|
|
6338
|
-
}
|
|
6339
|
-
|
|
6340
|
-
default:
|
|
6341
|
-
const openAiModel = new openai.ChatOpenAI({
|
|
6342
|
-
openAIApiKey: getApiKeyForModel(config),
|
|
6343
|
-
model,
|
|
6344
|
-
temperature: config.service.temperature || 0.2,
|
|
6345
|
-
});
|
|
6346
|
-
return openAiModel;
|
|
6085
|
+
temperature: config.service.temperature
|
|
6086
|
+
}
|
|
6087
|
+
});
|
|
6347
6088
|
}
|
|
6348
6089
|
}
|
|
6349
6090
|
|
|
6091
|
+
/**
|
|
6092
|
+
* Creates a PromptTemplate from a template string or returns a fallback template.
|
|
6093
|
+
*
|
|
6094
|
+
* @param params - The prompt creation parameters
|
|
6095
|
+
* @returns A configured PromptTemplate instance
|
|
6096
|
+
* @throws LangChainValidationError if neither template nor fallback is provided or if parameters are invalid
|
|
6097
|
+
* @throws LangChainExecutionError if PromptTemplate instantiation fails
|
|
6098
|
+
*/
|
|
6350
6099
|
function getPrompt({ template, variables, fallback }) {
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6100
|
+
// Validate that we have either a template or fallback
|
|
6101
|
+
if (!template && !fallback) {
|
|
6102
|
+
throw new LangChainValidationError('getPrompt: Must provide either a template string or a fallback PromptTemplate', { hasTemplate: !!template, hasFallback: !!fallback, variables });
|
|
6103
|
+
}
|
|
6104
|
+
// Validate variables array
|
|
6105
|
+
validateRequired(variables, 'variables', 'getPrompt');
|
|
6106
|
+
validateNonEmptyArray(variables, 'variables', 'getPrompt');
|
|
6107
|
+
// If using template, validate it and create PromptTemplate
|
|
6108
|
+
if (template) {
|
|
6109
|
+
validateNonEmptyString(template, 'template', 'getPrompt');
|
|
6110
|
+
try {
|
|
6111
|
+
return new prompts$1.PromptTemplate({
|
|
6112
|
+
template,
|
|
6113
|
+
inputVariables: variables,
|
|
6114
|
+
templateFormat: 'mustache',
|
|
6115
|
+
});
|
|
6116
|
+
}
|
|
6117
|
+
catch (error) {
|
|
6118
|
+
handleLangChainError(error, 'getPrompt: Failed to create PromptTemplate', {
|
|
6119
|
+
template: template.substring(0, 100) + (template.length > 100 ? '...' : ''),
|
|
6120
|
+
variables,
|
|
6121
|
+
templateFormat: 'mustache'
|
|
6122
|
+
});
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
// Validate fallback if using it
|
|
6126
|
+
if (fallback) {
|
|
6127
|
+
validateRequired(fallback, 'fallback', 'getPrompt');
|
|
6128
|
+
if (!(fallback instanceof prompts$1.PromptTemplate)) {
|
|
6129
|
+
throw new LangChainValidationError('getPrompt: Fallback must be a PromptTemplate instance', { fallbackType: typeof fallback, fallbackConstructor: fallback.constructor?.name });
|
|
6130
|
+
}
|
|
6131
|
+
return fallback;
|
|
6132
|
+
}
|
|
6133
|
+
// This should never be reached, but TypeScript requires it
|
|
6134
|
+
throw new LangChainExecutionError('getPrompt: Unexpected execution path - neither template nor fallback available', { template, fallback, variables });
|
|
6360
6135
|
}
|
|
6361
6136
|
|
|
6137
|
+
/**
|
|
6138
|
+
* Executes a LangChain pipeline with the provided LLM, prompt, variables, and parser.
|
|
6139
|
+
* @param params - The execution parameters
|
|
6140
|
+
* @returns The parsed result from the LLM chain
|
|
6141
|
+
* @throws LangChainExecutionError if the chain execution fails or returns empty results
|
|
6142
|
+
*/
|
|
6362
6143
|
const executeChain = async ({ llm, prompt, variables, parser }) => {
|
|
6363
|
-
|
|
6364
|
-
|
|
6144
|
+
// Validate all required parameters
|
|
6145
|
+
validateRequired(llm, 'llm', 'executeChain');
|
|
6146
|
+
validateRequired(prompt, 'prompt', 'executeChain');
|
|
6147
|
+
validateRequired(variables, 'variables', 'executeChain');
|
|
6148
|
+
validateRequired(parser, 'parser', 'executeChain');
|
|
6149
|
+
// Validate that variables is an object
|
|
6150
|
+
if (typeof variables !== 'object' || Array.isArray(variables)) {
|
|
6151
|
+
throw new LangChainExecutionError('executeChain: Variables must be a non-array object', { variables, type: typeof variables, isArray: Array.isArray(variables) });
|
|
6365
6152
|
}
|
|
6366
|
-
const chain = prompt.pipe(llm).pipe(parser);
|
|
6367
|
-
let res;
|
|
6368
6153
|
try {
|
|
6369
|
-
|
|
6154
|
+
const chain = prompt.pipe(llm).pipe(parser);
|
|
6155
|
+
const result = await chain.invoke(variables);
|
|
6156
|
+
if (result === null || result === undefined) {
|
|
6157
|
+
throw new LangChainExecutionError('executeChain: Chain execution returned null or undefined result', { variables, promptInputVariables: prompt.inputVariables });
|
|
6158
|
+
}
|
|
6159
|
+
return result;
|
|
6370
6160
|
}
|
|
6371
6161
|
catch (error) {
|
|
6372
|
-
|
|
6373
|
-
|
|
6162
|
+
// Re-throw LangChain errors as-is
|
|
6163
|
+
if (error instanceof LangChainExecutionError) {
|
|
6164
|
+
throw error;
|
|
6374
6165
|
}
|
|
6166
|
+
// Wrap other errors with context
|
|
6167
|
+
handleLangChainError(error, 'executeChain: Chain execution failed', {
|
|
6168
|
+
promptInputVariables: prompt.inputVariables,
|
|
6169
|
+
variableKeys: Object.keys(variables),
|
|
6170
|
+
parserType: parser.constructor.name
|
|
6171
|
+
});
|
|
6375
6172
|
}
|
|
6376
|
-
if (!res) {
|
|
6377
|
-
throw new Error('Empty response from LLMChain call');
|
|
6378
|
-
}
|
|
6379
|
-
return res;
|
|
6380
6173
|
};
|
|
6381
6174
|
|
|
6382
6175
|
function extractTicketIdFromBranchName(branchName) {
|
|
@@ -6415,19 +6208,20 @@ const getChangesSinceLastTag = async ({ git }) => {
|
|
|
6415
6208
|
};
|
|
6416
6209
|
|
|
6417
6210
|
/**
|
|
6418
|
-
* Retrieves the commit log range between two specified commits.
|
|
6211
|
+
* Retrieves the commit log range between two specified commits (inclusive of both commits).
|
|
6419
6212
|
*
|
|
6420
|
-
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name).
|
|
6421
|
-
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name).
|
|
6213
|
+
* @param from - The starting commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6214
|
+
* @param to - The ending commit (can be a commit hash, HEAD reference, or branch name). This commit will be included in the results.
|
|
6422
6215
|
* @param options - Additional options for retrieving the commit log range.
|
|
6423
|
-
* @returns A promise that resolves to an array of commit log messages.
|
|
6216
|
+
* @returns A promise that resolves to an array of commit log messages, including both the 'from' and 'to' commits.
|
|
6424
6217
|
* @throws If there is an error retrieving the commit log range.
|
|
6425
6218
|
*/
|
|
6426
6219
|
async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
6427
6220
|
try {
|
|
6428
|
-
// Use
|
|
6221
|
+
// Use from^..to to include the 'from' commit in the range
|
|
6222
|
+
// This works because from^..to means "commits reachable from 'to' but not from the parent of 'from'"
|
|
6429
6223
|
const logOptions = {
|
|
6430
|
-
from
|
|
6224
|
+
from: `${from}^`,
|
|
6431
6225
|
to,
|
|
6432
6226
|
'--no-merges': noMerges
|
|
6433
6227
|
};
|
|
@@ -6435,7 +6229,29 @@ async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
|
6435
6229
|
return commitLog.all.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6436
6230
|
}
|
|
6437
6231
|
catch (error) {
|
|
6438
|
-
// If
|
|
6232
|
+
// If from^ fails (e.g., 'from' is the first commit), fall back to using from..to and manually adding the 'from' commit
|
|
6233
|
+
if (error instanceof Error && error.message.includes('unknown revision')) {
|
|
6234
|
+
try {
|
|
6235
|
+
// Get the 'from' commit separately
|
|
6236
|
+
const fromCommitLog = await git.log({ from: from, maxCount: 1 });
|
|
6237
|
+
const fromCommit = fromCommitLog.latest;
|
|
6238
|
+
// Get the range from..to (excluding 'from')
|
|
6239
|
+
const rangeLogOptions = {
|
|
6240
|
+
from,
|
|
6241
|
+
to,
|
|
6242
|
+
'--no-merges': noMerges
|
|
6243
|
+
};
|
|
6244
|
+
const rangeCommitLog = await git.log(rangeLogOptions);
|
|
6245
|
+
// Combine the 'from' commit with the range commits
|
|
6246
|
+
const allCommits = fromCommit
|
|
6247
|
+
? [fromCommit, ...rangeCommitLog.all]
|
|
6248
|
+
: rangeCommitLog.all;
|
|
6249
|
+
return allCommits.map(({ message, date, body, author_name, hash, author_email }) => `[${date}] ${message}\n${body}\n(${hash}) - ${author_name}<${author_email}>`);
|
|
6250
|
+
}
|
|
6251
|
+
catch (fallbackError) {
|
|
6252
|
+
throw fallbackError;
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6439
6255
|
throw error;
|
|
6440
6256
|
}
|
|
6441
6257
|
}
|
|
@@ -6496,38 +6312,38 @@ async function getCommitLogAgainstBranch({ git, logger, targetBranch, }) {
|
|
|
6496
6312
|
*/
|
|
6497
6313
|
async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main', comparisonRemote = 'origin', }) {
|
|
6498
6314
|
try {
|
|
6499
|
-
|
|
6500
|
-
const
|
|
6501
|
-
// Check if the current branch has any commits
|
|
6502
|
-
const hasCommits = (await git.raw(['rev-list', '--count', branch])) !== '0';
|
|
6315
|
+
const branchName = await getCurrentBranchName({ git });
|
|
6316
|
+
const hasCommits = (await git.raw(['rev-list', '--count', branchName])) !== '0';
|
|
6503
6317
|
if (!hasCommits) {
|
|
6504
6318
|
logger?.log('No commits on the current branch.');
|
|
6505
6319
|
return [];
|
|
6506
6320
|
}
|
|
6507
|
-
// Get the list of commits that are unique to the current branch
|
|
6508
6321
|
let uniqueCommits;
|
|
6509
|
-
if (comparisonBranch ===
|
|
6322
|
+
if (comparisonBranch === branchName) {
|
|
6510
6323
|
// If the comparison branch is the same as the current branch, we compare against the remote.
|
|
6511
|
-
uniqueCommits = (await git.raw(['rev-list', `${comparisonRemote}/${comparisonBranch}..${
|
|
6324
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonRemote}/${comparisonBranch}..${branchName}`]))
|
|
6512
6325
|
.split('\n')
|
|
6513
6326
|
.filter(Boolean)
|
|
6514
6327
|
.reverse();
|
|
6515
6328
|
}
|
|
6516
6329
|
else {
|
|
6517
6330
|
// Your existing code for different branches
|
|
6518
|
-
uniqueCommits = (await git.raw(['rev-list', `${comparisonBranch}..${
|
|
6331
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonBranch}..${branchName}`]))
|
|
6519
6332
|
.split('\n')
|
|
6520
6333
|
.filter(Boolean)
|
|
6521
6334
|
.reverse();
|
|
6522
6335
|
}
|
|
6523
|
-
logger?.verbose(`Found ${uniqueCommits.length} unique commits on "${
|
|
6336
|
+
logger?.verbose(`Found ${uniqueCommits.length} unique commits on "${branchName}"`, {
|
|
6337
|
+
color: 'blue',
|
|
6338
|
+
});
|
|
6524
6339
|
const firstCommit = uniqueCommits[0];
|
|
6525
6340
|
const lastCommit = uniqueCommits[uniqueCommits.length - 1];
|
|
6526
6341
|
if (!firstCommit || !lastCommit) {
|
|
6527
|
-
logger?.log('Unable to determine first and last commit on the current branch', {
|
|
6342
|
+
logger?.log('Unable to determine first and last commit on the current branch', {
|
|
6343
|
+
color: 'yellow',
|
|
6344
|
+
});
|
|
6528
6345
|
return [];
|
|
6529
6346
|
}
|
|
6530
|
-
// Retrieve commit log with messages
|
|
6531
6347
|
return await getCommitLogRange(firstCommit, lastCommit, { git, noMerges: true });
|
|
6532
6348
|
}
|
|
6533
6349
|
catch (error) {
|
|
@@ -6656,17 +6472,35 @@ const CONVENTIONAL_COMMIT_PROMPT = new prompts$1.PromptTemplate({
|
|
|
6656
6472
|
*
|
|
6657
6473
|
* @param text template string
|
|
6658
6474
|
* @param inputVariables template variables
|
|
6659
|
-
* @
|
|
6475
|
+
* @throws Error if validation fails
|
|
6660
6476
|
*/
|
|
6661
6477
|
function validatePromptTemplate(text, inputVariables) {
|
|
6662
|
-
if (!text) {
|
|
6663
|
-
|
|
6478
|
+
if (!text || text.trim() === '') {
|
|
6479
|
+
throw new Error('Prompt template cannot be empty');
|
|
6664
6480
|
}
|
|
6665
|
-
if (!inputVariables.
|
|
6666
|
-
return
|
|
6667
|
-
|
|
6481
|
+
if (!inputVariables || inputVariables.length === 0) {
|
|
6482
|
+
return; // No variables to validate
|
|
6483
|
+
}
|
|
6484
|
+
// Extract variables from template using regex to find {variable} patterns
|
|
6485
|
+
// This regex matches {variable_name} with no whitespace inside braces
|
|
6486
|
+
// Excludes JSON-like patterns with quotes, colons, or whitespace
|
|
6487
|
+
const templateVariableRegex = /\{([^}\s:"']+)\}/g;
|
|
6488
|
+
const foundVariables = new Set();
|
|
6489
|
+
let match;
|
|
6490
|
+
while ((match = templateVariableRegex.exec(text)) !== null) {
|
|
6491
|
+
foundVariables.add(match[1]);
|
|
6492
|
+
}
|
|
6493
|
+
// Check if all required variables are present in template
|
|
6494
|
+
const missingVariables = inputVariables.filter(variable => !foundVariables.has(variable));
|
|
6495
|
+
if (missingVariables.length > 0) {
|
|
6496
|
+
throw new Error(`Prompt template is missing required variables: ${missingVariables.map(v => `{${v}}`).join(', ')}. ` +
|
|
6497
|
+
`Found variables: ${Array.from(foundVariables).map(v => `{${v}}`).join(', ') || 'none'}`);
|
|
6498
|
+
}
|
|
6499
|
+
// Warn about unused variables in template (optional check)
|
|
6500
|
+
const unusedVariables = Array.from(foundVariables).filter(variable => !inputVariables.includes(variable));
|
|
6501
|
+
if (unusedVariables.length > 0) {
|
|
6502
|
+
console.warn(`Prompt template contains undefined variables: ${unusedVariables.map(v => `{${v}}`).join(', ')}`);
|
|
6668
6503
|
}
|
|
6669
|
-
return true;
|
|
6670
6504
|
}
|
|
6671
6505
|
|
|
6672
6506
|
async function editPrompt(options) {
|
|
@@ -6675,7 +6509,15 @@ async function editPrompt(options) {
|
|
|
6675
6509
|
default: options.prompt?.length ? options.prompt : COMMIT_PROMPT.template,
|
|
6676
6510
|
waitForUseInput: false,
|
|
6677
6511
|
postfix: 'Press ENTER to continue',
|
|
6678
|
-
validate: (text) =>
|
|
6512
|
+
validate: (text) => {
|
|
6513
|
+
try {
|
|
6514
|
+
validatePromptTemplate(text, COMMIT_PROMPT.inputVariables);
|
|
6515
|
+
return true;
|
|
6516
|
+
}
|
|
6517
|
+
catch (error) {
|
|
6518
|
+
return error instanceof Error ? error.message : 'Invalid prompt template';
|
|
6519
|
+
}
|
|
6520
|
+
},
|
|
6679
6521
|
});
|
|
6680
6522
|
}
|
|
6681
6523
|
|
|
@@ -6894,7 +6736,9 @@ const handler$4 = async (argv, logger) => {
|
|
|
6894
6736
|
const llm = getLlm(provider, model, config);
|
|
6895
6737
|
const INTERACTIVE = isInteractive(config);
|
|
6896
6738
|
if (INTERACTIVE) {
|
|
6897
|
-
|
|
6739
|
+
if (!config.hideCocoBanner) {
|
|
6740
|
+
logger.log(LOGO);
|
|
6741
|
+
}
|
|
6898
6742
|
}
|
|
6899
6743
|
async function factory() {
|
|
6900
6744
|
const branchName = await getCurrentBranchName({ git });
|
|
@@ -6926,9 +6770,10 @@ const handler$4 = async (argv, logger) => {
|
|
|
6926
6770
|
logger.verbose(`No range, branch, or tag option provided. Defaulting to current branch`, {
|
|
6927
6771
|
color: 'yellow',
|
|
6928
6772
|
});
|
|
6773
|
+
const commits = await getCommitLogCurrentBranch({ git, logger });
|
|
6929
6774
|
return {
|
|
6930
6775
|
branch: branchName,
|
|
6931
|
-
commits
|
|
6776
|
+
commits,
|
|
6932
6777
|
};
|
|
6933
6778
|
}
|
|
6934
6779
|
async function parser({ branch, commits }) {
|
|
@@ -7005,16 +6850,16 @@ var changelog = {
|
|
|
7005
6850
|
|
|
7006
6851
|
const conventionalTypeRegex = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?:/;
|
|
7007
6852
|
// Regular commit message schema with basic validation
|
|
7008
|
-
const CommitMessageResponseSchema =
|
|
7009
|
-
title:
|
|
7010
|
-
body:
|
|
6853
|
+
const CommitMessageResponseSchema = objectType({
|
|
6854
|
+
title: stringType(),
|
|
6855
|
+
body: stringType(),
|
|
7011
6856
|
});
|
|
7012
6857
|
// Conventional commit message schema with strict formatting rules
|
|
7013
|
-
const ConventionalCommitMessageResponseSchema =
|
|
7014
|
-
title:
|
|
6858
|
+
const ConventionalCommitMessageResponseSchema = objectType({
|
|
6859
|
+
title: stringType()
|
|
7015
6860
|
.max(50, "Title must be 50 characters or less")
|
|
7016
6861
|
.refine((title) => conventionalTypeRegex.test(title), "Title must follow Conventional Commits format (e.g., 'feat: add new feature' or 'fix(scope): fix bug')"),
|
|
7017
|
-
body:
|
|
6862
|
+
body: stringType()
|
|
7018
6863
|
// .max(280, "Body must be 280 characters or less"),
|
|
7019
6864
|
});
|
|
7020
6865
|
const command$3 = 'commit';
|
|
@@ -7071,133 +6916,14 @@ const builder$3 = (yargs) => {
|
|
|
7071
6916
|
return yargs.options(options$3).usage(getCommandUsageHeader(command$3));
|
|
7072
6917
|
};
|
|
7073
6918
|
|
|
7074
|
-
|
|
7075
|
-
* Extract the path from a file path string.
|
|
7076
|
-
* @param {string} filePath - The full file path.
|
|
7077
|
-
* @returns {string} The path portion of the file path.
|
|
7078
|
-
*/
|
|
7079
|
-
function getPathFromFilePath(filePath) {
|
|
7080
|
-
return filePath.split('/').slice(0, -1).join('/');
|
|
7081
|
-
}
|
|
7082
|
-
|
|
7083
|
-
async function summarize(documents$1, { chain, textSplitter, options }) {
|
|
7084
|
-
const { returnIntermediateSteps = false } = options || {};
|
|
7085
|
-
const docs = await textSplitter.splitDocuments(documents$1.map((doc) => new documents.Document(doc)));
|
|
7086
|
-
const res = await chain.invoke({
|
|
7087
|
-
input_documents: docs,
|
|
7088
|
-
returnIntermediateSteps,
|
|
7089
|
-
});
|
|
7090
|
-
if (res.error)
|
|
7091
|
-
throw new Error(res.error);
|
|
7092
|
-
return res.text && res.text.trim();
|
|
7093
|
-
}
|
|
6919
|
+
new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
7094
6920
|
|
|
7095
6921
|
/**
|
|
7096
|
-
*
|
|
7097
|
-
* @param {DiffNode} node - The node info to start grouping.
|
|
7098
|
-
* @returns {DirectoryDiff[]} The groups created.
|
|
7099
|
-
*/
|
|
7100
|
-
function createDirectoryDiffs(node) {
|
|
7101
|
-
const groupByPath = {};
|
|
7102
|
-
function traverse(node) {
|
|
7103
|
-
node.diffs.forEach((diff) => {
|
|
7104
|
-
const path = getPathFromFilePath(diff.file);
|
|
7105
|
-
if (!groupByPath[path]) {
|
|
7106
|
-
groupByPath[path] = { diffs: [], path, tokenCount: 0 };
|
|
7107
|
-
}
|
|
7108
|
-
groupByPath[path].diffs.push(diff);
|
|
7109
|
-
groupByPath[path].tokenCount += diff.tokenCount;
|
|
7110
|
-
});
|
|
7111
|
-
node.children.forEach(traverse);
|
|
7112
|
-
}
|
|
7113
|
-
traverse(node);
|
|
7114
|
-
return Object.values(groupByPath);
|
|
7115
|
-
}
|
|
7116
|
-
/**
|
|
7117
|
-
* Summarize a directory diff asynchronously.
|
|
6922
|
+
* Base interface that all chains must implement.
|
|
7118
6923
|
*/
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
pageContent: diff.diff,
|
|
7123
|
-
metadata: {
|
|
7124
|
-
file: diff.file,
|
|
7125
|
-
summary: diff.summary,
|
|
7126
|
-
},
|
|
7127
|
-
})), {
|
|
7128
|
-
chain,
|
|
7129
|
-
textSplitter,
|
|
7130
|
-
options: {
|
|
7131
|
-
returnIntermediateSteps: true,
|
|
7132
|
-
},
|
|
7133
|
-
});
|
|
7134
|
-
const newTokenTotal = tokenizer(directorySummary);
|
|
7135
|
-
return {
|
|
7136
|
-
diffs: directory.diffs,
|
|
7137
|
-
path: directory.path,
|
|
7138
|
-
summary: directorySummary,
|
|
7139
|
-
tokenCount: newTokenTotal,
|
|
7140
|
-
};
|
|
7141
|
-
}
|
|
7142
|
-
catch (error) {
|
|
7143
|
-
console.error(error);
|
|
7144
|
-
return directory;
|
|
7145
|
-
}
|
|
7146
|
-
}
|
|
7147
|
-
const defaultOutputCallback = (group) => {
|
|
7148
|
-
let output = `
|
|
7149
|
-
-------\n* changes in "/${group.path}"\n\n`;
|
|
7150
|
-
if (group.summary) {
|
|
7151
|
-
output += `${group.diffs.map((diff) => ` • ${diff.summary}`).join('\n')}\n\nSummary:\n\n${group.summary}\n\n`;
|
|
7152
|
-
}
|
|
7153
|
-
else {
|
|
7154
|
-
output += `${group.diffs.map((diff) => ` • ${diff.summary}\n\n${diff.diff}`).join('\n\n')}\n\n`;
|
|
7155
|
-
}
|
|
7156
|
-
return output;
|
|
7157
|
-
};
|
|
7158
|
-
async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 2048, textSplitter, chain, handleOutput = defaultOutputCallback, }) {
|
|
7159
|
-
const queue = new pQueue({ concurrency: 8 });
|
|
7160
|
-
logger.startTimer().startSpinner(`Organizing Diffs...`, { color: 'blue' });
|
|
7161
|
-
const directoryDiffs = createDirectoryDiffs(rootDiffNode);
|
|
7162
|
-
// Sort by token count descending
|
|
7163
|
-
directoryDiffs.sort((a, b) => b.tokenCount - a.tokenCount);
|
|
7164
|
-
let totalTokenCount = directoryDiffs.reduce((sum, group) => sum + group.tokenCount, 0);
|
|
7165
|
-
logger.stopSpinner('Diffs Organized').stopTimer();
|
|
7166
|
-
logger.startSpinner(`Consolidating Diffs`, { color: 'blue' });
|
|
7167
|
-
const processingTasks = directoryDiffs.map((group, i) => {
|
|
7168
|
-
return queue.add(async () => {
|
|
7169
|
-
// If the diff token count is already less than the average req, we can skip summarizing.
|
|
7170
|
-
const isLessThanAvgTokenReq = group.tokenCount <= maxTokens / directoryDiffs.length;
|
|
7171
|
-
if (totalTokenCount <= maxTokens || isLessThanAvgTokenReq) {
|
|
7172
|
-
return group;
|
|
7173
|
-
}
|
|
7174
|
-
group = await summarizeDirectoryDiff(group, {
|
|
7175
|
-
chain,
|
|
7176
|
-
textSplitter,
|
|
7177
|
-
tokenizer,
|
|
7178
|
-
});
|
|
7179
|
-
// We need to subtract the old token count and add the new one
|
|
7180
|
-
totalTokenCount = totalTokenCount - directoryDiffs[i].tokenCount + group.tokenCount;
|
|
7181
|
-
directoryDiffs[i] = group;
|
|
7182
|
-
logger
|
|
7183
|
-
.verbose(`\n • Summarized diffs in "/${group.path}" `, { color: 'blue' })
|
|
7184
|
-
.verbose(`\nTotal token count: ${totalTokenCount}`, {
|
|
7185
|
-
color: totalTokenCount > maxTokens ? 'yellow' : 'green',
|
|
7186
|
-
});
|
|
7187
|
-
return group;
|
|
7188
|
-
}, { priority: group.tokenCount });
|
|
7189
|
-
});
|
|
7190
|
-
await Promise.all(processingTasks);
|
|
7191
|
-
logger.stopSpinner(`Summarized Diffs`);
|
|
7192
|
-
return directoryDiffs.map(handleOutput).join('');
|
|
7193
|
-
}
|
|
7194
|
-
|
|
7195
|
-
/**
|
|
7196
|
-
* Base interface that all chains must implement.
|
|
7197
|
-
*/
|
|
7198
|
-
class BaseChain extends base.BaseLangChain {
|
|
7199
|
-
get lc_namespace() {
|
|
7200
|
-
return ["langchain", "chains", this._chainType()];
|
|
6924
|
+
class BaseChain extends base.BaseLangChain {
|
|
6925
|
+
get lc_namespace() {
|
|
6926
|
+
return ["langchain", "chains", this._chainType()];
|
|
7201
6927
|
}
|
|
7202
6928
|
constructor(fields,
|
|
7203
6929
|
/** @deprecated */
|
|
@@ -7638,16 +7364,551 @@ class LLMChain extends BaseChain {
|
|
|
7638
7364
|
prompt: this.prompt.serialize(),
|
|
7639
7365
|
};
|
|
7640
7366
|
}
|
|
7641
|
-
_getNumTokens(text) {
|
|
7642
|
-
return _getLanguageModel(this.llm).getNumTokens(text);
|
|
7367
|
+
_getNumTokens(text) {
|
|
7368
|
+
return _getLanguageModel(this.llm).getNumTokens(text);
|
|
7369
|
+
}
|
|
7370
|
+
}
|
|
7371
|
+
|
|
7372
|
+
var llm_chain = /*#__PURE__*/Object.freeze({
|
|
7373
|
+
__proto__: null,
|
|
7374
|
+
LLMChain: LLMChain
|
|
7375
|
+
});
|
|
7376
|
+
|
|
7377
|
+
const NAIVE_FIX_TEMPLATE = `Instructions:
|
|
7378
|
+
--------------
|
|
7379
|
+
{instructions}
|
|
7380
|
+
--------------
|
|
7381
|
+
Completion:
|
|
7382
|
+
--------------
|
|
7383
|
+
{completion}
|
|
7384
|
+
--------------
|
|
7385
|
+
|
|
7386
|
+
Above, the Completion did not satisfy the constraints given in the Instructions.
|
|
7387
|
+
Error:
|
|
7388
|
+
--------------
|
|
7389
|
+
{error}
|
|
7390
|
+
--------------
|
|
7391
|
+
|
|
7392
|
+
Please try again. Please only respond with an answer that satisfies the constraints laid out in the Instructions:`;
|
|
7393
|
+
const NAIVE_FIX_PROMPT =
|
|
7394
|
+
/* #__PURE__ */ prompts$1.PromptTemplate.fromTemplate(NAIVE_FIX_TEMPLATE);
|
|
7395
|
+
|
|
7396
|
+
function isLLMChain(x) {
|
|
7397
|
+
return (x.prompt !== undefined && x.llm !== undefined);
|
|
7398
|
+
}
|
|
7399
|
+
/**
|
|
7400
|
+
* Class that extends the BaseOutputParser to handle situations where the
|
|
7401
|
+
* initial parsing attempt fails. It contains a retryChain for retrying
|
|
7402
|
+
* the parsing process in case of a failure.
|
|
7403
|
+
*/
|
|
7404
|
+
class OutputFixingParser extends output_parsers.BaseOutputParser {
|
|
7405
|
+
static lc_name() {
|
|
7406
|
+
return "OutputFixingParser";
|
|
7407
|
+
}
|
|
7408
|
+
/**
|
|
7409
|
+
* Static method to create a new instance of OutputFixingParser using a
|
|
7410
|
+
* given language model, parser, and optional fields.
|
|
7411
|
+
* @param llm The language model to be used.
|
|
7412
|
+
* @param parser The parser to be used.
|
|
7413
|
+
* @param fields Optional fields which may contain a prompt.
|
|
7414
|
+
* @returns A new instance of OutputFixingParser.
|
|
7415
|
+
*/
|
|
7416
|
+
static fromLLM(llm, parser, fields) {
|
|
7417
|
+
const prompt = fields?.prompt ?? NAIVE_FIX_PROMPT;
|
|
7418
|
+
const chain = new LLMChain({ llm, prompt });
|
|
7419
|
+
return new OutputFixingParser({ parser, retryChain: chain });
|
|
7420
|
+
}
|
|
7421
|
+
constructor({ parser, retryChain, }) {
|
|
7422
|
+
super(...arguments);
|
|
7423
|
+
Object.defineProperty(this, "lc_namespace", {
|
|
7424
|
+
enumerable: true,
|
|
7425
|
+
configurable: true,
|
|
7426
|
+
writable: true,
|
|
7427
|
+
value: ["langchain", "output_parsers", "fix"]
|
|
7428
|
+
});
|
|
7429
|
+
Object.defineProperty(this, "lc_serializable", {
|
|
7430
|
+
enumerable: true,
|
|
7431
|
+
configurable: true,
|
|
7432
|
+
writable: true,
|
|
7433
|
+
value: true
|
|
7434
|
+
});
|
|
7435
|
+
Object.defineProperty(this, "parser", {
|
|
7436
|
+
enumerable: true,
|
|
7437
|
+
configurable: true,
|
|
7438
|
+
writable: true,
|
|
7439
|
+
value: void 0
|
|
7440
|
+
});
|
|
7441
|
+
Object.defineProperty(this, "retryChain", {
|
|
7442
|
+
enumerable: true,
|
|
7443
|
+
configurable: true,
|
|
7444
|
+
writable: true,
|
|
7445
|
+
value: void 0
|
|
7446
|
+
});
|
|
7447
|
+
this.parser = parser;
|
|
7448
|
+
this.retryChain = retryChain;
|
|
7449
|
+
}
|
|
7450
|
+
/**
|
|
7451
|
+
* Method to parse the completion using the parser. If the initial parsing
|
|
7452
|
+
* fails, it uses the retryChain to attempt to fix the output and retry
|
|
7453
|
+
* the parsing process.
|
|
7454
|
+
* @param completion The completion to be parsed.
|
|
7455
|
+
* @param callbacks Optional callbacks to be used during parsing.
|
|
7456
|
+
* @returns The parsed output.
|
|
7457
|
+
*/
|
|
7458
|
+
async parse(completion, callbacks) {
|
|
7459
|
+
try {
|
|
7460
|
+
return await this.parser.parse(completion, callbacks);
|
|
7461
|
+
}
|
|
7462
|
+
catch (e) {
|
|
7463
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
7464
|
+
if (e instanceof output_parsers.OutputParserException) {
|
|
7465
|
+
const retryInput = {
|
|
7466
|
+
instructions: this.parser.getFormatInstructions(),
|
|
7467
|
+
completion,
|
|
7468
|
+
error: e,
|
|
7469
|
+
};
|
|
7470
|
+
if (isLLMChain(this.retryChain)) {
|
|
7471
|
+
const result = await this.retryChain.call(retryInput, callbacks);
|
|
7472
|
+
const newCompletion = result[this.retryChain.outputKey];
|
|
7473
|
+
return this.parser.parse(newCompletion, callbacks);
|
|
7474
|
+
}
|
|
7475
|
+
else {
|
|
7476
|
+
const result = await this.retryChain.invoke(retryInput, {
|
|
7477
|
+
callbacks,
|
|
7478
|
+
});
|
|
7479
|
+
return result;
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7482
|
+
throw e;
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
/**
|
|
7486
|
+
* Method to get the format instructions for the parser.
|
|
7487
|
+
* @returns The format instructions for the parser.
|
|
7488
|
+
*/
|
|
7489
|
+
getFormatInstructions() {
|
|
7490
|
+
return this.parser.getFormatInstructions();
|
|
7491
|
+
}
|
|
7492
|
+
}
|
|
7493
|
+
|
|
7494
|
+
/**
|
|
7495
|
+
* Creates a parser with built-in retry logic for schema-based generation
|
|
7496
|
+
* @param schema - Zod schema for the expected output structure
|
|
7497
|
+
* @param llm - LLM instance for retry attempts
|
|
7498
|
+
* @param options - Configuration options for retry behavior
|
|
7499
|
+
* @returns OutputFixingParser configured with retry logic
|
|
7500
|
+
* @throws LangChainExecutionError if parser creation fails
|
|
7501
|
+
*/
|
|
7502
|
+
function createSchemaParser(schema, llm, options = {}) {
|
|
7503
|
+
// Validate required parameters
|
|
7504
|
+
validateRequired(schema, 'schema', 'createSchemaParser');
|
|
7505
|
+
validateRequired(llm, 'llm', 'createSchemaParser');
|
|
7506
|
+
validateRequired(options, 'options', 'createSchemaParser');
|
|
7507
|
+
// Validate schema is actually a Zod schema
|
|
7508
|
+
if (typeof schema.parse !== 'function') {
|
|
7509
|
+
throw new LangChainExecutionError('createSchemaParser: Schema must be a valid Zod schema with a parse method', { schemaType: typeof schema, hasParseMethod: typeof schema.parse });
|
|
7510
|
+
}
|
|
7511
|
+
// Validate options structure
|
|
7512
|
+
if (typeof options !== 'object' || Array.isArray(options)) {
|
|
7513
|
+
throw new LangChainExecutionError('createSchemaParser: Options must be a non-array object', { options, type: typeof options, isArray: Array.isArray(options) });
|
|
7514
|
+
}
|
|
7515
|
+
const { retryTemplate } = options;
|
|
7516
|
+
// Validate retryTemplate if provided
|
|
7517
|
+
if (retryTemplate !== undefined && typeof retryTemplate !== 'string') {
|
|
7518
|
+
throw new LangChainExecutionError('createSchemaParser: retryTemplate must be a string when provided', { retryTemplate, type: typeof retryTemplate });
|
|
7519
|
+
}
|
|
7520
|
+
try {
|
|
7521
|
+
const baseParser = new output_parsers.StructuredOutputParser(schema);
|
|
7522
|
+
const defaultRetryTemplate = `The following text failed to parse as valid JSON. Please convert it into a valid JSON object that matches the required schema.
|
|
7523
|
+
|
|
7524
|
+
## Text to fix:
|
|
7525
|
+
{completion}
|
|
7526
|
+
|
|
7527
|
+
## Instructions:
|
|
7528
|
+
{instructions}
|
|
7529
|
+
|
|
7530
|
+
You must return ONLY valid JSON that matches the schema exactly. Do not include any additional text, explanations, or markdown formatting:`;
|
|
7531
|
+
const retryPromptTemplate = new prompts$1.PromptTemplate({
|
|
7532
|
+
template: retryTemplate || defaultRetryTemplate,
|
|
7533
|
+
inputVariables: ['completion', 'instructions'],
|
|
7534
|
+
});
|
|
7535
|
+
const retryChain = retryPromptTemplate.pipe(llm).pipe(baseParser);
|
|
7536
|
+
return new OutputFixingParser({
|
|
7537
|
+
parser: baseParser,
|
|
7538
|
+
retryChain: retryChain,
|
|
7539
|
+
});
|
|
7540
|
+
}
|
|
7541
|
+
catch (error) {
|
|
7542
|
+
handleLangChainError(error, 'createSchemaParser: Failed to create schema parser', {
|
|
7543
|
+
schemaName: schema.constructor.name,
|
|
7544
|
+
llmType: llm.constructor.name,
|
|
7545
|
+
hasRetryTemplate: !!retryTemplate
|
|
7546
|
+
});
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7549
|
+
|
|
7550
|
+
/**
|
|
7551
|
+
* High-level function that combines chain execution with schema-based parsing
|
|
7552
|
+
* Includes automatic retry logic and graceful degradation
|
|
7553
|
+
* @param schema - Zod schema for the expected output structure
|
|
7554
|
+
* @param llm - LLM instance
|
|
7555
|
+
* @param prompt - Prompt template
|
|
7556
|
+
* @param variables - Variables for the prompt
|
|
7557
|
+
* @param options - Configuration options
|
|
7558
|
+
* @returns Parsed result matching the schema type
|
|
7559
|
+
*/
|
|
7560
|
+
async function executeChainWithSchema(schema, llm, prompt, variables, options = {}) {
|
|
7561
|
+
const { retryOptions = { maxAttempts: 3 }, fallbackParser, onFallback, ...parserOptions } = options;
|
|
7562
|
+
const parser = createSchemaParser(schema, llm, parserOptions);
|
|
7563
|
+
// Define the operation to retry
|
|
7564
|
+
const operation = async () => {
|
|
7565
|
+
const result = await executeChain({
|
|
7566
|
+
llm,
|
|
7567
|
+
prompt,
|
|
7568
|
+
variables,
|
|
7569
|
+
parser,
|
|
7570
|
+
});
|
|
7571
|
+
return result;
|
|
7572
|
+
};
|
|
7573
|
+
try {
|
|
7574
|
+
// Use the general retry utility
|
|
7575
|
+
return await withRetry(operation, retryOptions);
|
|
7576
|
+
}
|
|
7577
|
+
catch (error) {
|
|
7578
|
+
// If all retries failed and we have a fallback parser, use it
|
|
7579
|
+
if (fallbackParser) {
|
|
7580
|
+
if (onFallback) {
|
|
7581
|
+
onFallback();
|
|
7582
|
+
}
|
|
7583
|
+
// Generate without structured parsing as fallback
|
|
7584
|
+
const fallbackResult = await executeChain({
|
|
7585
|
+
llm,
|
|
7586
|
+
prompt,
|
|
7587
|
+
variables,
|
|
7588
|
+
parser: new output_parsers.StringOutputParser(),
|
|
7589
|
+
});
|
|
7590
|
+
const fallbackText = typeof fallbackResult === 'string' ? fallbackResult : String(fallbackResult);
|
|
7591
|
+
return fallbackParser(fallbackText);
|
|
7592
|
+
}
|
|
7593
|
+
// No fallback available, re-throw the error
|
|
7594
|
+
throw error;
|
|
7595
|
+
}
|
|
7596
|
+
}
|
|
7597
|
+
|
|
7598
|
+
/**
|
|
7599
|
+
* Extract the path from a file path string.
|
|
7600
|
+
* @param {string} filePath - The full file path.
|
|
7601
|
+
* @returns {string} The path portion of the file path.
|
|
7602
|
+
*/
|
|
7603
|
+
function getPathFromFilePath(filePath) {
|
|
7604
|
+
return filePath.split('/').slice(0, -1).join('/');
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7607
|
+
async function summarize(documents$1, { chain, textSplitter, options }) {
|
|
7608
|
+
const { returnIntermediateSteps = false } = options || {};
|
|
7609
|
+
const docs = await textSplitter.splitDocuments(documents$1.map((doc) => new documents.Document(doc)));
|
|
7610
|
+
const res = await chain.invoke({
|
|
7611
|
+
input_documents: docs,
|
|
7612
|
+
returnIntermediateSteps,
|
|
7613
|
+
});
|
|
7614
|
+
if (res.error)
|
|
7615
|
+
throw new Error(res.error);
|
|
7616
|
+
return res.text && res.text.trim();
|
|
7617
|
+
}
|
|
7618
|
+
|
|
7619
|
+
/**
|
|
7620
|
+
* Create groups from a given node info.
|
|
7621
|
+
* @param {DiffNode} node - The node info to start grouping.
|
|
7622
|
+
* @returns {DirectoryDiff[]} The groups created.
|
|
7623
|
+
*/
|
|
7624
|
+
function createDirectoryDiffs(node) {
|
|
7625
|
+
const groupByPath = {};
|
|
7626
|
+
function traverse(node) {
|
|
7627
|
+
node.diffs.forEach((diff) => {
|
|
7628
|
+
const path = getPathFromFilePath(diff.file);
|
|
7629
|
+
if (!groupByPath[path]) {
|
|
7630
|
+
groupByPath[path] = { diffs: [], path, tokenCount: 0 };
|
|
7631
|
+
}
|
|
7632
|
+
groupByPath[path].diffs.push(diff);
|
|
7633
|
+
groupByPath[path].tokenCount += diff.tokenCount;
|
|
7634
|
+
});
|
|
7635
|
+
node.children.forEach(traverse);
|
|
7636
|
+
}
|
|
7637
|
+
traverse(node);
|
|
7638
|
+
return Object.values(groupByPath);
|
|
7639
|
+
}
|
|
7640
|
+
/**
|
|
7641
|
+
* Summarize a directory diff asynchronously.
|
|
7642
|
+
*/
|
|
7643
|
+
async function summarizeDirectoryDiff(directory, { chain, textSplitter, tokenizer }) {
|
|
7644
|
+
try {
|
|
7645
|
+
const directorySummary = await summarize(directory.diffs.map((diff) => ({
|
|
7646
|
+
pageContent: diff.diff,
|
|
7647
|
+
metadata: {
|
|
7648
|
+
file: diff.file,
|
|
7649
|
+
summary: diff.summary,
|
|
7650
|
+
},
|
|
7651
|
+
})), {
|
|
7652
|
+
chain,
|
|
7653
|
+
textSplitter,
|
|
7654
|
+
options: {
|
|
7655
|
+
returnIntermediateSteps: true,
|
|
7656
|
+
},
|
|
7657
|
+
});
|
|
7658
|
+
const newTokenTotal = tokenizer(directorySummary);
|
|
7659
|
+
return {
|
|
7660
|
+
diffs: directory.diffs,
|
|
7661
|
+
path: directory.path,
|
|
7662
|
+
summary: directorySummary,
|
|
7663
|
+
tokenCount: newTokenTotal,
|
|
7664
|
+
};
|
|
7665
|
+
}
|
|
7666
|
+
catch (error) {
|
|
7667
|
+
console.error(error);
|
|
7668
|
+
return directory;
|
|
7669
|
+
}
|
|
7670
|
+
}
|
|
7671
|
+
const defaultOutputCallback = (group) => {
|
|
7672
|
+
let output = `
|
|
7673
|
+
-------\n* changes in "/${group.path}"\n\n`;
|
|
7674
|
+
if (group.summary) {
|
|
7675
|
+
output += `${group.diffs.map((diff) => ` • ${diff.summary}`).join('\n')}\n\nSummary:\n\n${group.summary}\n\n`;
|
|
7676
|
+
}
|
|
7677
|
+
else {
|
|
7678
|
+
output += `${group.diffs.map((diff) => ` • ${diff.summary}\n\n${diff.diff}`).join('\n\n')}\n\n`;
|
|
7679
|
+
}
|
|
7680
|
+
return output;
|
|
7681
|
+
};
|
|
7682
|
+
async function summarizeDiffs(rootDiffNode, { tokenizer, logger, maxTokens = 2048, textSplitter, chain, handleOutput = defaultOutputCallback, }) {
|
|
7683
|
+
const queue = new pQueue({ concurrency: 8 });
|
|
7684
|
+
logger.startTimer().startSpinner(`Organizing Diffs...`, { color: 'blue' });
|
|
7685
|
+
const directoryDiffs = createDirectoryDiffs(rootDiffNode);
|
|
7686
|
+
// Sort by token count descending
|
|
7687
|
+
directoryDiffs.sort((a, b) => b.tokenCount - a.tokenCount);
|
|
7688
|
+
let totalTokenCount = directoryDiffs.reduce((sum, group) => sum + group.tokenCount, 0);
|
|
7689
|
+
logger.stopSpinner('Diffs Organized').stopTimer();
|
|
7690
|
+
logger.startSpinner(`Consolidating Diffs`, { color: 'blue' });
|
|
7691
|
+
const processingTasks = directoryDiffs.map((group, i) => {
|
|
7692
|
+
return queue.add(async () => {
|
|
7693
|
+
// If the diff token count is already less than the average req, we can skip summarizing.
|
|
7694
|
+
const isLessThanAvgTokenReq = group.tokenCount <= maxTokens / directoryDiffs.length;
|
|
7695
|
+
if (totalTokenCount <= maxTokens || isLessThanAvgTokenReq) {
|
|
7696
|
+
return group;
|
|
7697
|
+
}
|
|
7698
|
+
group = await summarizeDirectoryDiff(group, {
|
|
7699
|
+
chain,
|
|
7700
|
+
textSplitter,
|
|
7701
|
+
tokenizer,
|
|
7702
|
+
});
|
|
7703
|
+
// We need to subtract the old token count and add the new one
|
|
7704
|
+
totalTokenCount = totalTokenCount - directoryDiffs[i].tokenCount + group.tokenCount;
|
|
7705
|
+
directoryDiffs[i] = group;
|
|
7706
|
+
logger
|
|
7707
|
+
.verbose(`\n • Summarized diffs in "/${group.path}" `, { color: 'blue' })
|
|
7708
|
+
.verbose(`\nTotal token count: ${totalTokenCount}`, {
|
|
7709
|
+
color: totalTokenCount > maxTokens ? 'yellow' : 'green',
|
|
7710
|
+
});
|
|
7711
|
+
return group;
|
|
7712
|
+
}, { priority: group.tokenCount });
|
|
7713
|
+
});
|
|
7714
|
+
await Promise.all(processingTasks);
|
|
7715
|
+
logger.stopSpinner(`Summarized Diffs`);
|
|
7716
|
+
return directoryDiffs.map(handleOutput).join('');
|
|
7717
|
+
}
|
|
7718
|
+
|
|
7719
|
+
/**
|
|
7720
|
+
* Asynchronously collect diffs for a given node and its children.
|
|
7721
|
+
*/
|
|
7722
|
+
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
7723
|
+
// Collect diffs for the files of the current node
|
|
7724
|
+
const diffPromises = node.files.map(async (nodeFile) => {
|
|
7725
|
+
const diff = await getFileDiff(nodeFile);
|
|
7726
|
+
const tokenCount = tokenizer(diff);
|
|
7727
|
+
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
7728
|
+
color: 'magenta',
|
|
7729
|
+
});
|
|
7730
|
+
return {
|
|
7731
|
+
file: nodeFile.filePath,
|
|
7732
|
+
summary: nodeFile.summary,
|
|
7733
|
+
diff,
|
|
7734
|
+
tokenCount,
|
|
7735
|
+
};
|
|
7736
|
+
});
|
|
7737
|
+
// Collect diffs for the children of the current node
|
|
7738
|
+
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
7739
|
+
const [diffs, children] = await Promise.all([
|
|
7740
|
+
Promise.all(diffPromises),
|
|
7741
|
+
Promise.all(childrenPromises),
|
|
7742
|
+
]);
|
|
7743
|
+
return {
|
|
7744
|
+
path: node.getPath(),
|
|
7745
|
+
diffs,
|
|
7746
|
+
children,
|
|
7747
|
+
};
|
|
7748
|
+
}
|
|
7749
|
+
|
|
7750
|
+
class DiffTreeNode {
|
|
7751
|
+
constructor(path) {
|
|
7752
|
+
this.path = [];
|
|
7753
|
+
this.files = [];
|
|
7754
|
+
this.children = new Map();
|
|
7755
|
+
if (path)
|
|
7756
|
+
this.path = path;
|
|
7757
|
+
}
|
|
7758
|
+
addFile(file) {
|
|
7759
|
+
this.files.push(file);
|
|
7760
|
+
}
|
|
7761
|
+
addChild(part, node) {
|
|
7762
|
+
this.children.set(part, node);
|
|
7763
|
+
}
|
|
7764
|
+
getChild(part) {
|
|
7765
|
+
return this.children.get(part);
|
|
7766
|
+
}
|
|
7767
|
+
getPath() {
|
|
7768
|
+
return this.path.join('/');
|
|
7769
|
+
}
|
|
7770
|
+
print(indentation = 0) {
|
|
7771
|
+
const indent = ' '.repeat(indentation);
|
|
7772
|
+
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
7773
|
+
if (this.files.length > 0) {
|
|
7774
|
+
output += `${indent} Files:\n`;
|
|
7775
|
+
for (const file of this.files) {
|
|
7776
|
+
output += `${indent} - ${file.summary}\n`;
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7779
|
+
if (this.children.size > 0) {
|
|
7780
|
+
output += `${indent} Children:\n`;
|
|
7781
|
+
for (const [, child] of this.children) {
|
|
7782
|
+
output += child.print(indentation + 4);
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
return output;
|
|
7786
|
+
}
|
|
7787
|
+
}
|
|
7788
|
+
const createDiffTree = (changes) => {
|
|
7789
|
+
const root = new DiffTreeNode();
|
|
7790
|
+
for (const change of changes) {
|
|
7791
|
+
let currentParent = root;
|
|
7792
|
+
const parts = change.filePath.split('/');
|
|
7793
|
+
parts.pop();
|
|
7794
|
+
for (const part of parts) {
|
|
7795
|
+
let childNode = currentParent.getChild(part);
|
|
7796
|
+
if (!childNode) {
|
|
7797
|
+
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
7798
|
+
currentParent.addChild(part, childNode);
|
|
7799
|
+
}
|
|
7800
|
+
currentParent = childNode;
|
|
7801
|
+
}
|
|
7802
|
+
// Create a NodeFile object and add it to the parent
|
|
7803
|
+
currentParent.addFile({
|
|
7804
|
+
filePath: change.filePath,
|
|
7805
|
+
oldFilePath: change.oldFilePath,
|
|
7806
|
+
summary: change.summary,
|
|
7807
|
+
status: change.status,
|
|
7808
|
+
});
|
|
7809
|
+
}
|
|
7810
|
+
return root;
|
|
7811
|
+
};
|
|
7812
|
+
|
|
7813
|
+
/**
|
|
7814
|
+
* Parses the default file diff for a given nodeFile.
|
|
7815
|
+
*
|
|
7816
|
+
* @param nodeFile - The file change object.
|
|
7817
|
+
* @param commit - The commit to diff against. Defaults to '--staged'.
|
|
7818
|
+
* @param git - The SimpleGit instance.
|
|
7819
|
+
* @returns A Promise that resolves to the file diff as a string.
|
|
7820
|
+
*/
|
|
7821
|
+
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
7822
|
+
if (commit === '--staged') {
|
|
7823
|
+
return await git.diff(['--staged', nodeFile.filePath]);
|
|
7824
|
+
}
|
|
7825
|
+
else if (commit === '--unstaged') {
|
|
7826
|
+
return await git.diff([nodeFile.filePath]);
|
|
7827
|
+
}
|
|
7828
|
+
else if (commit === '--untracked') {
|
|
7829
|
+
// For untracked files, read the file content directly from the filesystem
|
|
7830
|
+
try {
|
|
7831
|
+
const fileContent = await fs.promises.readFile(nodeFile.filePath, 'utf-8');
|
|
7832
|
+
return fileContent;
|
|
7833
|
+
}
|
|
7834
|
+
catch (error) {
|
|
7835
|
+
throw new Error(`Error reading untracked file: ${error?.message || 'Unknown error'}`);
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
return await git.diff([commit, nodeFile.filePath]);
|
|
7839
|
+
}
|
|
7840
|
+
/**
|
|
7841
|
+
* Parses the diff for a renamed file.
|
|
7842
|
+
*
|
|
7843
|
+
* @param nodeFile - The file change object.
|
|
7844
|
+
* @param commit - The commit hash or '--staged'.
|
|
7845
|
+
* @param git - The SimpleGit instance.
|
|
7846
|
+
* @param logger - The logger instance.
|
|
7847
|
+
* @returns A Promise that resolves to the diff string.
|
|
7848
|
+
*/
|
|
7849
|
+
async function parseRenamedFileDiff(nodeFile, commit, git, logger) {
|
|
7850
|
+
let result = '';
|
|
7851
|
+
const oldFilePath = nodeFile?.oldFilePath || nodeFile.filePath;
|
|
7852
|
+
let previousCommitHash = 'HEAD';
|
|
7853
|
+
let newCommitHash = '';
|
|
7854
|
+
if (commit !== '--staged') {
|
|
7855
|
+
try {
|
|
7856
|
+
previousCommitHash = await git.revparse([`${commit}~1`]);
|
|
7857
|
+
}
|
|
7858
|
+
catch (err) {
|
|
7859
|
+
logger.verbose(`Error getting previous commit hash for ${nodeFile.filePath}`, {
|
|
7860
|
+
color: 'red',
|
|
7861
|
+
});
|
|
7862
|
+
}
|
|
7863
|
+
newCommitHash = commit;
|
|
7864
|
+
}
|
|
7865
|
+
try {
|
|
7866
|
+
const [previousContent, newContent] = await Promise.all([
|
|
7867
|
+
git.show([`${previousCommitHash}:${oldFilePath}`]),
|
|
7868
|
+
git.show([`${newCommitHash}:${nodeFile.filePath}`]),
|
|
7869
|
+
]);
|
|
7870
|
+
if (previousContent !== newContent) {
|
|
7871
|
+
result = diff.createTwoFilesPatch(oldFilePath, nodeFile.filePath, previousContent, newContent, '', '', {
|
|
7872
|
+
context: 3,
|
|
7873
|
+
});
|
|
7874
|
+
// remove the first 4 lines of the patch (they contain the old and new file names)
|
|
7875
|
+
result = result.split('\n').slice(4).join('\n');
|
|
7876
|
+
}
|
|
7877
|
+
else {
|
|
7878
|
+
result = 'File contents are unchanged.';
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7881
|
+
catch (err) {
|
|
7882
|
+
logger.verbose(`Error comparing file contents for ${nodeFile.filePath}`, { color: 'red' });
|
|
7883
|
+
result = 'Error comparing file contents.';
|
|
7884
|
+
}
|
|
7885
|
+
return result;
|
|
7886
|
+
}
|
|
7887
|
+
/**
|
|
7888
|
+
* Retrieves the diff for a given file change in a specific commit.
|
|
7889
|
+
* If the file is deleted, it returns a message indicating that the file has been deleted.
|
|
7890
|
+
* If the file is renamed, it parses the renamed file diff and returns it.
|
|
7891
|
+
* Otherwise, it retrieves the default diff from the index and returns it.
|
|
7892
|
+
*
|
|
7893
|
+
* @param nodeFile - The file change object.
|
|
7894
|
+
* @param commit - The commit hash.
|
|
7895
|
+
* @param git - The SimpleGit instance.
|
|
7896
|
+
* @param logger - The logger instance.
|
|
7897
|
+
* @returns A promise that resolves to the diff as a string.
|
|
7898
|
+
*/
|
|
7899
|
+
async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
7900
|
+
if (nodeFile.status === 'deleted') {
|
|
7901
|
+
return 'This file has been deleted.';
|
|
7902
|
+
}
|
|
7903
|
+
if (nodeFile.status === 'renamed' && nodeFile.oldFilePath) {
|
|
7904
|
+
const renamedDiff = await parseRenamedFileDiff(nodeFile, commit, git, logger);
|
|
7905
|
+
return renamedDiff;
|
|
7643
7906
|
}
|
|
7907
|
+
// If not deleted or renamed, get the diff from the index
|
|
7908
|
+
const defaultDiff = await parseDefaultFileDiff(nodeFile, commit, git);
|
|
7909
|
+
return defaultDiff;
|
|
7644
7910
|
}
|
|
7645
7911
|
|
|
7646
|
-
var llm_chain = /*#__PURE__*/Object.freeze({
|
|
7647
|
-
__proto__: null,
|
|
7648
|
-
LLMChain: LLMChain
|
|
7649
|
-
});
|
|
7650
|
-
|
|
7651
7912
|
/* eslint-disable spaced-comment */
|
|
7652
7913
|
const API_URL_RAW_PROMPT_TEMPLATE = `You are given the below API Documentation:
|
|
7653
7914
|
{api_docs}
|
|
@@ -9396,8 +9657,6 @@ const loadSummarizationChain = (llm, params = { type: "map_reduce" }) => {
|
|
|
9396
9657
|
throw new Error(`Invalid _type: ${params.type}`);
|
|
9397
9658
|
};
|
|
9398
9659
|
|
|
9399
|
-
new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
|
|
9400
|
-
|
|
9401
9660
|
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
|
|
9402
9661
|
function isNothing(subject) {
|
|
9403
9662
|
return (typeof subject === 'undefined') || (subject === null);
|
|
@@ -10422,225 +10681,12 @@ for (var i = 0; i < 256; i++) {
|
|
|
10422
10681
|
simpleEscapeMap[i] = simpleEscapeSequence(i);
|
|
10423
10682
|
}
|
|
10424
10683
|
|
|
10425
|
-
/**
|
|
10426
|
-
* Get Summarization Chain
|
|
10427
|
-
* @param model
|
|
10428
|
-
* @param options
|
|
10429
|
-
* @returns
|
|
10430
|
-
*/
|
|
10431
|
-
function getSummarizationChain(model, options = { type: 'map_reduce' }) {
|
|
10432
|
-
return loadSummarizationChain(model, options);
|
|
10433
|
-
}
|
|
10434
|
-
|
|
10435
|
-
/**
|
|
10436
|
-
* Get Recursive Character Text Splitter
|
|
10437
|
-
*
|
|
10438
|
-
* @param options
|
|
10439
|
-
* @returns
|
|
10440
|
-
*/
|
|
10441
|
-
function getTextSplitter(options = {}) {
|
|
10442
|
-
return new RecursiveCharacterTextSplitter(options);
|
|
10443
|
-
}
|
|
10444
|
-
|
|
10445
|
-
/**
|
|
10446
|
-
* Asynchronously collect diffs for a given node and its children.
|
|
10447
|
-
*/
|
|
10448
|
-
async function collectDiffs(node, getFileDiff, tokenizer, logger) {
|
|
10449
|
-
// Collect diffs for the files of the current node
|
|
10450
|
-
const diffPromises = node.files.map(async (nodeFile) => {
|
|
10451
|
-
const diff = await getFileDiff(nodeFile);
|
|
10452
|
-
const tokenCount = tokenizer(diff);
|
|
10453
|
-
logger.verbose(`Collected diff for ${nodeFile.filePath} (${tokenCount} tokens)`, {
|
|
10454
|
-
color: 'magenta',
|
|
10455
|
-
});
|
|
10456
|
-
return {
|
|
10457
|
-
file: nodeFile.filePath,
|
|
10458
|
-
summary: nodeFile.summary,
|
|
10459
|
-
diff,
|
|
10460
|
-
tokenCount,
|
|
10461
|
-
};
|
|
10462
|
-
});
|
|
10463
|
-
// Collect diffs for the children of the current node
|
|
10464
|
-
const childrenPromises = Array.from(node.children.values()).map(async (child) => collectDiffs(child, getFileDiff, tokenizer, logger));
|
|
10465
|
-
const [diffs, children] = await Promise.all([
|
|
10466
|
-
Promise.all(diffPromises),
|
|
10467
|
-
Promise.all(childrenPromises),
|
|
10468
|
-
]);
|
|
10469
|
-
return {
|
|
10470
|
-
path: node.getPath(),
|
|
10471
|
-
diffs,
|
|
10472
|
-
children,
|
|
10473
|
-
};
|
|
10474
|
-
}
|
|
10475
|
-
|
|
10476
|
-
class DiffTreeNode {
|
|
10477
|
-
constructor(path) {
|
|
10478
|
-
this.path = [];
|
|
10479
|
-
this.files = [];
|
|
10480
|
-
this.children = new Map();
|
|
10481
|
-
if (path)
|
|
10482
|
-
this.path = path;
|
|
10483
|
-
}
|
|
10484
|
-
addFile(file) {
|
|
10485
|
-
this.files.push(file);
|
|
10486
|
-
}
|
|
10487
|
-
addChild(part, node) {
|
|
10488
|
-
this.children.set(part, node);
|
|
10489
|
-
}
|
|
10490
|
-
getChild(part) {
|
|
10491
|
-
return this.children.get(part);
|
|
10492
|
-
}
|
|
10493
|
-
getPath() {
|
|
10494
|
-
return this.path.join('/');
|
|
10495
|
-
}
|
|
10496
|
-
print(indentation = 0) {
|
|
10497
|
-
const indent = ' '.repeat(indentation);
|
|
10498
|
-
let output = `${indent}- Path: ${this.getPath()}\n`;
|
|
10499
|
-
if (this.files.length > 0) {
|
|
10500
|
-
output += `${indent} Files:\n`;
|
|
10501
|
-
for (const file of this.files) {
|
|
10502
|
-
output += `${indent} - ${file.summary}\n`;
|
|
10503
|
-
}
|
|
10504
|
-
}
|
|
10505
|
-
if (this.children.size > 0) {
|
|
10506
|
-
output += `${indent} Children:\n`;
|
|
10507
|
-
for (const [, child] of this.children) {
|
|
10508
|
-
output += child.print(indentation + 4);
|
|
10509
|
-
}
|
|
10510
|
-
}
|
|
10511
|
-
return output;
|
|
10512
|
-
}
|
|
10513
|
-
}
|
|
10514
|
-
const createDiffTree = (changes) => {
|
|
10515
|
-
const root = new DiffTreeNode();
|
|
10516
|
-
for (const change of changes) {
|
|
10517
|
-
let currentParent = root;
|
|
10518
|
-
const parts = change.filePath.split('/');
|
|
10519
|
-
parts.pop();
|
|
10520
|
-
for (const part of parts) {
|
|
10521
|
-
let childNode = currentParent.getChild(part);
|
|
10522
|
-
if (!childNode) {
|
|
10523
|
-
childNode = new DiffTreeNode([...currentParent.path, part]);
|
|
10524
|
-
currentParent.addChild(part, childNode);
|
|
10525
|
-
}
|
|
10526
|
-
currentParent = childNode;
|
|
10527
|
-
}
|
|
10528
|
-
// Create a NodeFile object and add it to the parent
|
|
10529
|
-
currentParent.addFile({
|
|
10530
|
-
filePath: change.filePath,
|
|
10531
|
-
oldFilePath: change.oldFilePath,
|
|
10532
|
-
summary: change.summary,
|
|
10533
|
-
status: change.status,
|
|
10534
|
-
});
|
|
10535
|
-
}
|
|
10536
|
-
return root;
|
|
10537
|
-
};
|
|
10538
|
-
|
|
10539
|
-
/**
|
|
10540
|
-
* Parses the default file diff for a given nodeFile.
|
|
10541
|
-
*
|
|
10542
|
-
* @param nodeFile - The file change object.
|
|
10543
|
-
* @param commit - The commit to diff against. Defaults to '--staged'.
|
|
10544
|
-
* @param git - The SimpleGit instance.
|
|
10545
|
-
* @returns A Promise that resolves to the file diff as a string.
|
|
10546
|
-
*/
|
|
10547
|
-
async function parseDefaultFileDiff(nodeFile, commit = '--staged', git) {
|
|
10548
|
-
if (commit === '--staged') {
|
|
10549
|
-
return await git.diff(['--staged', nodeFile.filePath]);
|
|
10550
|
-
}
|
|
10551
|
-
else if (commit === '--unstaged') {
|
|
10552
|
-
return await git.diff([nodeFile.filePath]);
|
|
10553
|
-
}
|
|
10554
|
-
else if (commit === '--untracked') {
|
|
10555
|
-
// For untracked files, read the file content directly from the filesystem
|
|
10556
|
-
try {
|
|
10557
|
-
const fileContent = await fs.promises.readFile(nodeFile.filePath, 'utf-8');
|
|
10558
|
-
return fileContent;
|
|
10559
|
-
}
|
|
10560
|
-
catch (error) {
|
|
10561
|
-
throw new Error(`Error reading untracked file: ${error?.message || 'Unknown error'}`);
|
|
10562
|
-
}
|
|
10563
|
-
}
|
|
10564
|
-
return await git.diff([commit, nodeFile.filePath]);
|
|
10565
|
-
}
|
|
10566
|
-
/**
|
|
10567
|
-
* Parses the diff for a renamed file.
|
|
10568
|
-
*
|
|
10569
|
-
* @param nodeFile - The file change object.
|
|
10570
|
-
* @param commit - The commit hash or '--staged'.
|
|
10571
|
-
* @param git - The SimpleGit instance.
|
|
10572
|
-
* @param logger - The logger instance.
|
|
10573
|
-
* @returns A Promise that resolves to the diff string.
|
|
10574
|
-
*/
|
|
10575
|
-
async function parseRenamedFileDiff(nodeFile, commit, git, logger) {
|
|
10576
|
-
let result = '';
|
|
10577
|
-
const oldFilePath = nodeFile?.oldFilePath || nodeFile.filePath;
|
|
10578
|
-
let previousCommitHash = 'HEAD';
|
|
10579
|
-
let newCommitHash = '';
|
|
10580
|
-
if (commit !== '--staged') {
|
|
10581
|
-
try {
|
|
10582
|
-
previousCommitHash = await git.revparse([`${commit}~1`]);
|
|
10583
|
-
}
|
|
10584
|
-
catch (err) {
|
|
10585
|
-
logger.verbose(`Error getting previous commit hash for ${nodeFile.filePath}`, {
|
|
10586
|
-
color: 'red',
|
|
10587
|
-
});
|
|
10588
|
-
}
|
|
10589
|
-
newCommitHash = commit;
|
|
10590
|
-
}
|
|
10591
|
-
try {
|
|
10592
|
-
const [previousContent, newContent] = await Promise.all([
|
|
10593
|
-
git.show([`${previousCommitHash}:${oldFilePath}`]),
|
|
10594
|
-
git.show([`${newCommitHash}:${nodeFile.filePath}`]),
|
|
10595
|
-
]);
|
|
10596
|
-
if (previousContent !== newContent) {
|
|
10597
|
-
result = diff.createTwoFilesPatch(oldFilePath, nodeFile.filePath, previousContent, newContent, '', '', {
|
|
10598
|
-
context: 3,
|
|
10599
|
-
});
|
|
10600
|
-
// remove the first 4 lines of the patch (they contain the old and new file names)
|
|
10601
|
-
result = result.split('\n').slice(4).join('\n');
|
|
10602
|
-
}
|
|
10603
|
-
else {
|
|
10604
|
-
result = 'File contents are unchanged.';
|
|
10605
|
-
}
|
|
10606
|
-
}
|
|
10607
|
-
catch (err) {
|
|
10608
|
-
logger.verbose(`Error comparing file contents for ${nodeFile.filePath}`, { color: 'red' });
|
|
10609
|
-
result = 'Error comparing file contents.';
|
|
10610
|
-
}
|
|
10611
|
-
return result;
|
|
10612
|
-
}
|
|
10613
|
-
/**
|
|
10614
|
-
* Retrieves the diff for a given file change in a specific commit.
|
|
10615
|
-
* If the file is deleted, it returns a message indicating that the file has been deleted.
|
|
10616
|
-
* If the file is renamed, it parses the renamed file diff and returns it.
|
|
10617
|
-
* Otherwise, it retrieves the default diff from the index and returns it.
|
|
10618
|
-
*
|
|
10619
|
-
* @param nodeFile - The file change object.
|
|
10620
|
-
* @param commit - The commit hash.
|
|
10621
|
-
* @param git - The SimpleGit instance.
|
|
10622
|
-
* @param logger - The logger instance.
|
|
10623
|
-
* @returns A promise that resolves to the diff as a string.
|
|
10624
|
-
*/
|
|
10625
|
-
async function getDiff(nodeFile, commit, { git, logger, }) {
|
|
10626
|
-
if (nodeFile.status === 'deleted') {
|
|
10627
|
-
return 'This file has been deleted.';
|
|
10628
|
-
}
|
|
10629
|
-
if (nodeFile.status === 'renamed' && nodeFile.oldFilePath) {
|
|
10630
|
-
const renamedDiff = await parseRenamedFileDiff(nodeFile, commit, git, logger);
|
|
10631
|
-
return renamedDiff;
|
|
10632
|
-
}
|
|
10633
|
-
// If not deleted or renamed, get the diff from the index
|
|
10634
|
-
const defaultDiff = await parseDefaultFileDiff(nodeFile, commit, git);
|
|
10635
|
-
return defaultDiff;
|
|
10636
|
-
}
|
|
10637
|
-
|
|
10638
10684
|
// Max tokens for GPT-3 is 4096
|
|
10639
10685
|
// const MAX_TOKENS_PER_SUMMARY = 4096
|
|
10640
10686
|
const MAX_TOKENS_PER_SUMMARY = 12288;
|
|
10641
10687
|
async function fileChangeParser({ changes, commit, options: { tokenizer, git, llm: model, logger }, }) {
|
|
10642
|
-
const textSplitter =
|
|
10643
|
-
const summarizationChain =
|
|
10688
|
+
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 10000, chunkOverlap: 250 });
|
|
10689
|
+
const summarizationChain = loadSummarizationChain(model, {
|
|
10644
10690
|
type: 'map_reduce',
|
|
10645
10691
|
combineMapPrompt: SUMMARIZE_PROMPT,
|
|
10646
10692
|
combinePrompt: SUMMARIZE_PROMPT,
|
|
@@ -10911,11 +10957,18 @@ const handler$3 = async (argv, logger) => {
|
|
|
10911
10957
|
const llm = getLlm(provider, model, config);
|
|
10912
10958
|
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
10913
10959
|
if (INTERACTIVE) {
|
|
10914
|
-
|
|
10960
|
+
if (!config.hideCocoBanner) {
|
|
10961
|
+
logger.log(LOGO);
|
|
10962
|
+
}
|
|
10915
10963
|
}
|
|
10916
10964
|
else {
|
|
10917
10965
|
logger.setConfig({ silent: true });
|
|
10918
10966
|
}
|
|
10967
|
+
if (config.service.provider === 'ollama') {
|
|
10968
|
+
logger.verbose('⚠️ Ollama models may not strictly adhere to the output format instructions.', {
|
|
10969
|
+
color: 'yellow',
|
|
10970
|
+
});
|
|
10971
|
+
}
|
|
10919
10972
|
async function factory() {
|
|
10920
10973
|
const changes = await getChanges({
|
|
10921
10974
|
git,
|
|
@@ -10962,7 +11015,8 @@ const handler$3 = async (argv, logger) => {
|
|
|
10962
11015
|
const schema = useConventional
|
|
10963
11016
|
? ConventionalCommitMessageResponseSchema
|
|
10964
11017
|
: CommitMessageResponseSchema;
|
|
10965
|
-
const
|
|
11018
|
+
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:
|
|
11019
|
+
{{ body: string, title: string }}`;
|
|
10966
11020
|
// Use conventional commit prompt if enabled
|
|
10967
11021
|
const promptTemplate = useConventional ? CONVENTIONAL_COMMIT_PROMPT : COMMIT_PROMPT;
|
|
10968
11022
|
const prompt = getPrompt({
|
|
@@ -10970,7 +11024,6 @@ const handler$3 = async (argv, logger) => {
|
|
|
10970
11024
|
variables: promptTemplate.inputVariables,
|
|
10971
11025
|
fallback: promptTemplate,
|
|
10972
11026
|
});
|
|
10973
|
-
const formatInstructions = "Respond with a valid JSON object, containing two fields: 'title' and 'body', both strings.";
|
|
10974
11027
|
// Get additional context if provided
|
|
10975
11028
|
let additional_context = '';
|
|
10976
11029
|
if (argv.additional) {
|
|
@@ -11003,11 +11056,25 @@ const handler$3 = async (argv, logger) => {
|
|
|
11003
11056
|
commit_history: commit_history,
|
|
11004
11057
|
branch_name_context: branchNameContext,
|
|
11005
11058
|
};
|
|
11006
|
-
const
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11059
|
+
const maxAttempts = config.service.provider === 'ollama' && 'maxParsingAttempts' in config.service
|
|
11060
|
+
? config.service.maxParsingAttempts || 3
|
|
11061
|
+
: 3;
|
|
11062
|
+
const commitMsg = await executeChainWithSchema(schema, llm, prompt, variables, {
|
|
11063
|
+
retryOptions: {
|
|
11064
|
+
maxAttempts,
|
|
11065
|
+
onRetry: (attempt, error) => {
|
|
11066
|
+
logger.verbose(`Failed to parse commit message (attempt ${attempt}/${maxAttempts}): ${error.message}`, { color: 'yellow' });
|
|
11067
|
+
},
|
|
11068
|
+
},
|
|
11069
|
+
fallbackParser: (text) => ({
|
|
11070
|
+
title: text.split('\n')[0] || 'Auto-generated commit',
|
|
11071
|
+
body: text.split('\n').slice(1).join('\n') || 'Generated commit message',
|
|
11072
|
+
}),
|
|
11073
|
+
onFallback: () => {
|
|
11074
|
+
logger.verbose('Max retry attempts reached. Falling back to simple text output.', {
|
|
11075
|
+
color: 'red',
|
|
11076
|
+
});
|
|
11077
|
+
},
|
|
11011
11078
|
});
|
|
11012
11079
|
// Construct the full commit message
|
|
11013
11080
|
const appendedText = argv.append ? `\n\n${argv.append}` : '';
|
|
@@ -11225,12 +11292,15 @@ const OPEN_AI_MODELS = [
|
|
|
11225
11292
|
'gpt-3.5-turbo',
|
|
11226
11293
|
];
|
|
11227
11294
|
const ANTHROPIC_MODELS = [
|
|
11295
|
+
'claude-sonnet-4-0',
|
|
11296
|
+
'claude-3-7-sonnet-latest',
|
|
11297
|
+
'claude-3-5-haiku-latest',
|
|
11298
|
+
'claude-3-5-sonnet-latest',
|
|
11299
|
+
'claude-3-5-sonnet-20241022',
|
|
11228
11300
|
'claude-3-5-sonnet-20240620',
|
|
11229
11301
|
'claude-3-opus-20240229',
|
|
11230
11302
|
'claude-3-sonnet-20240229',
|
|
11231
11303
|
'claude-3-haiku-20240307',
|
|
11232
|
-
'claude-2.1',
|
|
11233
|
-
'claude-2.0',
|
|
11234
11304
|
];
|
|
11235
11305
|
|
|
11236
11306
|
const questions = {
|
|
@@ -11364,6 +11434,32 @@ const questions = {
|
|
|
11364
11434
|
});
|
|
11365
11435
|
return parseFloat(temperature);
|
|
11366
11436
|
},
|
|
11437
|
+
inputOllamaEndpoint: async () => {
|
|
11438
|
+
return await prompts.input({
|
|
11439
|
+
message: 'Ollama endpoint (e.g., http://localhost:11434):',
|
|
11440
|
+
default: 'http://localhost:11434',
|
|
11441
|
+
});
|
|
11442
|
+
},
|
|
11443
|
+
inputRequestTimeout: async () => {
|
|
11444
|
+
const timeout = await prompts.input({
|
|
11445
|
+
message: 'Request timeout in milliseconds:',
|
|
11446
|
+
default: '30000',
|
|
11447
|
+
});
|
|
11448
|
+
return parseInt(timeout);
|
|
11449
|
+
},
|
|
11450
|
+
inputRequestMaxRetries: async () => {
|
|
11451
|
+
const maxRetries = await prompts.input({
|
|
11452
|
+
message: 'Maximum number of request retries:',
|
|
11453
|
+
default: '3',
|
|
11454
|
+
});
|
|
11455
|
+
return parseInt(maxRetries);
|
|
11456
|
+
},
|
|
11457
|
+
inputServiceFields: async () => {
|
|
11458
|
+
return await prompts.editor({
|
|
11459
|
+
message: 'Enter additional service fields as a JSON string (optional):',
|
|
11460
|
+
default: '{}',
|
|
11461
|
+
});
|
|
11462
|
+
},
|
|
11367
11463
|
selectDefaultGitBranch: async () => (await prompts.input({
|
|
11368
11464
|
message: 'default branch for the repository:',
|
|
11369
11465
|
default: 'main',
|
|
@@ -11457,6 +11553,29 @@ const handler$2 = async (argv, logger) => {
|
|
|
11457
11553
|
tokenLimit: await questions.inputTokenLimit(),
|
|
11458
11554
|
};
|
|
11459
11555
|
config.verbose = await questions.enableVerboseMode();
|
|
11556
|
+
if (llmProvider === 'ollama') {
|
|
11557
|
+
config.service.endpoint = await questions.inputOllamaEndpoint();
|
|
11558
|
+
}
|
|
11559
|
+
config.service.requestOptions = {
|
|
11560
|
+
timeout: await questions.inputRequestTimeout(),
|
|
11561
|
+
maxRetries: await questions.inputRequestMaxRetries(),
|
|
11562
|
+
};
|
|
11563
|
+
const promptForServiceFields = await prompts.confirm({
|
|
11564
|
+
message: 'would you like to configure additional service fields (advanced)?',
|
|
11565
|
+
default: false,
|
|
11566
|
+
});
|
|
11567
|
+
if (promptForServiceFields) {
|
|
11568
|
+
const fieldsJson = await questions.inputServiceFields();
|
|
11569
|
+
try {
|
|
11570
|
+
config.service.fields = JSON.parse(fieldsJson);
|
|
11571
|
+
}
|
|
11572
|
+
catch (e) {
|
|
11573
|
+
logger.log('Invalid JSON for service fields. Skipping.', { color: 'red' });
|
|
11574
|
+
logger.verbose(`Error parsing service fields: ${e.message}`, {
|
|
11575
|
+
color: 'red',
|
|
11576
|
+
});
|
|
11577
|
+
}
|
|
11578
|
+
}
|
|
11460
11579
|
const promptForIgnores = await prompts.confirm({
|
|
11461
11580
|
message: 'would you like to configure ignored files and extensions?',
|
|
11462
11581
|
default: false,
|
|
@@ -11522,9 +11641,9 @@ var init = {
|
|
|
11522
11641
|
options: options$2,
|
|
11523
11642
|
};
|
|
11524
11643
|
|
|
11525
|
-
const RecapLlmResponseSchema =
|
|
11526
|
-
title:
|
|
11527
|
-
summary:
|
|
11644
|
+
const RecapLlmResponseSchema = objectType({
|
|
11645
|
+
title: stringType().optional(),
|
|
11646
|
+
summary: stringType().optional(),
|
|
11528
11647
|
});
|
|
11529
11648
|
const command$1 = 'recap';
|
|
11530
11649
|
/**
|
|
@@ -11598,7 +11717,9 @@ const handler$1 = async (argv, logger) => {
|
|
|
11598
11717
|
const llm = getLlm(provider, model, config);
|
|
11599
11718
|
const INTERACTIVE = argv.interactive || isInteractive(config);
|
|
11600
11719
|
if (INTERACTIVE) {
|
|
11601
|
-
|
|
11720
|
+
if (!config.hideCocoBanner) {
|
|
11721
|
+
logger.log(LOGO);
|
|
11722
|
+
}
|
|
11602
11723
|
}
|
|
11603
11724
|
else {
|
|
11604
11725
|
logger.setConfig({ silent: true });
|
|
@@ -11747,26 +11868,26 @@ var recap = {
|
|
|
11747
11868
|
options: options$1,
|
|
11748
11869
|
};
|
|
11749
11870
|
|
|
11750
|
-
const ReviewFeedbackItemSchema =
|
|
11751
|
-
title:
|
|
11752
|
-
summary:
|
|
11753
|
-
severity:
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11871
|
+
const ReviewFeedbackItemSchema = objectType({
|
|
11872
|
+
title: stringType(),
|
|
11873
|
+
summary: stringType(),
|
|
11874
|
+
severity: unionType([
|
|
11875
|
+
literalType(1),
|
|
11876
|
+
literalType(2),
|
|
11877
|
+
literalType(3),
|
|
11878
|
+
literalType(4),
|
|
11879
|
+
literalType(5),
|
|
11880
|
+
literalType(6),
|
|
11881
|
+
literalType(7),
|
|
11882
|
+
literalType(8),
|
|
11883
|
+
literalType(9),
|
|
11884
|
+
literalType(10),
|
|
11764
11885
|
]),
|
|
11765
|
-
category:
|
|
11766
|
-
filePath:
|
|
11886
|
+
category: stringType(),
|
|
11887
|
+
filePath: stringType(),
|
|
11767
11888
|
});
|
|
11768
11889
|
// Array schema for review feedback items
|
|
11769
|
-
const ReviewFeedbackItemArraySchema =
|
|
11890
|
+
const ReviewFeedbackItemArraySchema = arrayType(ReviewFeedbackItemSchema);
|
|
11770
11891
|
const command = 'review';
|
|
11771
11892
|
/**
|
|
11772
11893
|
* Command line options via yargs
|
|
@@ -14036,7 +14157,9 @@ const handler = async (argv, logger) => {
|
|
|
14036
14157
|
const llm = getLlm(provider, model, config);
|
|
14037
14158
|
const INTERACTIVE = isInteractive(config);
|
|
14038
14159
|
if (INTERACTIVE) {
|
|
14039
|
-
|
|
14160
|
+
if (!config.hideCocoBanner) {
|
|
14161
|
+
logger.log(LOGO);
|
|
14162
|
+
}
|
|
14040
14163
|
}
|
|
14041
14164
|
async function factory() {
|
|
14042
14165
|
if (argv.branch) {
|