@memnexus-ai/mx-agent-cli 0.1.1

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.
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Git worktree operations for the agent CLI.
3
+ * Borrowed and simplified from dev-tools/worktree-cli/src/git.ts and config.ts.
4
+ */
5
+ import { execSync } from 'child_process';
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from 'fs';
7
+ import { join, dirname } from 'path';
8
+ // ── Project root detection ────────────────────────────────────────────
9
+ /**
10
+ * Walk up from cwd to find the repo root (directory containing .git).
11
+ *
12
+ * Strategy:
13
+ * 1. Walk up from cwd looking for a directory with both .git AND mx-agent-system/ or worktree.toml.
14
+ * This finds the actual "agent platform" project root even when running from inside a
15
+ * nested .worktrees/ sub-path.
16
+ * 2. If no such directory found, any directory with .git qualifies.
17
+ */
18
+ /**
19
+ * Returns true when the .git entry at `dir` is a real git directory (main
20
+ * worktree), not a gitfile (linked worktree). In a linked worktree `.git`
21
+ * is a plain file containing "gitdir: …".
22
+ */
23
+ function isMainWorktree(dir) {
24
+ const gitPath = join(dir, '.git');
25
+ try {
26
+ return statSync(gitPath).isDirectory();
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ export function findProjectRoot() {
33
+ let candidate = process.cwd();
34
+ // Walk up looking for the main worktree (where .git is a directory, not a
35
+ // gitfile) that also contains our canonical marker. This correctly skips
36
+ // linked worktrees, which have .git as a file.
37
+ let firstMainGit = null;
38
+ while (candidate !== dirname(candidate)) {
39
+ if (isMainWorktree(candidate)) {
40
+ if (firstMainGit === null)
41
+ firstMainGit = candidate;
42
+ if (existsSync(join(candidate, 'mx-agent-system')) ||
43
+ existsSync(join(candidate, 'worktree.toml'))) {
44
+ return candidate;
45
+ }
46
+ }
47
+ candidate = dirname(candidate);
48
+ }
49
+ if (firstMainGit !== null)
50
+ return firstMainGit;
51
+ throw new Error('Could not find project root (no .git directory found)');
52
+ }
53
+ // ── Slot management (mirrors dev-tools/worktree-cli/src/ports.ts) ─────
54
+ const SLOTS_FILENAME = '.slots.json';
55
+ function getSlotsPath(projectRoot) {
56
+ return join(projectRoot, '.worktrees', SLOTS_FILENAME);
57
+ }
58
+ export function loadSlots(projectRoot) {
59
+ const filePath = getSlotsPath(projectRoot);
60
+ if (!existsSync(filePath))
61
+ return {};
62
+ try {
63
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
64
+ }
65
+ catch {
66
+ return {};
67
+ }
68
+ }
69
+ function saveSlots(projectRoot, slots) {
70
+ const dir = join(projectRoot, '.worktrees');
71
+ if (!existsSync(dir))
72
+ mkdirSync(dir, { recursive: true });
73
+ writeFileSync(getSlotsPath(projectRoot), JSON.stringify(slots, null, 2));
74
+ }
75
+ export function assignSlot(projectRoot, worktreeName, maxWorktrees = 25) {
76
+ const slots = loadSlots(projectRoot);
77
+ if (slots[worktreeName] !== undefined)
78
+ return slots[worktreeName];
79
+ const used = new Set(Object.values(slots));
80
+ for (let i = 1; i <= maxWorktrees; i++) {
81
+ if (!used.has(i)) {
82
+ slots[worktreeName] = i;
83
+ saveSlots(projectRoot, slots);
84
+ return i;
85
+ }
86
+ }
87
+ throw new Error(`No available slots (max: ${maxWorktrees}). Remove a worktree first.`);
88
+ }
89
+ export function getSlot(projectRoot, worktreeName) {
90
+ const slots = loadSlots(projectRoot);
91
+ return slots[worktreeName] ?? null;
92
+ }
93
+ // ── Git helpers ───────────────────────────────────────────────────────
94
+ export function getCurrentBranch(cwd) {
95
+ try {
96
+ return execSync('git branch --show-current', {
97
+ cwd,
98
+ encoding: 'utf-8',
99
+ stdio: 'pipe',
100
+ }).trim() || null;
101
+ }
102
+ catch {
103
+ return null;
104
+ }
105
+ }
106
+ export function fetchOrigin(cwd) {
107
+ try {
108
+ execSync('git fetch origin', { cwd, stdio: 'pipe' });
109
+ }
110
+ catch {
111
+ // Non-fatal — continue anyway
112
+ }
113
+ }
114
+ /**
115
+ * Check if a branch already exists (local or remote).
116
+ */
117
+ function branchExists(branch, cwd) {
118
+ try {
119
+ const local = execSync(`git branch --list ${branch}`, { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim();
120
+ const remote = execSync(`git branch -r --list origin/${branch}`, { cwd, encoding: 'utf-8', stdio: 'pipe' }).trim();
121
+ return Boolean(local || remote);
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ }
127
+ /**
128
+ * Create a git worktree at `worktreePath` on `branch` (branched from `baseBranch`).
129
+ */
130
+ export function createGitWorktree(worktreePath, branch, baseBranch, cwd) {
131
+ if (branchExists(branch, cwd)) {
132
+ execSync(`git worktree add "${worktreePath}" "${branch}"`, { cwd, stdio: 'inherit' });
133
+ }
134
+ else {
135
+ try {
136
+ execSync(`git worktree add "${worktreePath}" -b "${branch}" "origin/${baseBranch}"`, { cwd, stdio: 'inherit' });
137
+ }
138
+ catch {
139
+ // Fall back to local branch if origin doesn't have it
140
+ execSync(`git worktree add "${worktreePath}" -b "${branch}" "${baseBranch}"`, { cwd, stdio: 'inherit' });
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ * Add the worktree path to git safe.directory (so git works inside it).
146
+ */
147
+ export function addToGitSafeDirectory(worktreePath) {
148
+ try {
149
+ const dirs = execSync('git config --global --get-all safe.directory 2>/dev/null || true', {
150
+ encoding: 'utf-8',
151
+ }).trim().split('\n').filter(Boolean);
152
+ if (!dirs.includes(worktreePath)) {
153
+ execSync(`git config --global --add safe.directory "${worktreePath}"`, { stdio: 'pipe' });
154
+ }
155
+ }
156
+ catch {
157
+ // Non-fatal
158
+ }
159
+ }
160
+ /**
161
+ * Generate a datestamped branch name for a team worktree.
162
+ * e.g. "retrieval" → "worktree/retrieval-20260222"
163
+ */
164
+ export function generateBranchName(teamSlug) {
165
+ const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
166
+ return `worktree/${teamSlug}-${date}`;
167
+ }
168
+ /**
169
+ * Generate the worktree directory name.
170
+ * e.g. "retrieval" + "20260222" → "retrieval-20260222"
171
+ */
172
+ export function generateWorktreeDirName(teamSlug) {
173
+ const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
174
+ return `${teamSlug}-${date}`;
175
+ }
176
+ /**
177
+ * Find the worktree directory for a team.
178
+ * Looks for an exact match `<name>` or a prefix match `<name>-*` under .worktrees/.
179
+ */
180
+ export function findWorktreePath(projectRoot, teamName) {
181
+ const worktreesDir = join(projectRoot, '.worktrees');
182
+ if (!existsSync(worktreesDir))
183
+ return null;
184
+ // Try exact match first
185
+ const exact = join(worktreesDir, teamName);
186
+ if (existsSync(exact))
187
+ return exact;
188
+ // Prefix match: teamName-YYYYMMDD
189
+ try {
190
+ const entries = execSync(`ls "${worktreesDir}"`, { encoding: 'utf-8', stdio: 'pipe' })
191
+ .trim()
192
+ .split('\n')
193
+ .filter(Boolean);
194
+ for (const entry of entries) {
195
+ if (entry === teamName || entry.startsWith(`${teamName}-`)) {
196
+ const candidate = join(worktreesDir, entry);
197
+ // Confirm it's actually a git worktree (has .git file)
198
+ if (existsSync(join(candidate, '.git'))) {
199
+ return candidate;
200
+ }
201
+ }
202
+ }
203
+ }
204
+ catch {
205
+ // ignore
206
+ }
207
+ return null;
208
+ }
209
+ //# sourceMappingURL=worktree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/lib/worktree.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@memnexus-ai/mx-agent-cli",
3
+ "version": "0.1.1",
4
+ "description": "CLI for creating and managing AI agent teams",
5
+ "type": "module",
6
+ "bin": {
7
+ "mx-agent": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsc --watch",
12
+ "start": "node dist/index.js",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "files": [
16
+ "dist/",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "memnexus",
21
+ "agent",
22
+ "cli",
23
+ "internal"
24
+ ],
25
+ "author": "MemNexus Team",
26
+ "license": "UNLICENSED",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/memnexus-ai/memnexus.git",
30
+ "directory": "mx-agent-system/cli"
31
+ },
32
+ "publishConfig": {
33
+ "access": "restricted"
34
+ },
35
+ "dependencies": {
36
+ "chalk": "^5.3.0",
37
+ "commander": "^12.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.11.0",
41
+ "typescript": "^5.3.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ }
46
+ }