@renseiai/agentfactory-cli 0.8.9 → 0.8.11
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/src/agent.js +1 -1
- package/dist/src/analyze-logs.js +1 -1
- package/dist/src/cleanup.d.ts +1 -1
- package/dist/src/cleanup.js +2 -2
- package/dist/src/governor.js +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/lib/cleanup-runner.d.ts +1 -1
- package/dist/src/lib/cleanup-runner.d.ts.map +1 -1
- package/dist/src/lib/cleanup-runner.js +26 -4
- package/dist/src/lib/orchestrator-runner.js +1 -1
- package/dist/src/lib/setup-mergiraf-runner.d.ts +58 -0
- package/dist/src/lib/setup-mergiraf-runner.d.ts.map +1 -0
- package/dist/src/lib/setup-mergiraf-runner.js +239 -0
- package/dist/src/lib/worker-runner.js +1 -1
- package/dist/src/linear.js +1 -1
- package/dist/src/migrate-worktrees.d.ts +17 -0
- package/dist/src/migrate-worktrees.d.ts.map +1 -0
- package/dist/src/migrate-worktrees.js +231 -0
- package/dist/src/orchestrator.js +1 -1
- package/dist/src/queue-admin.js +1 -1
- package/dist/src/setup.d.ts +21 -0
- package/dist/src/setup.d.ts.map +1 -0
- package/dist/src/setup.js +142 -0
- package/dist/src/status.js +1 -1
- package/dist/src/worker-fleet.js +1 -1
- package/dist/src/worker.js +1 -1
- package/package.json +13 -6
package/dist/src/agent.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import path from 'path';
|
|
20
20
|
import { config } from 'dotenv';
|
|
21
21
|
// Load environment variables from .env.local in CWD
|
|
22
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
22
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
23
23
|
import { runAgent, C } from './lib/agent-runner.js';
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
25
|
// Usage
|
package/dist/src/analyze-logs.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import path from 'path';
|
|
26
26
|
import { config } from 'dotenv';
|
|
27
27
|
// Load environment variables from .env.local in CWD
|
|
28
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
28
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
29
29
|
import { runLogAnalyzer, printSummary } from './lib/analyze-logs-runner.js';
|
|
30
30
|
import { getVersion, checkForUpdate, printUpdateNotification } from './lib/version.js';
|
|
31
31
|
const DEFAULT_POLL_INTERVAL = 5000;
|
package/dist/src/cleanup.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Options:
|
|
11
11
|
* --dry-run Show what would be cleaned up without removing anything
|
|
12
12
|
* --force Force removal / include branches with gone remotes
|
|
13
|
-
* --path <dir> Custom worktrees directory (default: .
|
|
13
|
+
* --path <dir> Custom worktrees directory (default: ../{repoName}.wt)
|
|
14
14
|
* --skip-worktrees Skip worktree cleanup
|
|
15
15
|
* --skip-branches Skip branch cleanup
|
|
16
16
|
* --help, -h Show this help message
|
package/dist/src/cleanup.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Options:
|
|
11
11
|
* --dry-run Show what would be cleaned up without removing anything
|
|
12
12
|
* --force Force removal / include branches with gone remotes
|
|
13
|
-
* --path <dir> Custom worktrees directory (default: .
|
|
13
|
+
* --path <dir> Custom worktrees directory (default: ../{repoName}.wt)
|
|
14
14
|
* --skip-worktrees Skip worktree cleanup
|
|
15
15
|
* --skip-branches Skip branch cleanup
|
|
16
16
|
* --help, -h Show this help message
|
|
@@ -62,7 +62,7 @@ Usage:
|
|
|
62
62
|
Options:
|
|
63
63
|
--dry-run Show what would be cleaned up without removing
|
|
64
64
|
--force Force worktree removal + delete branches with gone remotes
|
|
65
|
-
--path <dir> Custom worktrees directory (default: .
|
|
65
|
+
--path <dir> Custom worktrees directory (default: ../{repoName}.wt)
|
|
66
66
|
--skip-worktrees Skip worktree cleanup
|
|
67
67
|
--skip-branches Skip branch cleanup
|
|
68
68
|
--help, -h Show this help message
|
package/dist/src/governor.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import path from 'path';
|
|
26
26
|
import { config } from 'dotenv';
|
|
27
27
|
// Load environment variables from .env.local
|
|
28
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
28
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
29
29
|
import { parseGovernorArgs, runGovernor, } from './lib/governor-runner.js';
|
|
30
30
|
import { createRealDependencies } from './lib/governor-dependencies.js';
|
|
31
31
|
import { printStartupBanner, printScanSummary, printCircuitBreakerWarning, } from './lib/governor-logger.js';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,QAAA,MAAM,OAAO,QAAkB,CAAA;AAE/B,iBAAS,SAAS,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,QAAA,MAAM,OAAO,QAAkB,CAAA;AAE/B,iBAAS,SAAS,IAAI,IAAI,CA0BzB"}
|
package/dist/src/index.js
CHANGED
|
@@ -25,6 +25,7 @@ Commands:
|
|
|
25
25
|
analyze-logs Analyze agent session logs for errors
|
|
26
26
|
linear Linear issue tracker operations
|
|
27
27
|
sync-routes Generate missing route and page files from manifest
|
|
28
|
+
setup Configure development tools (mergiraf, etc.)
|
|
28
29
|
status Show fleet status (inline one-line summary)
|
|
29
30
|
help Show this help message
|
|
30
31
|
|
|
@@ -64,6 +65,9 @@ switch (command) {
|
|
|
64
65
|
case 'sync-routes':
|
|
65
66
|
import('./sync-routes');
|
|
66
67
|
break;
|
|
68
|
+
case 'setup':
|
|
69
|
+
import('./setup');
|
|
70
|
+
break;
|
|
67
71
|
case 'status':
|
|
68
72
|
import('./status');
|
|
69
73
|
break;
|
|
@@ -9,7 +9,7 @@ export interface CleanupRunnerConfig {
|
|
|
9
9
|
dryRun?: boolean;
|
|
10
10
|
/** Force removal even if worktree appears active (default: false) */
|
|
11
11
|
force?: boolean;
|
|
12
|
-
/** Custom worktrees directory (default: {
|
|
12
|
+
/** Custom worktrees directory (default: ../{repoName}.wt) */
|
|
13
13
|
worktreePath?: string;
|
|
14
14
|
/** Git root for default worktree path (default: auto-detect) */
|
|
15
15
|
gitRoot?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanup-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/cleanup-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,
|
|
1
|
+
{"version":3,"file":"cleanup-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/cleanup-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC/C;AAED,MAAM,WAAW,aAAc,SAAQ,qBAAqB;IAC1D,QAAQ,EAAE,mBAAmB,CAAA;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjD;AAuBD,wBAAgB,UAAU,IAAI,MAAM,CASnC;AA8bD,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,aAAa,CAyCtE"}
|
|
@@ -430,14 +430,36 @@ function cleanupBranches(options) {
|
|
|
430
430
|
// ---------------------------------------------------------------------------
|
|
431
431
|
export function runCleanup(config) {
|
|
432
432
|
const gitRoot = config?.gitRoot ?? getGitRoot();
|
|
433
|
+
const defaultWorktreePath = resolve(gitRoot, '..', basename(gitRoot) + '.wt');
|
|
433
434
|
const options = {
|
|
434
435
|
dryRun: config?.dryRun ?? false,
|
|
435
436
|
force: config?.force ?? false,
|
|
436
|
-
worktreePath: config?.worktreePath ??
|
|
437
|
+
worktreePath: config?.worktreePath ?? defaultWorktreePath,
|
|
437
438
|
};
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
439
|
+
// Also scan legacy .worktrees/ location during migration period
|
|
440
|
+
const legacyPath = resolve(gitRoot, '.worktrees');
|
|
441
|
+
const hasLegacyWorktrees = !config?.worktreePath && existsSync(legacyPath);
|
|
442
|
+
if (hasLegacyWorktrees) {
|
|
443
|
+
console.log(`\nNote: Found worktrees at legacy location ${legacyPath}`);
|
|
444
|
+
console.log(' Run "af-migrate-worktrees" to move them to the new default location.\n');
|
|
445
|
+
}
|
|
446
|
+
let worktreeResult;
|
|
447
|
+
if (config?.skipWorktrees) {
|
|
448
|
+
worktreeResult = { scanned: 0, orphaned: 0, cleaned: 0, skipped: 0, errors: [] };
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
worktreeResult = cleanup(options);
|
|
452
|
+
// Merge results from legacy .worktrees/ location if it exists
|
|
453
|
+
if (hasLegacyWorktrees) {
|
|
454
|
+
const legacyOptions = { ...options, worktreePath: legacyPath };
|
|
455
|
+
const legacyResult = cleanup(legacyOptions);
|
|
456
|
+
worktreeResult.scanned += legacyResult.scanned;
|
|
457
|
+
worktreeResult.orphaned += legacyResult.orphaned;
|
|
458
|
+
worktreeResult.cleaned += legacyResult.cleaned;
|
|
459
|
+
worktreeResult.skipped += legacyResult.skipped;
|
|
460
|
+
worktreeResult.errors.push(...legacyResult.errors);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
441
463
|
const branchResult = config?.skipBranches
|
|
442
464
|
? { scanned: 0, deleted: 0, errors: [] }
|
|
443
465
|
: cleanupBranches(options);
|
|
@@ -84,7 +84,7 @@ export async function runOrchestrator(config) {
|
|
|
84
84
|
const orchestratorConfig = {
|
|
85
85
|
project: config.project,
|
|
86
86
|
maxConcurrent,
|
|
87
|
-
worktreePath: path.resolve(gitRoot, '.
|
|
87
|
+
worktreePath: path.resolve(gitRoot, '..', path.basename(gitRoot) + '.wt'),
|
|
88
88
|
linearApiKey: config.linearApiKey,
|
|
89
89
|
issueTrackerClient,
|
|
90
90
|
statusMappings,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Mergiraf Runner — Programmatic API for configuring mergiraf as git merge driver.
|
|
3
|
+
*
|
|
4
|
+
* Exports `setupMergiraf()` so mergiraf configuration can be invoked from code
|
|
5
|
+
* without going through process.argv / process.env / process.exit.
|
|
6
|
+
*/
|
|
7
|
+
export interface SetupMergirafConfig {
|
|
8
|
+
/** Show what would be done without making changes (default: false) */
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
/** Only configure for agent worktrees, not the whole repo (default: false) */
|
|
11
|
+
worktreeOnly?: boolean;
|
|
12
|
+
/** Skip mergiraf binary check (default: false) */
|
|
13
|
+
skipCheck?: boolean;
|
|
14
|
+
/** Git root directory (default: auto-detect) */
|
|
15
|
+
gitRoot?: string;
|
|
16
|
+
/** Worktree path for per-worktree configuration (used with worktreeOnly) */
|
|
17
|
+
worktreePath?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SetupMergirafResult {
|
|
20
|
+
mergirafFound: boolean;
|
|
21
|
+
mergirafVersion: string;
|
|
22
|
+
configuredFileTypes: string[];
|
|
23
|
+
gitattributesWritten: boolean;
|
|
24
|
+
mergeDriverConfigured: boolean;
|
|
25
|
+
worktreeMode: boolean;
|
|
26
|
+
repoConfigUpdated: boolean;
|
|
27
|
+
errors: string[];
|
|
28
|
+
/** Process exit code: 0 = success, 1 = error, 2 = mergiraf not found */
|
|
29
|
+
exitCode: number;
|
|
30
|
+
}
|
|
31
|
+
export declare function getGitRoot(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Detect mergiraf binary and return version info.
|
|
34
|
+
* Uses `which` to find the binary and `mergiraf --version` for the version string.
|
|
35
|
+
*/
|
|
36
|
+
export declare function detectMergiraf(): {
|
|
37
|
+
found: boolean;
|
|
38
|
+
version: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Configure .gitattributes with mergiraf merge driver entries.
|
|
42
|
+
* Idempotent — skips entries that already exist.
|
|
43
|
+
*/
|
|
44
|
+
export declare function configureGitattributes(gitRoot: string, config: SetupMergirafConfig): {
|
|
45
|
+
written: boolean;
|
|
46
|
+
fileTypes: string[];
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Configure git merge driver for mergiraf via `git config`.
|
|
50
|
+
* In worktree-only mode, uses `--worktree` flag for worktree-local config.
|
|
51
|
+
*/
|
|
52
|
+
export declare function configureMergeDriver(targetPath: string, config: SetupMergirafConfig): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Update .agentfactory/config.yaml with mergeDriver: mergiraf.
|
|
55
|
+
*/
|
|
56
|
+
export declare function updateRepoConfig(gitRoot: string, config: SetupMergirafConfig): boolean;
|
|
57
|
+
export declare function setupMergiraf(config?: SetupMergirafConfig): SetupMergirafResult;
|
|
58
|
+
//# sourceMappingURL=setup-mergiraf-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-mergiraf-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/setup-mergiraf-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,oBAAoB,EAAE,OAAO,CAAA;IAC7B,qBAAqB,EAAE,OAAO,CAAA;IAC9B,YAAY,EAAE,OAAO,CAAA;IACrB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAA;CACjB;AAMD,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAMD;;;GAGG;AACH,wBAAgB,cAAc,IAAI;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAuBpE;AAgBD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,GAC1B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAkD3C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAoCT;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAsCT;AAMD,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,CA0D/E"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Mergiraf Runner — Programmatic API for configuring mergiraf as git merge driver.
|
|
3
|
+
*
|
|
4
|
+
* Exports `setupMergiraf()` so mergiraf configuration can be invoked from code
|
|
5
|
+
* without going through process.argv / process.env / process.exit.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
9
|
+
import { resolve } from 'path';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Helpers
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
export function getGitRoot() {
|
|
14
|
+
try {
|
|
15
|
+
return execSync('git rev-parse --show-toplevel', {
|
|
16
|
+
encoding: 'utf-8',
|
|
17
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
18
|
+
}).trim();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return process.cwd();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Step functions
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Detect mergiraf binary and return version info.
|
|
29
|
+
* Uses `which` to find the binary and `mergiraf --version` for the version string.
|
|
30
|
+
*/
|
|
31
|
+
export function detectMergiraf() {
|
|
32
|
+
try {
|
|
33
|
+
execSync('which mergiraf', { stdio: 'pipe', encoding: 'utf-8' });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
console.log('mergiraf binary not found on PATH.\n');
|
|
37
|
+
console.log('Install mergiraf:');
|
|
38
|
+
console.log(' macOS: brew install mergiraf');
|
|
39
|
+
console.log(' Linux: cargo install mergiraf (or download from Codeberg releases)');
|
|
40
|
+
console.log(' Any: cargo install mergiraf (requires Rust toolchain)\n');
|
|
41
|
+
return { found: false, version: '' };
|
|
42
|
+
}
|
|
43
|
+
let version = '';
|
|
44
|
+
try {
|
|
45
|
+
version = execSync('mergiraf --version', {
|
|
46
|
+
encoding: 'utf-8',
|
|
47
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
48
|
+
}).trim();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
version = '(unknown)';
|
|
52
|
+
}
|
|
53
|
+
return { found: true, version };
|
|
54
|
+
}
|
|
55
|
+
/** File types that mergiraf supports for AST-aware merging. */
|
|
56
|
+
const MERGIRAF_FILE_TYPES = [
|
|
57
|
+
'*.ts', '*.tsx', '*.js', '*.jsx', '*.mjs', '*.json',
|
|
58
|
+
'*.yaml', '*.yml', '*.py', '*.go', '*.rs',
|
|
59
|
+
'*.java', '*.css', '*.html',
|
|
60
|
+
];
|
|
61
|
+
/** Lock files that should use merge=ours strategy. */
|
|
62
|
+
const LOCK_FILE_ENTRIES = [
|
|
63
|
+
'pnpm-lock.yaml merge=ours',
|
|
64
|
+
'package-lock.json merge=ours',
|
|
65
|
+
'yarn.lock merge=ours',
|
|
66
|
+
];
|
|
67
|
+
/**
|
|
68
|
+
* Configure .gitattributes with mergiraf merge driver entries.
|
|
69
|
+
* Idempotent — skips entries that already exist.
|
|
70
|
+
*/
|
|
71
|
+
export function configureGitattributes(gitRoot, config) {
|
|
72
|
+
const gitattributesPath = resolve(gitRoot, '.gitattributes');
|
|
73
|
+
let existing = '';
|
|
74
|
+
if (existsSync(gitattributesPath)) {
|
|
75
|
+
existing = readFileSync(gitattributesPath, 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
const lines = [];
|
|
78
|
+
const addedTypes = [];
|
|
79
|
+
// Add mergiraf merge driver entries
|
|
80
|
+
for (const ft of MERGIRAF_FILE_TYPES) {
|
|
81
|
+
const entry = `${ft} merge=mergiraf`;
|
|
82
|
+
if (!existing.includes(entry)) {
|
|
83
|
+
lines.push(entry);
|
|
84
|
+
addedTypes.push(ft);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Add lock file entries
|
|
88
|
+
for (const entry of LOCK_FILE_ENTRIES) {
|
|
89
|
+
if (!existing.includes(entry)) {
|
|
90
|
+
lines.push(entry);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (lines.length === 0) {
|
|
94
|
+
console.log(' .gitattributes already configured — no changes needed');
|
|
95
|
+
return { written: true, fileTypes: MERGIRAF_FILE_TYPES };
|
|
96
|
+
}
|
|
97
|
+
if (config.dryRun) {
|
|
98
|
+
console.log('[DRY RUN] Would add to .gitattributes:');
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
console.log(` ${line}`);
|
|
101
|
+
}
|
|
102
|
+
return { written: false, fileTypes: MERGIRAF_FILE_TYPES };
|
|
103
|
+
}
|
|
104
|
+
// Append new entries with a header comment
|
|
105
|
+
const newContent = existing.trimEnd() +
|
|
106
|
+
(existing.length > 0 ? '\n\n' : '') +
|
|
107
|
+
'# AST-aware merge driver (mergiraf)\n' +
|
|
108
|
+
lines.join('\n') + '\n';
|
|
109
|
+
writeFileSync(gitattributesPath, newContent, 'utf-8');
|
|
110
|
+
console.log(` .gitattributes updated: ${addedTypes.length} file type(s) added`);
|
|
111
|
+
return { written: true, fileTypes: MERGIRAF_FILE_TYPES };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Configure git merge driver for mergiraf via `git config`.
|
|
115
|
+
* In worktree-only mode, uses `--worktree` flag for worktree-local config.
|
|
116
|
+
*/
|
|
117
|
+
export function configureMergeDriver(targetPath, config) {
|
|
118
|
+
const scope = config.worktreeOnly ? ' --worktree' : '';
|
|
119
|
+
const label = config.worktreeOnly ? 'worktree-local config' : '.git/config';
|
|
120
|
+
if (config.dryRun) {
|
|
121
|
+
console.log('[DRY RUN] Would configure git merge driver:');
|
|
122
|
+
console.log(` git config${scope} merge.mergiraf.name "mergiraf"`);
|
|
123
|
+
console.log(` git config${scope} merge.mergiraf.driver "mergiraf merge --git %O %A %B -s %S -x %X -y %Y -p %P"`);
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
// Enable worktree config extension if using worktree-only mode
|
|
128
|
+
if (config.worktreeOnly) {
|
|
129
|
+
execSync('git config extensions.worktreeConfig true', {
|
|
130
|
+
stdio: 'pipe',
|
|
131
|
+
encoding: 'utf-8',
|
|
132
|
+
cwd: targetPath,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
execSync(`git config${scope} merge.mergiraf.name "mergiraf"`, {
|
|
136
|
+
stdio: 'pipe',
|
|
137
|
+
encoding: 'utf-8',
|
|
138
|
+
cwd: targetPath,
|
|
139
|
+
});
|
|
140
|
+
execSync(`git config${scope} merge.mergiraf.driver "mergiraf merge --git %O %A %B -s %S -x %X -y %Y -p %P"`, { stdio: 'pipe', encoding: 'utf-8', cwd: targetPath });
|
|
141
|
+
console.log(` Merge driver configured in ${label}`);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error(` Failed to configure merge driver: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Update .agentfactory/config.yaml with mergeDriver: mergiraf.
|
|
151
|
+
*/
|
|
152
|
+
export function updateRepoConfig(gitRoot, config) {
|
|
153
|
+
const configDir = resolve(gitRoot, '.agentfactory');
|
|
154
|
+
const configPath = resolve(configDir, 'config.yaml');
|
|
155
|
+
if (config.dryRun) {
|
|
156
|
+
console.log('[DRY RUN] Would set mergeDriver: mergiraf in .agentfactory/config.yaml');
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (!existsSync(configPath)) {
|
|
160
|
+
// Config file doesn't exist — skip (don't create one from scratch)
|
|
161
|
+
console.log(' .agentfactory/config.yaml not found — skipping repo config update');
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
let content = readFileSync(configPath, 'utf-8');
|
|
166
|
+
if (content.includes('mergeDriver: mergiraf')) {
|
|
167
|
+
console.log(' .agentfactory/config.yaml already has mergeDriver: mergiraf');
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
if (content.includes('mergeDriver:')) {
|
|
171
|
+
// Replace existing mergeDriver value
|
|
172
|
+
content = content.replace(/mergeDriver:\s*\S+/, 'mergeDriver: mergiraf');
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Append mergeDriver setting
|
|
176
|
+
content = content.trimEnd() + '\nmergeDriver: mergiraf\n';
|
|
177
|
+
}
|
|
178
|
+
writeFileSync(configPath, content, 'utf-8');
|
|
179
|
+
console.log(' .agentfactory/config.yaml updated: mergeDriver: mergiraf');
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
console.error(` Failed to update repo config: ${error instanceof Error ? error.message : String(error)}`);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// Runner
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
export function setupMergiraf(config) {
|
|
191
|
+
const gitRoot = config?.gitRoot ?? getGitRoot();
|
|
192
|
+
const isWorktreeMode = config?.worktreeOnly ?? false;
|
|
193
|
+
// In worktree-only mode, use the worktree path for .gitattributes and git config
|
|
194
|
+
const targetPath = isWorktreeMode && config?.worktreePath
|
|
195
|
+
? config.worktreePath
|
|
196
|
+
: gitRoot;
|
|
197
|
+
const result = {
|
|
198
|
+
mergirafFound: false,
|
|
199
|
+
mergirafVersion: '',
|
|
200
|
+
configuredFileTypes: [],
|
|
201
|
+
gitattributesWritten: false,
|
|
202
|
+
mergeDriverConfigured: false,
|
|
203
|
+
worktreeMode: isWorktreeMode,
|
|
204
|
+
repoConfigUpdated: false,
|
|
205
|
+
errors: [],
|
|
206
|
+
exitCode: 0,
|
|
207
|
+
};
|
|
208
|
+
// Step 1: Detect mergiraf binary
|
|
209
|
+
if (!config?.skipCheck) {
|
|
210
|
+
const detection = detectMergiraf();
|
|
211
|
+
result.mergirafFound = detection.found;
|
|
212
|
+
result.mergirafVersion = detection.version;
|
|
213
|
+
if (!detection.found) {
|
|
214
|
+
result.errors.push('mergiraf binary not found on PATH. Install with: brew install mergiraf (macOS) or cargo install mergiraf');
|
|
215
|
+
result.exitCode = 2;
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
result.mergirafFound = true;
|
|
221
|
+
result.mergirafVersion = '(check skipped)';
|
|
222
|
+
}
|
|
223
|
+
if (config?.dryRun) {
|
|
224
|
+
console.log('[DRY RUN] Would configure mergiraf in:', targetPath);
|
|
225
|
+
console.log('[DRY RUN] Worktree-only mode:', isWorktreeMode);
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
// Step 2: Configure .gitattributes (in worktree root or repo root)
|
|
229
|
+
const gitattributes = configureGitattributes(targetPath, config ?? {});
|
|
230
|
+
result.gitattributesWritten = gitattributes.written;
|
|
231
|
+
result.configuredFileTypes = gitattributes.fileTypes;
|
|
232
|
+
// Step 3: Configure git merge driver (worktree-local or repo-wide)
|
|
233
|
+
result.mergeDriverConfigured = configureMergeDriver(targetPath, config ?? {});
|
|
234
|
+
// Step 4: Update repo config (always in git root, not worktree)
|
|
235
|
+
if (!isWorktreeMode) {
|
|
236
|
+
result.repoConfigUpdated = updateRepoConfig(gitRoot, config ?? {});
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
@@ -421,7 +421,7 @@ export async function runWorker(config, signal) {
|
|
|
421
421
|
const statusMappings = createLinearStatusMappings();
|
|
422
422
|
const orchestrator = createOrchestrator({
|
|
423
423
|
maxConcurrent: 1,
|
|
424
|
-
worktreePath: path.resolve(gitRoot, '.
|
|
424
|
+
worktreePath: path.resolve(gitRoot, '..', path.basename(gitRoot) + '.wt'),
|
|
425
425
|
issueTrackerClient,
|
|
426
426
|
statusMappings,
|
|
427
427
|
toolPlugins: [linearPlugin, codeIntelligencePlugin],
|
package/dist/src/linear.js
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
import path from 'path';
|
|
38
38
|
import { config } from 'dotenv';
|
|
39
39
|
// Load environment variables from .env.local
|
|
40
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
40
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
41
41
|
import { runLinear, parseLinearArgs } from './lib/linear-runner.js';
|
|
42
42
|
function printHelp() {
|
|
43
43
|
console.log(`
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Worktree Migration CLI
|
|
4
|
+
*
|
|
5
|
+
* Migrates worktrees from the legacy .worktrees/ directory (inside repo)
|
|
6
|
+
* to the new sibling directory pattern (../{repoName}.wt/).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* af-migrate-worktrees [options]
|
|
10
|
+
*
|
|
11
|
+
* Options:
|
|
12
|
+
* --dry-run Preview changes without executing
|
|
13
|
+
* --force Move even if processes are using worktrees
|
|
14
|
+
* --help, -h Show this help message
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=migrate-worktrees.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-worktrees.d.ts","sourceRoot":"","sources":["../../src/migrate-worktrees.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Worktree Migration CLI
|
|
4
|
+
*
|
|
5
|
+
* Migrates worktrees from the legacy .worktrees/ directory (inside repo)
|
|
6
|
+
* to the new sibling directory pattern (../{repoName}.wt/).
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* af-migrate-worktrees [options]
|
|
10
|
+
*
|
|
11
|
+
* Options:
|
|
12
|
+
* --dry-run Preview changes without executing
|
|
13
|
+
* --force Move even if processes are using worktrees
|
|
14
|
+
* --help, -h Show this help message
|
|
15
|
+
*/
|
|
16
|
+
import { execSync } from 'child_process';
|
|
17
|
+
import { existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSync } from 'fs';
|
|
18
|
+
import { basename, resolve } from 'path';
|
|
19
|
+
function getGitRoot() {
|
|
20
|
+
try {
|
|
21
|
+
return execSync('git rev-parse --show-toplevel', {
|
|
22
|
+
encoding: 'utf-8',
|
|
23
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
24
|
+
}).trim();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return process.cwd();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function parseArgs() {
|
|
31
|
+
const args = process.argv.slice(2);
|
|
32
|
+
const result = { dryRun: false, force: false };
|
|
33
|
+
for (const arg of args) {
|
|
34
|
+
switch (arg) {
|
|
35
|
+
case '--dry-run':
|
|
36
|
+
result.dryRun = true;
|
|
37
|
+
break;
|
|
38
|
+
case '--force':
|
|
39
|
+
result.force = true;
|
|
40
|
+
break;
|
|
41
|
+
case '--help':
|
|
42
|
+
case '-h':
|
|
43
|
+
printHelp();
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
function printHelp() {
|
|
50
|
+
console.log(`
|
|
51
|
+
AgentFactory Worktree Migration
|
|
52
|
+
|
|
53
|
+
Migrates worktrees from .worktrees/ (inside repo) to ../{repoName}.wt/ (sibling directory).
|
|
54
|
+
This prevents VSCode file watcher crashes when running multiple concurrent agents.
|
|
55
|
+
|
|
56
|
+
Usage:
|
|
57
|
+
af-migrate-worktrees [options]
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
--dry-run Preview changes without executing
|
|
61
|
+
--force Move even if processes are using worktrees
|
|
62
|
+
--help, -h Show this help message
|
|
63
|
+
`);
|
|
64
|
+
}
|
|
65
|
+
function main() {
|
|
66
|
+
const { dryRun, force } = parseArgs();
|
|
67
|
+
const gitRoot = getGitRoot();
|
|
68
|
+
const repoName = basename(gitRoot);
|
|
69
|
+
const legacyDir = resolve(gitRoot, '.worktrees');
|
|
70
|
+
const newDir = resolve(gitRoot, '..', `${repoName}.wt`);
|
|
71
|
+
console.log('\n=== AgentFactory Worktree Migration ===\n');
|
|
72
|
+
if (dryRun) {
|
|
73
|
+
console.log('[DRY RUN MODE - No changes will be made]\n');
|
|
74
|
+
}
|
|
75
|
+
if (!existsSync(legacyDir)) {
|
|
76
|
+
console.log(`No legacy worktrees directory found at ${legacyDir}`);
|
|
77
|
+
console.log('Nothing to migrate.\n');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// List worktree entries (skip hidden directories like .patches)
|
|
81
|
+
const entries = readdirSync(legacyDir).filter(entry => {
|
|
82
|
+
if (entry.startsWith('.'))
|
|
83
|
+
return false;
|
|
84
|
+
try {
|
|
85
|
+
return statSync(resolve(legacyDir, entry)).isDirectory();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
if (entries.length === 0) {
|
|
92
|
+
console.log(`Legacy worktrees directory exists but is empty: ${legacyDir}`);
|
|
93
|
+
if (!dryRun) {
|
|
94
|
+
rmSync(legacyDir, { recursive: true, force: true });
|
|
95
|
+
console.log('Removed empty legacy directory.\n');
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
console.log(`Found ${entries.length} worktree(s) to migrate:`);
|
|
100
|
+
console.log(` From: ${legacyDir}`);
|
|
101
|
+
console.log(` To: ${newDir}\n`);
|
|
102
|
+
// Check for running processes unless --force
|
|
103
|
+
if (!force && !dryRun) {
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
const entryPath = resolve(legacyDir, entry);
|
|
106
|
+
try {
|
|
107
|
+
const lsofOutput = execSync(`lsof +D "${entryPath}" 2>/dev/null || true`, {
|
|
108
|
+
encoding: 'utf-8',
|
|
109
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
110
|
+
}).trim();
|
|
111
|
+
if (lsofOutput) {
|
|
112
|
+
console.log(`WARNING: Processes are using worktree ${entry}:`);
|
|
113
|
+
console.log(` ${lsofOutput.split('\n')[0]}`);
|
|
114
|
+
console.log(' Use --force to move anyway, or stop the processes first.\n');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// lsof not available or failed, skip check
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Ensure target directory exists
|
|
124
|
+
if (!dryRun && !existsSync(newDir)) {
|
|
125
|
+
mkdirSync(newDir, { recursive: true });
|
|
126
|
+
}
|
|
127
|
+
let migrated = 0;
|
|
128
|
+
let failed = 0;
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
const oldPath = resolve(legacyDir, entry);
|
|
131
|
+
const newPath = resolve(newDir, entry);
|
|
132
|
+
console.log(` ${entry}:`);
|
|
133
|
+
console.log(` ${oldPath} -> ${newPath}`);
|
|
134
|
+
if (dryRun) {
|
|
135
|
+
console.log(' [DRY RUN] Would move\n');
|
|
136
|
+
migrated++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (existsSync(newPath)) {
|
|
140
|
+
console.log(` SKIPPED: Target already exists\n`);
|
|
141
|
+
failed++;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
// Try git worktree move first (preferred — updates git tracking)
|
|
146
|
+
execSync(`git worktree move "${oldPath}" "${newPath}"`, {
|
|
147
|
+
stdio: 'pipe',
|
|
148
|
+
encoding: 'utf-8',
|
|
149
|
+
cwd: gitRoot,
|
|
150
|
+
});
|
|
151
|
+
console.log(' OK (git worktree move)\n');
|
|
152
|
+
migrated++;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Fallback: manual move + repair
|
|
156
|
+
try {
|
|
157
|
+
renameSync(oldPath, newPath);
|
|
158
|
+
execSync(`git worktree repair`, {
|
|
159
|
+
stdio: 'pipe',
|
|
160
|
+
encoding: 'utf-8',
|
|
161
|
+
cwd: gitRoot,
|
|
162
|
+
});
|
|
163
|
+
console.log(' OK (manual move + repair)\n');
|
|
164
|
+
migrated++;
|
|
165
|
+
}
|
|
166
|
+
catch (fallbackError) {
|
|
167
|
+
console.log(` FAILED: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}\n`);
|
|
168
|
+
failed++;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Move .patches directory if it exists
|
|
173
|
+
const legacyPatchDir = resolve(legacyDir, '.patches');
|
|
174
|
+
if (existsSync(legacyPatchDir)) {
|
|
175
|
+
const newPatchDir = resolve(newDir, '.patches');
|
|
176
|
+
if (!dryRun) {
|
|
177
|
+
try {
|
|
178
|
+
renameSync(legacyPatchDir, newPatchDir);
|
|
179
|
+
console.log(' Moved .patches directory\n');
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
console.log(` Failed to move .patches: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
console.log(' [DRY RUN] Would move .patches directory\n');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Clean up empty legacy directory
|
|
190
|
+
if (!dryRun && migrated > 0) {
|
|
191
|
+
try {
|
|
192
|
+
const remaining = readdirSync(legacyDir);
|
|
193
|
+
if (remaining.length === 0) {
|
|
194
|
+
rmSync(legacyDir, { recursive: true, force: true });
|
|
195
|
+
console.log(`Removed empty legacy directory: ${legacyDir}\n`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.log(`Legacy directory not empty (${remaining.length} remaining entries), keeping it.\n`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Ignore cleanup errors
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Summary
|
|
206
|
+
console.log('=== Summary ===\n');
|
|
207
|
+
console.log(` Migrated: ${migrated}`);
|
|
208
|
+
if (failed > 0) {
|
|
209
|
+
console.log(` Failed: ${failed}`);
|
|
210
|
+
}
|
|
211
|
+
console.log('');
|
|
212
|
+
// Verify git tracking
|
|
213
|
+
if (!dryRun && migrated > 0) {
|
|
214
|
+
try {
|
|
215
|
+
const worktreeList = execSync('git worktree list', {
|
|
216
|
+
encoding: 'utf-8',
|
|
217
|
+
cwd: gitRoot,
|
|
218
|
+
}).trim();
|
|
219
|
+
console.log('Git worktree list after migration:');
|
|
220
|
+
console.log(worktreeList);
|
|
221
|
+
console.log('');
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Ignore
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (failed > 0) {
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
main();
|
package/dist/src/orchestrator.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import path from 'path';
|
|
21
21
|
import { config } from 'dotenv';
|
|
22
22
|
// Load environment variables from .env.local
|
|
23
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
23
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
24
24
|
import { runOrchestrator } from './lib/orchestrator-runner.js';
|
|
25
25
|
import { getVersion, checkForUpdate, printUpdateNotification } from './lib/version.js';
|
|
26
26
|
function parseArgs() {
|
package/dist/src/queue-admin.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import path from 'path';
|
|
25
25
|
import { config } from 'dotenv';
|
|
26
26
|
// Load environment variables from .env.local in CWD
|
|
27
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
27
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
28
28
|
import { runQueueAdmin, C } from './lib/queue-admin-runner.js';
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
// Usage
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Setup CLI
|
|
4
|
+
*
|
|
5
|
+
* Configure development tools for agent workflows.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* af-setup <tool> [options]
|
|
9
|
+
* agentfactory setup <tool> [options]
|
|
10
|
+
*
|
|
11
|
+
* Tools:
|
|
12
|
+
* mergiraf Configure mergiraf AST-aware merge driver
|
|
13
|
+
*
|
|
14
|
+
* Options:
|
|
15
|
+
* --dry-run Show what would be done without making changes
|
|
16
|
+
* --worktree-only Only configure for agent worktrees
|
|
17
|
+
* --skip-check Skip mergiraf binary availability check
|
|
18
|
+
* --help, -h Show this help message
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/setup.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Setup CLI
|
|
4
|
+
*
|
|
5
|
+
* Configure development tools for agent workflows.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* af-setup <tool> [options]
|
|
9
|
+
* agentfactory setup <tool> [options]
|
|
10
|
+
*
|
|
11
|
+
* Tools:
|
|
12
|
+
* mergiraf Configure mergiraf AST-aware merge driver
|
|
13
|
+
*
|
|
14
|
+
* Options:
|
|
15
|
+
* --dry-run Show what would be done without making changes
|
|
16
|
+
* --worktree-only Only configure for agent worktrees
|
|
17
|
+
* --skip-check Skip mergiraf binary availability check
|
|
18
|
+
* --help, -h Show this help message
|
|
19
|
+
*/
|
|
20
|
+
import { setupMergiraf, getGitRoot } from './lib/setup-mergiraf-runner.js';
|
|
21
|
+
function parseArgs() {
|
|
22
|
+
const args = process.argv.slice(2);
|
|
23
|
+
const result = {
|
|
24
|
+
subcommand: undefined,
|
|
25
|
+
dryRun: false,
|
|
26
|
+
worktreeOnly: false,
|
|
27
|
+
skipCheck: false,
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
switch (arg) {
|
|
32
|
+
case '--dry-run':
|
|
33
|
+
result.dryRun = true;
|
|
34
|
+
break;
|
|
35
|
+
case '--worktree-only':
|
|
36
|
+
result.worktreeOnly = true;
|
|
37
|
+
break;
|
|
38
|
+
case '--skip-check':
|
|
39
|
+
result.skipCheck = true;
|
|
40
|
+
break;
|
|
41
|
+
case '--help':
|
|
42
|
+
case '-h':
|
|
43
|
+
printHelp();
|
|
44
|
+
process.exit(0);
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
// First non-flag argument is the subcommand (skip 'setup' if present)
|
|
48
|
+
if (!arg.startsWith('-') && arg !== 'setup') {
|
|
49
|
+
result.subcommand = arg;
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function printHelp() {
|
|
57
|
+
console.log(`
|
|
58
|
+
AgentFactory Setup - Configure development tools for agent workflows
|
|
59
|
+
|
|
60
|
+
Usage:
|
|
61
|
+
af-setup <tool> [options]
|
|
62
|
+
agentfactory setup <tool> [options]
|
|
63
|
+
|
|
64
|
+
Tools:
|
|
65
|
+
mergiraf Configure mergiraf AST-aware merge driver
|
|
66
|
+
|
|
67
|
+
Options:
|
|
68
|
+
--dry-run Show what would be done without making changes
|
|
69
|
+
--worktree-only Only configure for agent worktrees (not whole repo)
|
|
70
|
+
--skip-check Skip mergiraf binary availability check
|
|
71
|
+
--help, -h Show this help message
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
# Configure mergiraf for the entire repository
|
|
75
|
+
af-setup mergiraf
|
|
76
|
+
|
|
77
|
+
# Configure only for agent worktrees (recommended)
|
|
78
|
+
af-setup mergiraf --worktree-only
|
|
79
|
+
|
|
80
|
+
# Preview changes without modifying anything
|
|
81
|
+
af-setup mergiraf --dry-run
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
function printSummary(result) {
|
|
85
|
+
console.log('=== Summary ===\n');
|
|
86
|
+
if (result.mergirafFound) {
|
|
87
|
+
console.log(` Mergiraf: found (${result.mergirafVersion})`);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(' Mergiraf: NOT FOUND');
|
|
91
|
+
}
|
|
92
|
+
if (result.configuredFileTypes.length > 0) {
|
|
93
|
+
console.log(` File types: ${result.configuredFileTypes.join(', ')}`);
|
|
94
|
+
}
|
|
95
|
+
console.log(` .gitattributes: ${result.gitattributesWritten ? 'configured' : 'not configured'}`);
|
|
96
|
+
console.log(` Merge driver: ${result.mergeDriverConfigured ? 'configured' : 'not configured'}`);
|
|
97
|
+
console.log(` Worktree mode: ${result.worktreeMode ? 'yes' : 'no (repo-wide)'}`);
|
|
98
|
+
console.log(` Repo config: ${result.repoConfigUpdated ? 'updated' : 'not updated'}`);
|
|
99
|
+
if (result.errors.length > 0) {
|
|
100
|
+
console.log('\n Errors:');
|
|
101
|
+
for (const err of result.errors) {
|
|
102
|
+
console.log(` - ${err}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (result.gitattributesWritten && result.mergeDriverConfigured) {
|
|
106
|
+
console.log('\n See: https://github.com/RenseiAI/agentfactory/blob/main/docs/guides/mergiraf-setup.md');
|
|
107
|
+
}
|
|
108
|
+
console.log('');
|
|
109
|
+
}
|
|
110
|
+
// Main execution
|
|
111
|
+
function main() {
|
|
112
|
+
const args = parseArgs();
|
|
113
|
+
if (!args.subcommand) {
|
|
114
|
+
console.error('Error: No tool specified.\n');
|
|
115
|
+
printHelp();
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
switch (args.subcommand) {
|
|
119
|
+
case 'mergiraf': {
|
|
120
|
+
console.log('\n=== AgentFactory Setup: Mergiraf ===\n');
|
|
121
|
+
if (args.dryRun) {
|
|
122
|
+
console.log('[DRY RUN MODE - No changes will be made]\n');
|
|
123
|
+
}
|
|
124
|
+
const result = setupMergiraf({
|
|
125
|
+
dryRun: args.dryRun,
|
|
126
|
+
worktreeOnly: args.worktreeOnly,
|
|
127
|
+
skipCheck: args.skipCheck,
|
|
128
|
+
gitRoot: getGitRoot(),
|
|
129
|
+
});
|
|
130
|
+
printSummary(result);
|
|
131
|
+
if (result.errors.length > 0) {
|
|
132
|
+
process.exit(result.exitCode || 1);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
console.error(`Unknown tool: ${args.subcommand}\n`);
|
|
138
|
+
printHelp();
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
main();
|
package/dist/src/status.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import path from 'path';
|
|
18
18
|
import { config } from 'dotenv';
|
|
19
19
|
// Load environment variables from .env.local in CWD
|
|
20
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
20
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
21
21
|
import { runStatus, C } from './lib/status-runner.js';
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
23
23
|
// Usage
|
package/dist/src/worker-fleet.js
CHANGED
|
@@ -25,7 +25,7 @@ import path from 'path';
|
|
|
25
25
|
import os from 'os';
|
|
26
26
|
import { config as loadEnv } from 'dotenv';
|
|
27
27
|
// Load environment variables from .env.local in CWD
|
|
28
|
-
loadEnv({ path: path.resolve(process.cwd(), '.env.local') });
|
|
28
|
+
loadEnv({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
29
29
|
import { runWorkerFleet } from './lib/worker-fleet-runner.js';
|
|
30
30
|
// ANSI colors (kept for help output)
|
|
31
31
|
const colors = {
|
package/dist/src/worker.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import path from 'path';
|
|
26
26
|
import { config } from 'dotenv';
|
|
27
27
|
// Load environment variables from .env.local in CWD
|
|
28
|
-
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
28
|
+
config({ path: path.resolve(process.cwd(), '.env.local'), quiet: true });
|
|
29
29
|
import os from 'os';
|
|
30
30
|
import { runWorker } from './lib/worker-runner.js';
|
|
31
31
|
function parseArgs() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@renseiai/agentfactory-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI tools for AgentFactory — local orchestrator, remote worker, queue admin",
|
|
6
6
|
"author": "Rensei AI (https://rensei.ai)",
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
"af-linear": "dist/src/linear.js",
|
|
39
39
|
"af-governor": "dist/src/governor.js",
|
|
40
40
|
"af-sync-routes": "dist/src/sync-routes.js",
|
|
41
|
-
"af-
|
|
41
|
+
"af-setup": "dist/src/setup.js",
|
|
42
|
+
"af-status": "dist/src/status.js",
|
|
43
|
+
"af-migrate-worktrees": "dist/src/migrate-worktrees.js"
|
|
42
44
|
},
|
|
43
45
|
"main": "./dist/src/index.js",
|
|
44
46
|
"module": "./dist/src/index.js",
|
|
@@ -94,6 +96,11 @@
|
|
|
94
96
|
"import": "./dist/src/lib/sync-routes-runner.js",
|
|
95
97
|
"default": "./dist/src/lib/sync-routes-runner.js"
|
|
96
98
|
},
|
|
99
|
+
"./setup": {
|
|
100
|
+
"types": "./dist/src/lib/setup-mergiraf-runner.d.ts",
|
|
101
|
+
"import": "./dist/src/lib/setup-mergiraf-runner.js",
|
|
102
|
+
"default": "./dist/src/lib/setup-mergiraf-runner.js"
|
|
103
|
+
},
|
|
97
104
|
"./status": {
|
|
98
105
|
"types": "./dist/src/lib/status-runner.d.ts",
|
|
99
106
|
"import": "./dist/src/lib/status-runner.js",
|
|
@@ -107,10 +114,10 @@
|
|
|
107
114
|
],
|
|
108
115
|
"dependencies": {
|
|
109
116
|
"dotenv": "^17.2.3",
|
|
110
|
-
"@renseiai/agentfactory": "0.8.
|
|
111
|
-
"@renseiai/
|
|
112
|
-
"@renseiai/
|
|
113
|
-
"@renseiai/agentfactory
|
|
117
|
+
"@renseiai/agentfactory-server": "0.8.11",
|
|
118
|
+
"@renseiai/agentfactory-code-intelligence": "0.8.11",
|
|
119
|
+
"@renseiai/plugin-linear": "0.8.11",
|
|
120
|
+
"@renseiai/agentfactory": "0.8.11"
|
|
114
121
|
},
|
|
115
122
|
"devDependencies": {
|
|
116
123
|
"@types/node": "^22.5.4",
|