multi-agents-cli 1.1.16 → 1.1.18
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/core/workflow/agent.js +95 -94
- package/core/workflow/guards.js +9 -2
- package/package.json +1 -1
package/core/workflow/agent.js
CHANGED
|
@@ -123,96 +123,6 @@ if (!config.ide) {
|
|
|
123
123
|
process.exit(1);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
// ── Claude Code CLI gate ─────────────────────────────────────────────────────
|
|
127
|
-
|
|
128
|
-
const checkClaudeAuth = () => {
|
|
129
|
-
try { execSync('claude --version', { stdio: 'pipe' }); return true; } catch { return false; }
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const installClaudeCode = () => {
|
|
133
|
-
const frames = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
|
|
134
|
-
let i = 0;
|
|
135
|
-
const spin = setInterval(() => process.stdout.write(`\r ${frames[i++ % frames.length]} Installing Claude Code CLI...`), 60);
|
|
136
|
-
try {
|
|
137
|
-
execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'pipe' });
|
|
138
|
-
clearInterval(spin);
|
|
139
|
-
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
140
|
-
console.log(` ${green('✓')} Claude Code CLI installed\n`);
|
|
141
|
-
return true;
|
|
142
|
-
} catch {
|
|
143
|
-
clearInterval(spin);
|
|
144
|
-
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
145
|
-
console.log(` ${red('✖')} Installation failed - try manually: ${cyan('npm install -g @anthropic-ai/claude-code')}\n`);
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const runClaudeLogin = () => {
|
|
151
|
-
const { spawnSync } = require('child_process');
|
|
152
|
-
console.log(`\n ${dim('Running claude login...')}\n`);
|
|
153
|
-
const result = spawnSync('claude', ['login'], { stdio: 'inherit' });
|
|
154
|
-
return result.status === 0;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
let claudeInstalled = false;
|
|
158
|
-
try { execSync('which claude', { stdio: 'pipe' }); claudeInstalled = true; } catch {}
|
|
159
|
-
|
|
160
|
-
await (async () => {
|
|
161
|
-
if (!claudeInstalled) {
|
|
162
|
-
console.log(`\n${red(' ✖ Claude Code CLI not found.')}\n`);
|
|
163
|
-
const installIdx = await prompts({
|
|
164
|
-
type: 'select',
|
|
165
|
-
name: 'value',
|
|
166
|
-
message: 'How would you like to proceed?',
|
|
167
|
-
choices: [
|
|
168
|
-
{ title: `${green('→')} I have an account - install Claude Code for me`, value: 0 },
|
|
169
|
-
{ title: `${dim('→')} I don\'t have an account yet - show me how to get started`, value: 1 },
|
|
170
|
-
{ title: `${dim('←')} Exit`, value: 2 },
|
|
171
|
-
],
|
|
172
|
-
}, { onCancel: () => process.exit(0) });
|
|
173
|
-
|
|
174
|
-
if (installIdx.value === 2 || installIdx.value === undefined) process.exit(0);
|
|
175
|
-
|
|
176
|
-
if (installIdx.value === 1) {
|
|
177
|
-
console.log(`\n ${bold('To get started with Claude Code:')}\n`);
|
|
178
|
-
console.log(` ${bold('1.')} Create a free account at ${cyan('https://claude.ai/signup')}`);
|
|
179
|
-
console.log(` ${bold('2.')} Install Claude Code: ${cyan('npm install -g @anthropic-ai/claude-code')}`);
|
|
180
|
-
console.log(` ${bold('3.')} Authenticate: ${cyan('claude login')}`);
|
|
181
|
-
console.log(` ${bold('4.')} Re-run: ${cyan('npm run agent')}\n`);
|
|
182
|
-
const { execSync: _open } = require('child_process');
|
|
183
|
-
try { _open('open https://claude.ai/signup', { stdio: 'pipe' }); } catch {}
|
|
184
|
-
process.exit(0);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const installed = installClaudeCode();
|
|
188
|
-
if (!installed) process.exit(1);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Auth check
|
|
192
|
-
let claudeAuthed = false;
|
|
193
|
-
try { execSync('claude --version', { stdio: 'pipe' }); claudeAuthed = true; } catch {}
|
|
194
|
-
|
|
195
|
-
if (!claudeAuthed) {
|
|
196
|
-
console.log(`\n${red(' ✖ Claude Code not authenticated.')}\n`);
|
|
197
|
-
const authIdx = await prompts({
|
|
198
|
-
type: 'select',
|
|
199
|
-
name: 'value',
|
|
200
|
-
message: 'How would you like to proceed?',
|
|
201
|
-
choices: [
|
|
202
|
-
{ title: `${green('→')} Run claude login now`, value: 0 },
|
|
203
|
-
{ title: `${dim('←')} Exit`, value: 1 },
|
|
204
|
-
],
|
|
205
|
-
}, { onCancel: () => process.exit(0) });
|
|
206
|
-
|
|
207
|
-
if (authIdx.value === 1 || authIdx.value === undefined) process.exit(0);
|
|
208
|
-
const loggedIn = runClaudeLogin();
|
|
209
|
-
if (!loggedIn) {
|
|
210
|
-
console.log(`\n ${red('✖')} Login failed - re-run ${cyan('npm run agent')} after authenticating\n`);
|
|
211
|
-
process.exit(1);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
})();
|
|
215
|
-
|
|
216
126
|
// ── Open IDE ──────────────────────────────────────────────────────────────────
|
|
217
127
|
|
|
218
128
|
const openIDE = (worktreePath) => {
|
|
@@ -865,6 +775,95 @@ const main = async () => {
|
|
|
865
775
|
guards.validateConfig(config, ROOT);
|
|
866
776
|
const tracking = guards.loadTracking(ROOT, config);
|
|
867
777
|
|
|
778
|
+
// ── Claude Code CLI gate ───────────────────────────────────────────────────
|
|
779
|
+
|
|
780
|
+
const checkClaudeAuth = () => {
|
|
781
|
+
try { execSync('claude --version', { stdio: 'pipe' }); return true; } catch { return false; }
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
const installClaudeCode = () => {
|
|
785
|
+
const frames = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
|
|
786
|
+
let i = 0;
|
|
787
|
+
const spin = setInterval(() => process.stdout.write(`\r ${frames[i++ % frames.length]} Installing Claude Code CLI...`), 60);
|
|
788
|
+
try {
|
|
789
|
+
execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'pipe' });
|
|
790
|
+
clearInterval(spin);
|
|
791
|
+
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
792
|
+
console.log(` ${green('✓')} Claude Code CLI installed\n`);
|
|
793
|
+
return true;
|
|
794
|
+
} catch {
|
|
795
|
+
clearInterval(spin);
|
|
796
|
+
process.stdout.write('\r' + ' '.repeat(40) + '\r');
|
|
797
|
+
console.log(` ${red('✖')} Installation failed - try manually: ${cyan('npm install -g @anthropic-ai/claude-code')}\n`);
|
|
798
|
+
return false;
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
const runClaudeLogin = () => {
|
|
803
|
+
const { spawnSync } = require('child_process');
|
|
804
|
+
console.log(`\n ${dim('Running claude login...')}\n`);
|
|
805
|
+
const result = spawnSync('claude', ['login'], { stdio: 'inherit' });
|
|
806
|
+
return result.status === 0;
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
let claudeInstalled = false;
|
|
810
|
+
try { execSync('which claude', { stdio: 'pipe' }); claudeInstalled = true; } catch {}
|
|
811
|
+
|
|
812
|
+
if (!claudeInstalled) {
|
|
813
|
+
console.log(`\n${red(' ✖ Claude Code CLI not found.')}\n`);
|
|
814
|
+
const installIdx = await prompts({
|
|
815
|
+
type: 'select',
|
|
816
|
+
name: 'value',
|
|
817
|
+
message: 'How would you like to proceed?',
|
|
818
|
+
choices: [
|
|
819
|
+
{ title: `${green('→')} I have an account - install Claude Code for me`, value: 0 },
|
|
820
|
+
{ title: `${dim('→')} I don\'t have an account yet - show me how to get started`, value: 1 },
|
|
821
|
+
{ title: `${dim('←')} Exit`, value: 2 },
|
|
822
|
+
],
|
|
823
|
+
}, { onCancel: () => process.exit(0) });
|
|
824
|
+
|
|
825
|
+
if (installIdx.value === 2 || installIdx.value === undefined) process.exit(0);
|
|
826
|
+
|
|
827
|
+
if (installIdx.value === 1) {
|
|
828
|
+
console.log(`\n ${bold('To get started with Claude Code:')}\n`);
|
|
829
|
+
console.log(` ${bold('1.')} Create a free account at ${cyan('https://claude.ai/signup')}`);
|
|
830
|
+
console.log(` ${bold('2.')} Install Claude Code: ${cyan('npm install -g @anthropic-ai/claude-code')}`);
|
|
831
|
+
console.log(` ${bold('3.')} Authenticate: ${cyan('claude login')}`);
|
|
832
|
+
console.log(` ${bold('4.')} Re-run: ${cyan('npm run agent')}\n`);
|
|
833
|
+
const { execSync: _open } = require('child_process');
|
|
834
|
+
try { _open('open https://claude.ai/signup', { stdio: 'pipe' }); } catch {}
|
|
835
|
+
process.exit(0);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const installed = installClaudeCode();
|
|
839
|
+
if (!installed) process.exit(1);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// Auth check
|
|
843
|
+
let claudeAuthed = false;
|
|
844
|
+
try { execSync('claude --version', { stdio: 'pipe' }); claudeAuthed = true; } catch {}
|
|
845
|
+
|
|
846
|
+
if (!claudeAuthed) {
|
|
847
|
+
console.log(`\n${red(' ✖ Claude Code not authenticated.')}\n`);
|
|
848
|
+
const authIdx = await prompts({
|
|
849
|
+
type: 'select',
|
|
850
|
+
name: 'value',
|
|
851
|
+
message: 'How would you like to proceed?',
|
|
852
|
+
choices: [
|
|
853
|
+
{ title: `${green('→')} Run claude login now`, value: 0 },
|
|
854
|
+
{ title: `${dim('←')} Exit`, value: 1 },
|
|
855
|
+
],
|
|
856
|
+
}, { onCancel: () => process.exit(0) });
|
|
857
|
+
|
|
858
|
+
if (authIdx.value === 1 || authIdx.value === undefined) process.exit(0);
|
|
859
|
+
const loggedIn = runClaudeLogin();
|
|
860
|
+
if (!loggedIn) {
|
|
861
|
+
console.log(`\n ${red('✖')} Login failed - re-run ${cyan('npm run agent')} after authenticating\n`);
|
|
862
|
+
process.exit(1);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
|
|
868
867
|
// ── Project status snapshot ───────────────────────────────────────────────────
|
|
869
868
|
|
|
870
869
|
const rawEntries = parseBuildState();
|
|
@@ -1120,7 +1119,8 @@ const main = async () => {
|
|
|
1120
1119
|
if (active) {
|
|
1121
1120
|
// Read task from TASK.md if available
|
|
1122
1121
|
let activeTask = activeSlot.branch;
|
|
1123
|
-
const
|
|
1122
|
+
const activeWorktreePath = path.isAbsolute(activeSlot.worktreePath) ? activeSlot.worktreePath : path.resolve(ROOT, activeSlot.worktreePath);
|
|
1123
|
+
const activeTm = path.join(activeWorktreePath, 'TASK.md');
|
|
1124
1124
|
if (fs.existsSync(activeTm)) {
|
|
1125
1125
|
const tmContent = fs.readFileSync(activeTm, 'utf8');
|
|
1126
1126
|
const taskMatch = tmContent.match(/## Task\n.*Task:\s*(.+)/);
|
|
@@ -1144,9 +1144,9 @@ const main = async () => {
|
|
|
1144
1144
|
if (activeChoice === 1) {
|
|
1145
1145
|
separator();
|
|
1146
1146
|
console.log(`\n ${green('✓')} Opening existing workspace...\n`);
|
|
1147
|
-
openIDE(
|
|
1147
|
+
openIDE(activeWorktreePath);
|
|
1148
1148
|
console.log(` ${bold('Resume your task:')}`);
|
|
1149
|
-
console.log(` ${dim('1.')} IDE should be open at: ${cyan(
|
|
1149
|
+
console.log(` ${dim('1.')} IDE should be open at: ${cyan(activeWorktreePath)}`);
|
|
1150
1150
|
console.log(` ${dim('2.')} Open a NEW session in Claude Code CLI or Claude Code Extension - type go or start to resume`);
|
|
1151
1151
|
console.log(` ${dim('3.')} Type: ${cyan('Read TASK.md and continue from where you stopped.')}\n`);
|
|
1152
1152
|
separator(); rl.close(); return;
|
|
@@ -1186,7 +1186,8 @@ const main = async () => {
|
|
|
1186
1186
|
});
|
|
1187
1187
|
|
|
1188
1188
|
if (gateResult.action === 'recovered') {
|
|
1189
|
-
|
|
1189
|
+
const gateWorktreePath = path.isAbsolute(gateResult.worktreePath) ? gateResult.worktreePath : path.resolve(ROOT, gateResult.worktreePath);
|
|
1190
|
+
openIDE(gateWorktreePath);
|
|
1190
1191
|
rl.close();
|
|
1191
1192
|
return;
|
|
1192
1193
|
}
|
package/core/workflow/guards.js
CHANGED
|
@@ -113,7 +113,11 @@ const updateTrackingSlot = (tracking, scope, agent, data, ROOT) => {
|
|
|
113
113
|
if (!tracking[scope]) tracking[scope] = {};
|
|
114
114
|
if (!tracking[scope][agent]) tracking[scope][agent] = emptySlot();
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
const normalizedData = { ...data };
|
|
117
|
+
if (normalizedData.worktreePath && path.isAbsolute(normalizedData.worktreePath)) {
|
|
118
|
+
normalizedData.worktreePath = path.relative(ROOT, normalizedData.worktreePath);
|
|
119
|
+
}
|
|
120
|
+
tracking[scope][agent] = { ...tracking[scope][agent], ...normalizedData };
|
|
117
121
|
|
|
118
122
|
const trackingPath = path.join(ROOT, '.scaffold', '.tracking.json');
|
|
119
123
|
fs.writeFileSync(trackingPath, JSON.stringify(tracking, null, 2), 'utf8');
|
|
@@ -458,7 +462,10 @@ const runMissingGate = async (params) => {
|
|
|
458
462
|
worktreePath,
|
|
459
463
|
}, ROOT);
|
|
460
464
|
|
|
461
|
-
|
|
465
|
+
const resolvedWorktreePath = path.isAbsolute(worktreePath)
|
|
466
|
+
? worktreePath
|
|
467
|
+
: path.resolve(ROOT, worktreePath);
|
|
468
|
+
return { action: 'recovered', worktreePath: resolvedWorktreePath };
|
|
462
469
|
}
|
|
463
470
|
|
|
464
471
|
// ── Handle: Reset ──────────────────────────────────────────────────────────
|
package/package.json
CHANGED