@renseiai/agentfactory-cli 0.8.6 → 0.8.8
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/cleanup.d.ts +8 -6
- package/dist/src/cleanup.d.ts.map +1 -1
- package/dist/src/cleanup.js +74 -30
- 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/agent-runner.d.ts.map +1 -1
- package/dist/src/lib/agent-runner.js +18 -7
- package/dist/src/lib/cleanup-runner.d.ts +16 -1
- package/dist/src/lib/cleanup-runner.d.ts.map +1 -1
- package/dist/src/lib/cleanup-runner.js +151 -1
- package/dist/src/lib/governor-dependencies.d.ts +1 -1
- package/dist/src/lib/governor-dependencies.d.ts.map +1 -1
- package/dist/src/lib/governor-dependencies.js +2 -0
- package/dist/src/lib/governor-logger.d.ts +1 -1
- package/dist/src/lib/governor-logger.d.ts.map +1 -1
- package/dist/src/lib/linear-runner.d.ts +3 -3
- package/dist/src/lib/linear-runner.d.ts.map +1 -1
- package/dist/src/lib/linear-runner.js +3 -3
- package/dist/src/lib/orchestrator-runner.d.ts.map +1 -1
- package/dist/src/lib/orchestrator-runner.js +7 -0
- package/dist/src/lib/status-runner.d.ts +27 -0
- package/dist/src/lib/status-runner.d.ts.map +1 -0
- package/dist/src/lib/status-runner.js +101 -0
- package/dist/src/lib/worker-runner.d.ts.map +1 -1
- package/dist/src/lib/worker-runner.js +87 -44
- package/dist/src/linear.d.ts +1 -0
- package/dist/src/linear.d.ts.map +1 -1
- package/dist/src/linear.js +2 -0
- package/dist/src/status.d.ts +18 -0
- package/dist/src/status.d.ts.map +1 -0
- package/dist/src/status.js +78 -0
- package/package.json +12 -5
package/dist/src/cleanup.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* AgentFactory
|
|
3
|
+
* AgentFactory Cleanup CLI
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Cleans up orphaned git worktrees and stale local branches.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* af-cleanup [options]
|
|
9
9
|
*
|
|
10
10
|
* Options:
|
|
11
|
-
* --dry-run
|
|
12
|
-
* --force
|
|
13
|
-
* --path <dir>
|
|
14
|
-
* --
|
|
11
|
+
* --dry-run Show what would be cleaned up without removing anything
|
|
12
|
+
* --force Force removal / include branches with gone remotes
|
|
13
|
+
* --path <dir> Custom worktrees directory (default: .worktrees)
|
|
14
|
+
* --skip-worktrees Skip worktree cleanup
|
|
15
|
+
* --skip-branches Skip branch cleanup
|
|
16
|
+
* --help, -h Show this help message
|
|
15
17
|
*/
|
|
16
18
|
export {};
|
|
17
19
|
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/cleanup.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/cleanup.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|
package/dist/src/cleanup.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* AgentFactory
|
|
3
|
+
* AgentFactory Cleanup CLI
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Cleans up orphaned git worktrees and stale local branches.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* af-cleanup [options]
|
|
9
9
|
*
|
|
10
10
|
* Options:
|
|
11
|
-
* --dry-run
|
|
12
|
-
* --force
|
|
13
|
-
* --path <dir>
|
|
14
|
-
* --
|
|
11
|
+
* --dry-run Show what would be cleaned up without removing anything
|
|
12
|
+
* --force Force removal / include branches with gone remotes
|
|
13
|
+
* --path <dir> Custom worktrees directory (default: .worktrees)
|
|
14
|
+
* --skip-worktrees Skip worktree cleanup
|
|
15
|
+
* --skip-branches Skip branch cleanup
|
|
16
|
+
* --help, -h Show this help message
|
|
15
17
|
*/
|
|
16
18
|
import { basename } from 'path';
|
|
17
19
|
import { runCleanup, getGitRoot } from './lib/cleanup-runner.js';
|
|
@@ -21,6 +23,8 @@ function parseArgs() {
|
|
|
21
23
|
dryRun: false,
|
|
22
24
|
force: false,
|
|
23
25
|
worktreePath: undefined,
|
|
26
|
+
skipWorktrees: false,
|
|
27
|
+
skipBranches: false,
|
|
24
28
|
};
|
|
25
29
|
for (let i = 0; i < args.length; i++) {
|
|
26
30
|
const arg = args[i];
|
|
@@ -34,6 +38,12 @@ function parseArgs() {
|
|
|
34
38
|
case '--path':
|
|
35
39
|
result.worktreePath = args[++i];
|
|
36
40
|
break;
|
|
41
|
+
case '--skip-worktrees':
|
|
42
|
+
result.skipWorktrees = true;
|
|
43
|
+
break;
|
|
44
|
+
case '--skip-branches':
|
|
45
|
+
result.skipBranches = true;
|
|
46
|
+
break;
|
|
37
47
|
case '--help':
|
|
38
48
|
case '-h':
|
|
39
49
|
printHelp();
|
|
@@ -44,67 +54,101 @@ function parseArgs() {
|
|
|
44
54
|
}
|
|
45
55
|
function printHelp() {
|
|
46
56
|
console.log(`
|
|
47
|
-
AgentFactory
|
|
57
|
+
AgentFactory Cleanup - Remove orphaned worktrees and stale branches
|
|
48
58
|
|
|
49
59
|
Usage:
|
|
50
60
|
af-cleanup [options]
|
|
51
61
|
|
|
52
62
|
Options:
|
|
53
|
-
--dry-run
|
|
54
|
-
--force
|
|
55
|
-
--path <dir>
|
|
56
|
-
--
|
|
63
|
+
--dry-run Show what would be cleaned up without removing
|
|
64
|
+
--force Force worktree removal + delete branches with gone remotes
|
|
65
|
+
--path <dir> Custom worktrees directory (default: .worktrees)
|
|
66
|
+
--skip-worktrees Skip worktree cleanup
|
|
67
|
+
--skip-branches Skip branch cleanup
|
|
68
|
+
--help, -h Show this help message
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
Worktree cleanup:
|
|
71
|
+
Orphaned worktrees are identified by:
|
|
72
|
+
- Branch no longer exists (merged/deleted)
|
|
73
|
+
- Not listed in 'git worktree list' (stale directory)
|
|
74
|
+
|
|
75
|
+
Branch cleanup:
|
|
76
|
+
By default, deletes local branches already merged into main.
|
|
77
|
+
With --force, also deletes branches whose remote tracking branch is gone.
|
|
62
78
|
|
|
63
79
|
Examples:
|
|
64
80
|
# Preview what would be cleaned up
|
|
65
81
|
af-cleanup --dry-run
|
|
66
82
|
|
|
67
|
-
# Clean up orphaned worktrees
|
|
83
|
+
# Clean up everything (merged branches + orphaned worktrees)
|
|
68
84
|
af-cleanup
|
|
69
85
|
|
|
70
|
-
#
|
|
86
|
+
# Aggressive cleanup (includes branches with gone remotes)
|
|
71
87
|
af-cleanup --force
|
|
88
|
+
|
|
89
|
+
# Only clean up branches
|
|
90
|
+
af-cleanup --skip-worktrees
|
|
91
|
+
|
|
92
|
+
# Only clean up worktrees
|
|
93
|
+
af-cleanup --skip-branches
|
|
72
94
|
`);
|
|
73
95
|
}
|
|
74
96
|
function printSummary(result) {
|
|
75
97
|
console.log('=== Summary ===\n');
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
console.log(`
|
|
98
|
+
if (result.scanned > 0 || result.orphaned > 0) {
|
|
99
|
+
console.log(' Worktrees:');
|
|
100
|
+
console.log(` Scanned: ${result.scanned}`);
|
|
101
|
+
console.log(` Orphaned: ${result.orphaned}`);
|
|
102
|
+
console.log(` Cleaned: ${result.cleaned}`);
|
|
103
|
+
if (result.skipped > 0) {
|
|
104
|
+
console.log(` Skipped: ${result.skipped} (IDE/process still open — use --force)`);
|
|
105
|
+
}
|
|
106
|
+
if (result.errors.length > 0) {
|
|
107
|
+
console.log(` Errors: ${result.errors.length}`);
|
|
108
|
+
for (const err of result.errors) {
|
|
109
|
+
console.log(` - ${basename(err.path)}: ${err.error}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
console.log('');
|
|
81
113
|
}
|
|
82
|
-
if (result.
|
|
83
|
-
console.log(
|
|
84
|
-
|
|
85
|
-
|
|
114
|
+
if (result.branches.scanned > 0 || result.branches.deleted > 0) {
|
|
115
|
+
console.log(' Branches:');
|
|
116
|
+
console.log(` Scanned: ${result.branches.scanned}`);
|
|
117
|
+
console.log(` Deleted: ${result.branches.deleted}`);
|
|
118
|
+
if (result.branches.errors.length > 0) {
|
|
119
|
+
console.log(` Errors: ${result.branches.errors.length}`);
|
|
120
|
+
for (const err of result.branches.errors) {
|
|
121
|
+
console.log(` - ${err.branch}: ${err.error}`);
|
|
122
|
+
}
|
|
86
123
|
}
|
|
124
|
+
console.log('');
|
|
125
|
+
}
|
|
126
|
+
const totalErrors = result.errors.length + result.branches.errors.length;
|
|
127
|
+
if (totalErrors === 0 && result.cleaned === 0 && result.branches.deleted === 0) {
|
|
128
|
+
console.log(' Nothing to clean up.\n');
|
|
87
129
|
}
|
|
88
|
-
console.log('');
|
|
89
130
|
}
|
|
90
131
|
// Main execution
|
|
91
132
|
function main() {
|
|
92
133
|
const args = parseArgs();
|
|
93
|
-
console.log('\n=== AgentFactory
|
|
134
|
+
console.log('\n=== AgentFactory Cleanup ===\n');
|
|
94
135
|
if (args.dryRun) {
|
|
95
136
|
console.log('[DRY RUN MODE - No changes will be made]\n');
|
|
96
137
|
}
|
|
97
138
|
if (args.force) {
|
|
98
|
-
console.log('[FORCE MODE -
|
|
139
|
+
console.log('[FORCE MODE - Aggressive cleanup enabled]\n');
|
|
99
140
|
}
|
|
100
141
|
const result = runCleanup({
|
|
101
142
|
dryRun: args.dryRun,
|
|
102
143
|
force: args.force,
|
|
103
144
|
worktreePath: args.worktreePath,
|
|
104
145
|
gitRoot: getGitRoot(),
|
|
146
|
+
skipWorktrees: args.skipWorktrees,
|
|
147
|
+
skipBranches: args.skipBranches,
|
|
105
148
|
});
|
|
106
149
|
printSummary(result);
|
|
107
|
-
|
|
150
|
+
const totalErrors = result.errors.length + result.branches.errors.length;
|
|
151
|
+
if (totalErrors > 0) {
|
|
108
152
|
process.exit(1);
|
|
109
153
|
}
|
|
110
154
|
}
|
package/dist/src/governor.js
CHANGED
|
@@ -31,7 +31,7 @@ import { createRealDependencies } from './lib/governor-dependencies.js';
|
|
|
31
31
|
import { printStartupBanner, printScanSummary, printCircuitBreakerWarning, } from './lib/governor-logger.js';
|
|
32
32
|
import { getVersion, checkForUpdate, printUpdateNotification } from './lib/version.js';
|
|
33
33
|
import { maybeAutoUpdate } from './lib/auto-updater.js';
|
|
34
|
-
import { createLinearAgentClient } from '@renseiai/
|
|
34
|
+
import { createLinearAgentClient } from '@renseiai/plugin-linear';
|
|
35
35
|
import { createLogger, initTouchpointStorage } from '@renseiai/agentfactory';
|
|
36
36
|
import { RedisOverrideStorage, listStoredWorkspaces, getAccessToken, createRedisTokenBucket, createRedisCircuitBreaker, } from '@renseiai/agentfactory-server';
|
|
37
37
|
// ---------------------------------------------------------------------------
|
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,CAyBzB"}
|
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
|
+
status Show fleet status (inline one-line summary)
|
|
28
29
|
help Show this help message
|
|
29
30
|
|
|
30
31
|
Run 'agentfactory <command> --help' for command-specific options.
|
|
@@ -63,6 +64,9 @@ switch (command) {
|
|
|
63
64
|
case 'sync-routes':
|
|
64
65
|
import('./sync-routes');
|
|
65
66
|
break;
|
|
67
|
+
case 'status':
|
|
68
|
+
import('./status');
|
|
69
|
+
break;
|
|
66
70
|
case 'help':
|
|
67
71
|
case '--help':
|
|
68
72
|
case '-h':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/agent-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAA;AAE5E,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,OAAO,EAAE,YAAY,CAAA;IACrB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAMD,eAAO,MAAM,CAAC;;;;;;;CAOJ,CAAA;
|
|
1
|
+
{"version":3,"file":"agent-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/agent-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAA;AAE5E,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,OAAO,EAAE,YAAY,CAAA;IACrB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wEAAwE;IACxE,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAMD,eAAO,MAAM,CAAC;;;;;;;CAOJ,CAAA;AA8RV,wBAAsB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBvE"}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* agent sessions. Works by updating Redis state directly — workers poll for
|
|
6
6
|
* status changes and pending prompts every 5 seconds.
|
|
7
7
|
*/
|
|
8
|
-
import { getRedisClient, getAllSessions, updateSessionStatus, storeSessionState,
|
|
9
|
-
import { createLinearAgentClient } from '@renseiai/
|
|
8
|
+
import { getRedisClient, getAllSessions, updateSessionStatus, storeSessionState, publishUrgent, disconnectRedis, } from '@renseiai/agentfactory-server';
|
|
9
|
+
import { createLinearAgentClient } from '@renseiai/plugin-linear';
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
// ANSI colors
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
@@ -114,12 +114,23 @@ async function chatWithAgent(issueId, message) {
|
|
|
114
114
|
await disconnectRedis();
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
119
|
-
console.
|
|
117
|
+
const agentId = session.agentId;
|
|
118
|
+
if (!agentId) {
|
|
119
|
+
console.error(`${C.red}Session has no agentId — cannot publish to inbox${C.reset}`);
|
|
120
|
+
await disconnectRedis();
|
|
121
|
+
return;
|
|
120
122
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
try {
|
|
124
|
+
const streamId = await publishUrgent(agentId, {
|
|
125
|
+
type: 'directive',
|
|
126
|
+
sessionId: session.linearSessionId,
|
|
127
|
+
payload: message,
|
|
128
|
+
createdAt: Date.now(),
|
|
129
|
+
});
|
|
130
|
+
console.log(`${C.green}Message queued${C.reset} (id: ${streamId}) — worker will pick up within ~5 seconds`);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
console.error(`${C.red}Failed to publish to inbox: ${err instanceof Error ? err.message : String(err)}${C.reset}`);
|
|
123
134
|
}
|
|
124
135
|
await disconnectRedis();
|
|
125
136
|
}
|
|
@@ -13,8 +13,12 @@ export interface CleanupRunnerConfig {
|
|
|
13
13
|
worktreePath?: string;
|
|
14
14
|
/** Git root for default worktree path (default: auto-detect) */
|
|
15
15
|
gitRoot?: string;
|
|
16
|
+
/** Skip worktree cleanup (default: false) */
|
|
17
|
+
skipWorktrees?: boolean;
|
|
18
|
+
/** Skip branch cleanup (default: false) */
|
|
19
|
+
skipBranches?: boolean;
|
|
16
20
|
}
|
|
17
|
-
export interface
|
|
21
|
+
export interface WorktreeCleanupResult {
|
|
18
22
|
scanned: number;
|
|
19
23
|
orphaned: number;
|
|
20
24
|
cleaned: number;
|
|
@@ -24,6 +28,17 @@ export interface CleanupResult {
|
|
|
24
28
|
error: string;
|
|
25
29
|
}>;
|
|
26
30
|
}
|
|
31
|
+
export interface CleanupResult extends WorktreeCleanupResult {
|
|
32
|
+
branches: BranchCleanupResult;
|
|
33
|
+
}
|
|
34
|
+
export interface BranchCleanupResult {
|
|
35
|
+
scanned: number;
|
|
36
|
+
deleted: number;
|
|
37
|
+
errors: Array<{
|
|
38
|
+
branch: string;
|
|
39
|
+
error: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
27
42
|
export declare function getGitRoot(): string;
|
|
28
43
|
export declare function runCleanup(config?: CleanupRunnerConfig): CleanupResult;
|
|
29
44
|
//# sourceMappingURL=cleanup-runner.d.ts.map
|
|
@@ -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,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
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,iEAAiE;IACjE,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,CAkBtE"}
|
|
@@ -282,6 +282,150 @@ function cleanup(options) {
|
|
|
282
282
|
return result;
|
|
283
283
|
}
|
|
284
284
|
// ---------------------------------------------------------------------------
|
|
285
|
+
// Branch cleanup
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
/**
|
|
288
|
+
* Get the current branch name (to avoid deleting it).
|
|
289
|
+
*/
|
|
290
|
+
function getCurrentBranch() {
|
|
291
|
+
try {
|
|
292
|
+
return execSync('git rev-parse --abbrev-ref HEAD', {
|
|
293
|
+
encoding: 'utf-8',
|
|
294
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
295
|
+
}).trim();
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return '';
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get branches that have been merged into the given base branch.
|
|
303
|
+
*/
|
|
304
|
+
function getMergedBranches(baseBranch) {
|
|
305
|
+
try {
|
|
306
|
+
const output = execSync(`git branch --merged ${baseBranch}`, {
|
|
307
|
+
encoding: 'utf-8',
|
|
308
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
309
|
+
});
|
|
310
|
+
return output
|
|
311
|
+
.split('\n')
|
|
312
|
+
.map((line) => line.replace(/^[*+]?\s+/, '').trim())
|
|
313
|
+
.filter((b) => b && b !== baseBranch);
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return [];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get local branches whose remote tracking branch is gone.
|
|
321
|
+
*/
|
|
322
|
+
function getGoneBranches() {
|
|
323
|
+
try {
|
|
324
|
+
// Fetch prune first so we have up-to-date remote state
|
|
325
|
+
execSync('git fetch --prune 2>/dev/null || true', {
|
|
326
|
+
encoding: 'utf-8',
|
|
327
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
328
|
+
timeout: 15000,
|
|
329
|
+
});
|
|
330
|
+
const output = execSync('git branch -vv', {
|
|
331
|
+
encoding: 'utf-8',
|
|
332
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
333
|
+
});
|
|
334
|
+
const gone = [];
|
|
335
|
+
for (const line of output.split('\n')) {
|
|
336
|
+
// Match lines like " SUP-123 abc1234 [origin/SUP-123: gone] commit msg"
|
|
337
|
+
if (/\[.*: gone\]/.test(line)) {
|
|
338
|
+
const branch = line.replace(/^\*?\s+/, '').split(/\s+/)[0];
|
|
339
|
+
if (branch)
|
|
340
|
+
gone.push(branch);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return gone;
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return [];
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Clean up stale local branches.
|
|
351
|
+
*
|
|
352
|
+
* Default: deletes branches merged into main.
|
|
353
|
+
* With force: also deletes branches whose remote tracking branch is gone.
|
|
354
|
+
*/
|
|
355
|
+
function cleanupBranches(options) {
|
|
356
|
+
const result = {
|
|
357
|
+
scanned: 0,
|
|
358
|
+
deleted: 0,
|
|
359
|
+
errors: [],
|
|
360
|
+
};
|
|
361
|
+
// Prune stale worktree metadata first so that branches from prunable
|
|
362
|
+
// worktrees (e.g. research agents) are no longer locked.
|
|
363
|
+
try {
|
|
364
|
+
execSync('git worktree prune', {
|
|
365
|
+
encoding: 'utf-8',
|
|
366
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
// Ignore prune errors
|
|
371
|
+
}
|
|
372
|
+
console.log('Scanning local branches...\n');
|
|
373
|
+
const currentBranch = getCurrentBranch();
|
|
374
|
+
// Determine the base branch (main or master)
|
|
375
|
+
const baseBranch = branchExists('main') ? 'main' : branchExists('master') ? 'master' : '';
|
|
376
|
+
if (!baseBranch) {
|
|
377
|
+
console.log('Could not determine base branch (main/master). Skipping branch cleanup.\n');
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
// Collect branches to delete
|
|
381
|
+
const toDelete = new Set();
|
|
382
|
+
const mergedBranches = getMergedBranches(baseBranch);
|
|
383
|
+
for (const b of mergedBranches) {
|
|
384
|
+
toDelete.add(b);
|
|
385
|
+
}
|
|
386
|
+
if (options.force) {
|
|
387
|
+
const goneBranches = getGoneBranches();
|
|
388
|
+
for (const b of goneBranches) {
|
|
389
|
+
toDelete.add(b);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Never delete base branch or current branch
|
|
393
|
+
toDelete.delete(baseBranch);
|
|
394
|
+
toDelete.delete(currentBranch);
|
|
395
|
+
result.scanned = toDelete.size;
|
|
396
|
+
if (toDelete.size === 0) {
|
|
397
|
+
console.log('No stale branches found.\n');
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
const merged = new Set(mergedBranches);
|
|
401
|
+
const sorted = [...toDelete].sort();
|
|
402
|
+
for (const branch of sorted) {
|
|
403
|
+
const isMerged = merged.has(branch);
|
|
404
|
+
const reason = isMerged ? 'merged' : 'remote gone';
|
|
405
|
+
if (options.dryRun) {
|
|
406
|
+
console.log(` Would delete: ${branch} (${reason})`);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
// Use -d for merged, -D for gone (unmerged)
|
|
410
|
+
const flag = isMerged ? '-d' : '-D';
|
|
411
|
+
try {
|
|
412
|
+
execSync(`git branch ${flag} "${branch}"`, {
|
|
413
|
+
encoding: 'utf-8',
|
|
414
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
415
|
+
});
|
|
416
|
+
console.log(` deleted: ${branch} (${reason})`);
|
|
417
|
+
result.deleted++;
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
421
|
+
console.log(` FAILED: ${branch} — ${msg}`);
|
|
422
|
+
result.errors.push({ branch, error: msg });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
console.log('');
|
|
426
|
+
return result;
|
|
427
|
+
}
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
285
429
|
// Runner
|
|
286
430
|
// ---------------------------------------------------------------------------
|
|
287
431
|
export function runCleanup(config) {
|
|
@@ -291,5 +435,11 @@ export function runCleanup(config) {
|
|
|
291
435
|
force: config?.force ?? false,
|
|
292
436
|
worktreePath: config?.worktreePath ?? resolve(gitRoot, '.worktrees'),
|
|
293
437
|
};
|
|
294
|
-
|
|
438
|
+
const worktreeResult = config?.skipWorktrees
|
|
439
|
+
? { scanned: 0, orphaned: 0, cleaned: 0, skipped: 0, errors: [] }
|
|
440
|
+
: cleanup(options);
|
|
441
|
+
const branchResult = config?.skipBranches
|
|
442
|
+
? { scanned: 0, deleted: 0, errors: [] }
|
|
443
|
+
: cleanupBranches(options);
|
|
444
|
+
return { ...worktreeResult, branches: branchResult };
|
|
295
445
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* using the Linear SDK (via LinearAgentClient) and Redis storage
|
|
6
6
|
* (from @renseiai/agentfactory-server).
|
|
7
7
|
*/
|
|
8
|
-
import type { LinearAgentClient, WorkflowContext } from '@renseiai/
|
|
8
|
+
import type { LinearAgentClient, WorkflowContext } from '@renseiai/plugin-linear';
|
|
9
9
|
import type { GovernorDependencies } from '@renseiai/agentfactory';
|
|
10
10
|
export interface RealDependenciesConfig {
|
|
11
11
|
linearClient: LinearAgentClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governor-dependencies.d.ts","sourceRoot":"","sources":["../../../src/lib/governor-dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"governor-dependencies.d.ts","sourceRoot":"","sources":["../../../src/lib/governor-dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACjF,OAAO,KAAK,EACV,oBAAoB,EAGrB,MAAM,wBAAwB,CAAA;AAiC/B,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,iBAAiB,CAAA;IAC/B,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,eAAe,KAAK,MAAM,CAAA;CAC9H;AA6BD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,oBAAoB,CA8TtB"}
|
|
@@ -252,6 +252,8 @@ export function createRealDependencies(config) {
|
|
|
252
252
|
if (parentIssueIds.has(issueId)) {
|
|
253
253
|
if (workType === 'development')
|
|
254
254
|
workType = 'coordination';
|
|
255
|
+
else if (workType === 'inflight')
|
|
256
|
+
workType = 'inflight-coordination';
|
|
255
257
|
else if (workType === 'qa')
|
|
256
258
|
workType = 'qa-coordination';
|
|
257
259
|
else if (workType === 'acceptance')
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* to avoid external dependencies like chalk.
|
|
6
6
|
*/
|
|
7
7
|
import type { ScanResult } from '@renseiai/agentfactory';
|
|
8
|
-
import type { LinearApiQuota } from '@renseiai/
|
|
8
|
+
import type { LinearApiQuota } from '@renseiai/plugin-linear';
|
|
9
9
|
export interface StartupBannerConfig {
|
|
10
10
|
version: string;
|
|
11
11
|
projects: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governor-logger.d.ts","sourceRoot":"","sources":["../../../src/lib/governor-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"governor-logger.d.ts","sourceRoot":"","sources":["../../../src/lib/governor-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAkC7D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE;QACR,YAAY,EAAE,OAAO,CAAA;QACrB,mBAAmB,EAAE,OAAO,CAAA;QAC5B,eAAe,EAAE,OAAO,CAAA;QACxB,MAAM,EAAE,OAAO,CAAA;QACf,cAAc,EAAE,OAAO,CAAA;KACxB,CAAA;IACD,cAAc,EAAE,OAAO,CAAA;IACvB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAqFpE;AAMD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,UAAU,EAAE,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,cAAc,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CA6CN;AAMD,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAuC5E;AAMD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAa/D"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Linear CLI Runner — re-exports from @renseiai/
|
|
2
|
+
* Linear CLI Runner — re-exports from @renseiai/plugin-linear.
|
|
3
3
|
*
|
|
4
|
-
* The canonical implementation lives in packages/
|
|
4
|
+
* The canonical implementation lives in packages/linear/src/tools/linear-runner.ts
|
|
5
5
|
* so both the CLI and the in-process tool plugin share a single source of truth.
|
|
6
6
|
*/
|
|
7
|
-
export { runLinear, parseLinearArgs, type LinearRunnerConfig, type LinearRunnerResult, } from '@renseiai/
|
|
7
|
+
export { runLinear, parseLinearArgs, type LinearRunnerConfig, type LinearRunnerResult, } from '@renseiai/plugin-linear';
|
|
8
8
|
//# sourceMappingURL=linear-runner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/linear-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,SAAS,EACT,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,
|
|
1
|
+
{"version":3,"file":"linear-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/linear-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,SAAS,EACT,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Linear CLI Runner — re-exports from @renseiai/
|
|
2
|
+
* Linear CLI Runner — re-exports from @renseiai/plugin-linear.
|
|
3
3
|
*
|
|
4
|
-
* The canonical implementation lives in packages/
|
|
4
|
+
* The canonical implementation lives in packages/linear/src/tools/linear-runner.ts
|
|
5
5
|
* so both the CLI and the in-process tool plugin share a single source of truth.
|
|
6
6
|
*/
|
|
7
|
-
export { runLinear, parseLinearArgs, } from '@renseiai/
|
|
7
|
+
export { runLinear, parseLinearArgs, } from '@renseiai/plugin-linear';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/orchestrator-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAEL,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"orchestrator-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/orchestrator-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAA;AAY/B,MAAM,WAAW,wBAAwB;IACvC,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kDAAkD;IAClD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,qBAAqB,CAAA;IACjC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACpD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAC5C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAC/C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAC1D,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CAClD;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAA;IAChD,SAAS,EAAE,YAAY,EAAE,CAAA;CAC1B;AAMD,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYjD;AA0CD,wBAAsB,eAAe,CACnC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,wBAAwB,CAAC,CAmGnC"}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
10
|
import { createOrchestrator, } from '@renseiai/agentfactory';
|
|
11
|
+
import { LinearIssueTrackerClient, createLinearStatusMappings, linearPlugin, } from '@renseiai/plugin-linear';
|
|
12
|
+
import { codeIntelligencePlugin } from '@renseiai/agentfactory-code-intelligence';
|
|
11
13
|
// ---------------------------------------------------------------------------
|
|
12
14
|
// Helpers
|
|
13
15
|
// ---------------------------------------------------------------------------
|
|
@@ -77,11 +79,16 @@ export async function runOrchestrator(config) {
|
|
|
77
79
|
const dryRun = config.dryRun ?? false;
|
|
78
80
|
const gitRoot = config.gitRoot ?? getGitRoot();
|
|
79
81
|
const cb = config.callbacks ?? defaultCallbacks();
|
|
82
|
+
const issueTrackerClient = new LinearIssueTrackerClient({ apiKey: config.linearApiKey });
|
|
83
|
+
const statusMappings = createLinearStatusMappings();
|
|
80
84
|
const orchestratorConfig = {
|
|
81
85
|
project: config.project,
|
|
82
86
|
maxConcurrent,
|
|
83
87
|
worktreePath: path.resolve(gitRoot, '.worktrees'),
|
|
84
88
|
linearApiKey: config.linearApiKey,
|
|
89
|
+
issueTrackerClient,
|
|
90
|
+
statusMappings,
|
|
91
|
+
toolPlugins: [linearPlugin, codeIntelligencePlugin],
|
|
85
92
|
};
|
|
86
93
|
if (config.templateDir) {
|
|
87
94
|
orchestratorConfig.templateDir = config.templateDir;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Runner -- Programmatic API for the af-status CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides fleet status via the AgentFactory public API.
|
|
5
|
+
* In TTY mode, spawns the Go `af-status` binary for rich inline output.
|
|
6
|
+
* In piped/JSON mode, fetches stats directly from Node.js.
|
|
7
|
+
*/
|
|
8
|
+
export interface StatusRunnerConfig {
|
|
9
|
+
/** Output raw JSON instead of human-readable format */
|
|
10
|
+
json?: boolean;
|
|
11
|
+
/** Enable auto-refresh watch mode */
|
|
12
|
+
watch?: boolean;
|
|
13
|
+
/** Watch interval (e.g., "1s", "5s") — only used with watch */
|
|
14
|
+
interval?: string;
|
|
15
|
+
/** API base URL override */
|
|
16
|
+
url?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const C: {
|
|
19
|
+
readonly reset: "\u001B[0m";
|
|
20
|
+
readonly red: "\u001B[31m";
|
|
21
|
+
readonly green: "\u001B[32m";
|
|
22
|
+
readonly yellow: "\u001B[33m";
|
|
23
|
+
readonly cyan: "\u001B[36m";
|
|
24
|
+
readonly gray: "\u001B[90m";
|
|
25
|
+
};
|
|
26
|
+
export declare function runStatus(config: StatusRunnerConfig): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=status-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/status-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAMD,eAAO,MAAM,CAAC;;;;;;;CAOJ,CAAA;AAuEV,wBAAsB,SAAS,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzE"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Runner -- Programmatic API for the af-status CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides fleet status via the AgentFactory public API.
|
|
5
|
+
* In TTY mode, spawns the Go `af-status` binary for rich inline output.
|
|
6
|
+
* In piped/JSON mode, fetches stats directly from Node.js.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// ANSI colors (same as agent-runner)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
export const C = {
|
|
17
|
+
reset: '\x1b[0m',
|
|
18
|
+
red: '\x1b[31m',
|
|
19
|
+
green: '\x1b[32m',
|
|
20
|
+
yellow: '\x1b[33m',
|
|
21
|
+
cyan: '\x1b[36m',
|
|
22
|
+
gray: '\x1b[90m',
|
|
23
|
+
};
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Helpers
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
function getBaseURL(override) {
|
|
28
|
+
return override ?? process.env.WORKER_API_URL ?? 'http://localhost:3000';
|
|
29
|
+
}
|
|
30
|
+
async function fetchStats(baseURL) {
|
|
31
|
+
const url = `${baseURL.replace(/\/+$/, '')}/api/public/stats`;
|
|
32
|
+
const resp = await fetch(url);
|
|
33
|
+
if (!resp.ok) {
|
|
34
|
+
throw new Error(`API request failed: ${resp.status} ${resp.statusText}`);
|
|
35
|
+
}
|
|
36
|
+
return resp.json();
|
|
37
|
+
}
|
|
38
|
+
function resolveGoBinary() {
|
|
39
|
+
// Go binary lives in packages/tui/bin/af-status relative to the CLI package
|
|
40
|
+
return path.resolve(__dirname, '../../tui/bin/af-status');
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Command handlers
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
async function showJSON(baseURL) {
|
|
46
|
+
const stats = await fetchStats(baseURL);
|
|
47
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
48
|
+
}
|
|
49
|
+
function spawnGoBinary(config, baseURL) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const binPath = resolveGoBinary();
|
|
52
|
+
const args = ['--url', baseURL];
|
|
53
|
+
if (config.json)
|
|
54
|
+
args.push('--json');
|
|
55
|
+
if (config.watch)
|
|
56
|
+
args.push('--watch');
|
|
57
|
+
if (config.interval)
|
|
58
|
+
args.push('--interval', config.interval);
|
|
59
|
+
const child = spawn(binPath, args, {
|
|
60
|
+
stdio: 'inherit',
|
|
61
|
+
});
|
|
62
|
+
child.on('error', (err) => {
|
|
63
|
+
if (err.code === 'ENOENT') {
|
|
64
|
+
// Go binary not built yet — fall back to Node.js JSON output
|
|
65
|
+
console.error(`${C.yellow}Go binary not found at ${binPath}${C.reset}`);
|
|
66
|
+
console.error(`${C.gray}Falling back to JSON output. Build with: cd packages/tui && make build-status${C.reset}`);
|
|
67
|
+
showJSON(baseURL).then(resolve, reject);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
reject(err);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
child.on('close', (code) => {
|
|
74
|
+
if (code === 0) {
|
|
75
|
+
resolve();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
reject(new Error(`af-status exited with code ${code}`));
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Public entry point
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
export async function runStatus(config) {
|
|
87
|
+
const baseURL = getBaseURL(config.url);
|
|
88
|
+
const isTTY = process.stdout.isTTY ?? false;
|
|
89
|
+
// If piped (non-TTY) and not explicitly requesting watch, default to JSON
|
|
90
|
+
if (!isTTY && !config.watch) {
|
|
91
|
+
await showJSON(baseURL);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// If --json flag without watch, just fetch and print
|
|
95
|
+
if (config.json && !config.watch) {
|
|
96
|
+
await showJSON(baseURL);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// TTY mode or watch mode — delegate to Go binary
|
|
100
|
+
await spawnGoBinary(config, baseURL);
|
|
101
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/worker-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"worker-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/worker-runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyBH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mDAAmD;IACnD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAyED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA89Bf"}
|
|
@@ -9,6 +9,8 @@ import path from 'path';
|
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
10
|
import os from 'os';
|
|
11
11
|
import { createOrchestrator, createLogger, } from '@renseiai/agentfactory';
|
|
12
|
+
import { LinearIssueTrackerClient, createLinearStatusMappings, linearPlugin, } from '@renseiai/plugin-linear';
|
|
13
|
+
import { codeIntelligencePlugin } from '@renseiai/agentfactory-code-intelligence';
|
|
12
14
|
// ---------------------------------------------------------------------------
|
|
13
15
|
// Helpers (stateless)
|
|
14
16
|
// ---------------------------------------------------------------------------
|
|
@@ -275,25 +277,26 @@ export async function runWorker(config, signal) {
|
|
|
275
277
|
// -----------------------------------------------------------------------
|
|
276
278
|
async function pollForWork() {
|
|
277
279
|
if (!workerId)
|
|
278
|
-
return { work: [],
|
|
280
|
+
return { work: [], inboxMessages: {}, hasInboxMessages: false };
|
|
279
281
|
const result = await apiRequestWithError(`/api/workers/${workerId}/poll`);
|
|
280
282
|
if (result.error?.type === 'worker_not_found') {
|
|
281
283
|
await attemptReregistration();
|
|
282
|
-
return { work: [],
|
|
284
|
+
return { work: [], inboxMessages: {}, hasInboxMessages: false };
|
|
283
285
|
}
|
|
284
286
|
if (!result.data) {
|
|
285
|
-
return { work: [],
|
|
287
|
+
return { work: [], inboxMessages: {}, hasInboxMessages: false };
|
|
286
288
|
}
|
|
287
289
|
const pollData = result.data;
|
|
288
|
-
if (pollData.
|
|
289
|
-
const
|
|
290
|
-
log.info('Received
|
|
291
|
-
sessionCount: Object.keys(pollData.
|
|
292
|
-
|
|
293
|
-
sessions: Object.entries(pollData.
|
|
290
|
+
if (pollData.hasInboxMessages) {
|
|
291
|
+
const totalMessages = Object.values(pollData.inboxMessages).reduce((sum, messages) => sum + messages.length, 0);
|
|
292
|
+
log.info('Received inbox messages', {
|
|
293
|
+
sessionCount: Object.keys(pollData.inboxMessages).length,
|
|
294
|
+
totalMessages,
|
|
295
|
+
sessions: Object.entries(pollData.inboxMessages).map(([sessionId, messages]) => ({
|
|
294
296
|
sessionId: sessionId.substring(0, 8),
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
messageCount: messages.length,
|
|
298
|
+
messageIds: messages.map((m) => m.id),
|
|
299
|
+
types: messages.map((m) => m.type),
|
|
297
300
|
})),
|
|
298
301
|
});
|
|
299
302
|
}
|
|
@@ -307,6 +310,15 @@ export async function runWorker(config, signal) {
|
|
|
307
310
|
body: JSON.stringify({ workerId }),
|
|
308
311
|
});
|
|
309
312
|
}
|
|
313
|
+
async function ackInboxMessage(sessionId, message) {
|
|
314
|
+
await apiRequest(`/api/sessions/${sessionId}/inbox/ack`, {
|
|
315
|
+
method: 'POST',
|
|
316
|
+
body: JSON.stringify({
|
|
317
|
+
messageId: message.id,
|
|
318
|
+
lane: message.lane,
|
|
319
|
+
}),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
310
322
|
async function reportStatus(sessionId, status, extra) {
|
|
311
323
|
if (!workerId)
|
|
312
324
|
return;
|
|
@@ -405,9 +417,14 @@ export async function runWorker(config, signal) {
|
|
|
405
417
|
? `Resuming work on ${work.issueIdentifier}`
|
|
406
418
|
: `Worker claimed ${work.issueIdentifier}. Setting up environment...`);
|
|
407
419
|
// Create orchestrator with API activity proxy
|
|
420
|
+
const issueTrackerClient = new LinearIssueTrackerClient({ apiKey: linearApiKey });
|
|
421
|
+
const statusMappings = createLinearStatusMappings();
|
|
408
422
|
const orchestrator = createOrchestrator({
|
|
409
423
|
maxConcurrent: 1,
|
|
410
424
|
worktreePath: path.resolve(gitRoot, '.worktrees'),
|
|
425
|
+
issueTrackerClient,
|
|
426
|
+
statusMappings,
|
|
427
|
+
toolPlugins: [linearPlugin, codeIntelligencePlugin],
|
|
411
428
|
apiActivityConfig: {
|
|
412
429
|
baseUrl: workerConfig.apiUrl,
|
|
413
430
|
apiKey: workerConfig.apiKey,
|
|
@@ -689,68 +706,94 @@ export async function runWorker(config, signal) {
|
|
|
689
706
|
}
|
|
690
707
|
}
|
|
691
708
|
}
|
|
692
|
-
// Handle
|
|
693
|
-
if (pollResult.
|
|
694
|
-
for (const [sessionId,
|
|
695
|
-
for (const
|
|
696
|
-
|
|
709
|
+
// Handle inbox messages for active sessions (urgent-first)
|
|
710
|
+
if (pollResult.hasInboxMessages) {
|
|
711
|
+
for (const [sessionId, messages] of Object.entries(pollResult.inboxMessages)) {
|
|
712
|
+
for (const message of messages) {
|
|
713
|
+
// Handle nudge: no-op wake signal, just discard
|
|
714
|
+
if (message.type === 'nudge') {
|
|
715
|
+
log.debug('Nudge received (no-op)', {
|
|
716
|
+
sessionId: sessionId.substring(0, 8),
|
|
717
|
+
messageId: message.id,
|
|
718
|
+
});
|
|
719
|
+
await ackInboxMessage(sessionId, message);
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
const orchestrator = activeOrchestrators.get(sessionId);
|
|
723
|
+
// Handle stop signal: trigger graceful agent shutdown
|
|
724
|
+
if (message.type === 'stop') {
|
|
725
|
+
log.info('Stop signal received', {
|
|
726
|
+
sessionId: sessionId.substring(0, 8),
|
|
727
|
+
messageId: message.id,
|
|
728
|
+
});
|
|
729
|
+
if (orchestrator) {
|
|
730
|
+
const agent = orchestrator.getAgentBySession(sessionId);
|
|
731
|
+
if (agent) {
|
|
732
|
+
try {
|
|
733
|
+
await orchestrator.stopAgent(agent.issueId, false);
|
|
734
|
+
log.success('Agent stopped via inbox signal', {
|
|
735
|
+
sessionId: sessionId.substring(0, 8),
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
log.error('Failed to stop agent', {
|
|
740
|
+
sessionId: sessionId.substring(0, 8),
|
|
741
|
+
error: error instanceof Error ? error.message : String(error),
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
await ackInboxMessage(sessionId, message);
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
// Handle directive and hook-result: inject as follow-up prompt
|
|
750
|
+
log.info('Processing inbox message', {
|
|
697
751
|
sessionId: sessionId.substring(0, 8),
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
752
|
+
messageId: message.id,
|
|
753
|
+
type: message.type,
|
|
754
|
+
lane: message.lane,
|
|
755
|
+
payloadLength: message.payload.length,
|
|
756
|
+
userName: message.userName,
|
|
701
757
|
});
|
|
702
|
-
const orchestrator = activeOrchestrators.get(sessionId);
|
|
703
758
|
if (!orchestrator) {
|
|
704
759
|
log.warn('No active orchestrator found for session', {
|
|
705
760
|
sessionId: sessionId.substring(0, 8),
|
|
706
|
-
|
|
761
|
+
messageId: message.id,
|
|
707
762
|
});
|
|
708
763
|
continue;
|
|
709
764
|
}
|
|
710
765
|
const agent = orchestrator.getAgentBySession(sessionId);
|
|
711
766
|
const providerSessionId = agent?.providerSessionId;
|
|
712
|
-
log.info('Forwarding prompt to provider session', {
|
|
713
|
-
sessionId: sessionId.substring(0, 8),
|
|
714
|
-
promptId: prompt.id,
|
|
715
|
-
hasProviderSession: !!providerSessionId,
|
|
716
|
-
agentStatus: agent?.status,
|
|
717
|
-
});
|
|
718
767
|
try {
|
|
719
|
-
const result = await orchestrator.forwardPrompt(
|
|
768
|
+
const result = await orchestrator.forwardPrompt(agent?.issueId ?? '', sessionId, message.payload, providerSessionId, agent?.workType);
|
|
720
769
|
if (result.forwarded) {
|
|
721
770
|
log.success(result.injected
|
|
722
771
|
? 'Message injected into running session'
|
|
723
|
-
: '
|
|
772
|
+
: 'Inbox message forwarded successfully', {
|
|
724
773
|
sessionId: sessionId.substring(0, 8),
|
|
725
|
-
|
|
774
|
+
messageId: message.id,
|
|
775
|
+
type: message.type,
|
|
726
776
|
injected: result.injected ?? false,
|
|
727
777
|
resumed: result.resumed,
|
|
728
778
|
newAgentPid: result.agent?.pid,
|
|
729
779
|
});
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
body: JSON.stringify({ promptId: prompt.id }),
|
|
733
|
-
});
|
|
734
|
-
if (claimResult?.claimed) {
|
|
735
|
-
log.debug('Prompt claimed', { promptId: prompt.id });
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
log.warn('Failed to claim prompt', { promptId: prompt.id });
|
|
739
|
-
}
|
|
780
|
+
// ACK after successful delivery
|
|
781
|
+
await ackInboxMessage(sessionId, message);
|
|
740
782
|
}
|
|
741
783
|
else {
|
|
742
|
-
log.error('Failed to forward
|
|
784
|
+
log.error('Failed to forward inbox message', {
|
|
743
785
|
sessionId: sessionId.substring(0, 8),
|
|
744
|
-
|
|
786
|
+
messageId: message.id,
|
|
787
|
+
type: message.type,
|
|
745
788
|
reason: result.reason,
|
|
746
789
|
error: result.error?.message,
|
|
747
790
|
});
|
|
748
791
|
}
|
|
749
792
|
}
|
|
750
793
|
catch (error) {
|
|
751
|
-
log.error('Error forwarding
|
|
794
|
+
log.error('Error forwarding inbox message', {
|
|
752
795
|
sessionId: sessionId.substring(0, 8),
|
|
753
|
-
|
|
796
|
+
messageId: message.id,
|
|
754
797
|
error: error instanceof Error ? error.message : String(error),
|
|
755
798
|
});
|
|
756
799
|
}
|
package/dist/src/linear.d.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* update-issue <id> Update an existing issue
|
|
14
14
|
* list-comments <issueId> List comments on an issue
|
|
15
15
|
* create-comment <issueId> Create a comment on an issue
|
|
16
|
+
* list-issues List issues with flexible filters
|
|
16
17
|
* list-backlog-issues List backlog issues for a project
|
|
17
18
|
* list-unblocked-backlog List unblocked backlog issues
|
|
18
19
|
* check-blocked <id> Check if an issue is blocked
|
package/dist/src/linear.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/linear.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/linear.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG"}
|
package/dist/src/linear.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* update-issue <id> Update an existing issue
|
|
14
14
|
* list-comments <issueId> List comments on an issue
|
|
15
15
|
* create-comment <issueId> Create a comment on an issue
|
|
16
|
+
* list-issues List issues with flexible filters
|
|
16
17
|
* list-backlog-issues List backlog issues for a project
|
|
17
18
|
* list-unblocked-backlog List unblocked backlog issues
|
|
18
19
|
* check-blocked <id> Check if an issue is blocked
|
|
@@ -51,6 +52,7 @@ Commands:
|
|
|
51
52
|
update-issue <id> Update an existing issue
|
|
52
53
|
list-comments <issueId> List comments on an issue
|
|
53
54
|
create-comment <issueId> Create a comment on an issue
|
|
55
|
+
list-issues List issues with flexible filters
|
|
54
56
|
list-backlog-issues List backlog issues for a project
|
|
55
57
|
list-unblocked-backlog List unblocked backlog issues
|
|
56
58
|
check-blocked <id> Check if an issue is blocked
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Status CLI
|
|
4
|
+
*
|
|
5
|
+
* Quick fleet status checks for terminal and scripting use.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* af-status One-line fleet summary (via Go binary in TTY)
|
|
9
|
+
* af-status --json JSON stats to stdout
|
|
10
|
+
* af-status --watch Auto-refresh every 3 seconds
|
|
11
|
+
* af-status --watch --interval 5s Custom refresh interval
|
|
12
|
+
* af-status | jq Pipe-friendly (auto-detects non-TTY)
|
|
13
|
+
*
|
|
14
|
+
* Environment (loaded from .env.local in CWD):
|
|
15
|
+
* WORKER_API_URL API base URL (default: http://localhost:3000)
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/status.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentFactory Status CLI
|
|
4
|
+
*
|
|
5
|
+
* Quick fleet status checks for terminal and scripting use.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* af-status One-line fleet summary (via Go binary in TTY)
|
|
9
|
+
* af-status --json JSON stats to stdout
|
|
10
|
+
* af-status --watch Auto-refresh every 3 seconds
|
|
11
|
+
* af-status --watch --interval 5s Custom refresh interval
|
|
12
|
+
* af-status | jq Pipe-friendly (auto-detects non-TTY)
|
|
13
|
+
*
|
|
14
|
+
* Environment (loaded from .env.local in CWD):
|
|
15
|
+
* WORKER_API_URL API base URL (default: http://localhost:3000)
|
|
16
|
+
*/
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { config } from 'dotenv';
|
|
19
|
+
// Load environment variables from .env.local in CWD
|
|
20
|
+
config({ path: path.resolve(process.cwd(), '.env.local') });
|
|
21
|
+
import { runStatus, C } from './lib/status-runner.js';
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Usage
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
function printUsage() {
|
|
26
|
+
console.log(`
|
|
27
|
+
${C.cyan}AgentFactory Status${C.reset} - Quick fleet status checks
|
|
28
|
+
|
|
29
|
+
${C.yellow}Usage:${C.reset}
|
|
30
|
+
af-status [options]
|
|
31
|
+
|
|
32
|
+
${C.yellow}Options:${C.reset}
|
|
33
|
+
--json Output raw JSON stats to stdout
|
|
34
|
+
--watch Auto-refresh status every 3 seconds
|
|
35
|
+
--interval <duration> Custom refresh interval (e.g., 1s, 5s) [default: 3s]
|
|
36
|
+
--url <url> API base URL [default: WORKER_API_URL or http://localhost:3000]
|
|
37
|
+
--help, -h Show this help message
|
|
38
|
+
|
|
39
|
+
${C.yellow}Examples:${C.reset}
|
|
40
|
+
af-status One-line fleet summary
|
|
41
|
+
af-status --json JSON output
|
|
42
|
+
af-status --json | jq .agentsWorking Extract a field
|
|
43
|
+
af-status --watch Auto-refresh mode
|
|
44
|
+
af-status --watch --interval 1s Refresh every second
|
|
45
|
+
|
|
46
|
+
${C.yellow}Environment:${C.reset}
|
|
47
|
+
WORKER_API_URL API base URL (default: http://localhost:3000)
|
|
48
|
+
`);
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Main
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
async function main() {
|
|
54
|
+
const args = process.argv.slice(2);
|
|
55
|
+
if (args.includes('--help') || args.includes('-h') || args.includes('help')) {
|
|
56
|
+
printUsage();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const jsonMode = args.includes('--json');
|
|
60
|
+
const watchMode = args.includes('--watch');
|
|
61
|
+
// Parse --interval value
|
|
62
|
+
let interval;
|
|
63
|
+
const intervalIdx = args.indexOf('--interval');
|
|
64
|
+
if (intervalIdx !== -1 && intervalIdx + 1 < args.length) {
|
|
65
|
+
interval = args[intervalIdx + 1];
|
|
66
|
+
}
|
|
67
|
+
// Parse --url value
|
|
68
|
+
let url;
|
|
69
|
+
const urlIdx = args.indexOf('--url');
|
|
70
|
+
if (urlIdx !== -1 && urlIdx + 1 < args.length) {
|
|
71
|
+
url = args[urlIdx + 1];
|
|
72
|
+
}
|
|
73
|
+
await runStatus({ json: jsonMode, watch: watchMode, interval, url });
|
|
74
|
+
}
|
|
75
|
+
main().catch((error) => {
|
|
76
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@renseiai/agentfactory-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
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)",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"af-analyze-logs": "dist/src/analyze-logs.js",
|
|
38
38
|
"af-linear": "dist/src/linear.js",
|
|
39
39
|
"af-governor": "dist/src/governor.js",
|
|
40
|
-
"af-sync-routes": "dist/src/sync-routes.js"
|
|
40
|
+
"af-sync-routes": "dist/src/sync-routes.js",
|
|
41
|
+
"af-status": "dist/src/status.js"
|
|
41
42
|
},
|
|
42
43
|
"main": "./dist/src/index.js",
|
|
43
44
|
"module": "./dist/src/index.js",
|
|
@@ -92,6 +93,11 @@
|
|
|
92
93
|
"types": "./dist/src/lib/sync-routes-runner.d.ts",
|
|
93
94
|
"import": "./dist/src/lib/sync-routes-runner.js",
|
|
94
95
|
"default": "./dist/src/lib/sync-routes-runner.js"
|
|
96
|
+
},
|
|
97
|
+
"./status": {
|
|
98
|
+
"types": "./dist/src/lib/status-runner.d.ts",
|
|
99
|
+
"import": "./dist/src/lib/status-runner.js",
|
|
100
|
+
"default": "./dist/src/lib/status-runner.js"
|
|
95
101
|
}
|
|
96
102
|
},
|
|
97
103
|
"files": [
|
|
@@ -101,9 +107,10 @@
|
|
|
101
107
|
],
|
|
102
108
|
"dependencies": {
|
|
103
109
|
"dotenv": "^17.2.3",
|
|
104
|
-
"@renseiai/agentfactory": "0.8.
|
|
105
|
-
"@renseiai/
|
|
106
|
-
"@renseiai/agentfactory
|
|
110
|
+
"@renseiai/agentfactory-code-intelligence": "0.8.8",
|
|
111
|
+
"@renseiai/plugin-linear": "0.8.8",
|
|
112
|
+
"@renseiai/agentfactory": "0.8.8",
|
|
113
|
+
"@renseiai/agentfactory-server": "0.8.8"
|
|
107
114
|
},
|
|
108
115
|
"devDependencies": {
|
|
109
116
|
"@types/node": "^22.5.4",
|