@eldrforge/core 0.1.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.js +546 -81
- package/dist/index.js.map +1 -1
- package/dist/src/errors.d.ts +82 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/logging.d.ts.map +1 -1
- package/dist/src/transactionLog.d.ts +53 -0
- package/dist/src/transactionLog.d.ts.map +1 -0
- package/dist/src/types.d.ts +51 -7
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/util/progressTracker.d.ts +54 -0
- package/dist/src/util/progressTracker.d.ts.map +1 -0
- package/dist/src/util/validation.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExitError, createStorage, incrementPatchVersion, validateVersionString, convertToReleaseVersion, incrementPrereleaseVersion, UserCancellationError, CommandError } from '@eldrforge/shared';
|
|
2
2
|
export { calculateTargetVersion, convertToReleaseVersion, deepMerge, incrementMajorVersion, incrementMinorVersion, incrementPatchVersion, incrementPrereleaseVersion, stringifyJSON, validateVersionString } from '@eldrforge/shared';
|
|
3
3
|
import winston from 'winston';
|
|
4
|
+
import { Writable } from 'stream';
|
|
4
5
|
import * as fs from 'fs';
|
|
5
6
|
import { statSync } from 'fs';
|
|
6
7
|
import * as path from 'path';
|
|
@@ -419,8 +420,11 @@ const ensureDebugDirectory = ()=>{
|
|
|
419
420
|
});
|
|
420
421
|
debugDirectoryEnsured = true;
|
|
421
422
|
} catch (error) {
|
|
422
|
-
//
|
|
423
|
-
|
|
423
|
+
// Only log to console if not in MCP server mode (MCP mode requires clean stdout)
|
|
424
|
+
if (process.env.KODRDRIV_MCP_SERVER !== 'true') {
|
|
425
|
+
// eslint-disable-next-line no-console
|
|
426
|
+
console.error(`Failed to create debug directory ${debugDir}:`, error);
|
|
427
|
+
}
|
|
424
428
|
}
|
|
425
429
|
};
|
|
426
430
|
const generateDebugLogFilename = ()=>{
|
|
@@ -430,69 +434,66 @@ const generateDebugLogFilename = ()=>{
|
|
|
430
434
|
};
|
|
431
435
|
const createTransports = (level)=>{
|
|
432
436
|
const transports = [];
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
437
|
+
// When running as MCP server, NEVER add console transports as they interfere with the protocol
|
|
438
|
+
// All output must go through log capture mechanism instead
|
|
439
|
+
const isMcpServer = process.env.KODRDRIV_MCP_SERVER === 'true';
|
|
440
|
+
if (isMcpServer) {
|
|
441
|
+
// In MCP mode, add a silent Memory transport to prevent winston from logging transport errors
|
|
442
|
+
// Winston complains when there are no transports, so we add a silent one
|
|
443
|
+
// The log capture transport will be added separately via installLogCapture
|
|
444
|
+
// Use a no-op stream that discards all output
|
|
445
|
+
const silentStream = new Writable({
|
|
446
|
+
write (_chunk, _encoding, callback) {
|
|
447
|
+
// Silent - discard all output, log capture handles actual logging
|
|
448
|
+
callback();
|
|
449
|
+
},
|
|
450
|
+
// Suppress any errors from the stream itself
|
|
451
|
+
destroy: function(_err, callback) {
|
|
452
|
+
callback();
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
// Suppress winston transport errors by catching them
|
|
456
|
+
const silentTransport = new winston.transports.Stream({
|
|
457
|
+
stream: silentStream,
|
|
458
|
+
silent: true
|
|
459
|
+
});
|
|
460
|
+
// Override error handling on the transport to prevent winston from logging to stderr
|
|
461
|
+
silentTransport.on('error', ()=>{
|
|
462
|
+
// Silently ignore transport errors - don't output to stderr
|
|
463
|
+
});
|
|
464
|
+
transports.push(silentTransport);
|
|
446
465
|
} else {
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
// For info level messages, use simpler format without timestamp
|
|
452
|
-
if (level.includes('info')) {
|
|
466
|
+
// Add console transport for info level and above (only when NOT in MCP mode)
|
|
467
|
+
if (level === 'info') {
|
|
468
|
+
transports.push(new winston.transports.Console({
|
|
469
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ level, message, dryRun })=>{
|
|
453
470
|
const dryRunPrefix = dryRun ? '🔍 DRY RUN: ' : '';
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const filteredMeta = Object.keys(meta).reduce((acc, key)=>{
|
|
458
|
-
if (![
|
|
459
|
-
'level',
|
|
460
|
-
'message',
|
|
461
|
-
'timestamp',
|
|
462
|
-
'dryRun',
|
|
463
|
-
'service',
|
|
464
|
-
'splat',
|
|
465
|
-
'Symbol(level)',
|
|
466
|
-
'Symbol(message)'
|
|
467
|
-
].includes(key)) {
|
|
468
|
-
acc[key] = meta[key];
|
|
471
|
+
// For info level messages, don't show the level prefix
|
|
472
|
+
if (level.includes('info')) {
|
|
473
|
+
return `${dryRunPrefix}${String(message)}`;
|
|
469
474
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS_MILLISECONDS
|
|
486
|
-
}), winston.format.errors({
|
|
487
|
-
stack: true
|
|
488
|
-
}), winston.format.splat(), winston.format.printf(({ timestamp, level, message, service, ...meta })=>{
|
|
489
|
-
// Filter out winston internal metadata and properly format remaining meta
|
|
475
|
+
// For warn, error, etc., show the level prefix
|
|
476
|
+
return `${level}: ${dryRunPrefix}${String(message)}`;
|
|
477
|
+
}))
|
|
478
|
+
}));
|
|
479
|
+
} else {
|
|
480
|
+
// For debug/verbose levels, add console transport that shows info and above
|
|
481
|
+
transports.push(new winston.transports.Console({
|
|
482
|
+
level: 'info',
|
|
483
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ timestamp, level, message, dryRun, ...meta })=>{
|
|
484
|
+
// For info level messages, use simpler format without timestamp
|
|
485
|
+
if (level.includes('info')) {
|
|
486
|
+
const dryRunPrefix = dryRun ? '🔍 DRY RUN: ' : '';
|
|
487
|
+
return `${dryRunPrefix}${String(message)}`;
|
|
488
|
+
}
|
|
489
|
+
// Filter out winston internal metadata
|
|
490
490
|
const filteredMeta = Object.keys(meta).reduce((acc, key)=>{
|
|
491
|
-
// Skip internal winston fields
|
|
492
491
|
if (![
|
|
493
492
|
'level',
|
|
494
493
|
'message',
|
|
495
494
|
'timestamp',
|
|
495
|
+
'dryRun',
|
|
496
|
+
'service',
|
|
496
497
|
'splat',
|
|
497
498
|
'Symbol(level)',
|
|
498
499
|
'Symbol(message)'
|
|
@@ -502,12 +503,45 @@ const createTransports = (level)=>{
|
|
|
502
503
|
return acc;
|
|
503
504
|
}, {});
|
|
504
505
|
const metaStr = Object.keys(filteredMeta).length ? ` ${JSON.stringify(filteredMeta, null, 2)}` : '';
|
|
505
|
-
const
|
|
506
|
-
return `${timestamp}
|
|
506
|
+
const dryRunPrefix = dryRun ? '🔍 DRY RUN: ' : '';
|
|
507
|
+
return `${timestamp} ${level}: ${dryRunPrefix}${String(message)}${metaStr}`;
|
|
507
508
|
}))
|
|
508
509
|
}));
|
|
509
510
|
}
|
|
510
511
|
}
|
|
512
|
+
// Add file transport for debug levels (debug and silly)
|
|
513
|
+
if (level === 'debug' || level === 'silly') {
|
|
514
|
+
ensureDebugDirectory();
|
|
515
|
+
const debugLogPath = path__default.join(DEFAULT_OUTPUT_DIRECTORY, 'debug', generateDebugLogFilename());
|
|
516
|
+
transports.push(new winston.transports.File({
|
|
517
|
+
filename: debugLogPath,
|
|
518
|
+
level: 'debug',
|
|
519
|
+
format: winston.format.combine(winston.format.timestamp({
|
|
520
|
+
format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS_MILLISECONDS
|
|
521
|
+
}), winston.format.errors({
|
|
522
|
+
stack: true
|
|
523
|
+
}), winston.format.splat(), winston.format.printf(({ timestamp, level, message, service, ...meta })=>{
|
|
524
|
+
// Filter out winston internal metadata and properly format remaining meta
|
|
525
|
+
const filteredMeta = Object.keys(meta).reduce((acc, key)=>{
|
|
526
|
+
// Skip internal winston fields
|
|
527
|
+
if (![
|
|
528
|
+
'level',
|
|
529
|
+
'message',
|
|
530
|
+
'timestamp',
|
|
531
|
+
'splat',
|
|
532
|
+
'Symbol(level)',
|
|
533
|
+
'Symbol(message)'
|
|
534
|
+
].includes(key)) {
|
|
535
|
+
acc[key] = meta[key];
|
|
536
|
+
}
|
|
537
|
+
return acc;
|
|
538
|
+
}, {});
|
|
539
|
+
const metaStr = Object.keys(filteredMeta).length ? ` ${JSON.stringify(filteredMeta, null, 2)}` : '';
|
|
540
|
+
const serviceStr = service ? ` [${service}]` : '';
|
|
541
|
+
return `${timestamp}${serviceStr} ${level}: ${message}${metaStr}`;
|
|
542
|
+
}))
|
|
543
|
+
}));
|
|
544
|
+
}
|
|
511
545
|
return transports;
|
|
512
546
|
};
|
|
513
547
|
const createFormat = (level)=>{
|
|
@@ -557,17 +591,30 @@ const logger = winston.createLogger({
|
|
|
557
591
|
defaultMeta: {
|
|
558
592
|
service: PROGRAM_NAME
|
|
559
593
|
},
|
|
560
|
-
transports: createTransports('info')
|
|
594
|
+
transports: createTransports('info'),
|
|
595
|
+
// Suppress winston's own error handling in MCP mode to prevent stderr pollution
|
|
596
|
+
exceptionHandlers: process.env.KODRDRIV_MCP_SERVER === 'true' ? [] : undefined,
|
|
597
|
+
rejectionHandlers: process.env.KODRDRIV_MCP_SERVER === 'true' ? [] : undefined,
|
|
598
|
+
// Prevent winston from logging transport errors to stderr
|
|
599
|
+
handleExceptions: false,
|
|
600
|
+
handleRejections: false
|
|
561
601
|
});
|
|
562
602
|
const setLogLevel = (level)=>{
|
|
563
603
|
// Reconfigure the existing logger instead of creating a new one
|
|
604
|
+
const isMcpServer = process.env.KODRDRIV_MCP_SERVER === 'true';
|
|
564
605
|
logger.configure({
|
|
565
606
|
level,
|
|
566
607
|
format: createFormat(level),
|
|
567
608
|
defaultMeta: {
|
|
568
609
|
service: PROGRAM_NAME
|
|
569
610
|
},
|
|
570
|
-
transports: createTransports(level)
|
|
611
|
+
transports: createTransports(level),
|
|
612
|
+
// Suppress winston's own error handling in MCP mode to prevent stderr pollution
|
|
613
|
+
exceptionHandlers: isMcpServer ? [] : undefined,
|
|
614
|
+
rejectionHandlers: isMcpServer ? [] : undefined,
|
|
615
|
+
// Prevent winston from logging transport errors to stderr
|
|
616
|
+
handleExceptions: false,
|
|
617
|
+
handleRejections: false
|
|
571
618
|
});
|
|
572
619
|
};
|
|
573
620
|
const getLogger = ()=>logger;
|
|
@@ -1840,7 +1887,7 @@ const interactive = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.definePropert
|
|
|
1840
1887
|
return Boolean(config.enabled !== false && hasFilters);
|
|
1841
1888
|
}
|
|
1842
1889
|
|
|
1843
|
-
function _define_property$
|
|
1890
|
+
function _define_property$4(obj, key, value) {
|
|
1844
1891
|
if (key in obj) {
|
|
1845
1892
|
Object.defineProperty(obj, key, {
|
|
1846
1893
|
value: value,
|
|
@@ -1945,13 +1992,13 @@ function _define_property$1(obj, key, value) {
|
|
|
1945
1992
|
return this.lockAcquired;
|
|
1946
1993
|
}
|
|
1947
1994
|
constructor(lockPath){
|
|
1948
|
-
_define_property$
|
|
1949
|
-
_define_property$
|
|
1950
|
-
_define_property$
|
|
1951
|
-
_define_property$
|
|
1952
|
-
_define_property$
|
|
1953
|
-
_define_property$
|
|
1954
|
-
_define_property$
|
|
1995
|
+
_define_property$4(this, "lockPath", void 0);
|
|
1996
|
+
_define_property$4(this, "lockAcquired", false);
|
|
1997
|
+
_define_property$4(this, "maxRetries", 100); // Maximum number of lock attempts
|
|
1998
|
+
_define_property$4(this, "retryDelay", 100); // Initial retry delay in ms
|
|
1999
|
+
_define_property$4(this, "maxRetryDelay", 2000); // Maximum retry delay in ms
|
|
2000
|
+
_define_property$4(this, "lockTimeout", 30000); // Consider lock stale after 30 seconds
|
|
2001
|
+
_define_property$4(this, "logger", getLogger());
|
|
1955
2002
|
this.lockPath = lockPath;
|
|
1956
2003
|
}
|
|
1957
2004
|
}
|
|
@@ -2067,13 +2114,13 @@ function _define_property$1(obj, key, value) {
|
|
|
2067
2114
|
this.locks.clear();
|
|
2068
2115
|
}
|
|
2069
2116
|
constructor(){
|
|
2070
|
-
_define_property$
|
|
2071
|
-
_define_property$
|
|
2072
|
-
_define_property$
|
|
2117
|
+
_define_property$4(this, "locks", new Map());
|
|
2118
|
+
_define_property$4(this, "logger", getLogger());
|
|
2119
|
+
_define_property$4(this, "cleanupRegistered", false);
|
|
2073
2120
|
}
|
|
2074
2121
|
}
|
|
2075
2122
|
|
|
2076
|
-
function _define_property(obj, key, value) {
|
|
2123
|
+
function _define_property$3(obj, key, value) {
|
|
2077
2124
|
if (key in obj) {
|
|
2078
2125
|
Object.defineProperty(obj, key, {
|
|
2079
2126
|
value: value,
|
|
@@ -2114,8 +2161,8 @@ function _define_property(obj, key, value) {
|
|
|
2114
2161
|
this.lockManager.destroy();
|
|
2115
2162
|
}
|
|
2116
2163
|
constructor(){
|
|
2117
|
-
_define_property(this, "lockManager", void 0);
|
|
2118
|
-
_define_property(this, "logger", getLogger());
|
|
2164
|
+
_define_property$3(this, "lockManager", void 0);
|
|
2165
|
+
_define_property$3(this, "logger", getLogger());
|
|
2119
2166
|
this.lockManager = new RepositoryFileLockManager();
|
|
2120
2167
|
}
|
|
2121
2168
|
}
|
|
@@ -2383,9 +2430,11 @@ let globalGitMutexManager = null;
|
|
|
2383
2430
|
// Truncate if too long
|
|
2384
2431
|
if (sanitized.length > maxLength) {
|
|
2385
2432
|
const truncated = sanitized.substring(0, maxLength - 3) + '...';
|
|
2386
|
-
// Log truncation for debugging
|
|
2387
|
-
|
|
2388
|
-
|
|
2433
|
+
// Log truncation for debugging (only if not in MCP server mode)
|
|
2434
|
+
if (process.env.KODRDRIV_MCP_SERVER !== 'true') {
|
|
2435
|
+
// eslint-disable-next-line no-console
|
|
2436
|
+
console.warn(`Direction truncated from ${sanitized.length} to ${truncated.length} characters`);
|
|
2437
|
+
}
|
|
2389
2438
|
return truncated;
|
|
2390
2439
|
}
|
|
2391
2440
|
return sanitized;
|
|
@@ -2465,6 +2514,104 @@ let globalGitMutexManager = null;
|
|
|
2465
2514
|
warnings
|
|
2466
2515
|
});
|
|
2467
2516
|
|
|
2517
|
+
/**
|
|
2518
|
+
* Progress tracking for long-running operations
|
|
2519
|
+
*
|
|
2520
|
+
* Provides structured progress updates for MCP integrations
|
|
2521
|
+
*/ function _define_property$2(obj, key, value) {
|
|
2522
|
+
if (key in obj) {
|
|
2523
|
+
Object.defineProperty(obj, key, {
|
|
2524
|
+
value: value,
|
|
2525
|
+
enumerable: true,
|
|
2526
|
+
configurable: true,
|
|
2527
|
+
writable: true
|
|
2528
|
+
});
|
|
2529
|
+
} else {
|
|
2530
|
+
obj[key] = value;
|
|
2531
|
+
}
|
|
2532
|
+
return obj;
|
|
2533
|
+
}
|
|
2534
|
+
class ProgressTracker {
|
|
2535
|
+
/**
|
|
2536
|
+
* Set the total number of items
|
|
2537
|
+
*/ setTotal(total) {
|
|
2538
|
+
this.total = total;
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* Start a new step
|
|
2542
|
+
*/ startStep(stepName) {
|
|
2543
|
+
this.currentStep = stepName;
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Complete the current step
|
|
2547
|
+
*/ completeStep() {
|
|
2548
|
+
if (this.currentStep) {
|
|
2549
|
+
this.completedSteps.push(this.currentStep);
|
|
2550
|
+
this.current++;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
/**
|
|
2554
|
+
* Set remaining packages
|
|
2555
|
+
*/ setRemainingPackages(packages) {
|
|
2556
|
+
this.remainingPackages = packages;
|
|
2557
|
+
}
|
|
2558
|
+
/**
|
|
2559
|
+
* Get current progress
|
|
2560
|
+
*/ getProgress() {
|
|
2561
|
+
return {
|
|
2562
|
+
current: this.current,
|
|
2563
|
+
total: this.total,
|
|
2564
|
+
currentStep: this.currentStep,
|
|
2565
|
+
completedSteps: [
|
|
2566
|
+
...this.completedSteps
|
|
2567
|
+
],
|
|
2568
|
+
remainingPackages: [
|
|
2569
|
+
...this.remainingPackages
|
|
2570
|
+
],
|
|
2571
|
+
percentage: this.total > 0 ? Math.round(this.current / this.total * 100) : 0
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* Reset progress
|
|
2576
|
+
*/ reset() {
|
|
2577
|
+
this.completedSteps = [];
|
|
2578
|
+
this.currentStep = '';
|
|
2579
|
+
this.current = 0;
|
|
2580
|
+
this.remainingPackages = [];
|
|
2581
|
+
}
|
|
2582
|
+
/**
|
|
2583
|
+
* Create a progress update for a package execution
|
|
2584
|
+
*/ static forPackage(packageName, index, total, completedPackages, remainingPackages) {
|
|
2585
|
+
return {
|
|
2586
|
+
current: index,
|
|
2587
|
+
total: total,
|
|
2588
|
+
currentStep: `Processing: ${packageName}`,
|
|
2589
|
+
completedSteps: completedPackages.map((pkg)=>`Completed: ${pkg}`),
|
|
2590
|
+
remainingPackages: remainingPackages,
|
|
2591
|
+
percentage: total > 0 ? Math.round(index / total * 100) : 0
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
/**
|
|
2595
|
+
* Create a progress update for a build phase
|
|
2596
|
+
*/ static forPhase(phase, completedPhases, totalPhases) {
|
|
2597
|
+
return {
|
|
2598
|
+
current: completedPhases.length,
|
|
2599
|
+
total: totalPhases,
|
|
2600
|
+
currentStep: phase,
|
|
2601
|
+
completedSteps: completedPhases,
|
|
2602
|
+
percentage: totalPhases > 0 ? Math.round(completedPhases.length / totalPhases * 100) : 0
|
|
2603
|
+
};
|
|
2604
|
+
}
|
|
2605
|
+
constructor(total = 0){
|
|
2606
|
+
_define_property$2(this, "completedSteps", []);
|
|
2607
|
+
_define_property$2(this, "currentStep", '');
|
|
2608
|
+
_define_property$2(this, "current", 0);
|
|
2609
|
+
_define_property$2(this, "total", 0);
|
|
2610
|
+
_define_property$2(this, "remainingPackages", []);
|
|
2611
|
+
this.total = total;
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2468
2615
|
const ConfigSchema = z.object({
|
|
2469
2616
|
dryRun: z.boolean().optional(),
|
|
2470
2617
|
verbose: z.boolean().optional(),
|
|
@@ -2542,6 +2689,7 @@ const ConfigSchema = z.object({
|
|
|
2542
2689
|
noMilestones: z.boolean().optional(),
|
|
2543
2690
|
fromMain: z.boolean().optional(),
|
|
2544
2691
|
currentBranch: z.string().optional(),
|
|
2692
|
+
version: z.string().optional(),
|
|
2545
2693
|
// Agentic options (always enabled)
|
|
2546
2694
|
maxAgenticIterations: z.number().optional(),
|
|
2547
2695
|
selfReflection: z.boolean().optional()
|
|
@@ -2594,6 +2742,9 @@ const ConfigSchema = z.object({
|
|
|
2594
2742
|
]).optional(),
|
|
2595
2743
|
openaiMaxOutputTokens: z.number().optional()
|
|
2596
2744
|
}).optional(),
|
|
2745
|
+
precommit: z.object({
|
|
2746
|
+
fix: z.boolean().optional()
|
|
2747
|
+
}).optional(),
|
|
2597
2748
|
publish: z.object({
|
|
2598
2749
|
mergeMethod: z.enum([
|
|
2599
2750
|
'merge',
|
|
@@ -2623,7 +2774,8 @@ const ConfigSchema = z.object({
|
|
|
2623
2774
|
skipPrePublishMerge: z.boolean().optional(),
|
|
2624
2775
|
updateDeps: z.string().optional(),
|
|
2625
2776
|
agenticPublish: z.boolean().optional(),
|
|
2626
|
-
agenticPublishMaxIterations: z.number().optional()
|
|
2777
|
+
agenticPublishMaxIterations: z.number().optional(),
|
|
2778
|
+
skipLinkCleanup: z.boolean().optional()
|
|
2627
2779
|
}).optional(),
|
|
2628
2780
|
branches: z.record(z.string(), z.object({
|
|
2629
2781
|
targetBranch: z.string().optional(),
|
|
@@ -2669,6 +2821,7 @@ const ConfigSchema = z.object({
|
|
|
2669
2821
|
packageArgument: z.string().optional(),
|
|
2670
2822
|
cleanNodeModules: z.boolean().optional(),
|
|
2671
2823
|
externals: z.array(z.string()).optional(),
|
|
2824
|
+
fix: z.boolean().optional(),
|
|
2672
2825
|
// Parallel execution options
|
|
2673
2826
|
parallel: z.boolean().optional(),
|
|
2674
2827
|
maxConcurrency: z.number().optional(),
|
|
@@ -2704,7 +2857,8 @@ const ConfigSchema = z.object({
|
|
|
2704
2857
|
resetPackage: z.string().optional(),
|
|
2705
2858
|
statusParallel: z.boolean().optional(),
|
|
2706
2859
|
auditBranches: z.boolean().optional(),
|
|
2707
|
-
validateState: z.boolean().optional()
|
|
2860
|
+
validateState: z.boolean().optional(),
|
|
2861
|
+
order: z.boolean().optional()
|
|
2708
2862
|
}).optional(),
|
|
2709
2863
|
development: z.object({
|
|
2710
2864
|
targetVersion: z.string().optional(),
|
|
@@ -2758,5 +2912,316 @@ const CommandConfigSchema = z.object({
|
|
|
2758
2912
|
commandName: z.string().optional()
|
|
2759
2913
|
});
|
|
2760
2914
|
|
|
2761
|
-
|
|
2915
|
+
/**
|
|
2916
|
+
* Structured error types for kodrdriv operations
|
|
2917
|
+
*
|
|
2918
|
+
* These errors provide detailed context for MCP integrations and AI agents
|
|
2919
|
+
* to understand failures and provide actionable recovery steps.
|
|
2920
|
+
*/ function _define_property$1(obj, key, value) {
|
|
2921
|
+
if (key in obj) {
|
|
2922
|
+
Object.defineProperty(obj, key, {
|
|
2923
|
+
value: value,
|
|
2924
|
+
enumerable: true,
|
|
2925
|
+
configurable: true,
|
|
2926
|
+
writable: true
|
|
2927
|
+
});
|
|
2928
|
+
} else {
|
|
2929
|
+
obj[key] = value;
|
|
2930
|
+
}
|
|
2931
|
+
return obj;
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2934
|
+
* Base error class for all kodrdriv operations
|
|
2935
|
+
*/ class KodrdrivError extends Error {
|
|
2936
|
+
constructor(message, context, recoverable = true){
|
|
2937
|
+
super(message), _define_property$1(this, "context", void 0), _define_property$1(this, "recoverable", void 0), this.context = context, this.recoverable = recoverable;
|
|
2938
|
+
this.name = 'KodrdrivError';
|
|
2939
|
+
// Capture stack trace
|
|
2940
|
+
if (Error.captureStackTrace) {
|
|
2941
|
+
Error.captureStackTrace(this, this.constructor);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
/**
|
|
2946
|
+
* Error specific to publish operations
|
|
2947
|
+
*/ class PublishError extends KodrdrivError {
|
|
2948
|
+
constructor(message, context){
|
|
2949
|
+
super(message, {
|
|
2950
|
+
...context,
|
|
2951
|
+
operation: 'publish'
|
|
2952
|
+
});
|
|
2953
|
+
this.name = 'PublishError';
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
/**
|
|
2957
|
+
* Error specific to tree operations (monorepo orchestration)
|
|
2958
|
+
*/ class TreeExecutionError extends KodrdrivError {
|
|
2959
|
+
constructor(message, context, failedPackages = [], completedPackages = [], checkpointPath){
|
|
2960
|
+
super(message, {
|
|
2961
|
+
...context,
|
|
2962
|
+
operation: 'tree'
|
|
2963
|
+
}), _define_property$1(this, "failedPackages", void 0), _define_property$1(this, "completedPackages", void 0), _define_property$1(this, "checkpointPath", void 0), this.failedPackages = failedPackages, this.completedPackages = completedPackages, this.checkpointPath = checkpointPath;
|
|
2964
|
+
this.name = 'TreeExecutionError';
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Error for validation failures (pre-flight checks)
|
|
2969
|
+
*/ class ValidationError extends KodrdrivError {
|
|
2970
|
+
constructor(message, context, validationErrors = [], validationWarnings = []){
|
|
2971
|
+
super(message, {
|
|
2972
|
+
...context,
|
|
2973
|
+
operation: 'validation'
|
|
2974
|
+
}, false), _define_property$1(this, "validationErrors", void 0), _define_property$1(this, "validationWarnings", void 0), this.validationErrors = validationErrors, this.validationWarnings = validationWarnings;
|
|
2975
|
+
this.name = 'ValidationError';
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
/**
|
|
2979
|
+
* Error for workspace structure issues
|
|
2980
|
+
*/ class WorkspaceError extends KodrdrivError {
|
|
2981
|
+
constructor(message, context, expectedStructure){
|
|
2982
|
+
super(message, {
|
|
2983
|
+
...context,
|
|
2984
|
+
operation: 'workspace'
|
|
2985
|
+
}, false), _define_property$1(this, "expectedStructure", void 0), this.expectedStructure = expectedStructure;
|
|
2986
|
+
this.name = 'WorkspaceError';
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
/**
|
|
2990
|
+
* Format error for MCP tool responses
|
|
2991
|
+
*/ function formatErrorForMCP(error) {
|
|
2992
|
+
// Handle TreeExecutionError
|
|
2993
|
+
if (error instanceof TreeExecutionError) {
|
|
2994
|
+
const recovery = [];
|
|
2995
|
+
if (error.failedPackages.length > 0) {
|
|
2996
|
+
recovery.push(`Fix the issue in: ${error.failedPackages.join(', ')}`);
|
|
2997
|
+
}
|
|
2998
|
+
if (error.checkpointPath) {
|
|
2999
|
+
recovery.push(`Then resume with: kodrdriv tree_publish --continue`);
|
|
3000
|
+
recovery.push(`Or via MCP: kodrdriv_tree_publish({directory: "...", continue: true})`);
|
|
3001
|
+
}
|
|
3002
|
+
return {
|
|
3003
|
+
message: error.message,
|
|
3004
|
+
context: {
|
|
3005
|
+
...error.context,
|
|
3006
|
+
failedPackages: error.failedPackages,
|
|
3007
|
+
completedPackages: error.completedPackages,
|
|
3008
|
+
checkpointPath: error.checkpointPath,
|
|
3009
|
+
recoverable: error.recoverable
|
|
3010
|
+
},
|
|
3011
|
+
recovery: recovery.length > 0 ? recovery : undefined
|
|
3012
|
+
};
|
|
3013
|
+
}
|
|
3014
|
+
// Handle ValidationError
|
|
3015
|
+
if (error instanceof ValidationError) {
|
|
3016
|
+
const recovery = [];
|
|
3017
|
+
if (error.validationErrors.length > 0) {
|
|
3018
|
+
recovery.push('Fix the following validation errors:');
|
|
3019
|
+
error.validationErrors.forEach((err, idx)=>{
|
|
3020
|
+
recovery.push(` ${idx + 1}. ${err.check}: ${err.message}`);
|
|
3021
|
+
if (err.files && err.files.length > 0) {
|
|
3022
|
+
recovery.push(` Files: ${err.files.join(', ')}`);
|
|
3023
|
+
}
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3026
|
+
return {
|
|
3027
|
+
message: error.message,
|
|
3028
|
+
context: {
|
|
3029
|
+
...error.context,
|
|
3030
|
+
validationErrors: error.validationErrors,
|
|
3031
|
+
validationWarnings: error.validationWarnings,
|
|
3032
|
+
recoverable: error.recoverable
|
|
3033
|
+
},
|
|
3034
|
+
recovery: recovery.length > 0 ? recovery : undefined
|
|
3035
|
+
};
|
|
3036
|
+
}
|
|
3037
|
+
// Handle PublishError
|
|
3038
|
+
if (error instanceof PublishError) {
|
|
3039
|
+
const recovery = [];
|
|
3040
|
+
if (error.context.phase) {
|
|
3041
|
+
recovery.push(`Failed during: ${error.context.phase}`);
|
|
3042
|
+
}
|
|
3043
|
+
if (error.context.files && error.context.files.length > 0) {
|
|
3044
|
+
recovery.push(`Check these files: ${error.context.files.join(', ')}`);
|
|
3045
|
+
}
|
|
3046
|
+
if (error.context.command) {
|
|
3047
|
+
recovery.push(`Failed command: ${error.context.command}`);
|
|
3048
|
+
if (error.context.exitCode) {
|
|
3049
|
+
recovery.push(`Exit code: ${error.context.exitCode}`);
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
return {
|
|
3053
|
+
message: error.message,
|
|
3054
|
+
context: {
|
|
3055
|
+
...error.context,
|
|
3056
|
+
recoverable: error.recoverable
|
|
3057
|
+
},
|
|
3058
|
+
recovery: recovery.length > 0 ? recovery : undefined
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
// Handle WorkspaceError
|
|
3062
|
+
if (error instanceof WorkspaceError) {
|
|
3063
|
+
const recovery = [];
|
|
3064
|
+
if (error.expectedStructure) {
|
|
3065
|
+
recovery.push(`Expected structure: ${error.expectedStructure}`);
|
|
3066
|
+
}
|
|
3067
|
+
if (error.context.files && error.context.files.length > 0) {
|
|
3068
|
+
recovery.push(`Missing or invalid files: ${error.context.files.join(', ')}`);
|
|
3069
|
+
}
|
|
3070
|
+
return {
|
|
3071
|
+
message: error.message,
|
|
3072
|
+
context: {
|
|
3073
|
+
...error.context,
|
|
3074
|
+
expectedStructure: error.expectedStructure,
|
|
3075
|
+
recoverable: error.recoverable
|
|
3076
|
+
},
|
|
3077
|
+
recovery: recovery.length > 0 ? recovery : undefined
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
3080
|
+
// Handle generic KodrdrivError
|
|
3081
|
+
if (error instanceof KodrdrivError) {
|
|
3082
|
+
return {
|
|
3083
|
+
message: error.message,
|
|
3084
|
+
context: {
|
|
3085
|
+
...error.context,
|
|
3086
|
+
recoverable: error.recoverable
|
|
3087
|
+
}
|
|
3088
|
+
};
|
|
3089
|
+
}
|
|
3090
|
+
// Handle generic Error
|
|
3091
|
+
return {
|
|
3092
|
+
message: error.message || 'Unknown error occurred',
|
|
3093
|
+
context: {
|
|
3094
|
+
name: error.name,
|
|
3095
|
+
stack: error.stack
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Extract error details from command execution errors
|
|
3101
|
+
*/ function extractCommandErrorDetails(error) {
|
|
3102
|
+
const context = {};
|
|
3103
|
+
// Extract stdout/stderr from various error formats
|
|
3104
|
+
if (error.stdout) {
|
|
3105
|
+
context.stdout = typeof error.stdout === 'string' ? error.stdout : String(error.stdout);
|
|
3106
|
+
}
|
|
3107
|
+
if (error.stderr) {
|
|
3108
|
+
context.stderr = typeof error.stderr === 'string' ? error.stderr : String(error.stderr);
|
|
3109
|
+
}
|
|
3110
|
+
// Extract exit code
|
|
3111
|
+
if (error.code !== undefined) {
|
|
3112
|
+
context.exitCode = error.code;
|
|
3113
|
+
} else if (error.exitCode !== undefined) {
|
|
3114
|
+
context.exitCode = error.exitCode;
|
|
3115
|
+
}
|
|
3116
|
+
// Extract command if available
|
|
3117
|
+
if (error.cmd) {
|
|
3118
|
+
context.command = error.cmd;
|
|
3119
|
+
} else if (error.command) {
|
|
3120
|
+
context.command = error.command;
|
|
3121
|
+
}
|
|
3122
|
+
return context;
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
function _define_property(obj, key, value) {
|
|
3126
|
+
if (key in obj) {
|
|
3127
|
+
Object.defineProperty(obj, key, {
|
|
3128
|
+
value: value,
|
|
3129
|
+
enumerable: true,
|
|
3130
|
+
configurable: true,
|
|
3131
|
+
writable: true
|
|
3132
|
+
});
|
|
3133
|
+
} else {
|
|
3134
|
+
obj[key] = value;
|
|
3135
|
+
}
|
|
3136
|
+
return obj;
|
|
3137
|
+
}
|
|
3138
|
+
class TransactionLog {
|
|
3139
|
+
/**
|
|
3140
|
+
* Record an operation with its rollback function
|
|
3141
|
+
*/ async record(type, details, rollback) {
|
|
3142
|
+
this.operations.push({
|
|
3143
|
+
type,
|
|
3144
|
+
timestamp: new Date(),
|
|
3145
|
+
details,
|
|
3146
|
+
rollback
|
|
3147
|
+
});
|
|
3148
|
+
this.logger.debug(`TRANSACTION_RECORDED: ${type} | Details: ${JSON.stringify(details)}`);
|
|
3149
|
+
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Roll back all operations in reverse order
|
|
3152
|
+
*/ async rollbackAll() {
|
|
3153
|
+
this.logger.info('TRANSACTION_ROLLBACK_STARTING: Rolling back operations | Count: ' + this.operations.length);
|
|
3154
|
+
const errors = [];
|
|
3155
|
+
// Rollback in reverse order (LIFO)
|
|
3156
|
+
for(let i = this.operations.length - 1; i >= 0; i--){
|
|
3157
|
+
const op = this.operations[i];
|
|
3158
|
+
try {
|
|
3159
|
+
this.logger.info(`TRANSACTION_ROLLBACK: Rolling back ${op.type} | Timestamp: ${op.timestamp.toISOString()}`);
|
|
3160
|
+
await op.rollback();
|
|
3161
|
+
this.logger.info(`TRANSACTION_ROLLBACK_SUCCESS: ${op.type} rolled back successfully`);
|
|
3162
|
+
} catch (error) {
|
|
3163
|
+
this.logger.error(`TRANSACTION_ROLLBACK_FAILED: Failed to rollback ${op.type} | Error: ${error.message}`);
|
|
3164
|
+
errors.push(error);
|
|
3165
|
+
// Continue rolling back other operations even if one fails
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
if (errors.length > 0) {
|
|
3169
|
+
this.logger.error(`TRANSACTION_ROLLBACK_PARTIAL: ${errors.length} rollback operation(s) failed`);
|
|
3170
|
+
throw new Error(`Rollback completed with ${errors.length} error(s). See logs for details.`);
|
|
3171
|
+
}
|
|
3172
|
+
this.logger.info('TRANSACTION_ROLLBACK_COMPLETE: All operations rolled back successfully');
|
|
3173
|
+
this.operations = [];
|
|
3174
|
+
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Clear the transaction log without rolling back
|
|
3177
|
+
*/ clear() {
|
|
3178
|
+
this.operations = [];
|
|
3179
|
+
this.logger.debug('TRANSACTION_LOG_CLEARED: Transaction log cleared');
|
|
3180
|
+
}
|
|
3181
|
+
/**
|
|
3182
|
+
* Get the number of recorded operations
|
|
3183
|
+
*/ get count() {
|
|
3184
|
+
return this.operations.length;
|
|
3185
|
+
}
|
|
3186
|
+
/**
|
|
3187
|
+
* Get all operations
|
|
3188
|
+
*/ getOperations() {
|
|
3189
|
+
return [
|
|
3190
|
+
...this.operations
|
|
3191
|
+
];
|
|
3192
|
+
}
|
|
3193
|
+
/**
|
|
3194
|
+
* Check if there are any recorded operations
|
|
3195
|
+
*/ hasOperations() {
|
|
3196
|
+
return this.operations.length > 0;
|
|
3197
|
+
}
|
|
3198
|
+
constructor(){
|
|
3199
|
+
_define_property(this, "operations", []);
|
|
3200
|
+
_define_property(this, "logger", getLogger());
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
/**
|
|
3204
|
+
* Create a no-op rollback function for operations that can't be rolled back
|
|
3205
|
+
*/ function noopRollback() {
|
|
3206
|
+
return Promise.resolve();
|
|
3207
|
+
}
|
|
3208
|
+
/**
|
|
3209
|
+
* Helper to create a file restore rollback
|
|
3210
|
+
*/ function createFileRestoreRollback(filePath, originalContent) {
|
|
3211
|
+
return async ()=>{
|
|
3212
|
+
const { createStorage } = await import('@eldrforge/shared');
|
|
3213
|
+
const storage = createStorage();
|
|
3214
|
+
await storage.writeFile(filePath, originalContent, 'utf-8');
|
|
3215
|
+
};
|
|
3216
|
+
}
|
|
3217
|
+
/**
|
|
3218
|
+
* Helper to create a git command rollback
|
|
3219
|
+
*/ function createGitRollback(command) {
|
|
3220
|
+
return async ()=>{
|
|
3221
|
+
const { run } = await import('@eldrforge/git-tools');
|
|
3222
|
+
await run(command);
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
export { ALLOWED_COMMANDS, COMMAND_AUDIO_COMMIT, COMMAND_AUDIO_REVIEW, COMMAND_CHECK_CONFIG, COMMAND_CLEAN, COMMAND_COMMIT, COMMAND_DEVELOPMENT, COMMAND_INIT_CONFIG, COMMAND_LINK, COMMAND_PRECOMMIT, COMMAND_PUBLISH, COMMAND_RELEASE, COMMAND_REVIEW, COMMAND_SELECT_AUDIO, COMMAND_TREE, COMMAND_UNLINK, COMMAND_UPDATES, COMMAND_VERSIONS, CommandConfigSchema, ConfigSchema, DATE_FORMAT_DAY, DATE_FORMAT_HOURS, DATE_FORMAT_MILLISECONDS, DATE_FORMAT_MINUTES, DATE_FORMAT_MONTH, DATE_FORMAT_MONTH_DAY, DATE_FORMAT_SECONDS, DATE_FORMAT_SHORT_TIMESTAMP, DATE_FORMAT_YEAR, DATE_FORMAT_YEAR_MONTH, DATE_FORMAT_YEAR_MONTH_DAY, DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES, DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS, DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS_MILLISECONDS, DATE_FORMAT_YEAR_MONTH_DAY_SLASH, DEFAULT_ADD, DEFAULT_AMEND_MODE, DEFAULT_BINARY_TO_TEXT_ENCODING, DEFAULT_CACHED, DEFAULT_CHARACTER_ENCODING, DEFAULT_COMMAND, DEFAULT_CONFIG_DIR, DEFAULT_CONTEXT_DIRECTORIES, DEFAULT_DEBUG, DEFAULT_DIFF, DEFAULT_DIRECTORY_PREFIX, DEFAULT_DRY_RUN, DEFAULT_EXCLUDED_PATTERNS, DEFAULT_FROM_COMMIT_ALIAS, DEFAULT_GIT_COMMAND_MAX_BUFFER, DEFAULT_IGNORE_PATTERNS, DEFAULT_INSTRUCTIONS_COMMIT_FILE, DEFAULT_INSTRUCTIONS_DIR, DEFAULT_INSTRUCTIONS_MAP, DEFAULT_INSTRUCTIONS_RELEASE_FILE, DEFAULT_INSTRUCTIONS_REVIEW_FILE, DEFAULT_INTERACTIVE_MODE, DEFAULT_LOG, DEFAULT_MAX_DIFF_BYTES, DEFAULT_MERGE_METHOD, DEFAULT_MESSAGE_LIMIT, DEFAULT_MODEL, DEFAULT_MODEL_STRONG, DEFAULT_OPENAI_MAX_OUTPUT_TOKENS, DEFAULT_OPENAI_REASONING, DEFAULT_OUTPUT_DIRECTORY, DEFAULT_OVERRIDES, DEFAULT_PATH_SEPARATOR, DEFAULT_PERSONA_DIR, DEFAULT_PERSONA_MAP, DEFAULT_PERSONA_RELEASER_FILE, DEFAULT_PERSONA_YOU_FILE, DEFAULT_PREFERENCES_DIRECTORY, DEFAULT_SENDIT_MODE, DEFAULT_TO_COMMIT_ALIAS, DEFAULT_VERBOSE, diff as Diff, FileLock, files as Files, INTERNAL_DATETIME_FORMAT, INTERNAL_DEFAULT_OUTPUT_FILE, KODRDRIV_DEFAULTS, KodrdrivError, log as Log, PROGRAM_NAME, ProgressTracker, PublishError, RepositoryFileLockManager, RepositoryMutexManager, SecureConfigSchema, TransactionLog, TreeExecutionError, VERSION, ValidationError, WorkspaceError, areInSameRepository, calculateBranchDependentVersion, checkIfTagExists, confirmVersionInteractively, createErrorResult, createFileRestoreRollback, createGitRollback, createLoggerAdapter, createStorageAdapter, createSuccessResult, destroyGitMutexManager, executeWithErrorHandling, extractCommandErrorDetails, filterContent, findDevelopmentBranch, formatErrorForMCP, getDryRunLogger, getExpectedVersionPattern, getGitMutexManager, getGitRepositoryRoot, getLogger, getNpmPublishedVersion, getOutputPath, getTagInfo, getTimestampedArchivedAudioFilename, getTimestampedArchivedTranscriptFilename, getTimestampedAudioFilename, getTimestampedCommitFilename, getTimestampedFilename, getTimestampedReleaseNotesFilename, getTimestampedRequestFilename, getTimestampedResponseFilename, getTimestampedReviewFilename, getTimestampedReviewNotesFilename, getTimestampedTranscriptFilename, getVersionFromBranch, handleCommandError, haveSamePrereleaseTag, improveContentWithLLM, isDevelopmentVersion, isInGitRepository, isReleaseVersion, isStopContextEnabled, isVersionPublishedOnNpm, noopRollback, runGitWithLock, sanitizeDirection, setLogLevel, toAIConfig, validateReleaseSummary, validateTranscriptionResult, validateVersionForBranch };
|
|
2762
3227
|
//# sourceMappingURL=index.js.map
|