@bhimudev/gnanai 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +270 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +188 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/commands/cleanup.d.ts +21 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +380 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/dispatch.d.ts +13 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +85 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +155 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +167 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +711 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/knowledge-sync.d.ts +69 -0
- package/dist/commands/knowledge-sync.d.ts.map +1 -0
- package/dist/commands/knowledge-sync.js +661 -0
- package/dist/commands/knowledge-sync.js.map +1 -0
- package/dist/commands/knowledge.d.ts +35 -0
- package/dist/commands/knowledge.d.ts.map +1 -0
- package/dist/commands/knowledge.js +254 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/rollback.d.ts +13 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/rollback.js +186 -0
- package/dist/commands/rollback.js.map +1 -0
- package/dist/commands/setup-config.d.ts +6 -0
- package/dist/commands/setup-config.d.ts.map +1 -0
- package/dist/commands/setup-config.js +663 -0
- package/dist/commands/setup-config.js.map +1 -0
- package/dist/commands/setup-project.d.ts +6 -0
- package/dist/commands/setup-project.d.ts.map +1 -0
- package/dist/commands/setup-project.js +361 -0
- package/dist/commands/setup-project.js.map +1 -0
- package/dist/commands/setup.d.ts +3 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +293 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +51 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +182 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +3 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +173 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +435 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/worktree.d.ts +30 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +262 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/generator/claude-cli.d.ts +24 -0
- package/dist/generator/claude-cli.d.ts.map +1 -0
- package/dist/generator/claude-cli.js +239 -0
- package/dist/generator/claude-cli.js.map +1 -0
- package/dist/generator/prompt-builder.d.ts +7 -0
- package/dist/generator/prompt-builder.d.ts.map +1 -0
- package/dist/generator/prompt-builder.js +144 -0
- package/dist/generator/prompt-builder.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/embeddings.d.ts +53 -0
- package/dist/mcp/embeddings.d.ts.map +1 -0
- package/dist/mcp/embeddings.js +68 -0
- package/dist/mcp/embeddings.js.map +1 -0
- package/dist/mcp/hybrid-search.d.ts +25 -0
- package/dist/mcp/hybrid-search.d.ts.map +1 -0
- package/dist/mcp/hybrid-search.js +72 -0
- package/dist/mcp/hybrid-search.js.map +1 -0
- package/dist/mcp/knowledge-server.d.ts +4 -0
- package/dist/mcp/knowledge-server.d.ts.map +1 -0
- package/dist/mcp/knowledge-server.js +294 -0
- package/dist/mcp/knowledge-server.js.map +1 -0
- package/dist/mcp/knowledge-utils.d.ts +65 -0
- package/dist/mcp/knowledge-utils.d.ts.map +1 -0
- package/dist/mcp/knowledge-utils.js +207 -0
- package/dist/mcp/knowledge-utils.js.map +1 -0
- package/dist/mcp/search-factory.d.ts +9 -0
- package/dist/mcp/search-factory.d.ts.map +1 -0
- package/dist/mcp/search-factory.js +23 -0
- package/dist/mcp/search-factory.js.map +1 -0
- package/dist/mcp/search-index.d.ts +45 -0
- package/dist/mcp/search-index.d.ts.map +1 -0
- package/dist/mcp/search-index.js +2 -0
- package/dist/mcp/search-index.js.map +1 -0
- package/dist/mcp/search-minisearch.d.ts +46 -0
- package/dist/mcp/search-minisearch.d.ts.map +1 -0
- package/dist/mcp/search-minisearch.js +99 -0
- package/dist/mcp/search-minisearch.js.map +1 -0
- package/dist/mcp/search-sqlite.d.ts +30 -0
- package/dist/mcp/search-sqlite.d.ts.map +1 -0
- package/dist/mcp/search-sqlite.js +188 -0
- package/dist/mcp/search-sqlite.js.map +1 -0
- package/dist/mcp/vector-store.d.ts +52 -0
- package/dist/mcp/vector-store.d.ts.map +1 -0
- package/dist/mcp/vector-store.js +183 -0
- package/dist/mcp/vector-store.js.map +1 -0
- package/dist/scaffold/copy-core-agents.d.ts +2 -0
- package/dist/scaffold/copy-core-agents.d.ts.map +1 -0
- package/dist/scaffold/copy-core-agents.js +90 -0
- package/dist/scaffold/copy-core-agents.js.map +1 -0
- package/dist/scaffold/create-claude-settings.d.ts +40 -0
- package/dist/scaffold/create-claude-settings.d.ts.map +1 -0
- package/dist/scaffold/create-claude-settings.js +422 -0
- package/dist/scaffold/create-claude-settings.js.map +1 -0
- package/dist/scaffold/create-config.d.ts +14 -0
- package/dist/scaffold/create-config.d.ts.map +1 -0
- package/dist/scaffold/create-config.js +199 -0
- package/dist/scaffold/create-config.js.map +1 -0
- package/dist/scaffold/create-project-description.d.ts +12 -0
- package/dist/scaffold/create-project-description.d.ts.map +1 -0
- package/dist/scaffold/create-project-description.js +104 -0
- package/dist/scaffold/create-project-description.js.map +1 -0
- package/dist/scaffold/create-structure.d.ts +2 -0
- package/dist/scaffold/create-structure.d.ts.map +1 -0
- package/dist/scaffold/create-structure.js +146 -0
- package/dist/scaffold/create-structure.js.map +1 -0
- package/dist/types/dependency-analysis.d.ts +11 -0
- package/dist/types/dependency-analysis.d.ts.map +1 -0
- package/dist/types/dependency-analysis.js +2 -0
- package/dist/types/dependency-analysis.js.map +1 -0
- package/dist/types/index.d.ts +526 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/task.d.ts +25 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +3 -0
- package/dist/types/task.js.map +1 -0
- package/dist/utils/analyze-files.d.ts +7 -0
- package/dist/utils/analyze-files.d.ts.map +1 -0
- package/dist/utils/analyze-files.js +27 -0
- package/dist/utils/analyze-files.js.map +1 -0
- package/dist/utils/backup.d.ts +102 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +352 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/ci-provider.d.ts +23 -0
- package/dist/utils/ci-provider.d.ts.map +1 -0
- package/dist/utils/ci-provider.js +525 -0
- package/dist/utils/ci-provider.js.map +1 -0
- package/dist/utils/ci-status.d.ts +57 -0
- package/dist/utils/ci-status.d.ts.map +1 -0
- package/dist/utils/ci-status.js +349 -0
- package/dist/utils/ci-status.js.map +1 -0
- package/dist/utils/dependency-analysis.d.ts +34 -0
- package/dist/utils/dependency-analysis.d.ts.map +1 -0
- package/dist/utils/dependency-analysis.js +298 -0
- package/dist/utils/dependency-analysis.js.map +1 -0
- package/dist/utils/detect-git.d.ts +57 -0
- package/dist/utils/detect-git.d.ts.map +1 -0
- package/dist/utils/detect-git.js +439 -0
- package/dist/utils/detect-git.js.map +1 -0
- package/dist/utils/detect-mcp.d.ts +32 -0
- package/dist/utils/detect-mcp.d.ts.map +1 -0
- package/dist/utils/detect-mcp.js +178 -0
- package/dist/utils/detect-mcp.js.map +1 -0
- package/dist/utils/detect-project.d.ts +3 -0
- package/dist/utils/detect-project.d.ts.map +1 -0
- package/dist/utils/detect-project.js +155 -0
- package/dist/utils/detect-project.js.map +1 -0
- package/dist/utils/file-comparison.d.ts +89 -0
- package/dist/utils/file-comparison.d.ts.map +1 -0
- package/dist/utils/file-comparison.js +301 -0
- package/dist/utils/file-comparison.js.map +1 -0
- package/dist/utils/file-merger.d.ts +74 -0
- package/dist/utils/file-merger.d.ts.map +1 -0
- package/dist/utils/file-merger.js +350 -0
- package/dist/utils/file-merger.js.map +1 -0
- package/dist/utils/logger.d.ts +26 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/managed-process.d.ts +109 -0
- package/dist/utils/managed-process.d.ts.map +1 -0
- package/dist/utils/managed-process.js +481 -0
- package/dist/utils/managed-process.js.map +1 -0
- package/dist/utils/merge-claude-settings.d.ts +65 -0
- package/dist/utils/merge-claude-settings.d.ts.map +1 -0
- package/dist/utils/merge-claude-settings.js +133 -0
- package/dist/utils/merge-claude-settings.js.map +1 -0
- package/dist/utils/migration.d.ts +74 -0
- package/dist/utils/migration.d.ts.map +1 -0
- package/dist/utils/migration.js +345 -0
- package/dist/utils/migration.js.map +1 -0
- package/dist/utils/process-health.d.ts +51 -0
- package/dist/utils/process-health.d.ts.map +1 -0
- package/dist/utils/process-health.js +123 -0
- package/dist/utils/process-health.js.map +1 -0
- package/dist/utils/process-registry.d.ts +20 -0
- package/dist/utils/process-registry.d.ts.map +1 -0
- package/dist/utils/process-registry.js +151 -0
- package/dist/utils/process-registry.js.map +1 -0
- package/dist/utils/process-tree.d.ts +51 -0
- package/dist/utils/process-tree.d.ts.map +1 -0
- package/dist/utils/process-tree.js +499 -0
- package/dist/utils/process-tree.js.map +1 -0
- package/dist/utils/repair-mcp-config.d.ts +15 -0
- package/dist/utils/repair-mcp-config.d.ts.map +1 -0
- package/dist/utils/repair-mcp-config.js +129 -0
- package/dist/utils/repair-mcp-config.js.map +1 -0
- package/dist/utils/task-lifecycle.d.ts +60 -0
- package/dist/utils/task-lifecycle.d.ts.map +1 -0
- package/dist/utils/task-lifecycle.js +310 -0
- package/dist/utils/task-lifecycle.js.map +1 -0
- package/dist/utils/update-agent-mcp.d.ts +7 -0
- package/dist/utils/update-agent-mcp.d.ts.map +1 -0
- package/dist/utils/update-agent-mcp.js +115 -0
- package/dist/utils/update-agent-mcp.js.map +1 -0
- package/dist/utils/update-agent-templates.d.ts +6 -0
- package/dist/utils/update-agent-templates.d.ts.map +1 -0
- package/dist/utils/update-agent-templates.js +56 -0
- package/dist/utils/update-agent-templates.js.map +1 -0
- package/dist/utils/update-config-ci.d.ts +7 -0
- package/dist/utils/update-config-ci.d.ts.map +1 -0
- package/dist/utils/update-config-ci.js +72 -0
- package/dist/utils/update-config-ci.js.map +1 -0
- package/dist/utils/update-config-git.d.ts +18 -0
- package/dist/utils/update-config-git.d.ts.map +1 -0
- package/dist/utils/update-config-git.js +146 -0
- package/dist/utils/update-config-git.js.map +1 -0
- package/dist/utils/update-config-mcp.d.ts +7 -0
- package/dist/utils/update-config-mcp.d.ts.map +1 -0
- package/dist/utils/update-config-mcp.js +98 -0
- package/dist/utils/update-config-mcp.js.map +1 -0
- package/dist/utils/validate-config.d.ts +3 -0
- package/dist/utils/validate-config.d.ts.map +1 -0
- package/dist/utils/validate-config.js +109 -0
- package/dist/utils/validate-config.js.map +1 -0
- package/dist/utils/version-tracker.d.ts +130 -0
- package/dist/utils/version-tracker.d.ts.map +1 -0
- package/dist/utils/version-tracker.js +298 -0
- package/dist/utils/version-tracker.js.map +1 -0
- package/dist/utils/worktree.d.ts +68 -0
- package/dist/utils/worktree.d.ts.map +1 -0
- package/dist/utils/worktree.js +446 -0
- package/dist/utils/worktree.js.map +1 -0
- package/package.json +77 -0
- package/templates/ARCHAI_README.md +329 -0
- package/templates/CLAUDE.md +67 -0
- package/templates/PROMPTS.md +506 -0
- package/templates/core-agents/boss-agent.md +671 -0
- package/templates/core-agents/cleanup-agent.md +145 -0
- package/templates/core-agents/code-reviewer.md +175 -0
- package/templates/core-agents/critical-reviewer.md +117 -0
- package/templates/core-agents/deep-analyst.md +216 -0
- package/templates/core-agents/finalization-agent.md +252 -0
- package/templates/core-agents/git-coordinator.md +240 -0
- package/templates/core-agents/implementation-agent.md +151 -0
- package/templates/core-agents/maestro-agent.md +413 -0
- package/templates/core-agents/maestro-headless-agent.md +422 -0
- package/templates/core-agents/plan-validator.md +198 -0
- package/templates/core-agents/quick-fix.md +56 -0
- package/templates/core-agents/routing-templates.md +338 -0
- package/templates/core-agents/task-orchestrator.md +143 -0
- package/templates/core-agents/task-prep.md +202 -0
- package/templates/core-agents/tdd-designer.md +143 -0
- package/templates/specialist-meta.md +275 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Required .gitignore entries for archai.
|
|
6
|
+
* These patterns must be present for agents to work correctly.
|
|
7
|
+
*/
|
|
8
|
+
const REQUIRED_GITIGNORE_ENTRIES = [
|
|
9
|
+
'.agents/scratch/*',
|
|
10
|
+
'.agents/thoughts/*',
|
|
11
|
+
'.agents/plans/*',
|
|
12
|
+
'.claude/state/*',
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Check if the current directory is a Git repository.
|
|
16
|
+
*/
|
|
17
|
+
export async function detectGitRepo() {
|
|
18
|
+
return fs.pathExists('.git');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if the current directory is inside a linked git worktree.
|
|
22
|
+
* Returns true if .git is a file (linked worktree), false if directory (main repo) or missing.
|
|
23
|
+
*/
|
|
24
|
+
export async function isWorktree() {
|
|
25
|
+
try {
|
|
26
|
+
const stat = await fs.stat('.git');
|
|
27
|
+
return stat.isFile();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Run a git command and return trimmed stdout, or null on failure.
|
|
35
|
+
* Never makes network calls.
|
|
36
|
+
*/
|
|
37
|
+
function gitCommand(cmd, cwd) {
|
|
38
|
+
try {
|
|
39
|
+
const result = execSync(cmd, {
|
|
40
|
+
encoding: 'utf-8',
|
|
41
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
42
|
+
timeout: 5000,
|
|
43
|
+
...(cwd ? { cwd } : {}),
|
|
44
|
+
});
|
|
45
|
+
return result.trim() || null;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Discover Git defaults by running local git commands.
|
|
53
|
+
* No network calls are made.
|
|
54
|
+
*/
|
|
55
|
+
export async function discoverGitDefaults() {
|
|
56
|
+
// Current branch
|
|
57
|
+
const currentBranch = gitCommand('git branch --show-current') || 'unknown';
|
|
58
|
+
// Remote info
|
|
59
|
+
const remoteOutput = gitCommand('git remote -v');
|
|
60
|
+
let remote = null;
|
|
61
|
+
let remoteUrl = null;
|
|
62
|
+
if (remoteOutput) {
|
|
63
|
+
// Parse first fetch line: "origin\thttps://github.com/user/repo.git (fetch)"
|
|
64
|
+
const fetchLine = remoteOutput.split('\n').find(line => line.includes('(fetch)'));
|
|
65
|
+
if (fetchLine) {
|
|
66
|
+
const parts = fetchLine.split(/\s+/);
|
|
67
|
+
remote = parts[0] || null;
|
|
68
|
+
remoteUrl = parts[1] || null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Default branch discovery — try multiple methods
|
|
72
|
+
let defaultBranch = null;
|
|
73
|
+
// Method 1: git config init.defaultBranch
|
|
74
|
+
defaultBranch = gitCommand('git config init.defaultBranch');
|
|
75
|
+
// Method 2: remote HEAD reference
|
|
76
|
+
if (!defaultBranch && remote) {
|
|
77
|
+
const symref = gitCommand(`git symbolic-ref refs/remotes/${remote}/HEAD 2>/dev/null`);
|
|
78
|
+
if (symref) {
|
|
79
|
+
// refs/remotes/origin/HEAD -> refs/remotes/origin/main
|
|
80
|
+
const match = symref.match(/refs\/remotes\/[^/]+\/(.+)/);
|
|
81
|
+
if (match) {
|
|
82
|
+
defaultBranch = match[1];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Method 3: check if main or master branch exists locally
|
|
87
|
+
if (!defaultBranch) {
|
|
88
|
+
const branches = gitCommand('git branch --list main master');
|
|
89
|
+
if (branches) {
|
|
90
|
+
const branchList = branches.split('\n').map(b => b.replace(/^\*?\s*/, '').trim()).filter(Boolean);
|
|
91
|
+
if (branchList.includes('main')) {
|
|
92
|
+
defaultBranch = 'main';
|
|
93
|
+
}
|
|
94
|
+
else if (branchList.includes('master')) {
|
|
95
|
+
defaultBranch = 'master';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Final fallback
|
|
100
|
+
if (!defaultBranch) {
|
|
101
|
+
defaultBranch = 'main';
|
|
102
|
+
}
|
|
103
|
+
// Read branch convention from archai.config.md Git Conventions section if available.
|
|
104
|
+
// During archai setup, this value is overridden by detectGitPatterns() result.
|
|
105
|
+
// At runtime (agent operations), this is the primary source of the convention.
|
|
106
|
+
let branchConvention = 'agent/{task-id}-{description}';
|
|
107
|
+
try {
|
|
108
|
+
if (await fs.pathExists('archai.config.md')) {
|
|
109
|
+
const configContent = await fs.readFile('archai.config.md', 'utf-8');
|
|
110
|
+
// Extract the Git Conventions section first
|
|
111
|
+
const conventionsSection = configContent.match(/## Git Conventions\n[\s\S]*?(?=\n---\n|\n## |$)/);
|
|
112
|
+
if (conventionsSection) {
|
|
113
|
+
// Look for Branch Convention field WITHIN the Git Conventions section only
|
|
114
|
+
const conventionMatch = conventionsSection[0].match(/\*\*Branch Convention:\*\*\s*(.+)/);
|
|
115
|
+
if (conventionMatch && conventionMatch[1].trim() &&
|
|
116
|
+
!conventionMatch[1].includes('auto-configure')) {
|
|
117
|
+
branchConvention = conventionMatch[1].trim();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Fallback to default silently
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
defaultBranch,
|
|
127
|
+
remote,
|
|
128
|
+
remoteUrl,
|
|
129
|
+
currentBranch,
|
|
130
|
+
branchConvention,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Validate that .gitignore contains all required archai entries.
|
|
135
|
+
*/
|
|
136
|
+
export async function validateGitignore() {
|
|
137
|
+
const gitignorePath = '.gitignore';
|
|
138
|
+
const missing = [];
|
|
139
|
+
if (!await fs.pathExists(gitignorePath)) {
|
|
140
|
+
return { valid: false, missing: [...REQUIRED_GITIGNORE_ENTRIES] };
|
|
141
|
+
}
|
|
142
|
+
const content = await fs.readFile(gitignorePath, 'utf-8');
|
|
143
|
+
for (const entry of REQUIRED_GITIGNORE_ENTRIES) {
|
|
144
|
+
if (!content.includes(entry)) {
|
|
145
|
+
missing.push(entry);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { valid: missing.length === 0, missing };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Fix .gitignore by appending missing archai entries.
|
|
152
|
+
*/
|
|
153
|
+
export async function fixGitignore(missing) {
|
|
154
|
+
if (missing.length === 0)
|
|
155
|
+
return;
|
|
156
|
+
const gitignorePath = '.gitignore';
|
|
157
|
+
let content = '';
|
|
158
|
+
if (await fs.pathExists(gitignorePath)) {
|
|
159
|
+
content = await fs.readFile(gitignorePath, 'utf-8');
|
|
160
|
+
// Ensure trailing newline before appending
|
|
161
|
+
if (content.length > 0 && !content.endsWith('\n')) {
|
|
162
|
+
content += '\n';
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const additions = '\n# archai - Agent working files (auto-added by archai setup)\n' +
|
|
166
|
+
missing.map(entry => entry).join('\n') + '\n';
|
|
167
|
+
await fs.writeFile(gitignorePath, content + additions);
|
|
168
|
+
logger.debug('Fixed .gitignore', { added: missing });
|
|
169
|
+
}
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// Known branch prefixes for classification
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
const KNOWN_PREFIXES = [
|
|
174
|
+
'feature/', 'feat/', 'fix/', 'bugfix/', 'hotfix/',
|
|
175
|
+
'release/', 'chore/', 'docs/', 'ci/', 'test/',
|
|
176
|
+
'refactor/', 'agent/', 'archai/',
|
|
177
|
+
'perf/', 'style/', 'build/', 'wip/', 'deps/',
|
|
178
|
+
'improvement/', 'experiment/',
|
|
179
|
+
];
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
// Pure helper functions (exported for testability)
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
/**
|
|
184
|
+
* Parse git for-each-ref output into cleaned branch names.
|
|
185
|
+
* Strips remote prefixes, deduplicates, and filters HEAD pointers.
|
|
186
|
+
*/
|
|
187
|
+
export function parseBranchNames(rawOutput) {
|
|
188
|
+
if (!rawOutput || !rawOutput.trim())
|
|
189
|
+
return [];
|
|
190
|
+
const rawEntries = [];
|
|
191
|
+
const detectedRemotes = new Set();
|
|
192
|
+
for (const line of rawOutput.split('\n')) {
|
|
193
|
+
const name = line.trim();
|
|
194
|
+
if (!name)
|
|
195
|
+
continue;
|
|
196
|
+
// Detect remote names from HEAD pointer entries (e.g., origin/HEAD)
|
|
197
|
+
if (name.endsWith('/HEAD')) {
|
|
198
|
+
const remoteName = name.substring(0, name.length - '/HEAD'.length);
|
|
199
|
+
if (remoteName)
|
|
200
|
+
detectedRemotes.add(remoteName);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (name === 'HEAD')
|
|
204
|
+
continue;
|
|
205
|
+
rawEntries.push(name);
|
|
206
|
+
}
|
|
207
|
+
const rawSet = new Set(rawEntries);
|
|
208
|
+
const cleaned = [];
|
|
209
|
+
const cleanedSet = new Set();
|
|
210
|
+
for (const name of rawEntries) {
|
|
211
|
+
const slashIdx = name.indexOf('/');
|
|
212
|
+
let cleanName = name;
|
|
213
|
+
if (slashIdx > 0) {
|
|
214
|
+
const firstSegment = name.substring(0, slashIdx);
|
|
215
|
+
const rest = name.substring(slashIdx + 1);
|
|
216
|
+
if (rest) {
|
|
217
|
+
const strippedExists = rawSet.has(rest);
|
|
218
|
+
const firstIsKnown = KNOWN_PREFIXES.includes(firstSegment + '/');
|
|
219
|
+
const restPrefix = rest.includes('/') ? rest.split('/')[0] + '/' : '';
|
|
220
|
+
const restHasKnownPrefix = restPrefix !== '' && KNOWN_PREFIXES.includes(restPrefix);
|
|
221
|
+
let peerStrippedExists = false;
|
|
222
|
+
if (!firstIsKnown) {
|
|
223
|
+
for (const other of rawSet) {
|
|
224
|
+
if (other !== name && other.startsWith(firstSegment + '/')) {
|
|
225
|
+
const otherRest = other.substring(firstSegment.length + 1);
|
|
226
|
+
if (rawSet.has(otherRest)) {
|
|
227
|
+
peerStrippedExists = true;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const isDetectedRemote = detectedRemotes.has(firstSegment);
|
|
234
|
+
const isRemote = !firstIsKnown && (strippedExists || restHasKnownPrefix || peerStrippedExists || isDetectedRemote);
|
|
235
|
+
if (isRemote) {
|
|
236
|
+
cleanName = rest;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (cleanName && !cleanedSet.has(cleanName)) {
|
|
241
|
+
cleanedSet.add(cleanName);
|
|
242
|
+
cleaned.push(cleanName);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return cleaned;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Classify branch names by their prefix (first path segment before /).
|
|
249
|
+
* Returns a map of prefix/ -> count for all branches containing a slash.
|
|
250
|
+
*/
|
|
251
|
+
export function classifyBranchPrefixes(branches) {
|
|
252
|
+
const counts = new Map();
|
|
253
|
+
for (const branch of branches) {
|
|
254
|
+
const slashIdx = branch.indexOf('/');
|
|
255
|
+
if (slashIdx <= 0)
|
|
256
|
+
continue;
|
|
257
|
+
const prefix = branch.substring(0, slashIdx + 1);
|
|
258
|
+
counts.set(prefix, (counts.get(prefix) || 0) + 1);
|
|
259
|
+
}
|
|
260
|
+
return counts;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Parse git log output (format: %H %P\n%s) to detect merge commits and PR platforms.
|
|
264
|
+
*/
|
|
265
|
+
export function parseMergeCommits(rawLogOutput) {
|
|
266
|
+
if (!rawLogOutput || !rawLogOutput.trim()) {
|
|
267
|
+
return { mergeCount: 0, totalCount: 0, prPlatform: null, usesPRs: false };
|
|
268
|
+
}
|
|
269
|
+
const lines = rawLogOutput.split('\n');
|
|
270
|
+
let totalCount = 0;
|
|
271
|
+
let mergeCount = 0;
|
|
272
|
+
let githubPRs = 0;
|
|
273
|
+
let gitlabMRs = 0;
|
|
274
|
+
let bitbucketPRs = 0;
|
|
275
|
+
let azurePRs = 0;
|
|
276
|
+
// Process pairs of lines: hash line + subject line
|
|
277
|
+
for (let i = 0; i < lines.length; i += 2) {
|
|
278
|
+
const hashLine = lines[i]?.trim();
|
|
279
|
+
const subject = lines[i + 1]?.trim();
|
|
280
|
+
if (!hashLine)
|
|
281
|
+
continue;
|
|
282
|
+
totalCount++;
|
|
283
|
+
// Check if merge commit: hash line has 3+ space-separated tokens (commit hash + 2+ parent hashes)
|
|
284
|
+
const parts = hashLine.split(/\s+/);
|
|
285
|
+
const isMerge = parts.length >= 3;
|
|
286
|
+
if (isMerge) {
|
|
287
|
+
mergeCount++;
|
|
288
|
+
}
|
|
289
|
+
// Check PR/MR platform from subject line
|
|
290
|
+
if (subject) {
|
|
291
|
+
if (/Merge pull request #\d+/.test(subject))
|
|
292
|
+
githubPRs++;
|
|
293
|
+
else if (/See merge request.*!\d+/.test(subject))
|
|
294
|
+
gitlabMRs++;
|
|
295
|
+
else if (/Merged in .* \(pull request #\d+\)/.test(subject))
|
|
296
|
+
bitbucketPRs++;
|
|
297
|
+
else if (/Merged PR \d+:/.test(subject))
|
|
298
|
+
azurePRs++;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Determine dominant PR platform
|
|
302
|
+
let prPlatform = null;
|
|
303
|
+
const prCounts = [
|
|
304
|
+
{ platform: 'github', count: githubPRs },
|
|
305
|
+
{ platform: 'gitlab', count: gitlabMRs },
|
|
306
|
+
{ platform: 'bitbucket', count: bitbucketPRs },
|
|
307
|
+
{ platform: 'azure', count: azurePRs },
|
|
308
|
+
];
|
|
309
|
+
const maxPR = prCounts.reduce((max, curr) => curr.count > max.count ? curr : max, prCounts[0]);
|
|
310
|
+
if (maxPR.count > 0) {
|
|
311
|
+
prPlatform = maxPR.platform;
|
|
312
|
+
}
|
|
313
|
+
const usesPRs = prPlatform !== null;
|
|
314
|
+
return { mergeCount, totalCount, prPlatform, usesPRs };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Determine the dominant merge strategy based on merge commit ratio.
|
|
318
|
+
*/
|
|
319
|
+
export function determineMergeStrategy(mergeCount, totalCount) {
|
|
320
|
+
if (totalCount < 5)
|
|
321
|
+
return 'unknown';
|
|
322
|
+
const mergeRatio = mergeCount / totalCount;
|
|
323
|
+
if (mergeRatio > 0.7)
|
|
324
|
+
return 'merge';
|
|
325
|
+
if (totalCount >= 20 && mergeRatio < 0.1)
|
|
326
|
+
return 'rebase';
|
|
327
|
+
if (mergeRatio >= 0.1 && mergeRatio <= 0.7)
|
|
328
|
+
return 'mixed';
|
|
329
|
+
// Default: covers 5 <= totalCount < 20 with mergeRatio < 0.1
|
|
330
|
+
return 'unknown';
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Build the agent branch naming convention based on detected patterns.
|
|
334
|
+
*/
|
|
335
|
+
export function buildAgentConvention(topPrefix, isUsernamePattern, isJiraPattern) {
|
|
336
|
+
if (isUsernamePattern) {
|
|
337
|
+
return 'archai/{task-id}-{description}';
|
|
338
|
+
}
|
|
339
|
+
if (isJiraPattern) {
|
|
340
|
+
return 'agent/{task-id}-{description}';
|
|
341
|
+
}
|
|
342
|
+
if (topPrefix && topPrefix !== 'agent/' && topPrefix !== 'archai/') {
|
|
343
|
+
return `${topPrefix}agent-{task-id}-{description}`;
|
|
344
|
+
}
|
|
345
|
+
if (topPrefix === 'archai/') {
|
|
346
|
+
return 'archai/{task-id}-{description}';
|
|
347
|
+
}
|
|
348
|
+
return 'agent/{task-id}-{description}';
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Detect git branching and merge patterns from repository history.
|
|
352
|
+
* Analyzes branch names (up to 100) and merge commits (up to 200).
|
|
353
|
+
* Never throws -- returns sensible defaults on any error.
|
|
354
|
+
*/
|
|
355
|
+
export async function detectGitPatterns(projectRoot) {
|
|
356
|
+
const defaults = {
|
|
357
|
+
branchPrefix: '',
|
|
358
|
+
agentBranchConvention: 'agent/{task-id}-{description}',
|
|
359
|
+
targetBranch: 'main',
|
|
360
|
+
mergeStrategy: 'unknown',
|
|
361
|
+
usesPullRequests: false,
|
|
362
|
+
prPlatform: null,
|
|
363
|
+
detectedPrefixes: [],
|
|
364
|
+
branchesAnalyzed: 0,
|
|
365
|
+
mergeCommitsAnalyzed: 0,
|
|
366
|
+
};
|
|
367
|
+
try {
|
|
368
|
+
// Step 1: Get branch names (up to 100)
|
|
369
|
+
const branchOutput = gitCommand('git for-each-ref --count=100 --sort=-committerdate refs/heads refs/remotes --format=%(refname:short)', projectRoot);
|
|
370
|
+
const branches = branchOutput ? parseBranchNames(branchOutput) : [];
|
|
371
|
+
// Step 2: Classify branch prefixes
|
|
372
|
+
const prefixCounts = classifyBranchPrefixes(branches);
|
|
373
|
+
// Find top prefix by count
|
|
374
|
+
let topPrefix = '';
|
|
375
|
+
let topCount = 0;
|
|
376
|
+
for (const [prefix, count] of prefixCounts) {
|
|
377
|
+
if (count > topCount) {
|
|
378
|
+
topPrefix = prefix;
|
|
379
|
+
topCount = count;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Determine if top prefix is username pattern or JIRA pattern
|
|
383
|
+
let isUsernamePattern = false;
|
|
384
|
+
let isJiraPattern = false;
|
|
385
|
+
if (topPrefix && !KNOWN_PREFIXES.includes(topPrefix)) {
|
|
386
|
+
if (/^[a-z]+\/$/.test(topPrefix)) {
|
|
387
|
+
isUsernamePattern = true;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (!topPrefix) {
|
|
391
|
+
const jiraBranches = branches.filter(b => /^[A-Z]+-\d+/.test(b));
|
|
392
|
+
if (jiraBranches.length >= 2) {
|
|
393
|
+
isJiraPattern = true;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// Step 3: Build agent convention
|
|
397
|
+
const agentBranchConvention = buildAgentConvention(topPrefix, isUsernamePattern, isJiraPattern);
|
|
398
|
+
// Step 4: Discover target branch
|
|
399
|
+
let targetBranch = 'main';
|
|
400
|
+
const defaultBranchConfig = gitCommand('git config init.defaultBranch', projectRoot);
|
|
401
|
+
if (defaultBranchConfig) {
|
|
402
|
+
targetBranch = defaultBranchConfig;
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
const branchList = gitCommand('git branch --list main master', projectRoot);
|
|
406
|
+
if (branchList) {
|
|
407
|
+
const branchNames = branchList.split('\n').map(b => b.replace(/^\*?\s*/, '').trim()).filter(Boolean);
|
|
408
|
+
if (branchNames.includes('main'))
|
|
409
|
+
targetBranch = 'main';
|
|
410
|
+
else if (branchNames.includes('master'))
|
|
411
|
+
targetBranch = 'master';
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Step 5: Analyze merge commits (up to 200)
|
|
415
|
+
const logOutput = gitCommand('git log --first-parent -200 --format=%H %P%n%s', projectRoot);
|
|
416
|
+
const defaultMerge = { mergeCount: 0, totalCount: 0, prPlatform: null, usesPRs: false };
|
|
417
|
+
const mergeResult = logOutput ? parseMergeCommits(logOutput) : defaultMerge;
|
|
418
|
+
const mergeStrategy = determineMergeStrategy(mergeResult.mergeCount, mergeResult.totalCount);
|
|
419
|
+
// Step 6: Build detected prefixes list (sorted by count descending)
|
|
420
|
+
const detectedPrefixes = [...prefixCounts.entries()]
|
|
421
|
+
.sort((a, b) => b[1] - a[1])
|
|
422
|
+
.map(([prefix]) => prefix);
|
|
423
|
+
return {
|
|
424
|
+
branchPrefix: topPrefix,
|
|
425
|
+
agentBranchConvention,
|
|
426
|
+
targetBranch,
|
|
427
|
+
mergeStrategy,
|
|
428
|
+
usesPullRequests: mergeResult.usesPRs,
|
|
429
|
+
prPlatform: mergeResult.prPlatform,
|
|
430
|
+
detectedPrefixes,
|
|
431
|
+
branchesAnalyzed: branches.length,
|
|
432
|
+
mergeCommitsAnalyzed: mergeResult.totalCount,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
return defaults;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=detect-git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-git.js","sourceRoot":"","sources":["../../src/utils/detect-git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { McpServer, McpIntrospectionResult } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Check if Claude CLI is available by running `claude --version`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function checkClaudeCli(): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Discover installed MCP servers by running `claude mcp list`.
|
|
8
|
+
* Parses the plain-text output line by line.
|
|
9
|
+
*
|
|
10
|
+
* Expected format:
|
|
11
|
+
* ```
|
|
12
|
+
* Checking MCP server health...
|
|
13
|
+
* claude.ai Figma: https://mcp.figma.com/mcp - ✓ Connected
|
|
14
|
+
* monday: mcp-server-monday-api -t <token> - ✓ Connected
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function discoverMcpServers(): McpServer[];
|
|
18
|
+
/**
|
|
19
|
+
* Identify which servers are task management MCPs based on name pattern matching.
|
|
20
|
+
* Only returns connected servers.
|
|
21
|
+
*/
|
|
22
|
+
export declare function identifyTaskManagers(servers: McpServer[]): McpServer[];
|
|
23
|
+
/**
|
|
24
|
+
* Get the provider display name for a task manager server.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getProviderName(serverName: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Introspect a task manager MCP via `claude -p` to discover boards and concept mapping.
|
|
29
|
+
* Returns null if introspection fails or response cannot be parsed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function introspectTaskManager(serverName: string): McpIntrospectionResult | null;
|
|
32
|
+
//# sourceMappingURL=detect-mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-mcp.d.ts","sourceRoot":"","sources":["../../src/utils/detect-mcp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAoC3E;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAGxC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,EAAE,CA2ChD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAMtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAkEvF"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { logger } from './logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Known task manager name patterns (case-insensitive match against server name).
|
|
5
|
+
*/
|
|
6
|
+
const TASK_MANAGER_PATTERNS = {
|
|
7
|
+
monday: 'monday.com',
|
|
8
|
+
linear: 'linear',
|
|
9
|
+
jira: 'jira',
|
|
10
|
+
asana: 'asana',
|
|
11
|
+
clickup: 'clickup',
|
|
12
|
+
notion: 'notion',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Run a claude CLI command with CLAUDECODE unset.
|
|
16
|
+
* Returns stdout on success, null on failure.
|
|
17
|
+
*/
|
|
18
|
+
function runClaudeCommand(args, timeoutMs = 30000) {
|
|
19
|
+
try {
|
|
20
|
+
const result = execSync(`CLAUDECODE= claude ${args}`, {
|
|
21
|
+
encoding: 'utf-8',
|
|
22
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
23
|
+
timeout: timeoutMs,
|
|
24
|
+
env: { ...process.env, CLAUDECODE: '' },
|
|
25
|
+
});
|
|
26
|
+
return result.trim() || null;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
logger.debug('Claude CLI command failed', {
|
|
30
|
+
args,
|
|
31
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
32
|
+
});
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if Claude CLI is available by running `claude --version`.
|
|
38
|
+
*/
|
|
39
|
+
export function checkClaudeCli() {
|
|
40
|
+
const result = runClaudeCommand('--version', 10000);
|
|
41
|
+
return result !== null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Discover installed MCP servers by running `claude mcp list`.
|
|
45
|
+
* Parses the plain-text output line by line.
|
|
46
|
+
*
|
|
47
|
+
* Expected format:
|
|
48
|
+
* ```
|
|
49
|
+
* Checking MCP server health...
|
|
50
|
+
* claude.ai Figma: https://mcp.figma.com/mcp - ✓ Connected
|
|
51
|
+
* monday: mcp-server-monday-api -t <token> - ✓ Connected
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function discoverMcpServers() {
|
|
55
|
+
const output = runClaudeCommand('mcp list', 15000);
|
|
56
|
+
if (!output) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const servers = [];
|
|
60
|
+
const lines = output.split('\n');
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
// Skip empty lines and header lines (like "Checking MCP server health...")
|
|
64
|
+
if (!trimmed || !trimmed.includes(' - ')) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Parse: "name: connectionInfo - status"
|
|
68
|
+
// The last " - " separates the status from the rest
|
|
69
|
+
const lastDashIndex = trimmed.lastIndexOf(' - ');
|
|
70
|
+
if (lastDashIndex === -1)
|
|
71
|
+
continue;
|
|
72
|
+
const statusPart = trimmed.slice(lastDashIndex + 3).trim();
|
|
73
|
+
const nameAndConnection = trimmed.slice(0, lastDashIndex).trim();
|
|
74
|
+
// Split name from connection info at the first ":"
|
|
75
|
+
const colonIndex = nameAndConnection.indexOf(':');
|
|
76
|
+
if (colonIndex === -1)
|
|
77
|
+
continue;
|
|
78
|
+
const name = nameAndConnection.slice(0, colonIndex).trim();
|
|
79
|
+
const connectionInfo = nameAndConnection.slice(colonIndex + 1).trim();
|
|
80
|
+
const isConnected = statusPart.toLowerCase().includes('connected');
|
|
81
|
+
servers.push({
|
|
82
|
+
name,
|
|
83
|
+
connectionInfo,
|
|
84
|
+
status: isConnected ? 'connected' : 'disconnected',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return servers;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Identify which servers are task management MCPs based on name pattern matching.
|
|
91
|
+
* Only returns connected servers.
|
|
92
|
+
*/
|
|
93
|
+
export function identifyTaskManagers(servers) {
|
|
94
|
+
return servers.filter(server => {
|
|
95
|
+
if (server.status !== 'connected')
|
|
96
|
+
return false;
|
|
97
|
+
const lowerName = server.name.toLowerCase();
|
|
98
|
+
return Object.keys(TASK_MANAGER_PATTERNS).some(pattern => lowerName.includes(pattern));
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the provider display name for a task manager server.
|
|
103
|
+
*/
|
|
104
|
+
export function getProviderName(serverName) {
|
|
105
|
+
const lowerName = serverName.toLowerCase();
|
|
106
|
+
for (const [pattern, provider] of Object.entries(TASK_MANAGER_PATTERNS)) {
|
|
107
|
+
if (lowerName.includes(pattern)) {
|
|
108
|
+
return provider;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return serverName;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Introspect a task manager MCP via `claude -p` to discover boards and concept mapping.
|
|
115
|
+
* Returns null if introspection fails or response cannot be parsed.
|
|
116
|
+
*/
|
|
117
|
+
export function introspectTaskManager(serverName) {
|
|
118
|
+
const prompt = [
|
|
119
|
+
`You have access to ${serverName} MCP tools.`,
|
|
120
|
+
'Complete these steps in order:',
|
|
121
|
+
'1. List available workspaces/boards/projects (use the appropriate MCP tool)',
|
|
122
|
+
'2. For each, note the ID and name',
|
|
123
|
+
'3. Map the task manager concepts to these Archai concepts:',
|
|
124
|
+
' - Epic (large feature/initiative)',
|
|
125
|
+
' - Task (unit of work)',
|
|
126
|
+
' - Subtask (part of a task)',
|
|
127
|
+
' - Status (workflow states)',
|
|
128
|
+
'4. Output ONLY a JSON block (no other text before or after) with this exact structure:',
|
|
129
|
+
' {"provider":"...","boards":[{"id":"...","name":"..."}],"mapping":{"epic":"...","task":"...","subtask":"...","statuses":["..."]}}',
|
|
130
|
+
].join('\n');
|
|
131
|
+
// Escape the prompt for shell usage
|
|
132
|
+
const escapedPrompt = prompt.replace(/"/g, '\\"');
|
|
133
|
+
const output = runClaudeCommand(`-p "${escapedPrompt}" --output-format text`, 120000);
|
|
134
|
+
if (!output) {
|
|
135
|
+
logger.debug('Introspection returned no output');
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
// Extract JSON from the response
|
|
139
|
+
const jsonMatch = output.match(/\{[\s\S]*\}/);
|
|
140
|
+
if (!jsonMatch) {
|
|
141
|
+
logger.debug('No JSON found in introspection response', output.slice(0, 500));
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
146
|
+
// Validate required fields
|
|
147
|
+
if (!parsed.provider || !parsed.boards || !parsed.mapping) {
|
|
148
|
+
logger.debug('Introspection JSON missing required fields');
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
if (!parsed.mapping.epic || !parsed.mapping.task || !parsed.mapping.subtask || !Array.isArray(parsed.mapping.statuses)) {
|
|
152
|
+
logger.debug('Introspection mapping missing required fields');
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
provider: String(parsed.provider),
|
|
157
|
+
boards: Array.isArray(parsed.boards)
|
|
158
|
+
? parsed.boards.map((b) => ({
|
|
159
|
+
id: String(b.id || ''),
|
|
160
|
+
name: String(b.name || ''),
|
|
161
|
+
}))
|
|
162
|
+
: [],
|
|
163
|
+
mapping: {
|
|
164
|
+
epic: String(parsed.mapping.epic),
|
|
165
|
+
task: String(parsed.mapping.task),
|
|
166
|
+
subtask: String(parsed.mapping.subtask),
|
|
167
|
+
statuses: parsed.mapping.statuses.map(String),
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
logger.debug('Failed to parse introspection JSON', {
|
|
173
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
174
|
+
});
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=detect-mcp.js.map
|