codymaster 4.1.2 β 4.1.4
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/CHANGELOG.md +25 -2
- package/README.md +108 -35
- package/dist/index.js +728 -658
- package/dist/ui/box.js +237 -0
- package/dist/ui/hamster.js +223 -0
- package/dist/ui/hooks.js +253 -0
- package/dist/ui/onboarding.js +315 -0
- package/dist/ui/theme.js +105 -0
- package/install.sh +143 -64
- package/package.json +5 -6
- package/skills/cm-quality-gate/SKILL.md +15 -0
- package/skills/cm-safe-i18n/SKILL.md +4 -1
- package/skills/cm-tdd/SKILL.md +8 -8
package/dist/index.js
CHANGED
|
@@ -59,28 +59,84 @@ const skill_chain_1 = require("./skill-chain");
|
|
|
59
59
|
const path_1 = __importDefault(require("path"));
|
|
60
60
|
const os_1 = __importDefault(require("os"));
|
|
61
61
|
const https_1 = __importDefault(require("https"));
|
|
62
|
-
|
|
62
|
+
// πΉ Hamster Shell UI modules
|
|
63
|
+
const theme_1 = require("./ui/theme");
|
|
64
|
+
const box_1 = require("./ui/box");
|
|
65
|
+
const hamster_1 = require("./ui/hamster");
|
|
66
|
+
const hooks_1 = require("./ui/hooks");
|
|
67
|
+
const onboarding_1 = require("./ui/onboarding");
|
|
68
|
+
const VERSION = require('../package.json').version;
|
|
69
|
+
// βββ Update Check βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
70
|
+
let _updateMessage = '';
|
|
71
|
+
function checkForUpdates() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
try {
|
|
74
|
+
const cacheDir = path_1.default.join(os_1.default.homedir(), '.codymaster');
|
|
75
|
+
const cacheFile = path_1.default.join(cacheDir, '.update-check');
|
|
76
|
+
// Check cache (24h TTL)
|
|
77
|
+
try {
|
|
78
|
+
if (fs_1.default.existsSync(cacheFile)) {
|
|
79
|
+
const stat = fs_1.default.statSync(cacheFile);
|
|
80
|
+
const age = Date.now() - stat.mtimeMs;
|
|
81
|
+
if (age < 24 * 60 * 60 * 1000) {
|
|
82
|
+
const cached = fs_1.default.readFileSync(cacheFile, 'utf-8').trim();
|
|
83
|
+
if (cached && cached !== VERSION) {
|
|
84
|
+
_updateMessage = cached;
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch ( /* ignore cache errors */_a) { /* ignore cache errors */ }
|
|
91
|
+
// Fetch latest version from npm (2s timeout)
|
|
92
|
+
const latestVersion = yield new Promise((resolve, reject) => {
|
|
93
|
+
const timer = setTimeout(() => reject(new Error('timeout')), 2000);
|
|
94
|
+
https_1.default.get('https://registry.npmjs.org/codymaster/latest', { headers: { 'Accept': 'application/json' } }, (res) => {
|
|
95
|
+
let data = '';
|
|
96
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
97
|
+
res.on('end', () => {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
try {
|
|
100
|
+
const json = JSON.parse(data);
|
|
101
|
+
resolve(json.version || VERSION);
|
|
102
|
+
}
|
|
103
|
+
catch (_a) {
|
|
104
|
+
resolve(VERSION);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}).on('error', () => { clearTimeout(timer); reject(new Error('fetch failed')); });
|
|
108
|
+
});
|
|
109
|
+
// Cache result
|
|
110
|
+
try {
|
|
111
|
+
if (!fs_1.default.existsSync(cacheDir))
|
|
112
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
113
|
+
fs_1.default.writeFileSync(cacheFile, latestVersion);
|
|
114
|
+
}
|
|
115
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
116
|
+
if (latestVersion !== VERSION) {
|
|
117
|
+
_updateMessage = latestVersion;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch ( /* silently skip β offline or timeout */_c) { /* silently skip β offline or timeout */ }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function printUpdateNotice() {
|
|
124
|
+
if (_updateMessage) {
|
|
125
|
+
console.log(chalk_1.default.yellow(` β οΈ Update available: ${VERSION} β ${_updateMessage}`) + chalk_1.default.gray(' Run: ') + chalk_1.default.cyan('npm i -g codymaster'));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
63
128
|
// βββ Branding βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
64
129
|
function showBanner() {
|
|
65
130
|
const cPath = process.cwd().replace(os_1.default.homedir(), '~');
|
|
66
|
-
const
|
|
67
|
-
console.log(
|
|
68
|
-
|
|
69
|
-
console.log(` ${bg.black.bold(' CM ')} ${chalk_1.default.gray('34 Skills. Ship 10x faster.')}`);
|
|
70
|
-
console.log(` ${bg(' ')} ${chalk_1.default.gray(cPath)}`);
|
|
71
|
-
console.log(chalk_1.default.gray(' ' + 'β'.repeat(46)));
|
|
131
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
132
|
+
console.log((0, hamster_1.renderHamsterBanner)(profile.userName || undefined, VERSION, cPath));
|
|
133
|
+
printUpdateNotice();
|
|
72
134
|
}
|
|
73
135
|
// βββ Utility ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
'low': chalk_1.default.green, 'medium': chalk_1.default.yellow, 'high': chalk_1.default.red, 'urgent': chalk_1.default.magenta,
|
|
79
|
-
};
|
|
80
|
-
const STATUS_COLORS = {
|
|
81
|
-
'success': chalk_1.default.green, 'failed': chalk_1.default.red, 'pending': chalk_1.default.yellow,
|
|
82
|
-
'running': chalk_1.default.blue, 'rolled_back': chalk_1.default.magenta,
|
|
83
|
-
};
|
|
136
|
+
// Color maps now imported from ./ui/theme (COL, PRI, STATUS)
|
|
137
|
+
const COL_COLORS = theme_1.COL;
|
|
138
|
+
const PRIORITY_COLORS = theme_1.PRI;
|
|
139
|
+
const STATUS_COLORS = theme_1.STATUS;
|
|
84
140
|
function padRight(str, len) {
|
|
85
141
|
return str.length >= len ? str.substring(0, len) : str + ' '.repeat(len - str.length);
|
|
86
142
|
}
|
|
@@ -94,138 +150,132 @@ function openUrl(url) {
|
|
|
94
150
|
// βββ Post-install Onboarding βββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
95
151
|
function postInstallOnboarding(platform) {
|
|
96
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
153
|
+
// Run the self-onboarding wizard
|
|
154
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
155
|
+
if (!profile.onboardingComplete) {
|
|
156
|
+
// Set platform from install if not already set
|
|
157
|
+
if (platform && !profile.platform) {
|
|
158
|
+
profile.platform = platform;
|
|
159
|
+
(0, hooks_1.saveProfile)(profile);
|
|
160
|
+
}
|
|
161
|
+
yield (0, onboarding_1.runOnboarding)(VERSION);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Already onboarded β show returning welcome
|
|
165
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
166
|
+
console.log('');
|
|
167
|
+
console.log((0, hamster_1.getHamsterArt)('celebrating'));
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(` ${(0, theme_1.success)('π')} ${(0, theme_1.brandBold)(`Welcome back, ${profile.userName || 'friend'}!`)}`);
|
|
170
|
+
console.log('');
|
|
171
|
+
const action = yield p.select({
|
|
172
|
+
message: 'What would you like to do?',
|
|
173
|
+
options: [
|
|
174
|
+
{ label: `${theme_1.ICONS.dashboard} Launch Dashboard`, value: 'dashboard', hint: `localhost:${data_1.DEFAULT_PORT}` },
|
|
175
|
+
{ label: `${theme_1.ICONS.skill} Browse all 34 skills`, value: 'skills' },
|
|
176
|
+
{ label: `${theme_1.ICONS.deploy} Start with your AI`, value: 'invoke', hint: profile.platform || 'any agent' },
|
|
177
|
+
{ label: `${(0, theme_1.success)('β')} Done`, value: 'done' },
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
if (p.isCancel(action))
|
|
181
|
+
return;
|
|
182
|
+
switch (action) {
|
|
183
|
+
case 'dashboard':
|
|
184
|
+
if (!isDashboardRunning()) {
|
|
185
|
+
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, false);
|
|
186
|
+
yield new Promise(r => setTimeout(r, 800));
|
|
187
|
+
}
|
|
188
|
+
console.log((0, theme_1.info)(`\n π Opening http://localhost:${data_1.DEFAULT_PORT} ...\n`));
|
|
189
|
+
openUrl(`http://localhost:${data_1.DEFAULT_PORT}`);
|
|
190
|
+
break;
|
|
191
|
+
case 'skills':
|
|
192
|
+
console.log('');
|
|
193
|
+
skillList();
|
|
194
|
+
break;
|
|
195
|
+
case 'invoke':
|
|
196
|
+
console.log('');
|
|
197
|
+
const invoke = profile.platform === 'claude' ? '/cm:demo' :
|
|
198
|
+
profile.platform === 'gemini' ? '@[/cm-planning]' :
|
|
199
|
+
'@cm-planning';
|
|
200
|
+
console.log(` ${(0, theme_1.brand)('β')} Type ${(0, theme_1.brandBold)(invoke)} in your AI agent\n`);
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
console.log((0, theme_1.dim)('\n Run cm any time! πΉ\n'));
|
|
143
204
|
}
|
|
144
|
-
case 'invoke':
|
|
145
|
-
console.log();
|
|
146
|
-
if (platform === 'claude') {
|
|
147
|
-
console.log(chalk_1.default.white('Open Claude Code and type:\n'));
|
|
148
|
-
console.log(chalk_1.default.cyan(' /cm:demo'));
|
|
149
|
-
console.log(chalk_1.default.gray('\n This will run an interactive tour of all 34 skills.\n'));
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
console.log(chalk_1.default.cyan(` ${invoke}\n`));
|
|
153
|
-
}
|
|
154
|
-
break;
|
|
155
|
-
case 'skills':
|
|
156
|
-
console.log();
|
|
157
|
-
skillList();
|
|
158
|
-
break;
|
|
159
|
-
case 'global':
|
|
160
|
-
console.log();
|
|
161
|
-
console.log(chalk_1.default.white('Run this to install the `cm` CLI globally:\n'));
|
|
162
|
-
console.log(chalk_1.default.cyan(' npm install -g codymaster'));
|
|
163
|
-
console.log(chalk_1.default.gray('\nThen use:'));
|
|
164
|
-
console.log(chalk_1.default.cyan(' cm task add "My task"'));
|
|
165
|
-
console.log(chalk_1.default.cyan(' cm dashboard'));
|
|
166
|
-
console.log(chalk_1.default.cyan(' cm status\n'));
|
|
167
|
-
break;
|
|
168
|
-
default:
|
|
169
|
-
console.log(chalk_1.default.gray('\nRun `npx codymaster` any time to open the menu.\n'));
|
|
170
205
|
}
|
|
171
206
|
});
|
|
172
207
|
}
|
|
173
208
|
// βββ Interactive Quick Menu (no-args entry point) βββββββββββββββββββββββββββββ
|
|
174
209
|
function showInteractiveMenu() {
|
|
175
210
|
return __awaiter(this, void 0, void 0, function* () {
|
|
211
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
212
|
+
// π³ First Run β Start onboarding wizard
|
|
213
|
+
if (!profile.onboardingComplete) {
|
|
214
|
+
yield (0, onboarding_1.runOnboarding)(VERSION);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// πͺ Hook: Record command + check achievements
|
|
218
|
+
(0, hooks_1.recordCommand)(profile, 'menu');
|
|
219
|
+
const newAchievements = (0, hooks_1.checkAchievements)(profile);
|
|
220
|
+
(0, hooks_1.saveProfile)(profile);
|
|
221
|
+
// Show banner with hamster
|
|
176
222
|
showBanner();
|
|
223
|
+
// πͺ Hook: Contextual trigger
|
|
224
|
+
const data = (0, data_1.loadData)();
|
|
225
|
+
const taskCounts = {
|
|
226
|
+
tasksInProgress: data.tasks.filter(t => t.column === 'in-progress').length,
|
|
227
|
+
tasksInReview: data.tasks.filter(t => t.column === 'review').length,
|
|
228
|
+
tasksDone: data.tasks.filter(t => t.column === 'done').length,
|
|
229
|
+
totalTasks: data.tasks.length,
|
|
230
|
+
};
|
|
231
|
+
const trigger = (0, hooks_1.getContextualTrigger)(profile, taskCounts);
|
|
232
|
+
console.log(` ${(0, theme_1.brand)(theme_1.ICONS.hamster)} ${(0, theme_1.dim)(trigger)}`);
|
|
233
|
+
// Dashboard status
|
|
177
234
|
const dashStatus = isDashboardRunning()
|
|
178
|
-
?
|
|
179
|
-
:
|
|
180
|
-
console.log(
|
|
181
|
-
console.log();
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
title: chalk_1.default.yellow('β Add a Task'), value: 'addtask',
|
|
206
|
-
description: 'Quickly add a task to backlog'
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
title: chalk_1.default.green('β‘ Install/Update Skills'), value: 'install',
|
|
210
|
-
description: 'npx codymaster add --all'
|
|
211
|
-
},
|
|
212
|
-
{ title: chalk_1.default.gray('β Help'), value: 'help' },
|
|
235
|
+
? (0, theme_1.success)(`${theme_1.ICONS.dot} RUNNING`) + (0, theme_1.dim)(` http://localhost:${data_1.DEFAULT_PORT}`)
|
|
236
|
+
: (0, theme_1.muted)(`${theme_1.ICONS.dotEmpty} stopped`);
|
|
237
|
+
console.log(` ${(0, theme_1.dim)('Dashboard:')} ${dashStatus}`);
|
|
238
|
+
console.log('');
|
|
239
|
+
// Show new achievements
|
|
240
|
+
for (const id of newAchievements) {
|
|
241
|
+
console.log((0, hooks_1.formatAchievement)(id));
|
|
242
|
+
}
|
|
243
|
+
if (newAchievements.length > 0)
|
|
244
|
+
console.log('');
|
|
245
|
+
// Level indicator
|
|
246
|
+
console.log(` ${(0, theme_1.dim)('Level:')} ${(0, hooks_1.getLevelDisplay)(profile.level)} ${(0, theme_1.dim)('β’')} ${(0, theme_1.dim)('Streak:')} ${profile.streak > 0 ? (0, theme_1.brand)(`${theme_1.ICONS.fire} ${profile.streak}d`) : (0, theme_1.muted)('β')}`);
|
|
247
|
+
console.log('');
|
|
248
|
+
// Quick menu with @clack/prompts
|
|
249
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
250
|
+
const action = yield p.select({
|
|
251
|
+
message: 'Quick menu',
|
|
252
|
+
options: [
|
|
253
|
+
{ label: `${theme_1.ICONS.dashboard} Dashboard`, value: 'dashboard', hint: isDashboardRunning() ? 'Open' : 'Start & open' },
|
|
254
|
+
{ label: `${theme_1.ICONS.task} My Tasks`, value: 'tasks', hint: `${taskCounts.totalTasks} total` },
|
|
255
|
+
{ label: `π Status`, value: 'status', hint: 'Health snapshot' },
|
|
256
|
+
{ label: `${theme_1.ICONS.skill} Browse Skills`, value: 'skills', hint: '34 skills' },
|
|
257
|
+
{ label: `β Add a Task`, value: 'addtask', hint: 'Quick add' },
|
|
258
|
+
{ label: `β‘ Install Skills`, value: 'install', hint: 'Update all' },
|
|
259
|
+
{ label: `${theme_1.ICONS.hamster} My Profile`, value: 'profile', hint: `${profile.level}` },
|
|
260
|
+
{ label: `β Help`, value: 'help' },
|
|
213
261
|
],
|
|
214
|
-
hint: 'ββ navigate Β· Enter select Β· Ctrl+C exit',
|
|
215
262
|
});
|
|
216
|
-
|
|
217
|
-
|
|
263
|
+
if (p.isCancel(action)) {
|
|
264
|
+
console.log((0, theme_1.dim)('\n See you soon! πΉ\n'));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
console.log('');
|
|
268
|
+
switch (action) {
|
|
218
269
|
case 'dashboard':
|
|
219
270
|
if (!isDashboardRunning()) {
|
|
220
271
|
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, false);
|
|
221
272
|
yield new Promise(r => setTimeout(r, 800));
|
|
222
273
|
}
|
|
223
|
-
console.log(
|
|
274
|
+
console.log((0, theme_1.info)(` π Opening http://localhost:${data_1.DEFAULT_PORT} ...`));
|
|
224
275
|
openUrl(`http://localhost:${data_1.DEFAULT_PORT}`);
|
|
225
|
-
console.log(
|
|
276
|
+
console.log((0, theme_1.dim)(' Dashboard is running. Ctrl+C to stop.\n'));
|
|
226
277
|
break;
|
|
227
278
|
case 'tasks':
|
|
228
|
-
// Inline task list
|
|
229
279
|
require('child_process').spawnSync(process.execPath, [process.argv[1], 'task', 'list'], { stdio: 'inherit' });
|
|
230
280
|
break;
|
|
231
281
|
case 'status':
|
|
@@ -235,25 +285,41 @@ function showInteractiveMenu() {
|
|
|
235
285
|
skillList();
|
|
236
286
|
break;
|
|
237
287
|
case 'addtask': {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
288
|
+
const title = yield p.text({
|
|
289
|
+
message: 'Task title:',
|
|
290
|
+
placeholder: 'What are you working on?',
|
|
291
|
+
validate: (val) => {
|
|
292
|
+
if (!val || val.trim().length === 0)
|
|
293
|
+
return 'Give your task a title!';
|
|
294
|
+
return undefined;
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
if (!p.isCancel(title) && title) {
|
|
298
|
+
require('child_process').spawnSync(process.execPath, [process.argv[1], 'task', 'add', title], { stdio: 'inherit' });
|
|
241
299
|
}
|
|
242
300
|
break;
|
|
243
301
|
}
|
|
244
302
|
case 'install':
|
|
245
|
-
console.log(
|
|
303
|
+
console.log(` ${(0, theme_1.brand)('β')} Run: ${(0, theme_1.brandBold)('npx codymaster add --all')}\n`);
|
|
304
|
+
break;
|
|
305
|
+
case 'profile':
|
|
306
|
+
console.log((0, hooks_1.formatProfileSummary)(profile));
|
|
246
307
|
break;
|
|
247
308
|
case 'help':
|
|
248
|
-
default:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
309
|
+
default: {
|
|
310
|
+
const helpItems = [
|
|
311
|
+
`${(0, theme_1.brand)('cm')} ${(0, theme_1.dim)('Quick menu')}`,
|
|
312
|
+
`${(0, theme_1.brand)('cm task add')} ${(0, theme_1.dim)('"..."')} ${(0, theme_1.dim)('Add a task')}`,
|
|
313
|
+
`${(0, theme_1.brand)('cm task list')} ${(0, theme_1.dim)('View tasks')}`,
|
|
314
|
+
`${(0, theme_1.brand)('cm status')} ${(0, theme_1.dim)('Project health')}`,
|
|
315
|
+
`${(0, theme_1.brand)('cm dashboard')} ${(0, theme_1.dim)('Mission Control')}`,
|
|
316
|
+
`${(0, theme_1.brand)('cm list')} ${(0, theme_1.dim)('Browse 34 skills')}`,
|
|
317
|
+
`${(0, theme_1.brand)('cm deploy')} ${(0, theme_1.dim)('<env>')} ${(0, theme_1.dim)('Record deploy')}`,
|
|
318
|
+
`${(0, theme_1.brand)('cm profile')} ${(0, theme_1.dim)('Your stats')}`,
|
|
319
|
+
];
|
|
320
|
+
console.log((0, box_1.renderBox)(helpItems, { title: 'Commands', width: 52 }));
|
|
321
|
+
console.log('');
|
|
322
|
+
}
|
|
257
323
|
}
|
|
258
324
|
});
|
|
259
325
|
}
|
|
@@ -279,8 +345,7 @@ program
|
|
|
279
345
|
case 'start':
|
|
280
346
|
case undefined:
|
|
281
347
|
if (isDashboardRunning()) {
|
|
282
|
-
console.log(
|
|
283
|
-
console.log(chalk_1.default.gray(` URL: http://localhost:${port}`));
|
|
348
|
+
console.log((0, box_1.renderResult)('warning', 'Dashboard already running.', [`${(0, theme_1.dim)('URL:')} ${(0, theme_1.brand)(`http://localhost:${port}`)}`]));
|
|
284
349
|
return;
|
|
285
350
|
}
|
|
286
351
|
(0, dashboard_1.launchDashboard)(port);
|
|
@@ -292,15 +357,13 @@ program
|
|
|
292
357
|
dashboardStatus(port);
|
|
293
358
|
break;
|
|
294
359
|
case 'open':
|
|
295
|
-
console.log(
|
|
360
|
+
console.log((0, box_1.renderResult)('info', `Opening http://localhost:${port} ...`));
|
|
296
361
|
openUrl(`http://localhost:${port}`);
|
|
297
362
|
break;
|
|
298
363
|
case 'url':
|
|
299
364
|
console.log(`http://localhost:${port}`);
|
|
300
365
|
break;
|
|
301
|
-
default:
|
|
302
|
-
console.log(chalk_1.default.red(`Unknown: ${cmd}`));
|
|
303
|
-
console.log(chalk_1.default.gray('Available: start, stop, status, open, url'));
|
|
366
|
+
default: console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: start, stop, status, open, url')]));
|
|
304
367
|
}
|
|
305
368
|
});
|
|
306
369
|
function isDashboardRunning() {
|
|
@@ -322,7 +385,7 @@ function isDashboardRunning() {
|
|
|
322
385
|
function stopDashboard() {
|
|
323
386
|
try {
|
|
324
387
|
if (!fs_1.default.existsSync(data_1.PID_FILE)) {
|
|
325
|
-
console.log(
|
|
388
|
+
console.log((0, box_1.renderResult)('warning', 'No dashboard running.'));
|
|
326
389
|
return;
|
|
327
390
|
}
|
|
328
391
|
const pid = parseInt(fs_1.default.readFileSync(data_1.PID_FILE, 'utf-8').trim());
|
|
@@ -331,10 +394,10 @@ function stopDashboard() {
|
|
|
331
394
|
fs_1.default.unlinkSync(data_1.PID_FILE);
|
|
332
395
|
}
|
|
333
396
|
catch (_a) { }
|
|
334
|
-
console.log(
|
|
397
|
+
console.log((0, box_1.renderResult)('success', `Dashboard stopped (PID ${pid}).`));
|
|
335
398
|
}
|
|
336
399
|
catch (err) {
|
|
337
|
-
console.log(
|
|
400
|
+
console.log((0, box_1.renderResult)('error', `Failed to stop: ${err.message}`));
|
|
338
401
|
try {
|
|
339
402
|
fs_1.default.unlinkSync(data_1.PID_FILE);
|
|
340
403
|
}
|
|
@@ -344,13 +407,10 @@ function stopDashboard() {
|
|
|
344
407
|
function dashboardStatus(port) {
|
|
345
408
|
if (isDashboardRunning()) {
|
|
346
409
|
const pid = fs_1.default.readFileSync(data_1.PID_FILE, 'utf-8').trim();
|
|
347
|
-
console.log(
|
|
348
|
-
console.log(chalk_1.default.gray(` PID: ${pid}`));
|
|
349
|
-
console.log(chalk_1.default.gray(` URL: http://localhost:${port}`));
|
|
410
|
+
console.log((0, box_1.renderResult)('success', 'Dashboard RUNNING', [`${(0, theme_1.dim)('PID:')} ${(0, theme_1.brand)(pid)}`, `${(0, theme_1.dim)('URL:')} ${(0, theme_1.brand)(`http://localhost:${port}`)}`]));
|
|
350
411
|
}
|
|
351
412
|
else {
|
|
352
|
-
console.log(
|
|
353
|
-
console.log(chalk_1.default.gray(' Start with: cm dashboard start'));
|
|
413
|
+
console.log((0, box_1.renderResult)('warning', 'Dashboard NOT running', [(0, theme_1.dim)('Start with: cm dashboard start')]));
|
|
354
414
|
}
|
|
355
415
|
}
|
|
356
416
|
// βββ Task Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -390,14 +450,12 @@ program
|
|
|
390
450
|
case 'stuck':
|
|
391
451
|
taskStuck(opts);
|
|
392
452
|
break;
|
|
393
|
-
default:
|
|
394
|
-
console.log(chalk_1.default.red(`Unknown: ${cmd}`));
|
|
395
|
-
console.log(chalk_1.default.gray('Available: add, list, move, done, rm, dispatch, stuck'));
|
|
453
|
+
default: console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: add, list, move, done, rm, dispatch, stuck')]));
|
|
396
454
|
}
|
|
397
455
|
});
|
|
398
456
|
function taskAdd(title, opts) {
|
|
399
457
|
if (!title) {
|
|
400
|
-
console.log(
|
|
458
|
+
console.log((0, box_1.renderResult)('error', 'Title required. Usage: cm task add "My task"'));
|
|
401
459
|
return;
|
|
402
460
|
}
|
|
403
461
|
const data = (0, data_1.loadData)();
|
|
@@ -405,7 +463,7 @@ function taskAdd(title, opts) {
|
|
|
405
463
|
if (opts.project) {
|
|
406
464
|
const project = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
407
465
|
if (!project) {
|
|
408
|
-
console.log(
|
|
466
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
409
467
|
return;
|
|
410
468
|
}
|
|
411
469
|
projectId = project.id;
|
|
@@ -427,8 +485,9 @@ function taskAdd(title, opts) {
|
|
|
427
485
|
(0, data_1.logActivity)(data, 'task_created', `Task "${task.title}" created via CLI`, projectId, opts.agent || '');
|
|
428
486
|
(0, data_1.saveData)(data);
|
|
429
487
|
const project = data.projects.find(p => p.id === projectId);
|
|
430
|
-
console.log(
|
|
431
|
-
|
|
488
|
+
console.log((0, box_1.renderResult)('success', `Task created: ${title}`, [
|
|
489
|
+
`${(0, theme_1.dim)('ID:')} ${(0, theme_1.brand)((0, data_1.shortId)(task.id))} ${(0, theme_1.dim)('|')} ${(0, theme_1.dim)('Project:')} ${(0, theme_1.brand)((project === null || project === void 0 ? void 0 : project.name) || 'Default')} ${(0, theme_1.dim)('|')} ${(0, theme_1.dim)(column)} ${(0, theme_1.dim)('|')} ${(0, theme_1.dim)(opts.priority || 'medium')}`,
|
|
490
|
+
]));
|
|
432
491
|
}
|
|
433
492
|
function taskList(opts) {
|
|
434
493
|
const data = (0, data_1.loadData)();
|
|
@@ -436,45 +495,45 @@ function taskList(opts) {
|
|
|
436
495
|
if (opts.project && !opts.all) {
|
|
437
496
|
const project = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
438
497
|
if (!project) {
|
|
439
|
-
console.log(
|
|
498
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
440
499
|
return;
|
|
441
500
|
}
|
|
442
501
|
tasks = tasks.filter(t => t.projectId === project.id);
|
|
443
|
-
console.log(
|
|
502
|
+
console.log((0, box_1.renderCommandHeader)(`Tasks β ${project.name}`, 'π'));
|
|
444
503
|
}
|
|
445
504
|
else {
|
|
446
|
-
console.log(
|
|
505
|
+
console.log((0, box_1.renderCommandHeader)('All Tasks', 'π'));
|
|
447
506
|
}
|
|
448
507
|
if (tasks.length === 0) {
|
|
449
|
-
console.log(
|
|
508
|
+
console.log(` ${(0, theme_1.dim)('No tasks found.')}\n`);
|
|
450
509
|
return;
|
|
451
510
|
}
|
|
452
|
-
console.log(
|
|
453
|
-
console.log(
|
|
511
|
+
console.log((0, theme_1.dim)(' ' + padRight('ID', 10) + padRight('Title', 36) + padRight('Column', 14) + padRight('Priority', 10) + padRight('Agent', 14) + 'Project'));
|
|
512
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(100)));
|
|
454
513
|
const co = ['backlog', 'in-progress', 'review', 'done'];
|
|
455
514
|
tasks.sort((a, b) => co.indexOf(a.column) - co.indexOf(b.column) || a.order - b.order);
|
|
456
515
|
for (const task of tasks) {
|
|
457
516
|
const cc = COL_COLORS[task.column] || chalk_1.default.white;
|
|
458
517
|
const pc = PRIORITY_COLORS[task.priority] || chalk_1.default.white;
|
|
459
518
|
const project = data.projects.find(p => p.id === task.projectId);
|
|
460
|
-
console.log(' ' +
|
|
519
|
+
console.log(' ' + (0, theme_1.dim)(padRight((0, data_1.shortId)(task.id), 10)) + padRight(task.title.substring(0, 34), 36) + cc(padRight(task.column, 14)) + pc(padRight(task.priority, 10)) + (0, theme_1.dim)(padRight(task.agent || 'β', 14)) + (0, theme_1.dim)((project === null || project === void 0 ? void 0 : project.name) || 'β'));
|
|
461
520
|
}
|
|
462
|
-
console.log(
|
|
521
|
+
console.log((0, theme_1.dim)(`\n Total: ${tasks.length} tasks\n`));
|
|
463
522
|
}
|
|
464
523
|
function taskMove(idPrefix, targetColumn) {
|
|
465
524
|
if (!idPrefix || !targetColumn) {
|
|
466
|
-
console.log(
|
|
525
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm task move <id> <column>'));
|
|
467
526
|
return;
|
|
468
527
|
}
|
|
469
528
|
const vc = ['backlog', 'in-progress', 'review', 'done'];
|
|
470
529
|
if (!vc.includes(targetColumn)) {
|
|
471
|
-
console.log(
|
|
530
|
+
console.log((0, box_1.renderResult)('error', `Invalid column: ${targetColumn}`, [(0, theme_1.dim)(`Valid: ${vc.join(', ')}`)]));
|
|
472
531
|
return;
|
|
473
532
|
}
|
|
474
533
|
const data = (0, data_1.loadData)();
|
|
475
534
|
const task = (0, data_1.findTaskByIdPrefix)(data, idPrefix);
|
|
476
535
|
if (!task) {
|
|
477
|
-
console.log(
|
|
536
|
+
console.log((0, box_1.renderResult)('error', `Task not found: ${idPrefix}`));
|
|
478
537
|
return;
|
|
479
538
|
}
|
|
480
539
|
const oldCol = task.column;
|
|
@@ -487,12 +546,11 @@ function taskMove(idPrefix, targetColumn) {
|
|
|
487
546
|
};
|
|
488
547
|
const allowed = VALID_TRANSITIONS[oldCol] || [];
|
|
489
548
|
if (oldCol !== targetColumn && !allowed.includes(targetColumn)) {
|
|
490
|
-
console.log(
|
|
491
|
-
console.log(chalk_1.default.gray(` Allowed transitions: ${allowed.join(', ')}`));
|
|
549
|
+
console.log((0, box_1.renderResult)('error', `Invalid transition: ${oldCol} β ${targetColumn}`, [(0, theme_1.dim)(`Allowed: ${allowed.join(', ')}`)]));
|
|
492
550
|
return;
|
|
493
551
|
}
|
|
494
552
|
if (oldCol === targetColumn) {
|
|
495
|
-
console.log(
|
|
553
|
+
console.log(` ${(0, theme_1.dim)(`Task already in ${targetColumn}.`)}`);
|
|
496
554
|
return;
|
|
497
555
|
}
|
|
498
556
|
task.column = targetColumn;
|
|
@@ -500,8 +558,9 @@ function taskMove(idPrefix, targetColumn) {
|
|
|
500
558
|
task.stuckSince = undefined;
|
|
501
559
|
(0, data_1.logActivity)(data, targetColumn === 'done' ? 'task_done' : 'task_transitioned', `Task "${task.title}" moved: ${oldCol} β ${targetColumn} (CLI)`, task.projectId, task.agent, { from: oldCol, to: targetColumn });
|
|
502
560
|
(0, data_1.saveData)(data);
|
|
503
|
-
console.log(
|
|
504
|
-
|
|
561
|
+
console.log((0, box_1.renderResult)('success', `Moved "${task.title}"`, [
|
|
562
|
+
`${(0, theme_1.dim)(oldCol)} ${(0, theme_1.brand)('β')} ${(COL_COLORS[targetColumn] || chalk_1.default.white)(targetColumn)}`,
|
|
563
|
+
]));
|
|
505
564
|
}
|
|
506
565
|
function taskStuck(opts) {
|
|
507
566
|
const data = (0, data_1.loadData)();
|
|
@@ -511,7 +570,7 @@ function taskStuck(opts) {
|
|
|
511
570
|
if (opts.project) {
|
|
512
571
|
const project = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
513
572
|
if (!project) {
|
|
514
|
-
console.log(
|
|
573
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
515
574
|
return;
|
|
516
575
|
}
|
|
517
576
|
tasks = tasks.filter(t => t.projectId === project.id);
|
|
@@ -521,56 +580,56 @@ function taskStuck(opts) {
|
|
|
521
580
|
return elapsed > thresholdMin * 60 * 1000;
|
|
522
581
|
}).sort((a, b) => new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime());
|
|
523
582
|
if (stuck.length === 0) {
|
|
524
|
-
console.log(
|
|
583
|
+
console.log((0, box_1.renderResult)('success', `No stuck tasks! All in-progress tasks updated within ${thresholdMin}m.`));
|
|
525
584
|
return;
|
|
526
585
|
}
|
|
527
|
-
console.log(
|
|
528
|
-
console.log(
|
|
529
|
-
console.log(
|
|
586
|
+
console.log((0, box_1.renderCommandHeader)(`${stuck.length} Stuck Tasks (>${thresholdMin}m in progress)`, 'β οΈ'));
|
|
587
|
+
console.log((0, theme_1.dim)(' ' + padRight('ID', 10) + padRight('Title', 36) + padRight('Stuck For', 12) + padRight('Agent', 14) + 'Priority'));
|
|
588
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(86)));
|
|
530
589
|
for (const task of stuck) {
|
|
531
590
|
const elapsed = now - new Date(task.updatedAt).getTime();
|
|
532
591
|
const minutes = Math.round(elapsed / 60000);
|
|
533
592
|
const timeStr = minutes < 60 ? `${minutes}m` : `${Math.floor(minutes / 60)}h ${minutes % 60}m`;
|
|
534
593
|
const project = data.projects.find(p => p.id === task.projectId);
|
|
535
594
|
const pc = PRIORITY_COLORS[task.priority] || chalk_1.default.white;
|
|
536
|
-
console.log(' ' +
|
|
595
|
+
console.log(' ' + (0, theme_1.dim)(padRight((0, data_1.shortId)(task.id), 10)) + padRight(task.title.substring(0, 34), 36) + (0, theme_1.warning)(padRight(timeStr, 12)) + (0, theme_1.dim)(padRight(task.agent || 'β', 14)) + pc(task.priority));
|
|
537
596
|
}
|
|
538
597
|
console.log();
|
|
539
|
-
console.log(
|
|
598
|
+
console.log((0, theme_1.dim)(' Tip: Move tasks with: cm task move <id> review|done|backlog'));
|
|
540
599
|
console.log();
|
|
541
600
|
}
|
|
542
601
|
function taskDone(idPrefix) {
|
|
543
602
|
if (!idPrefix) {
|
|
544
|
-
console.log(
|
|
603
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm task done <id>'));
|
|
545
604
|
return;
|
|
546
605
|
}
|
|
547
606
|
taskMove(idPrefix, 'done');
|
|
548
607
|
}
|
|
549
608
|
function taskRemove(idPrefix) {
|
|
550
609
|
if (!idPrefix) {
|
|
551
|
-
console.log(
|
|
610
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm task rm <id>'));
|
|
552
611
|
return;
|
|
553
612
|
}
|
|
554
613
|
const data = (0, data_1.loadData)();
|
|
555
614
|
const idx = data.tasks.findIndex(t => t.id === idPrefix || t.id.startsWith(idPrefix));
|
|
556
615
|
if (idx === -1) {
|
|
557
|
-
console.log(
|
|
616
|
+
console.log((0, box_1.renderResult)('error', `Task not found: ${idPrefix}`));
|
|
558
617
|
return;
|
|
559
618
|
}
|
|
560
619
|
const [removed] = data.tasks.splice(idx, 1);
|
|
561
620
|
(0, data_1.logActivity)(data, 'task_deleted', `Task "${removed.title}" deleted via CLI`, removed.projectId, removed.agent);
|
|
562
621
|
(0, data_1.saveData)(data);
|
|
563
|
-
console.log(
|
|
622
|
+
console.log((0, box_1.renderResult)('success', `Deleted: "${removed.title}" (${(0, data_1.shortId)(removed.id)})`));
|
|
564
623
|
}
|
|
565
624
|
function taskDispatch(idPrefix, opts) {
|
|
566
625
|
if (!idPrefix) {
|
|
567
|
-
console.log(
|
|
626
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm task dispatch <id> [--force]'));
|
|
568
627
|
return;
|
|
569
628
|
}
|
|
570
629
|
const data = (0, data_1.loadData)();
|
|
571
630
|
const task = (0, data_1.findTaskByIdPrefix)(data, idPrefix);
|
|
572
631
|
if (!task) {
|
|
573
|
-
console.log(
|
|
632
|
+
console.log((0, box_1.renderResult)('error', `Task not found: ${idPrefix}`));
|
|
574
633
|
return;
|
|
575
634
|
}
|
|
576
635
|
const project = data.projects.find(p => p.id === task.projectId);
|
|
@@ -584,20 +643,21 @@ function taskDispatch(idPrefix, opts) {
|
|
|
584
643
|
taskId: task.id, filePath: result.filePath, force: opts.force || false,
|
|
585
644
|
});
|
|
586
645
|
(0, data_1.saveData)(data);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
646
|
+
const details = [
|
|
647
|
+
`${(0, theme_1.dim)('Task:')} ${(0, theme_1.brand)(task.title)}`,
|
|
648
|
+
`${(0, theme_1.dim)('Agent:')} ${(0, theme_1.brand)(task.agent)}`,
|
|
649
|
+
];
|
|
590
650
|
if (task.skill)
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
console.log();
|
|
651
|
+
details.push(`${(0, theme_1.dim)('Skill:')} ${(0, theme_1.brand)(task.skill)}`);
|
|
652
|
+
details.push(`${(0, theme_1.dim)('File:')} ${(0, theme_1.brand)(result.filePath)}`);
|
|
653
|
+
console.log((0, box_1.renderResult)('success', `Task dispatched to ${task.agent}!`, details));
|
|
594
654
|
}
|
|
595
655
|
else {
|
|
596
656
|
task.dispatchStatus = 'failed';
|
|
597
657
|
task.dispatchError = result.error;
|
|
598
658
|
task.updatedAt = new Date().toISOString();
|
|
599
659
|
(0, data_1.saveData)(data);
|
|
600
|
-
console.log(
|
|
660
|
+
console.log((0, box_1.renderResult)('error', `Dispatch failed: ${result.error}`));
|
|
601
661
|
}
|
|
602
662
|
}
|
|
603
663
|
// βββ Project Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -619,14 +679,12 @@ program
|
|
|
619
679
|
case 'delete':
|
|
620
680
|
projectRemove(args[0]);
|
|
621
681
|
break;
|
|
622
|
-
default:
|
|
623
|
-
console.log(chalk_1.default.red(`Unknown: ${cmd}`));
|
|
624
|
-
console.log(chalk_1.default.gray('Available: add, list, rm'));
|
|
682
|
+
default: console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: add, list, rm')]));
|
|
625
683
|
}
|
|
626
684
|
});
|
|
627
685
|
function projectAdd(name, opts) {
|
|
628
686
|
if (!name) {
|
|
629
|
-
console.log(
|
|
687
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm project add "my-project"'));
|
|
630
688
|
return;
|
|
631
689
|
}
|
|
632
690
|
const data = (0, data_1.loadData)();
|
|
@@ -634,35 +692,36 @@ function projectAdd(name, opts) {
|
|
|
634
692
|
data.projects.push(project);
|
|
635
693
|
(0, data_1.logActivity)(data, 'project_created', `Project "${project.name}" created via CLI`, project.id);
|
|
636
694
|
(0, data_1.saveData)(data);
|
|
637
|
-
console.log(
|
|
638
|
-
|
|
695
|
+
console.log((0, box_1.renderResult)('success', `Project created: ${name}`, [
|
|
696
|
+
`${(0, theme_1.dim)('ID:')} ${(0, theme_1.brand)((0, data_1.shortId)(project.id))} ${(0, theme_1.dim)('|')} ${(0, theme_1.dim)('Path:')} ${(0, theme_1.brand)(project.path)}`,
|
|
697
|
+
]));
|
|
639
698
|
}
|
|
640
699
|
function projectList() {
|
|
641
700
|
const data = (0, data_1.loadData)();
|
|
642
701
|
if (data.projects.length === 0) {
|
|
643
|
-
console.log(
|
|
702
|
+
console.log(`\n ${(0, theme_1.dim)('No projects.')}\n`);
|
|
644
703
|
return;
|
|
645
704
|
}
|
|
646
|
-
console.log(
|
|
647
|
-
console.log(
|
|
648
|
-
console.log(
|
|
705
|
+
console.log((0, box_1.renderCommandHeader)('Projects', 'π¦'));
|
|
706
|
+
console.log((0, theme_1.dim)(' ' + padRight('ID', 10) + padRight('Name', 24) + padRight('Tasks', 8) + padRight('Agents', 20) + 'Path'));
|
|
707
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(90)));
|
|
649
708
|
for (const project of data.projects) {
|
|
650
709
|
const pt = data.tasks.filter(t => t.projectId === project.id);
|
|
651
710
|
const agents = [...new Set(pt.map(t => t.agent).filter(Boolean))];
|
|
652
711
|
const done = pt.filter(t => t.column === 'done').length;
|
|
653
|
-
console.log(' ' +
|
|
712
|
+
console.log(' ' + (0, theme_1.dim)(padRight((0, data_1.shortId)(project.id), 10)) + (0, theme_1.brand)(padRight(project.name, 24)) + (0, theme_1.dim)(padRight(`${done}/${pt.length}`, 8)) + (0, theme_1.dim)(padRight(agents.join(', ') || 'β', 20)) + (0, theme_1.dim)(project.path || 'β'));
|
|
654
713
|
}
|
|
655
714
|
console.log();
|
|
656
715
|
}
|
|
657
716
|
function projectRemove(query) {
|
|
658
717
|
if (!query) {
|
|
659
|
-
console.log(
|
|
718
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm project rm <name-or-id>'));
|
|
660
719
|
return;
|
|
661
720
|
}
|
|
662
721
|
const data = (0, data_1.loadData)();
|
|
663
722
|
const project = (0, data_1.findProjectByNameOrId)(data, query);
|
|
664
723
|
if (!project) {
|
|
665
|
-
console.log(
|
|
724
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${query}`));
|
|
666
725
|
return;
|
|
667
726
|
}
|
|
668
727
|
const tc = data.tasks.filter(t => t.projectId === project.id).length;
|
|
@@ -670,7 +729,7 @@ function projectRemove(query) {
|
|
|
670
729
|
data.tasks = data.tasks.filter(t => t.projectId !== project.id);
|
|
671
730
|
(0, data_1.logActivity)(data, 'project_deleted', `Project "${project.name}" deleted via CLI`, project.id);
|
|
672
731
|
(0, data_1.saveData)(data);
|
|
673
|
-
console.log(
|
|
732
|
+
console.log((0, box_1.renderResult)('success', `Deleted project "${project.name}" and ${tc} tasks.`));
|
|
674
733
|
}
|
|
675
734
|
// βββ Deploy Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
676
735
|
program
|
|
@@ -695,9 +754,7 @@ program
|
|
|
695
754
|
case 'ls':
|
|
696
755
|
deployList(opts);
|
|
697
756
|
break;
|
|
698
|
-
default:
|
|
699
|
-
console.log(chalk_1.default.red(`Unknown: ${cmd}`));
|
|
700
|
-
console.log(chalk_1.default.gray('Available: staging, production, list'));
|
|
757
|
+
default: console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: staging, production, list')]));
|
|
701
758
|
}
|
|
702
759
|
});
|
|
703
760
|
function deployRecord(env, opts) {
|
|
@@ -706,7 +763,7 @@ function deployRecord(env, opts) {
|
|
|
706
763
|
if (opts.project) {
|
|
707
764
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
708
765
|
if (!p) {
|
|
709
|
-
console.log(
|
|
766
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
710
767
|
return;
|
|
711
768
|
}
|
|
712
769
|
projectId = p.id;
|
|
@@ -715,7 +772,7 @@ function deployRecord(env, opts) {
|
|
|
715
772
|
projectId = data.projects[0].id;
|
|
716
773
|
}
|
|
717
774
|
else {
|
|
718
|
-
console.log(
|
|
775
|
+
console.log((0, box_1.renderResult)('error', 'No projects. Create one first: cm project add "my-project"'));
|
|
719
776
|
return;
|
|
720
777
|
}
|
|
721
778
|
const now = new Date().toISOString();
|
|
@@ -728,17 +785,18 @@ function deployRecord(env, opts) {
|
|
|
728
785
|
data.deployments.unshift(dep);
|
|
729
786
|
(0, data_1.logActivity)(data, env === 'staging' ? 'deploy_staging' : 'deploy_production', `Deployed to ${env}: ${dep.message}`, projectId, opts.agent || '', { deploymentId: dep.id });
|
|
730
787
|
(0, data_1.saveData)(data);
|
|
731
|
-
const envColor = env === 'production' ?
|
|
788
|
+
const envColor = env === 'production' ? theme_1.success : theme_1.warning;
|
|
732
789
|
const project = data.projects.find(p => p.id === projectId);
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
790
|
+
const details = [
|
|
791
|
+
`${(0, theme_1.dim)('ID:')} ${(0, theme_1.brand)((0, data_1.shortId)(dep.id))}`,
|
|
792
|
+
`${(0, theme_1.dim)('Env:')} ${envColor(env)}`,
|
|
793
|
+
`${(0, theme_1.dim)('Project:')} ${(0, theme_1.brand)((project === null || project === void 0 ? void 0 : project.name) || 'β')}`,
|
|
794
|
+
`${(0, theme_1.dim)('Message:')} ${dep.message}`,
|
|
795
|
+
];
|
|
738
796
|
if (dep.commit)
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
console.log();
|
|
797
|
+
details.push(`${(0, theme_1.dim)('Commit:')} ${(0, theme_1.brand)(dep.commit)}`);
|
|
798
|
+
details.push(`${(0, theme_1.dim)('Branch:')} ${(0, theme_1.brand)(dep.branch)}`);
|
|
799
|
+
console.log((0, box_1.renderResult)('success', 'Deployment recorded!', details));
|
|
742
800
|
}
|
|
743
801
|
function deployList(opts) {
|
|
744
802
|
const data = (0, data_1.loadData)();
|
|
@@ -746,26 +804,26 @@ function deployList(opts) {
|
|
|
746
804
|
if (opts.project) {
|
|
747
805
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
748
806
|
if (!p) {
|
|
749
|
-
console.log(
|
|
807
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
750
808
|
return;
|
|
751
809
|
}
|
|
752
810
|
deps = deps.filter(d => d.projectId === p.id);
|
|
753
811
|
}
|
|
754
812
|
if (deps.length === 0) {
|
|
755
|
-
console.log(
|
|
813
|
+
console.log(`\n ${(0, theme_1.dim)('No deployments yet.')}\n`);
|
|
756
814
|
return;
|
|
757
815
|
}
|
|
758
|
-
console.log(
|
|
759
|
-
console.log(
|
|
760
|
-
console.log(
|
|
816
|
+
console.log((0, box_1.renderCommandHeader)('Deployment History', 'π'));
|
|
817
|
+
console.log((0, theme_1.dim)(' ' + padRight('ID', 10) + padRight('Env', 12) + padRight('Status', 14) + padRight('Message', 32) + padRight('Branch', 12) + 'Time'));
|
|
818
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(100)));
|
|
761
819
|
for (const dep of deps.slice(0, 20)) {
|
|
762
820
|
const sc = STATUS_COLORS[dep.status] || chalk_1.default.white;
|
|
763
|
-
const ec = dep.env === 'production' ?
|
|
821
|
+
const ec = dep.env === 'production' ? theme_1.success : theme_1.warning;
|
|
764
822
|
const timeAgo = formatTimeAgoCli(dep.startedAt);
|
|
765
823
|
const rollbackFlag = dep.rollbackOf ? ' βͺ' : '';
|
|
766
|
-
console.log(' ' +
|
|
824
|
+
console.log(' ' + (0, theme_1.dim)(padRight((0, data_1.shortId)(dep.id), 10)) + ec(padRight(dep.env, 12)) + sc(padRight(dep.status.replace('_', ' ') + rollbackFlag, 14)) + padRight(dep.message.substring(0, 30), 32) + (0, theme_1.dim)(padRight(dep.branch || 'β', 12)) + (0, theme_1.dim)(timeAgo));
|
|
767
825
|
}
|
|
768
|
-
console.log(
|
|
826
|
+
console.log((0, theme_1.dim)(`\n Total: ${deps.length} deployments\n`));
|
|
769
827
|
}
|
|
770
828
|
// βββ Rollback Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
771
829
|
program
|
|
@@ -777,11 +835,11 @@ program
|
|
|
777
835
|
const data = (0, data_1.loadData)();
|
|
778
836
|
const dep = data.deployments.find(d => d.id === deployId || d.id.startsWith(deployId));
|
|
779
837
|
if (!dep) {
|
|
780
|
-
console.log(
|
|
838
|
+
console.log((0, box_1.renderResult)('error', `Deployment not found: ${deployId}`));
|
|
781
839
|
return;
|
|
782
840
|
}
|
|
783
841
|
if (dep.status === 'rolled_back') {
|
|
784
|
-
console.log(
|
|
842
|
+
console.log((0, box_1.renderResult)('warning', 'Already rolled back.'));
|
|
785
843
|
return;
|
|
786
844
|
}
|
|
787
845
|
dep.status = 'rolled_back';
|
|
@@ -794,10 +852,11 @@ program
|
|
|
794
852
|
data.deployments.unshift(rollback);
|
|
795
853
|
(0, data_1.logActivity)(data, 'rollback', `Rolled back ${dep.env} deploy: ${dep.message}`, dep.projectId, opts.agent || '', { originalDeployId: dep.id, rollbackId: rollback.id });
|
|
796
854
|
(0, data_1.saveData)(data);
|
|
797
|
-
console.log(
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
855
|
+
console.log((0, box_1.renderResult)('success', 'Rollback complete!', [
|
|
856
|
+
`${(0, theme_1.dim)('Original:')} ${(0, theme_1.brand)((0, data_1.shortId)(dep.id))} ${(0, theme_1.dim)(`(${dep.env})`)}`,
|
|
857
|
+
`${(0, theme_1.dim)('Rollback ID:')} ${(0, theme_1.brand)((0, data_1.shortId)(rollback.id))}`,
|
|
858
|
+
`${(0, theme_1.dim)('Status:')} ${dep.message} β rolled back`,
|
|
859
|
+
]));
|
|
801
860
|
});
|
|
802
861
|
// βββ History Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
803
862
|
program
|
|
@@ -812,7 +871,7 @@ program
|
|
|
812
871
|
if (opts.project) {
|
|
813
872
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
814
873
|
if (!p) {
|
|
815
|
-
console.log(
|
|
874
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
816
875
|
return;
|
|
817
876
|
}
|
|
818
877
|
acts = acts.filter(a => a.projectId === p.id);
|
|
@@ -820,23 +879,23 @@ program
|
|
|
820
879
|
const limit = parseInt(opts.limit) || 20;
|
|
821
880
|
acts = acts.slice(0, limit);
|
|
822
881
|
if (acts.length === 0) {
|
|
823
|
-
console.log(
|
|
882
|
+
console.log(`\n ${(0, theme_1.dim)('No activity yet.')}\n`);
|
|
824
883
|
return;
|
|
825
884
|
}
|
|
826
|
-
const
|
|
885
|
+
const ACT_ICONS = {
|
|
827
886
|
'task_created': 'β¨', 'task_moved': 'βοΈ', 'task_done': 'β
', 'task_deleted': 'ποΈ', 'task_updated': 'βοΈ',
|
|
828
887
|
'project_created': 'π¦', 'project_deleted': 'ποΈ',
|
|
829
888
|
'deploy_staging': 'π‘', 'deploy_production': 'π', 'deploy_failed': 'β', 'rollback': 'βͺ',
|
|
830
889
|
'git_push': 'π€', 'changelog_added': 'π',
|
|
831
890
|
};
|
|
832
|
-
console.log(
|
|
891
|
+
console.log((0, box_1.renderCommandHeader)(`Activity History (latest ${acts.length})`, 'π'));
|
|
833
892
|
for (const a of acts) {
|
|
834
|
-
const icon =
|
|
893
|
+
const icon = ACT_ICONS[a.type] || 'π';
|
|
835
894
|
const proj = data.projects.find(p => p.id === a.projectId);
|
|
836
|
-
const projTag = proj ?
|
|
837
|
-
const agentTag = a.agent ?
|
|
895
|
+
const projTag = proj ? (0, theme_1.dim)(` [${proj.name}]`) : '';
|
|
896
|
+
const agentTag = a.agent ? (0, theme_1.dim)(` @${a.agent}`) : '';
|
|
838
897
|
const time = formatTimeAgoCli(a.createdAt);
|
|
839
|
-
console.log(` ${icon} ${a.message}${projTag}${agentTag} ${
|
|
898
|
+
console.log(` ${icon} ${a.message}${projTag}${agentTag} ${(0, theme_1.dim)(`β ${time}`)}`);
|
|
840
899
|
}
|
|
841
900
|
console.log();
|
|
842
901
|
});
|
|
@@ -856,14 +915,12 @@ program
|
|
|
856
915
|
case 'ls':
|
|
857
916
|
changelogList(opts);
|
|
858
917
|
break;
|
|
859
|
-
default:
|
|
860
|
-
console.log(chalk_1.default.red(`Unknown: ${cmd}`));
|
|
861
|
-
console.log(chalk_1.default.gray('Available: add, list'));
|
|
918
|
+
default: console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: add, list')]));
|
|
862
919
|
}
|
|
863
920
|
});
|
|
864
921
|
function changelogAdd(args, opts) {
|
|
865
922
|
if (args.length < 2) {
|
|
866
|
-
console.log(
|
|
923
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm changelog add <version> "<title>" [changes...]'));
|
|
867
924
|
return;
|
|
868
925
|
}
|
|
869
926
|
const data = (0, data_1.loadData)();
|
|
@@ -871,7 +928,7 @@ function changelogAdd(args, opts) {
|
|
|
871
928
|
if (opts.project) {
|
|
872
929
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
873
930
|
if (!p) {
|
|
874
|
-
console.log(
|
|
931
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
875
932
|
return;
|
|
876
933
|
}
|
|
877
934
|
projectId = p.id;
|
|
@@ -889,13 +946,11 @@ function changelogAdd(args, opts) {
|
|
|
889
946
|
data.changelog.unshift(entry);
|
|
890
947
|
(0, data_1.logActivity)(data, 'changelog_added', `Changelog ${version}: ${title}`, projectId, opts.agent || '');
|
|
891
948
|
(0, data_1.saveData)(data);
|
|
892
|
-
|
|
893
|
-
console.log(chalk_1.default.gray(` Version: ${version}`));
|
|
894
|
-
console.log(chalk_1.default.gray(` Title: ${title}`));
|
|
949
|
+
const details = [`${(0, theme_1.dim)('Version:')} ${(0, theme_1.brand)(version)}`, `${(0, theme_1.dim)('Title:')} ${title}`];
|
|
895
950
|
if (changes.length > 0) {
|
|
896
|
-
changes.forEach(c =>
|
|
951
|
+
changes.forEach(c => details.push(`${(0, theme_1.dim)('β’')} ${c}`));
|
|
897
952
|
}
|
|
898
|
-
console.log();
|
|
953
|
+
console.log((0, box_1.renderResult)('success', 'Changelog entry added!', details));
|
|
899
954
|
}
|
|
900
955
|
function changelogList(opts) {
|
|
901
956
|
const data = (0, data_1.loadData)();
|
|
@@ -903,21 +958,21 @@ function changelogList(opts) {
|
|
|
903
958
|
if (opts.project) {
|
|
904
959
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
905
960
|
if (!p) {
|
|
906
|
-
console.log(
|
|
961
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
907
962
|
return;
|
|
908
963
|
}
|
|
909
964
|
entries = entries.filter(c => c.projectId === p.id);
|
|
910
965
|
}
|
|
911
966
|
if (entries.length === 0) {
|
|
912
|
-
console.log(
|
|
967
|
+
console.log(`\n ${(0, theme_1.dim)('No changelog entries.')}\n`);
|
|
913
968
|
return;
|
|
914
969
|
}
|
|
915
|
-
console.log(
|
|
970
|
+
console.log((0, box_1.renderCommandHeader)('Changelog', 'π'));
|
|
916
971
|
for (const entry of entries) {
|
|
917
972
|
const proj = data.projects.find(p => p.id === entry.projectId);
|
|
918
|
-
console.log(
|
|
973
|
+
console.log((0, theme_1.brand)(` ${entry.version}`) + ` β ${entry.title}` + (0, theme_1.dim)(` (${formatTimeAgoCli(entry.createdAt)})${proj ? ' [' + proj.name + ']' : ''}`));
|
|
919
974
|
if (entry.changes.length > 0) {
|
|
920
|
-
entry.changes.forEach(c => console.log(
|
|
975
|
+
entry.changes.forEach(c => console.log((0, theme_1.dim)(` β’ ${c}`)));
|
|
921
976
|
}
|
|
922
977
|
}
|
|
923
978
|
console.log();
|
|
@@ -930,32 +985,32 @@ program
|
|
|
930
985
|
.action(() => {
|
|
931
986
|
const data = (0, data_1.loadData)();
|
|
932
987
|
showBanner();
|
|
933
|
-
console.log(
|
|
988
|
+
console.log((0, box_1.renderCommandHeader)('Status Overview', 'π'));
|
|
934
989
|
// Projects
|
|
935
|
-
console.log(
|
|
990
|
+
console.log((0, theme_1.brand)(` Projects: ${data.projects.length}`));
|
|
936
991
|
for (const p of data.projects) {
|
|
937
992
|
const pt = data.tasks.filter(t => t.projectId === p.id);
|
|
938
993
|
const done = pt.filter(t => t.column === 'done').length;
|
|
939
994
|
const pct = pt.length > 0 ? Math.round((done / pt.length) * 100) : 0;
|
|
940
|
-
console.log(
|
|
995
|
+
console.log((0, theme_1.dim)(` π¦ ${padRight(p.name, 20)} ${progressBar(pct)} ${done}/${pt.length} (${pct}%)`));
|
|
941
996
|
}
|
|
942
997
|
// Tasks
|
|
943
998
|
const total = data.tasks.length;
|
|
944
999
|
const byCol = { backlog: 0, 'in-progress': 0, review: 0, done: 0 };
|
|
945
1000
|
data.tasks.forEach(t => { byCol[t.column] = (byCol[t.column] || 0) + 1; });
|
|
946
1001
|
console.log();
|
|
947
|
-
console.log(
|
|
948
|
-
console.log(
|
|
949
|
-
console.log(
|
|
950
|
-
console.log(
|
|
951
|
-
console.log(
|
|
1002
|
+
console.log((0, theme_1.brand)(` Tasks: ${total}`));
|
|
1003
|
+
console.log((0, theme_1.dim)(` βͺ Backlog: ${byCol.backlog}`));
|
|
1004
|
+
console.log((0, theme_1.info)(` π’ In Progress: ${byCol['in-progress']}`));
|
|
1005
|
+
console.log((0, theme_1.warning)(` π‘ Review: ${byCol.review}`));
|
|
1006
|
+
console.log((0, theme_1.success)(` π’ Done: ${byCol.done}`));
|
|
952
1007
|
// Deploys
|
|
953
1008
|
if (data.deployments.length > 0) {
|
|
954
1009
|
console.log();
|
|
955
|
-
console.log(
|
|
1010
|
+
console.log((0, theme_1.brand)(` Deployments: ${data.deployments.length}`));
|
|
956
1011
|
const latest = data.deployments[0];
|
|
957
1012
|
const sc = STATUS_COLORS[latest.status] || chalk_1.default.white;
|
|
958
|
-
console.log(
|
|
1013
|
+
console.log((0, theme_1.dim)(` Latest: ${latest.env} β ${sc(latest.status)} β ${latest.message} (${formatTimeAgoCli(latest.startedAt)})`));
|
|
959
1014
|
}
|
|
960
1015
|
// Agents
|
|
961
1016
|
const agentCounts = {};
|
|
@@ -964,18 +1019,18 @@ program
|
|
|
964
1019
|
const agentNames = Object.keys(agentCounts);
|
|
965
1020
|
if (agentNames.length > 0) {
|
|
966
1021
|
console.log();
|
|
967
|
-
console.log(
|
|
1022
|
+
console.log((0, theme_1.brand)(` Active Agents: ${agentNames.length}`));
|
|
968
1023
|
for (const agent of agentNames.sort()) {
|
|
969
|
-
console.log(
|
|
1024
|
+
console.log((0, theme_1.dim)(` π€ ${padRight(agent, 16)} ${agentCounts[agent]} tasks`));
|
|
970
1025
|
}
|
|
971
1026
|
}
|
|
972
1027
|
// Dashboard
|
|
973
1028
|
console.log();
|
|
974
1029
|
if (isDashboardRunning()) {
|
|
975
|
-
console.log(
|
|
1030
|
+
console.log((0, theme_1.success)(` π Dashboard: RUNNING at http://codymaster.localhost:${data_1.DEFAULT_PORT}`));
|
|
976
1031
|
}
|
|
977
1032
|
else {
|
|
978
|
-
console.log(
|
|
1033
|
+
console.log((0, theme_1.dim)(` β« Dashboard: not running (start with: cm dashboard)`));
|
|
979
1034
|
}
|
|
980
1035
|
console.log();
|
|
981
1036
|
});
|
|
@@ -1003,22 +1058,24 @@ program
|
|
|
1003
1058
|
.description('Install an agent skill')
|
|
1004
1059
|
.option('-p, --platform <platform>', 'Target platform (gemini|claude|cursor|windsurf|cline)')
|
|
1005
1060
|
.action((skill, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1006
|
-
console.log(
|
|
1061
|
+
console.log((0, theme_1.brand)(` Installing skill: ${skill}...`));
|
|
1007
1062
|
if (!opts.platform) {
|
|
1008
|
-
const
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
{
|
|
1013
|
-
{
|
|
1014
|
-
{
|
|
1015
|
-
{
|
|
1016
|
-
{
|
|
1017
|
-
]
|
|
1063
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
1064
|
+
const platform = yield p.select({
|
|
1065
|
+
message: 'Which platform?',
|
|
1066
|
+
options: [
|
|
1067
|
+
{ label: 'π’ Google Antigravity', value: 'gemini' },
|
|
1068
|
+
{ label: 'π£ Claude Code', value: 'claude' },
|
|
1069
|
+
{ label: 'π΅ Cursor', value: 'cursor' },
|
|
1070
|
+
{ label: 'π Windsurf', value: 'windsurf' },
|
|
1071
|
+
{ label: 'π€ Cline / RooCode', value: 'cline' },
|
|
1072
|
+
],
|
|
1018
1073
|
});
|
|
1019
|
-
|
|
1074
|
+
if (p.isCancel(platform))
|
|
1075
|
+
return;
|
|
1076
|
+
opts.platform = platform;
|
|
1020
1077
|
}
|
|
1021
|
-
console.log(
|
|
1078
|
+
console.log((0, box_1.renderResult)('success', `Skill '${skill}' installed for ${opts.platform}!`));
|
|
1022
1079
|
}));
|
|
1023
1080
|
// βββ Add Command (npx codymaster add --skill cm-debugging) βββββββββββββββββββ
|
|
1024
1081
|
const ALL_SKILLS = [
|
|
@@ -1043,6 +1100,10 @@ const PLATFORM_TARGETS = {
|
|
|
1043
1100
|
opencode: { dir: '.opencode/skills', invoke: '@[/<skill>]', note: 'OpenCode skills directory' },
|
|
1044
1101
|
kiro: { dir: '.kiro/steering', invoke: '@<skill>', note: 'Kiro steering documents' },
|
|
1045
1102
|
copilot: { dir: '.github', invoke: '(auto-context)', note: 'Added to copilot-instructions.md' },
|
|
1103
|
+
aider: { dir: '.aider/skills', invoke: '@[/<skill>]', note: 'Aider skills directory (reference in .aider.conf.yml)' },
|
|
1104
|
+
continue: { dir: '.continue/rules', invoke: '@<skill>', note: 'Continue.dev rules directory' },
|
|
1105
|
+
amazonq: { dir: '.aws/amazonq/skills', invoke: '@<skill>', note: 'Amazon Q skills directory' },
|
|
1106
|
+
amp: { dir: '.amp/skills', invoke: '@<skill>', note: 'Amp skills directory' },
|
|
1046
1107
|
};
|
|
1047
1108
|
const RAW_BASE = 'https://raw.githubusercontent.com/tody-agent/codymaster/main';
|
|
1048
1109
|
function autoDetectPlatform() {
|
|
@@ -1092,12 +1153,11 @@ function doAddSkills(skills, platform) {
|
|
|
1092
1153
|
console.log();
|
|
1093
1154
|
const { execFileSync } = require('child_process');
|
|
1094
1155
|
if (platform === 'claude') {
|
|
1095
|
-
console.log(
|
|
1096
|
-
console.log(
|
|
1097
|
-
// Step 1: Register marketplace
|
|
1098
|
-
console.log(
|
|
1156
|
+
console.log((0, theme_1.brand)('π£ Claude Code β Installing via plugin system'));
|
|
1157
|
+
console.log((0, theme_1.dim)(' (Claude installs all 34 skills as one bundle)\n'));
|
|
1158
|
+
// Step 1: Register marketplace
|
|
1159
|
+
console.log((0, theme_1.dim)(' $ claude plugin marketplace add tody-agent/codymaster'));
|
|
1099
1160
|
try {
|
|
1100
|
-
// Use 'pipe' so we can inspect output on failure; print stdout ourselves
|
|
1101
1161
|
const r1 = require('child_process').spawnSync('claude', ['plugin', 'marketplace', 'add', 'tody-agent/codymaster'], { encoding: 'utf8' });
|
|
1102
1162
|
if (r1.stdout)
|
|
1103
1163
|
process.stdout.write(r1.stdout);
|
|
@@ -1105,47 +1165,35 @@ function doAddSkills(skills, platform) {
|
|
|
1105
1165
|
process.stderr.write(r1.stderr);
|
|
1106
1166
|
const combined = String(r1.stdout || '') + String(r1.stderr || '');
|
|
1107
1167
|
if (r1.status !== 0 && !combined.includes('already installed') && !combined.includes('already exists')) {
|
|
1108
|
-
console.log(
|
|
1168
|
+
console.log((0, box_1.renderResult)('warning', 'Marketplace warning β continuing anyway'));
|
|
1109
1169
|
}
|
|
1110
1170
|
else if (combined.includes('already installed') || combined.includes('already exists')) {
|
|
1111
|
-
console.log(
|
|
1171
|
+
console.log((0, theme_1.dim)(' βΉοΈ Marketplace already registered'));
|
|
1112
1172
|
}
|
|
1113
1173
|
}
|
|
1114
1174
|
catch (_a) {
|
|
1115
|
-
console.log(
|
|
1175
|
+
console.log((0, box_1.renderResult)('warning', 'Could not reach marketplace β continuing'));
|
|
1116
1176
|
}
|
|
1117
1177
|
// Step 2: Install / update the plugin
|
|
1118
|
-
console.log(
|
|
1178
|
+
console.log((0, theme_1.dim)(' $ claude plugin install codymaster@codymaster'));
|
|
1119
1179
|
try {
|
|
1120
1180
|
execFileSync('claude', ['plugin', 'install', 'codymaster@codymaster'], { stdio: 'inherit' });
|
|
1121
|
-
console.log(
|
|
1181
|
+
console.log((0, box_1.renderResult)('success', 'All 34 skills installed!'));
|
|
1122
1182
|
yield postInstallOnboarding('claude');
|
|
1123
1183
|
}
|
|
1124
1184
|
catch (_b) {
|
|
1125
|
-
console.log(
|
|
1126
|
-
console.log(
|
|
1127
|
-
console.log(
|
|
1128
|
-
console.log(
|
|
1129
|
-
}
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
if (platform === 'gemini') {
|
|
1133
|
-
console.log(chalk_1.default.cyan('π» Gemini CLI β Installing via extensions'));
|
|
1134
|
-
try {
|
|
1135
|
-
execFileSync('gemini', ['extensions', 'install', 'https://github.com/tody-agent/codymaster'], { stdio: 'inherit' });
|
|
1136
|
-
console.log('\n' + chalk_1.default.green('β
All 34 skills installed for Gemini CLI!'));
|
|
1137
|
-
yield postInstallOnboarding('gemini');
|
|
1138
|
-
}
|
|
1139
|
-
catch (_c) {
|
|
1140
|
-
console.log(chalk_1.default.yellow('π‘ Run this in your terminal:\n'));
|
|
1141
|
-
console.log(chalk_1.default.cyan(' gemini extensions install https://github.com/tody-agent/codymaster\n'));
|
|
1185
|
+
console.log((0, box_1.renderResult)('warning', 'Plugin install failed. Run manually:'));
|
|
1186
|
+
console.log((0, theme_1.brand)(' claude plugin install codymaster@codymaster'));
|
|
1187
|
+
console.log((0, theme_1.dim)('\n Or one-liner:'));
|
|
1188
|
+
console.log((0, theme_1.brand)(' bash <(curl -fsSL https://raw.githubusercontent.com/tody-agent/codymaster/main/install.sh) --claude'));
|
|
1142
1189
|
}
|
|
1143
1190
|
return;
|
|
1144
1191
|
}
|
|
1192
|
+
// Removed the fictional gemini extensions install block.
|
|
1193
|
+
// Gemini now falls through to the standard file-cloning logic below.
|
|
1145
1194
|
const target = PLATFORM_TARGETS[platform];
|
|
1146
1195
|
if (!target) {
|
|
1147
|
-
console.log(
|
|
1148
|
-
console.log(chalk_1.default.gray(` Supported: claude, gemini, cursor, windsurf, cline, opencode, kiro, copilot`));
|
|
1196
|
+
console.log((0, box_1.renderResult)('error', `Unknown platform: ${platform}`, [(0, theme_1.dim)('Supported: claude, gemini, cursor, windsurf, cline, opencode, kiro, copilot')]));
|
|
1149
1197
|
return;
|
|
1150
1198
|
}
|
|
1151
1199
|
if (platform === 'copilot') {
|
|
@@ -1157,41 +1205,61 @@ function doAddSkills(skills, platform) {
|
|
|
1157
1205
|
if (!existing.includes('Cody Master Skills')) {
|
|
1158
1206
|
fs_1.default.appendFileSync(instrFile, header + lines + '\n');
|
|
1159
1207
|
}
|
|
1160
|
-
console.log(
|
|
1161
|
-
console.log(chalk_1.default.gray(' GitHub Copilot will use these as context automatically.'));
|
|
1208
|
+
console.log((0, box_1.renderResult)('success', `${skills.length} skills referenced in ${instrFile}`, [(0, theme_1.dim)('GitHub Copilot will use these as context automatically.')]));
|
|
1162
1209
|
return;
|
|
1163
1210
|
}
|
|
1164
1211
|
const icons = { cursor: 'π΅', windsurf: 'π ', cline: 'β«', opencode: 'π¦', kiro: 'πΆ' };
|
|
1165
1212
|
const icon = icons[platform] || 'π¦';
|
|
1166
1213
|
const label = skills.length === ALL_SKILLS.length ? 'all 34 skills' : skills.join(', ');
|
|
1167
|
-
console.log(`${icon} ${platform} β Installing ${label}`);
|
|
1168
|
-
console.log(
|
|
1214
|
+
console.log(`${icon} ${(0, theme_1.brand)(`${platform} β Installing ${label}`)}`);
|
|
1215
|
+
console.log((0, theme_1.dim)(` Target: ./${target.dir}/\n`));
|
|
1169
1216
|
let ok = 0, fail = 0;
|
|
1170
1217
|
for (const skill of skills) {
|
|
1171
1218
|
const url = `${RAW_BASE}/skills/${skill}/SKILL.md`;
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
if (
|
|
1175
|
-
|
|
1219
|
+
let dest = path_1.default.join(target.dir, skill, 'SKILL.md');
|
|
1220
|
+
// Formatting logic to adapt to specific IDE required formats
|
|
1221
|
+
if (platform === 'cursor') {
|
|
1222
|
+
dest = path_1.default.join(target.dir, `${skill}.mdc`);
|
|
1223
|
+
}
|
|
1224
|
+
else if (platform === 'continue') {
|
|
1225
|
+
dest = path_1.default.join(target.dir, `${skill}.md`);
|
|
1226
|
+
}
|
|
1227
|
+
const ok_result = yield downloadFile(url, dest);
|
|
1228
|
+
// Prepend Cursor MDC glob formatting
|
|
1229
|
+
if (ok_result && platform === 'cursor') {
|
|
1230
|
+
try {
|
|
1231
|
+
const content = fs_1.default.readFileSync(dest, 'utf-8');
|
|
1232
|
+
if (!content.startsWith('---')) {
|
|
1233
|
+
const yamlFrontmatter = `---\ndescription: ${skill}\nglobs: *\n---\n`;
|
|
1234
|
+
fs_1.default.writeFileSync(dest, yamlFrontmatter + content);
|
|
1235
|
+
}
|
|
1236
|
+
else if (!content.includes('globs:')) {
|
|
1237
|
+
const newContent = content.replace(/^---/, '---\nglobs: *');
|
|
1238
|
+
fs_1.default.writeFileSync(dest, newContent);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
catch (err) { }
|
|
1242
|
+
}
|
|
1243
|
+
if (ok_result) {
|
|
1244
|
+
process.stdout.write((0, theme_1.success)(` β
${skill}\n`));
|
|
1176
1245
|
ok++;
|
|
1177
1246
|
}
|
|
1178
1247
|
else {
|
|
1179
|
-
process.stdout.write(
|
|
1248
|
+
process.stdout.write((0, theme_1.error)(` β ${skill}\n`));
|
|
1180
1249
|
fail++;
|
|
1181
1250
|
}
|
|
1182
1251
|
}
|
|
1183
1252
|
console.log();
|
|
1184
1253
|
if (ok > 0) {
|
|
1185
|
-
console.log(
|
|
1254
|
+
console.log((0, box_1.renderResult)('success', `${ok} skill${ok > 1 ? 's' : ''} installed β ./${target.dir}/`));
|
|
1186
1255
|
const invoke = target.invoke.replace('<skill>', skills[0]);
|
|
1187
|
-
console.log(
|
|
1256
|
+
console.log((0, theme_1.brand)(` π Usage: ${invoke} Your prompt here`));
|
|
1188
1257
|
if (target.note)
|
|
1189
|
-
console.log(
|
|
1258
|
+
console.log((0, theme_1.dim)(` Note: ${target.note}`));
|
|
1190
1259
|
yield postInstallOnboarding(platform);
|
|
1191
1260
|
}
|
|
1192
1261
|
if (fail > 0) {
|
|
1193
|
-
console.log(
|
|
1194
|
-
console.log(chalk_1.default.gray(` git clone https://github.com/tody-agent/codymaster.git`));
|
|
1262
|
+
console.log((0, box_1.renderResult)('warning', `${fail} failed β check connection or clone manually:`, [(0, theme_1.dim)('git clone https://github.com/tody-agent/codymaster.git')]));
|
|
1195
1263
|
}
|
|
1196
1264
|
});
|
|
1197
1265
|
}
|
|
@@ -1215,8 +1283,8 @@ program
|
|
|
1215
1283
|
}
|
|
1216
1284
|
else if (opts.skill) {
|
|
1217
1285
|
if (!ALL_SKILLS.includes(opts.skill)) {
|
|
1218
|
-
console.log(
|
|
1219
|
-
|
|
1286
|
+
console.log((0, box_1.renderResult)('error', `Unknown skill: ${opts.skill}`, [(0, theme_1.dim)('Run: npx codymaster add --list')]));
|
|
1287
|
+
return;
|
|
1220
1288
|
return;
|
|
1221
1289
|
}
|
|
1222
1290
|
skills = [opts.skill];
|
|
@@ -1224,23 +1292,27 @@ program
|
|
|
1224
1292
|
// Detect or prompt platform
|
|
1225
1293
|
let platform = opts.platform || autoDetectPlatform();
|
|
1226
1294
|
if (platform === 'manual') {
|
|
1227
|
-
const
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
{
|
|
1232
|
-
{
|
|
1233
|
-
{
|
|
1234
|
-
{
|
|
1235
|
-
{
|
|
1236
|
-
{
|
|
1237
|
-
{
|
|
1238
|
-
{
|
|
1295
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
1296
|
+
const platform_choice = yield p.select({
|
|
1297
|
+
message: 'Select your AI coding platform:',
|
|
1298
|
+
options: [
|
|
1299
|
+
{ label: 'π£ Claude Code (recommended)', value: 'claude' },
|
|
1300
|
+
{ label: 'π» Gemini CLI & Antigravity', value: 'gemini' },
|
|
1301
|
+
{ label: 'π΅ Cursor', value: 'cursor' },
|
|
1302
|
+
{ label: 'π Windsurf', value: 'windsurf' },
|
|
1303
|
+
{ label: 'β« Cline / RooCode', value: 'cline' },
|
|
1304
|
+
{ label: 'π¦ OpenCode', value: 'opencode' },
|
|
1305
|
+
{ label: 'πΆ Kiro (AWS)', value: 'kiro' },
|
|
1306
|
+
{ label: 'π GitHub Copilot', value: 'copilot' },
|
|
1307
|
+
{ label: 'π€ Aider', value: 'aider' },
|
|
1308
|
+
{ label: 'π Continue.dev', value: 'continue' },
|
|
1309
|
+
{ label: 'βοΈ Amazon Q', value: 'amazonq' },
|
|
1310
|
+
{ label: 'β‘ Amp', value: 'amp' },
|
|
1239
1311
|
],
|
|
1240
1312
|
});
|
|
1241
|
-
if (
|
|
1313
|
+
if (p.isCancel(platform_choice))
|
|
1242
1314
|
return;
|
|
1243
|
-
platform =
|
|
1315
|
+
platform = platform_choice;
|
|
1244
1316
|
}
|
|
1245
1317
|
// If no skills chosen yet, prompt
|
|
1246
1318
|
if (!skills) {
|
|
@@ -1248,25 +1320,27 @@ program
|
|
|
1248
1320
|
skills = ALL_SKILLS;
|
|
1249
1321
|
}
|
|
1250
1322
|
else {
|
|
1251
|
-
const
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
{
|
|
1256
|
-
{
|
|
1323
|
+
const p = yield Promise.resolve().then(() => __importStar(require('@clack/prompts')));
|
|
1324
|
+
const mode = yield p.select({
|
|
1325
|
+
message: 'What to install?',
|
|
1326
|
+
options: [
|
|
1327
|
+
{ label: 'All 34 skills (full kit)', value: 'all' },
|
|
1328
|
+
{ label: 'Search & pick one skill', value: 'pick' },
|
|
1257
1329
|
],
|
|
1258
1330
|
});
|
|
1259
|
-
if (
|
|
1331
|
+
if (p.isCancel(mode))
|
|
1332
|
+
return;
|
|
1333
|
+
if (mode === 'all') {
|
|
1260
1334
|
skills = ALL_SKILLS;
|
|
1261
1335
|
}
|
|
1262
1336
|
else {
|
|
1263
|
-
const pick = yield
|
|
1264
|
-
|
|
1265
|
-
|
|
1337
|
+
const pick = yield p.select({
|
|
1338
|
+
message: 'Select a skill:',
|
|
1339
|
+
options: ALL_SKILLS.map(s => ({ label: s, value: s })),
|
|
1266
1340
|
});
|
|
1267
|
-
if (
|
|
1341
|
+
if (p.isCancel(pick))
|
|
1268
1342
|
return;
|
|
1269
|
-
skills = [pick
|
|
1343
|
+
skills = [pick];
|
|
1270
1344
|
}
|
|
1271
1345
|
}
|
|
1272
1346
|
}
|
|
@@ -1281,6 +1355,24 @@ program
|
|
|
1281
1355
|
.action((opts) => {
|
|
1282
1356
|
skillList(opts.domain);
|
|
1283
1357
|
});
|
|
1358
|
+
// βββ Profile Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1359
|
+
program
|
|
1360
|
+
.command('profile')
|
|
1361
|
+
.description('View your CodyMaster profile, stats, and achievements')
|
|
1362
|
+
.action(() => {
|
|
1363
|
+
const profile = (0, hooks_1.loadProfile)();
|
|
1364
|
+
if (!profile.onboardingComplete) {
|
|
1365
|
+
console.log((0, theme_1.dim)('\n Run cm first to complete setup! πΉ\n'));
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
(0, hooks_1.recordCommand)(profile, 'profile');
|
|
1369
|
+
const newAchievements = (0, hooks_1.checkAchievements)(profile);
|
|
1370
|
+
(0, hooks_1.saveProfile)(profile);
|
|
1371
|
+
console.log((0, hooks_1.formatProfileSummary)(profile));
|
|
1372
|
+
for (const id of newAchievements) {
|
|
1373
|
+
console.log((0, hooks_1.formatAchievement)(id));
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1284
1376
|
// βββ Continuity Command (Working Memory) ββββββββββββββββββββββββββββββββββββ
|
|
1285
1377
|
program
|
|
1286
1378
|
.command('continuity [cmd]')
|
|
@@ -1315,43 +1407,38 @@ program
|
|
|
1315
1407
|
});
|
|
1316
1408
|
function continuityInit(projectPath) {
|
|
1317
1409
|
if ((0, continuity_1.hasCmDir)(projectPath)) {
|
|
1318
|
-
console.log(
|
|
1319
|
-
console.log(chalk_1.default.gray(` Path: ${projectPath}/.cm/`));
|
|
1410
|
+
console.log((0, box_1.renderResult)('warning', '.cm/ directory already exists.', [(0, theme_1.dim)(`Path: ${projectPath}/.cm/`)]));
|
|
1320
1411
|
return;
|
|
1321
1412
|
}
|
|
1322
1413
|
(0, continuity_1.ensureCmDir)(projectPath);
|
|
1323
|
-
console.log(
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
console.log(
|
|
1414
|
+
console.log((0, box_1.renderResult)('success', 'Working memory initialized!', [
|
|
1415
|
+
(0, theme_1.dim)(`Created: ${projectPath}/.cm/`),
|
|
1416
|
+
(0, theme_1.dim)('βββ CONTINUITY.md (working memory)'),
|
|
1417
|
+
(0, theme_1.dim)('βββ config.yaml (RARV settings)'),
|
|
1418
|
+
(0, theme_1.dim)('βββ memory/'),
|
|
1419
|
+
(0, theme_1.dim)(' βββ learnings.json (error patterns)'),
|
|
1420
|
+
(0, theme_1.dim)(' βββ decisions.json (architecture decisions)'),
|
|
1421
|
+
]));
|
|
1422
|
+
console.log((0, theme_1.info)('π‘ Protocol: Read CONTINUITY.md at session start, update at session end.'));
|
|
1332
1423
|
}
|
|
1333
1424
|
function continuityStatus(projectPath) {
|
|
1334
1425
|
const status = (0, continuity_1.getContinuityStatus)(projectPath);
|
|
1335
1426
|
if (!status.initialized) {
|
|
1336
|
-
console.log(
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
console.log(
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
}
|
|
1350
|
-
console.log();
|
|
1351
|
-
console.log(chalk_1.default.gray(` β
Completed: ${status.completedCount} | π§ Blockers: ${status.blockerCount}`));
|
|
1352
|
-
console.log(chalk_1.default.gray(` π Learnings: ${status.learningCount} | π Decisions: ${status.decisionCount}`));
|
|
1427
|
+
console.log((0, box_1.renderResult)('warning', 'Working memory not initialized.', [(0, theme_1.dim)('Run: cm continuity init')]));
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
console.log((0, box_1.renderCommandHeader)('Working Memory Status', 'π§ '));
|
|
1431
|
+
console.log((0, box_1.renderKeyValue)([
|
|
1432
|
+
['Project', String(status.project)],
|
|
1433
|
+
['Phase', phaseColor(status.phase)(status.phase)],
|
|
1434
|
+
['Iteration', String(status.iteration)],
|
|
1435
|
+
...(status.activeGoal ? [['Goal', String(status.activeGoal)]] : []),
|
|
1436
|
+
...(status.currentTask ? [['Task', String(status.currentTask)]] : []),
|
|
1437
|
+
]));
|
|
1438
|
+
console.log((0, theme_1.dim)(` β
Completed: ${status.completedCount} | π§ Blockers: ${status.blockerCount}`));
|
|
1439
|
+
console.log((0, theme_1.dim)(` π Learnings: ${status.learningCount} | π Decisions: ${status.decisionCount}`));
|
|
1353
1440
|
if (status.lastUpdated) {
|
|
1354
|
-
console.log(
|
|
1441
|
+
console.log((0, theme_1.dim)(` π Updated: ${formatTimeAgoCli(status.lastUpdated)}`));
|
|
1355
1442
|
}
|
|
1356
1443
|
console.log();
|
|
1357
1444
|
}
|
|
@@ -1364,46 +1451,45 @@ function phaseColor(phase) {
|
|
|
1364
1451
|
}
|
|
1365
1452
|
function continuityReset(projectPath) {
|
|
1366
1453
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1367
|
-
console.log(
|
|
1454
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found.'));
|
|
1368
1455
|
return;
|
|
1369
1456
|
}
|
|
1370
1457
|
(0, continuity_1.resetContinuity)(projectPath);
|
|
1371
|
-
console.log(
|
|
1372
|
-
console.log(chalk_1.default.gray(' CONTINUITY.md cleared. Learnings preserved.'));
|
|
1458
|
+
console.log((0, box_1.renderResult)('success', 'Working memory reset.', [(0, theme_1.dim)('CONTINUITY.md cleared. Learnings preserved.')]));
|
|
1373
1459
|
}
|
|
1374
1460
|
function continuityLearnings(projectPath) {
|
|
1375
1461
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1376
|
-
console.log(
|
|
1462
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found. Run: cm continuity init'));
|
|
1377
1463
|
return;
|
|
1378
1464
|
}
|
|
1379
1465
|
const learnings = (0, continuity_1.getLearnings)(projectPath);
|
|
1380
1466
|
if (learnings.length === 0) {
|
|
1381
|
-
console.log(
|
|
1467
|
+
console.log(`\n ${(0, theme_1.dim)('No learnings captured yet. π')}\n`);
|
|
1382
1468
|
return;
|
|
1383
1469
|
}
|
|
1384
|
-
console.log(
|
|
1470
|
+
console.log((0, box_1.renderCommandHeader)(`Mistakes & Learnings (${learnings.length})`, 'π'));
|
|
1385
1471
|
for (const l of learnings.slice(-10)) {
|
|
1386
|
-
console.log(
|
|
1387
|
-
console.log(
|
|
1388
|
-
console.log(
|
|
1389
|
-
console.log(
|
|
1472
|
+
console.log((0, theme_1.error)(` β ${l.whatFailed}`));
|
|
1473
|
+
console.log((0, theme_1.dim)(` Why: ${l.whyFailed}`));
|
|
1474
|
+
console.log((0, theme_1.success)(` Fix: ${l.howToPrevent}`));
|
|
1475
|
+
console.log((0, theme_1.dim)(` ${formatTimeAgoCli(l.timestamp)} | ${l.agent || 'unknown'}\n`));
|
|
1390
1476
|
}
|
|
1391
1477
|
}
|
|
1392
1478
|
function continuityDecisions(projectPath) {
|
|
1393
1479
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1394
|
-
console.log(
|
|
1480
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found. Run: cm continuity init'));
|
|
1395
1481
|
return;
|
|
1396
1482
|
}
|
|
1397
1483
|
const decisions = (0, continuity_1.getDecisions)(projectPath);
|
|
1398
1484
|
if (decisions.length === 0) {
|
|
1399
|
-
console.log(
|
|
1485
|
+
console.log(`\n ${(0, theme_1.dim)('No decisions recorded yet.')}\n`);
|
|
1400
1486
|
return;
|
|
1401
1487
|
}
|
|
1402
|
-
console.log(
|
|
1488
|
+
console.log((0, box_1.renderCommandHeader)(`Key Decisions (${decisions.length})`, 'π'));
|
|
1403
1489
|
for (const d of decisions.slice(-10)) {
|
|
1404
|
-
console.log(
|
|
1405
|
-
console.log(
|
|
1406
|
-
console.log(
|
|
1490
|
+
console.log((0, theme_1.brand)(` π ${d.decision}`));
|
|
1491
|
+
console.log((0, theme_1.dim)(` Rationale: ${d.rationale}`));
|
|
1492
|
+
console.log((0, theme_1.dim)(` ${formatTimeAgoCli(d.timestamp)} | ${d.agent || 'unknown'}\n`));
|
|
1407
1493
|
}
|
|
1408
1494
|
}
|
|
1409
1495
|
// βββ Brain Command (Enhanced Memory Explorer) ββββββββββββββββββββββββββββββββ
|
|
@@ -1446,13 +1532,11 @@ program
|
|
|
1446
1532
|
brainExport(projectPath, opts);
|
|
1447
1533
|
break;
|
|
1448
1534
|
default:
|
|
1449
|
-
// Try as delete: cm brain learning <id> or cm brain decision <id>
|
|
1450
1535
|
if (cmd === 'learning' || cmd === 'decision') {
|
|
1451
|
-
console.log(
|
|
1536
|
+
console.log((0, theme_1.dim)(`Did you mean: cm brain ${cmd}s ?`));
|
|
1452
1537
|
}
|
|
1453
1538
|
else {
|
|
1454
|
-
console.log(
|
|
1455
|
-
console.log(chalk_1.default.gray('Available: status, learnings, decisions, delete, stats, export'));
|
|
1539
|
+
console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: status, learnings, decisions, delete, stats, export')]));
|
|
1456
1540
|
}
|
|
1457
1541
|
}
|
|
1458
1542
|
});
|
|
@@ -1467,40 +1551,38 @@ program
|
|
|
1467
1551
|
function brainStatus(projectPath) {
|
|
1468
1552
|
const status = (0, continuity_1.getContinuityStatus)(projectPath);
|
|
1469
1553
|
if (!status.initialized) {
|
|
1470
|
-
console.log(
|
|
1471
|
-
console.log(chalk_1.default.gray(' Run: cm continuity init'));
|
|
1554
|
+
console.log((0, box_1.renderResult)('warning', 'Working memory not initialized.', [(0, theme_1.dim)('Run: cm continuity init')]));
|
|
1472
1555
|
return;
|
|
1473
1556
|
}
|
|
1474
1557
|
showBanner();
|
|
1475
|
-
console.log(
|
|
1558
|
+
console.log((0, box_1.renderCommandHeader)('Brain β Memory Status', 'π§ '));
|
|
1476
1559
|
// Stats row
|
|
1477
|
-
console.log(
|
|
1478
|
-
console.log(
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
console.log(
|
|
1560
|
+
console.log((0, theme_1.brand)(' ββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ'));
|
|
1561
|
+
console.log((0, theme_1.brand)(' β') + (0, theme_1.error)(` β€ Learn: ${padRight(String(status.learningCount), 4)}`) +
|
|
1562
|
+
(0, theme_1.brand)(' β') + (0, theme_1.brand)(` π Decide: ${padRight(String(status.decisionCount), 3)}`) +
|
|
1563
|
+
(0, theme_1.brand)(' β') + phaseColor(status.phase)(` β ${padRight(status.phase, 9)}`) +
|
|
1564
|
+
(0, theme_1.brand)(' β') + (0, theme_1.dim)(` #${padRight(String(status.iteration), 10)}`) + (0, theme_1.brand)('β'));
|
|
1565
|
+
console.log((0, theme_1.brand)(' ββββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ'));
|
|
1483
1566
|
console.log();
|
|
1484
|
-
console.log(
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
console.log(` ${chalk_1.default.white('Updated:')} ${formatTimeAgoCli(status.lastUpdated)}`);
|
|
1567
|
+
console.log((0, box_1.renderKeyValue)([
|
|
1568
|
+
['Project', String(status.project)],
|
|
1569
|
+
...(status.activeGoal ? [['Goal', String(status.activeGoal)]] : []),
|
|
1570
|
+
...(status.currentTask ? [['Task', String(status.currentTask)]] : []),
|
|
1571
|
+
['Completed', `${status.completedCount} items`],
|
|
1572
|
+
['Blockers', status.blockerCount > 0 ? (0, theme_1.warning)(`π§ ${status.blockerCount}`) : (0, theme_1.success)('β
None')],
|
|
1573
|
+
...(status.lastUpdated ? [['Updated', formatTimeAgoCli(status.lastUpdated)]] : []),
|
|
1574
|
+
]));
|
|
1493
1575
|
console.log();
|
|
1494
|
-
console.log(
|
|
1495
|
-
console.log(
|
|
1496
|
-
console.log(
|
|
1497
|
-
console.log(
|
|
1498
|
-
console.log(
|
|
1576
|
+
console.log((0, theme_1.dim)(' Commands:'));
|
|
1577
|
+
console.log((0, theme_1.dim)(' cm brain learnings β View mistakes & lessons'));
|
|
1578
|
+
console.log((0, theme_1.dim)(' cm brain decisions β View architecture decisions'));
|
|
1579
|
+
console.log((0, theme_1.dim)(' cm brain stats β Memory statistics'));
|
|
1580
|
+
console.log((0, theme_1.dim)(' cm brain export β Export memory data'));
|
|
1499
1581
|
console.log();
|
|
1500
1582
|
}
|
|
1501
1583
|
function brainLearnings(projectPath, opts) {
|
|
1502
1584
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1503
|
-
console.log(
|
|
1585
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found. Run: cm continuity init'));
|
|
1504
1586
|
return;
|
|
1505
1587
|
}
|
|
1506
1588
|
let learnings = (0, continuity_1.getLearnings)(projectPath);
|
|
@@ -1515,95 +1597,96 @@ function brainLearnings(projectPath, opts) {
|
|
|
1515
1597
|
const limit = opts.last ? parseInt(opts.last) : 15;
|
|
1516
1598
|
const display = learnings.slice(-limit);
|
|
1517
1599
|
if (display.length === 0) {
|
|
1518
|
-
console.log(
|
|
1600
|
+
console.log(`\n ${(0, theme_1.dim)(`No learnings ${opts.search ? 'matching "' + opts.search + '"' : 'captured yet'}. π`)}\n`);
|
|
1519
1601
|
return;
|
|
1520
1602
|
}
|
|
1521
|
-
console.log(
|
|
1603
|
+
console.log((0, box_1.renderCommandHeader)(`Learnings (${display.length}${learnings.length > limit ? '/' + learnings.length : ''})`, 'π'));
|
|
1522
1604
|
for (const l of display) {
|
|
1523
1605
|
const shortId = l.id ? l.id.substring(0, 8) : '???';
|
|
1524
|
-
console.log(
|
|
1606
|
+
console.log((0, theme_1.error)(` β ${l.whatFailed}`) + (0, theme_1.dim)(` [${shortId}]`));
|
|
1525
1607
|
if (l.whyFailed)
|
|
1526
|
-
console.log(
|
|
1608
|
+
console.log((0, theme_1.dim)(` Why: ${l.whyFailed}`));
|
|
1527
1609
|
if (l.howToPrevent)
|
|
1528
|
-
console.log(
|
|
1529
|
-
console.log(
|
|
1610
|
+
console.log((0, theme_1.success)(` Fix: ${l.howToPrevent}`));
|
|
1611
|
+
console.log((0, theme_1.dim)(` ${formatTimeAgoCli(l.timestamp)} | ${l.agent || 'unknown'}${l.module ? ' | π¦ ' + l.module : ''}\n`));
|
|
1530
1612
|
}
|
|
1531
1613
|
}
|
|
1532
1614
|
function brainDecisions(projectPath, opts) {
|
|
1533
1615
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1534
|
-
console.log(
|
|
1616
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found. Run: cm continuity init'));
|
|
1535
1617
|
return;
|
|
1536
1618
|
}
|
|
1537
1619
|
const decisions = (0, continuity_1.getDecisions)(projectPath);
|
|
1538
1620
|
const limit = opts.last ? parseInt(opts.last) : 15;
|
|
1539
1621
|
const display = decisions.slice(-limit);
|
|
1540
1622
|
if (display.length === 0) {
|
|
1541
|
-
console.log(
|
|
1623
|
+
console.log(`\n ${(0, theme_1.dim)('No decisions recorded yet.')}\n`);
|
|
1542
1624
|
return;
|
|
1543
1625
|
}
|
|
1544
|
-
console.log(
|
|
1626
|
+
console.log((0, box_1.renderCommandHeader)(`Key Decisions (${display.length}${decisions.length > limit ? '/' + decisions.length : ''})`, 'π'));
|
|
1545
1627
|
for (const d of display) {
|
|
1546
1628
|
const shortId = d.id ? d.id.substring(0, 8) : '???';
|
|
1547
|
-
console.log(
|
|
1629
|
+
console.log((0, theme_1.brand)(` π ${d.decision}`) + (0, theme_1.dim)(` [${shortId}]`));
|
|
1548
1630
|
if (d.rationale)
|
|
1549
|
-
console.log(
|
|
1550
|
-
console.log(
|
|
1631
|
+
console.log((0, theme_1.dim)(` Rationale: ${d.rationale}`));
|
|
1632
|
+
console.log((0, theme_1.dim)(` ${formatTimeAgoCli(d.timestamp)} | ${d.agent || 'unknown'}\n`));
|
|
1551
1633
|
}
|
|
1552
1634
|
}
|
|
1553
1635
|
function brainDelete(projectPath, type, id) {
|
|
1554
1636
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1555
|
-
console.log(
|
|
1637
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found.'));
|
|
1556
1638
|
return;
|
|
1557
1639
|
}
|
|
1558
1640
|
if (type === 'learning' || type === 'l') {
|
|
1559
1641
|
const learnings = (0, continuity_1.getLearnings)(projectPath);
|
|
1560
1642
|
const target = learnings.find(l => l.id && l.id.startsWith(id));
|
|
1561
1643
|
if (!target) {
|
|
1562
|
-
console.log(
|
|
1644
|
+
console.log((0, box_1.renderResult)('error', `Learning not found with ID prefix: ${id}`));
|
|
1563
1645
|
return;
|
|
1564
1646
|
}
|
|
1565
|
-
const
|
|
1566
|
-
if (
|
|
1567
|
-
console.log(
|
|
1647
|
+
const del_success = (0, continuity_1.deleteLearning)(projectPath, target.id);
|
|
1648
|
+
if (del_success) {
|
|
1649
|
+
console.log((0, box_1.renderResult)('success', `Deleted learning: ${target.whatFailed}`));
|
|
1568
1650
|
}
|
|
1569
1651
|
else {
|
|
1570
|
-
console.log(
|
|
1652
|
+
console.log((0, box_1.renderResult)('error', 'Failed to delete'));
|
|
1571
1653
|
}
|
|
1572
1654
|
}
|
|
1573
1655
|
else if (type === 'decision' || type === 'd') {
|
|
1574
1656
|
const decisions = (0, continuity_1.getDecisions)(projectPath);
|
|
1575
1657
|
const target = decisions.find(d => d.id && d.id.startsWith(id));
|
|
1576
1658
|
if (!target) {
|
|
1577
|
-
console.log(
|
|
1659
|
+
console.log((0, box_1.renderResult)('error', `Decision not found with ID prefix: ${id}`));
|
|
1578
1660
|
return;
|
|
1579
1661
|
}
|
|
1580
|
-
const
|
|
1581
|
-
if (
|
|
1582
|
-
console.log(
|
|
1662
|
+
const del_success = (0, continuity_1.deleteDecision)(projectPath, target.id);
|
|
1663
|
+
if (del_success) {
|
|
1664
|
+
console.log((0, box_1.renderResult)('success', `Deleted decision: ${target.decision}`));
|
|
1583
1665
|
}
|
|
1584
1666
|
else {
|
|
1585
|
-
console.log(
|
|
1667
|
+
console.log((0, box_1.renderResult)('error', 'Failed to delete'));
|
|
1586
1668
|
}
|
|
1587
1669
|
}
|
|
1588
1670
|
else {
|
|
1589
|
-
console.log(
|
|
1590
|
-
console.log(chalk_1.default.gray(' Use: cm brain-delete learning <id> | cm brain-delete decision <id>'));
|
|
1671
|
+
console.log((0, box_1.renderResult)('error', `Unknown type: ${type}`, [(0, theme_1.dim)('Use: cm brain-delete learning <id> | cm brain-delete decision <id>')]));
|
|
1591
1672
|
}
|
|
1592
1673
|
}
|
|
1593
1674
|
function brainStats(projectPath) {
|
|
1594
1675
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1595
|
-
console.log(
|
|
1676
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found. Run: cm continuity init'));
|
|
1596
1677
|
return;
|
|
1597
1678
|
}
|
|
1598
1679
|
const status = (0, continuity_1.getContinuityStatus)(projectPath);
|
|
1599
1680
|
const learnings = (0, continuity_1.getLearnings)(projectPath);
|
|
1600
1681
|
const decisions = (0, continuity_1.getDecisions)(projectPath);
|
|
1601
|
-
console.log(
|
|
1602
|
-
console.log(
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1682
|
+
console.log((0, box_1.renderCommandHeader)('Brain Statistics', 'π'));
|
|
1683
|
+
console.log((0, box_1.renderKeyValue)([
|
|
1684
|
+
['Learnings', String(learnings.length)],
|
|
1685
|
+
['Decisions', String(decisions.length)],
|
|
1686
|
+
['Completed', `${status.completedCount} items`],
|
|
1687
|
+
['Blockers', String(status.blockerCount)],
|
|
1688
|
+
['Iteration', `#${status.iteration}`],
|
|
1689
|
+
]));
|
|
1607
1690
|
// Agent breakdown
|
|
1608
1691
|
const agentMap = {};
|
|
1609
1692
|
learnings.forEach(l => { if (l.agent)
|
|
@@ -1613,9 +1696,9 @@ function brainStats(projectPath) {
|
|
|
1613
1696
|
const agents = Object.entries(agentMap).sort((a, b) => b[1] - a[1]);
|
|
1614
1697
|
if (agents.length > 0) {
|
|
1615
1698
|
console.log();
|
|
1616
|
-
console.log(
|
|
1699
|
+
console.log((0, theme_1.brand)(' Agents:'));
|
|
1617
1700
|
for (const [agent, count] of agents) {
|
|
1618
|
-
console.log(
|
|
1701
|
+
console.log((0, theme_1.dim)(` π€ ${padRight(agent, 20)} ${count} entries`));
|
|
1619
1702
|
}
|
|
1620
1703
|
}
|
|
1621
1704
|
// Module breakdown
|
|
@@ -1625,23 +1708,23 @@ function brainStats(projectPath) {
|
|
|
1625
1708
|
const modules = Object.entries(moduleMap).sort((a, b) => b[1] - a[1]);
|
|
1626
1709
|
if (modules.length > 0) {
|
|
1627
1710
|
console.log();
|
|
1628
|
-
console.log(
|
|
1711
|
+
console.log((0, theme_1.brand)(' Modules (most error-prone):'));
|
|
1629
1712
|
for (const [mod, count] of modules.slice(0, 5)) {
|
|
1630
|
-
console.log(
|
|
1713
|
+
console.log((0, theme_1.dim)(` π¦ ${padRight(mod, 20)} ${count} learnings`));
|
|
1631
1714
|
}
|
|
1632
1715
|
}
|
|
1633
1716
|
// Time range
|
|
1634
1717
|
const allTimestamps = [...learnings.map(l => l.timestamp), ...decisions.map(d => d.timestamp)].filter(Boolean).sort();
|
|
1635
1718
|
if (allTimestamps.length > 0) {
|
|
1636
1719
|
console.log();
|
|
1637
|
-
console.log(
|
|
1638
|
-
console.log(
|
|
1720
|
+
console.log((0, theme_1.dim)(` First entry: ${formatTimeAgoCli(allTimestamps[0])}`));
|
|
1721
|
+
console.log((0, theme_1.dim)(` Latest: ${formatTimeAgoCli(allTimestamps[allTimestamps.length - 1])}`));
|
|
1639
1722
|
}
|
|
1640
1723
|
console.log();
|
|
1641
1724
|
}
|
|
1642
1725
|
function brainExport(projectPath, opts) {
|
|
1643
1726
|
if (!(0, continuity_1.hasCmDir)(projectPath)) {
|
|
1644
|
-
console.log(
|
|
1727
|
+
console.log((0, box_1.renderResult)('warning', 'No .cm/ directory found.'));
|
|
1645
1728
|
return;
|
|
1646
1729
|
}
|
|
1647
1730
|
const learnings = (0, continuity_1.getLearnings)(projectPath);
|
|
@@ -1652,8 +1735,7 @@ function brainExport(projectPath, opts) {
|
|
|
1652
1735
|
const data = { status, learnings, decisions, exportedAt: new Date().toISOString() };
|
|
1653
1736
|
const outFile = `brain-export-${new Date().toISOString().slice(0, 10)}.json`;
|
|
1654
1737
|
fs_1.default.writeFileSync(outFile, JSON.stringify(data, null, 2));
|
|
1655
|
-
console.log(
|
|
1656
|
-
console.log(chalk_1.default.gray(` ${learnings.length} learnings, ${decisions.length} decisions`));
|
|
1738
|
+
console.log((0, box_1.renderResult)('success', `Exported to ${outFile}`, [(0, theme_1.dim)(`${learnings.length} learnings, ${decisions.length} decisions`)]));
|
|
1657
1739
|
}
|
|
1658
1740
|
else if (format === 'md') {
|
|
1659
1741
|
let md = `# Brain Export\n\n**Project:** ${status.project || 'Unknown'}\n**Exported:** ${new Date().toISOString()}\n\n`;
|
|
@@ -1667,12 +1749,10 @@ function brainExport(projectPath, opts) {
|
|
|
1667
1749
|
}
|
|
1668
1750
|
const outFile = `brain-export-${new Date().toISOString().slice(0, 10)}.md`;
|
|
1669
1751
|
fs_1.default.writeFileSync(outFile, md);
|
|
1670
|
-
console.log(
|
|
1671
|
-
console.log(chalk_1.default.gray(` ${learnings.length} learnings, ${decisions.length} decisions`));
|
|
1752
|
+
console.log((0, box_1.renderResult)('success', `Exported to ${outFile}`, [(0, theme_1.dim)(`${learnings.length} learnings, ${decisions.length} decisions`)]));
|
|
1672
1753
|
}
|
|
1673
1754
|
else {
|
|
1674
|
-
console.log(
|
|
1675
|
-
console.log(chalk_1.default.gray(' Use: --format json | --format md'));
|
|
1755
|
+
console.log((0, box_1.renderResult)('error', `Unknown format: ${format}`, [(0, theme_1.dim)('Use: --format json | --format md')]));
|
|
1676
1756
|
}
|
|
1677
1757
|
}
|
|
1678
1758
|
// βββ Skill Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -1754,7 +1834,7 @@ program
|
|
|
1754
1834
|
break;
|
|
1755
1835
|
case 'info':
|
|
1756
1836
|
if (!name) {
|
|
1757
|
-
console.log(
|
|
1837
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm skill info <skill-name>'));
|
|
1758
1838
|
return;
|
|
1759
1839
|
}
|
|
1760
1840
|
skillInfo(name);
|
|
@@ -1772,52 +1852,51 @@ function skillList(filterDomain) {
|
|
|
1772
1852
|
? Object.entries(SKILL_CATALOG).filter(([d]) => d.toLowerCase().startsWith(filterDomain.toLowerCase()))
|
|
1773
1853
|
: Object.entries(SKILL_CATALOG);
|
|
1774
1854
|
if (entries.length === 0) {
|
|
1775
|
-
console.log(
|
|
1776
|
-
console.log(chalk_1.default.gray(' Domains: engineering, operations, product, growth, orchestration, workflow'));
|
|
1855
|
+
console.log((0, box_1.renderResult)('error', `Domain not found: ${filterDomain}`, [(0, theme_1.dim)('Domains: engineering, operations, product, growth, orchestration, workflow')]));
|
|
1777
1856
|
return;
|
|
1778
1857
|
}
|
|
1779
|
-
console.log(
|
|
1858
|
+
console.log((0, box_1.renderCommandHeader)('Cody Master β 34 Skills', 'π§©'));
|
|
1780
1859
|
let total = 0;
|
|
1781
1860
|
for (const [domain, data] of entries) {
|
|
1782
|
-
console.log(
|
|
1861
|
+
console.log((0, theme_1.brand)(` ${data.icon} ${domain.charAt(0).toUpperCase() + domain.slice(1)}`));
|
|
1783
1862
|
for (const skill of data.skills) {
|
|
1784
|
-
console.log(` ${
|
|
1863
|
+
console.log(` ${(0, theme_1.brand)(padRight(skill.name, 26))} ${(0, theme_1.dim)(skill.desc)}`);
|
|
1785
1864
|
total++;
|
|
1786
1865
|
}
|
|
1787
1866
|
console.log();
|
|
1788
1867
|
}
|
|
1789
|
-
console.log(
|
|
1790
|
-
console.log(
|
|
1791
|
-
console.log(
|
|
1868
|
+
console.log((0, theme_1.dim)(` ${total} skills across ${entries.length} domains`));
|
|
1869
|
+
console.log((0, theme_1.dim)(` Install: npx codymaster add --all`));
|
|
1870
|
+
console.log((0, theme_1.dim)(` Add one: npx codymaster add --skill <name>\n`));
|
|
1792
1871
|
}
|
|
1793
1872
|
function skillInfo(name) {
|
|
1794
1873
|
for (const [domain, data] of Object.entries(SKILL_CATALOG)) {
|
|
1795
1874
|
const skill = data.skills.find(s => s.name === name);
|
|
1796
1875
|
if (skill) {
|
|
1797
|
-
console.log(
|
|
1798
|
-
console.log(` ${chalk_1.default.white('Domain:')} ${domain}`);
|
|
1799
|
-
console.log(` ${chalk_1.default.white('Description:')} ${skill.desc}`);
|
|
1876
|
+
console.log((0, box_1.renderCommandHeader)(`Skill: ${skill.name}`, 'π§©'));
|
|
1800
1877
|
const agents = (0, judge_1.suggestAgentsForSkill)(skill.name);
|
|
1801
|
-
console.log(
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1878
|
+
console.log((0, box_1.renderKeyValue)([
|
|
1879
|
+
['Domain', domain],
|
|
1880
|
+
['Description', skill.desc],
|
|
1881
|
+
['Best Agents', agents.join(', ')],
|
|
1882
|
+
['Invoke', `@[/${skill.name}] (Antigravity/Gemini)`],
|
|
1883
|
+
['', `/${skill.name} (Claude Code)`],
|
|
1884
|
+
['', `@${skill.name} (Cursor/Windsurf/Cline)`],
|
|
1885
|
+
]));
|
|
1805
1886
|
console.log();
|
|
1806
1887
|
return;
|
|
1807
1888
|
}
|
|
1808
1889
|
}
|
|
1809
|
-
console.log(
|
|
1810
|
-
console.log(chalk_1.default.gray(' Use "cm skill list" to see all available skills.'));
|
|
1890
|
+
console.log((0, box_1.renderResult)('error', `Skill not found: ${name}`, [(0, theme_1.dim)('Use "cm skill list" to see all available skills.')]));
|
|
1811
1891
|
}
|
|
1812
1892
|
function skillDomains() {
|
|
1813
|
-
console.log(
|
|
1893
|
+
console.log((0, box_1.renderCommandHeader)('Skill Domains', 'π―'));
|
|
1814
1894
|
let total = 0;
|
|
1815
1895
|
for (const [domain, data] of Object.entries(SKILL_CATALOG)) {
|
|
1816
|
-
console.log(` ${data.icon} ${
|
|
1896
|
+
console.log(` ${data.icon} ${(0, theme_1.brand)(padRight(domain.charAt(0).toUpperCase() + domain.slice(1), 16))} ${(0, theme_1.dim)(`${data.skills.length} skills`)}`);
|
|
1817
1897
|
total += data.skills.length;
|
|
1818
1898
|
}
|
|
1819
|
-
console.log(
|
|
1820
|
-
console.log();
|
|
1899
|
+
console.log((0, theme_1.dim)(`\n Total: ${total} skills across ${Object.keys(SKILL_CATALOG).length} domains\n`));
|
|
1821
1900
|
}
|
|
1822
1901
|
// βββ Judge Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1823
1902
|
program
|
|
@@ -1831,7 +1910,7 @@ program
|
|
|
1831
1910
|
// Single task evaluation
|
|
1832
1911
|
const task = (0, data_1.findTaskByIdPrefix)(data, taskId);
|
|
1833
1912
|
if (!task) {
|
|
1834
|
-
console.log(
|
|
1913
|
+
console.log((0, box_1.renderResult)('error', `Task not found: ${taskId}`));
|
|
1835
1914
|
return;
|
|
1836
1915
|
}
|
|
1837
1916
|
const project = data.projects.find(p => p.id === task.projectId);
|
|
@@ -1840,15 +1919,17 @@ program
|
|
|
1840
1919
|
learnings = (0, continuity_1.getLearnings)(project.path);
|
|
1841
1920
|
}
|
|
1842
1921
|
const decision = (0, judge_1.evaluateTaskState)(task, data.tasks, learnings);
|
|
1843
|
-
console.log(
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1922
|
+
console.log((0, box_1.renderCommandHeader)('Judge Decision', 'π€'));
|
|
1923
|
+
const details = [
|
|
1924
|
+
['Task', task.title],
|
|
1925
|
+
['Column', task.column],
|
|
1926
|
+
['Action', `${decision.badge} ${decision.action}`],
|
|
1927
|
+
['Reason', decision.reason],
|
|
1928
|
+
['Confidence', `${Math.round(decision.confidence * 100)}%`],
|
|
1929
|
+
];
|
|
1930
|
+
if (decision.suggestedNextSkill)
|
|
1931
|
+
details.push(['Suggested', decision.suggestedNextSkill]);
|
|
1932
|
+
console.log((0, box_1.renderKeyValue)(details));
|
|
1852
1933
|
console.log();
|
|
1853
1934
|
}
|
|
1854
1935
|
else {
|
|
@@ -1857,7 +1938,7 @@ program
|
|
|
1857
1938
|
if (opts.project) {
|
|
1858
1939
|
const project = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
1859
1940
|
if (!project) {
|
|
1860
|
-
console.log(
|
|
1941
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
1861
1942
|
return;
|
|
1862
1943
|
}
|
|
1863
1944
|
tasks = tasks.filter(t => t.projectId === project.id);
|
|
@@ -1870,19 +1951,19 @@ program
|
|
|
1870
1951
|
}
|
|
1871
1952
|
const decisions = (0, judge_1.evaluateAllTasks)(tasks, allLearnings);
|
|
1872
1953
|
if (decisions.size === 0) {
|
|
1873
|
-
console.log(
|
|
1954
|
+
console.log(`\n ${(0, theme_1.dim)('No active tasks to evaluate.')}\n`);
|
|
1874
1955
|
return;
|
|
1875
1956
|
}
|
|
1876
|
-
console.log(
|
|
1877
|
-
console.log(
|
|
1878
|
-
console.log(
|
|
1957
|
+
console.log((0, box_1.renderCommandHeader)(`Judge Decisions (${decisions.size} active tasks)`, 'π€'));
|
|
1958
|
+
console.log((0, theme_1.dim)(' ' + padRight('Badge', 8) + padRight('Action', 12) + padRight('Confidence', 12) + 'Task'));
|
|
1959
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(70)));
|
|
1879
1960
|
for (const [tid, dec] of decisions) {
|
|
1880
1961
|
const task = tasks.find(t => t.id === tid);
|
|
1881
|
-
const actionColor = dec.action === 'CONTINUE' ?
|
|
1882
|
-
: dec.action === 'COMPLETE' ?
|
|
1883
|
-
: dec.action === 'ESCALATE' ?
|
|
1884
|
-
:
|
|
1885
|
-
console.log(' ' + padRight(dec.badge, 8) + actionColor(padRight(dec.action, 12)) +
|
|
1962
|
+
const actionColor = dec.action === 'CONTINUE' ? theme_1.success
|
|
1963
|
+
: dec.action === 'COMPLETE' ? theme_1.brand
|
|
1964
|
+
: dec.action === 'ESCALATE' ? theme_1.warning
|
|
1965
|
+
: theme_1.brand;
|
|
1966
|
+
console.log(' ' + padRight(dec.badge, 8) + actionColor(padRight(dec.action, 12)) + (0, theme_1.dim)(padRight(`${Math.round(dec.confidence * 100)}%`, 12)) + ((task === null || task === void 0 ? void 0 : task.title) || tid.substring(0, 8)));
|
|
1886
1967
|
}
|
|
1887
1968
|
console.log();
|
|
1888
1969
|
}
|
|
@@ -1900,8 +1981,7 @@ program
|
|
|
1900
1981
|
// Check if already exists
|
|
1901
1982
|
const existing = data.projects.find(p => p.path === projectPath || p.name === projectName);
|
|
1902
1983
|
if (existing) {
|
|
1903
|
-
console.log(
|
|
1904
|
-
console.log(chalk_1.default.gray(` ID: ${(0, data_1.shortId)(existing.id)} | Path: ${existing.path}`));
|
|
1984
|
+
console.log((0, box_1.renderResult)('warning', `Project already exists: ${existing.name}`, [(0, theme_1.dim)(`ID: ${(0, data_1.shortId)(existing.id)} | Path: ${existing.path}`)]));
|
|
1905
1985
|
return;
|
|
1906
1986
|
}
|
|
1907
1987
|
const project = {
|
|
@@ -1916,19 +1996,19 @@ program
|
|
|
1916
1996
|
(0, data_1.saveData)(data);
|
|
1917
1997
|
// Also init working memory
|
|
1918
1998
|
(0, continuity_1.ensureCmDir)(projectPath);
|
|
1919
|
-
console.log(
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1999
|
+
console.log((0, box_1.renderResult)('success', `Project initialized: ${projectName}`, [
|
|
2000
|
+
(0, theme_1.dim)(`ID: ${(0, data_1.shortId)(project.id)}`),
|
|
2001
|
+
(0, theme_1.dim)(`Path: ${projectPath}`),
|
|
2002
|
+
(0, theme_1.dim)(`.cm/ Working memory created`),
|
|
2003
|
+
]));
|
|
1923
2004
|
console.log();
|
|
1924
2005
|
if (!isDashboardRunning()) {
|
|
1925
2006
|
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT);
|
|
1926
|
-
console.log(
|
|
2007
|
+
console.log((0, theme_1.success)(` π Dashboard auto-started! You can track progress at http://codymaster.localhost:${data_1.DEFAULT_PORT}`));
|
|
1927
2008
|
}
|
|
1928
|
-
console.log(
|
|
1929
|
-
console.log(
|
|
1930
|
-
console.log(
|
|
1931
|
-
console.log();
|
|
2009
|
+
console.log((0, theme_1.info)('π‘ Next steps:'));
|
|
2010
|
+
console.log((0, theme_1.dim)(' cm task add "My first task"'));
|
|
2011
|
+
console.log((0, theme_1.dim)(' cm open\n'));
|
|
1932
2012
|
});
|
|
1933
2013
|
// βββ Open Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1934
2014
|
program
|
|
@@ -1939,12 +2019,12 @@ program
|
|
|
1939
2019
|
.action((opts) => {
|
|
1940
2020
|
const port = parseInt(opts.port) || data_1.DEFAULT_PORT;
|
|
1941
2021
|
if (!isDashboardRunning()) {
|
|
1942
|
-
console.log(
|
|
2022
|
+
console.log((0, box_1.renderResult)('warning', 'Dashboard not running. Starting it first...'));
|
|
1943
2023
|
(0, dashboard_1.launchDashboard)(port);
|
|
1944
2024
|
setTimeout(() => openUrl(`http://codymaster.localhost:${port}`), 1500);
|
|
1945
2025
|
}
|
|
1946
2026
|
else {
|
|
1947
|
-
console.log(
|
|
2027
|
+
console.log((0, theme_1.info)(`π Opening http://codymaster.localhost:${port} ...`));
|
|
1948
2028
|
openUrl(`http://codymaster.localhost:${port}`);
|
|
1949
2029
|
}
|
|
1950
2030
|
});
|
|
@@ -1954,31 +2034,32 @@ program
|
|
|
1954
2034
|
.alias('cfg')
|
|
1955
2035
|
.description('Show configuration & data paths')
|
|
1956
2036
|
.action(() => {
|
|
1957
|
-
console.log(
|
|
1958
|
-
console.log(
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2037
|
+
console.log((0, box_1.renderCommandHeader)('Cody Configuration', 'βοΈ'));
|
|
2038
|
+
console.log((0, box_1.renderKeyValue)([
|
|
2039
|
+
['Version', VERSION],
|
|
2040
|
+
['Data Dir', data_1.DATA_DIR],
|
|
2041
|
+
['Data File', data_1.DATA_FILE],
|
|
2042
|
+
['PID File', data_1.PID_FILE],
|
|
2043
|
+
['Port', String(data_1.DEFAULT_PORT)],
|
|
2044
|
+
['CLI Names', 'cm | cm | codymaster'],
|
|
2045
|
+
]));
|
|
1964
2046
|
console.log();
|
|
1965
2047
|
// Show data stats
|
|
1966
2048
|
const data = (0, data_1.loadData)();
|
|
1967
|
-
console.log(
|
|
1968
|
-
console.log(
|
|
1969
|
-
console.log(
|
|
1970
|
-
console.log(
|
|
1971
|
-
console.log(
|
|
1972
|
-
console.log(
|
|
2049
|
+
console.log((0, theme_1.brand)(' Data Stats:'));
|
|
2050
|
+
console.log((0, theme_1.dim)(` Projects: ${data.projects.length}`));
|
|
2051
|
+
console.log((0, theme_1.dim)(` Tasks: ${data.tasks.length}`));
|
|
2052
|
+
console.log((0, theme_1.dim)(` Deploys: ${data.deployments.length}`));
|
|
2053
|
+
console.log((0, theme_1.dim)(` Activities: ${data.activities.length}`));
|
|
2054
|
+
console.log((0, theme_1.dim)(` Changelog: ${data.changelog.length}`));
|
|
1973
2055
|
console.log();
|
|
1974
2056
|
// Dashboard status
|
|
1975
2057
|
if (isDashboardRunning()) {
|
|
1976
|
-
console.log(
|
|
2058
|
+
console.log((0, theme_1.success)(` π Dashboard: RUNNING at http://codymaster.localhost:${data_1.DEFAULT_PORT}\n`));
|
|
1977
2059
|
}
|
|
1978
2060
|
else {
|
|
1979
|
-
console.log(
|
|
2061
|
+
console.log((0, theme_1.dim)(` β« Dashboard: not running\n`));
|
|
1980
2062
|
}
|
|
1981
|
-
console.log();
|
|
1982
2063
|
});
|
|
1983
2064
|
// βββ Agents Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1984
2065
|
const AGENT_LIST = [
|
|
@@ -1999,24 +2080,23 @@ program
|
|
|
1999
2080
|
// Suggest best agents for skill
|
|
2000
2081
|
const domain = (0, judge_1.getSkillDomain)(skill);
|
|
2001
2082
|
const agents = (0, judge_1.suggestAgentsForSkill)(skill);
|
|
2002
|
-
console.log(
|
|
2003
|
-
console.log(
|
|
2083
|
+
console.log((0, box_1.renderCommandHeader)(`Agent Suggestions for ${skill}`, 'π€'));
|
|
2084
|
+
console.log((0, theme_1.dim)(` Domain: ${domain}\n`));
|
|
2004
2085
|
agents.forEach((agentId, index) => {
|
|
2005
2086
|
const agent = AGENT_LIST.find(a => a.id === agentId);
|
|
2006
|
-
const affinity = index === 0 ?
|
|
2087
|
+
const affinity = index === 0 ? (0, theme_1.success)('β
BEST') : index === 1 ? (0, theme_1.warning)('β GOOD') : (0, theme_1.dim)('β OK');
|
|
2007
2088
|
console.log(` ${(agent === null || agent === void 0 ? void 0 : agent.icon) || 'π€'} ${padRight((agent === null || agent === void 0 ? void 0 : agent.name) || agentId, 24)} ${affinity}`);
|
|
2008
2089
|
});
|
|
2009
2090
|
console.log();
|
|
2010
2091
|
}
|
|
2011
2092
|
else {
|
|
2012
2093
|
// List all agents
|
|
2013
|
-
console.log(
|
|
2094
|
+
console.log((0, box_1.renderCommandHeader)('Available Agents', 'π€'));
|
|
2014
2095
|
for (const agent of AGENT_LIST) {
|
|
2015
|
-
console.log(` ${agent.icon} ${
|
|
2096
|
+
console.log(` ${agent.icon} ${(0, theme_1.brand)(padRight(agent.name, 24))} ${(0, theme_1.dim)(agent.id)}`);
|
|
2016
2097
|
}
|
|
2017
2098
|
console.log();
|
|
2018
|
-
console.log(
|
|
2019
|
-
console.log();
|
|
2099
|
+
console.log((0, theme_1.dim)(' π‘ Tip: cm agents <skill-name> to see best agents for a skill\n'));
|
|
2020
2100
|
}
|
|
2021
2101
|
});
|
|
2022
2102
|
// βββ Sync Command βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -2029,7 +2109,7 @@ program
|
|
|
2029
2109
|
.action((file, opts) => {
|
|
2030
2110
|
const filePath = path_1.default.resolve(file);
|
|
2031
2111
|
if (!fs_1.default.existsSync(filePath)) {
|
|
2032
|
-
console.log(
|
|
2112
|
+
console.log((0, box_1.renderResult)('error', `File not found: ${filePath}`));
|
|
2033
2113
|
return;
|
|
2034
2114
|
}
|
|
2035
2115
|
let tasks;
|
|
@@ -2041,8 +2121,7 @@ program
|
|
|
2041
2121
|
throw new Error('Invalid format');
|
|
2042
2122
|
}
|
|
2043
2123
|
catch (err) {
|
|
2044
|
-
console.log(
|
|
2045
|
-
console.log(chalk_1.default.gray(' Expected format: [{"title": "...", "priority": "...", "column": "..."}]'));
|
|
2124
|
+
console.log((0, box_1.renderResult)('error', `Invalid JSON file: ${err.message}`, [(0, theme_1.dim)('Expected format: [{"title": "...", "priority": "...", "column": "..."}]')]));
|
|
2046
2125
|
return;
|
|
2047
2126
|
}
|
|
2048
2127
|
const data = (0, data_1.loadData)();
|
|
@@ -2050,7 +2129,7 @@ program
|
|
|
2050
2129
|
if (opts.project) {
|
|
2051
2130
|
const p = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
2052
2131
|
if (!p) {
|
|
2053
|
-
console.log(
|
|
2132
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
2054
2133
|
return;
|
|
2055
2134
|
}
|
|
2056
2135
|
projectId = p.id;
|
|
@@ -2085,12 +2164,11 @@ program
|
|
|
2085
2164
|
(0, data_1.logActivity)(data, 'task_created', `Synced ${count} tasks from ${path_1.default.basename(filePath)}`, projectId, opts.agent || '', { count, file: filePath });
|
|
2086
2165
|
(0, data_1.saveData)(data);
|
|
2087
2166
|
const project = data.projects.find(p => p.id === projectId);
|
|
2088
|
-
console.log(
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
console.log();
|
|
2167
|
+
console.log((0, box_1.renderResult)('success', `Synced ${count} tasks!`, [
|
|
2168
|
+
(0, theme_1.dim)(`Project: ${(project === null || project === void 0 ? void 0 : project.name) || 'Default'}`),
|
|
2169
|
+
(0, theme_1.dim)(`Source: ${filePath}`),
|
|
2170
|
+
...(opts.agent ? [(0, theme_1.dim)(`Agent: ${opts.agent}`)] : []),
|
|
2171
|
+
]));
|
|
2094
2172
|
});
|
|
2095
2173
|
// βββ Chain Command ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
2096
2174
|
// TRIZ #40 Composite Materials β skills compose into pipelines
|
|
@@ -2134,67 +2212,66 @@ program
|
|
|
2134
2212
|
chainHistory();
|
|
2135
2213
|
break;
|
|
2136
2214
|
default:
|
|
2137
|
-
console.log(
|
|
2138
|
-
console.log(chalk_1.default.gray('Available: list, info, start, status, advance, skip, abort, auto, history'));
|
|
2215
|
+
console.log((0, box_1.renderResult)('error', `Unknown: ${cmd}`, [(0, theme_1.dim)('Available: list, info, start, status, advance, skip, abort, auto, history')]));
|
|
2139
2216
|
}
|
|
2140
2217
|
});
|
|
2141
2218
|
function chainList() {
|
|
2142
2219
|
const chains = (0, skill_chain_1.listChains)();
|
|
2143
|
-
console.log(
|
|
2220
|
+
console.log((0, box_1.renderCommandHeader)('Available Skill Chains', 'π'));
|
|
2144
2221
|
for (const chain of chains) {
|
|
2145
|
-
console.log(` ${chain.icon} ${
|
|
2146
|
-
console.log(
|
|
2222
|
+
console.log(` ${chain.icon} ${(0, theme_1.brand)(padRight(chain.name, 24))} ${(0, theme_1.dim)(chain.description)}`);
|
|
2223
|
+
console.log((0, theme_1.dim)(` ID: ${chain.id} | Steps: ${chain.steps.length} | Triggers: ${chain.triggers.slice(0, 4).join(', ')}...`));
|
|
2147
2224
|
console.log();
|
|
2148
2225
|
}
|
|
2149
|
-
console.log(
|
|
2150
|
-
console.log(
|
|
2151
|
-
console.log(
|
|
2152
|
-
console.log(
|
|
2153
|
-
console.log();
|
|
2226
|
+
console.log((0, theme_1.dim)(` Total: ${chains.length} chains\n`));
|
|
2227
|
+
console.log((0, theme_1.info)('π‘ Quick start:'));
|
|
2228
|
+
console.log((0, theme_1.dim)(' cm chain auto "Build user authentication" # Auto-detect chain'));
|
|
2229
|
+
console.log((0, theme_1.dim)(' cm chain start feature-development "My task" # Start specific chain\n'));
|
|
2154
2230
|
}
|
|
2155
2231
|
function chainInfo(chainId) {
|
|
2156
2232
|
if (!chainId) {
|
|
2157
|
-
console.log(
|
|
2233
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain info <chain-id>'));
|
|
2158
2234
|
return;
|
|
2159
2235
|
}
|
|
2160
2236
|
const chain = (0, skill_chain_1.findChain)(chainId);
|
|
2161
2237
|
if (!chain) {
|
|
2162
|
-
console.log(
|
|
2163
|
-
console.log(chalk_1.default.gray(' Use "cm chain list" to see available chains.'));
|
|
2238
|
+
console.log((0, box_1.renderResult)('error', `Chain not found: ${chainId}`, [(0, theme_1.dim)('Use "cm chain list" to see available chains.')]));
|
|
2164
2239
|
return;
|
|
2165
2240
|
}
|
|
2166
|
-
console.log(
|
|
2167
|
-
console.log(
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2241
|
+
console.log((0, box_1.renderCommandHeader)(`Chain: ${chain.name}`, chain.icon));
|
|
2242
|
+
console.log((0, box_1.renderKeyValue)([
|
|
2243
|
+
['ID', chain.id],
|
|
2244
|
+
['Description', chain.description],
|
|
2245
|
+
['Steps', String(chain.steps.length)],
|
|
2246
|
+
['Triggers', chain.triggers.join(', ')],
|
|
2247
|
+
]));
|
|
2171
2248
|
console.log();
|
|
2172
|
-
console.log(
|
|
2249
|
+
console.log((0, theme_1.brand)(' Pipeline:'));
|
|
2173
2250
|
for (let i = 0; i < chain.steps.length; i++) {
|
|
2174
2251
|
const step = chain.steps[i];
|
|
2175
|
-
const condBadge = step.condition === 'always' ?
|
|
2176
|
-
const optBadge = step.optional ?
|
|
2252
|
+
const condBadge = step.condition === 'always' ? (0, theme_1.success)('ALWAYS') : step.condition === 'if-complex' ? (0, theme_1.warning)('IF-COMPLEX') : (0, theme_1.brand)('IF-READY');
|
|
2253
|
+
const optBadge = step.optional ? (0, theme_1.dim)(' (optional)') : '';
|
|
2177
2254
|
const connector = i < chain.steps.length - 1 ? ' β' : ' ';
|
|
2178
|
-
console.log(` ${
|
|
2179
|
-
console.log(
|
|
2255
|
+
console.log(` ${(0, theme_1.brand)(`${i + 1}.`)} ${padRight(step.skill, 24)} ${condBadge}${optBadge}`);
|
|
2256
|
+
console.log((0, theme_1.dim)(` ${connector} ${step.description}`));
|
|
2180
2257
|
if (i < chain.steps.length - 1)
|
|
2181
|
-
console.log(
|
|
2258
|
+
console.log((0, theme_1.dim)(' β'));
|
|
2182
2259
|
}
|
|
2183
2260
|
console.log();
|
|
2184
2261
|
}
|
|
2185
2262
|
function chainStart(chainId, taskTitle, opts) {
|
|
2186
2263
|
var _a, _b, _c;
|
|
2187
2264
|
if (!chainId) {
|
|
2188
|
-
console.log(
|
|
2265
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain start <chain-id> "Task title"'));
|
|
2189
2266
|
return;
|
|
2190
2267
|
}
|
|
2191
2268
|
if (!taskTitle) {
|
|
2192
|
-
console.log(
|
|
2269
|
+
console.log((0, box_1.renderResult)('error', 'Task title required. Usage: cm chain start <chain-id> "My task"'));
|
|
2193
2270
|
return;
|
|
2194
2271
|
}
|
|
2195
2272
|
const chain = (0, skill_chain_1.findChain)(chainId);
|
|
2196
2273
|
if (!chain) {
|
|
2197
|
-
console.log(
|
|
2274
|
+
console.log((0, box_1.renderResult)('error', `Chain not found: ${chainId}`));
|
|
2198
2275
|
return;
|
|
2199
2276
|
}
|
|
2200
2277
|
const data = (0, data_1.loadData)();
|
|
@@ -2202,7 +2279,7 @@ function chainStart(chainId, taskTitle, opts) {
|
|
|
2202
2279
|
if (opts.project) {
|
|
2203
2280
|
const project = (0, data_1.findProjectByNameOrId)(data, opts.project);
|
|
2204
2281
|
if (!project) {
|
|
2205
|
-
console.log(
|
|
2282
|
+
console.log((0, box_1.renderResult)('error', `Project not found: ${opts.project}`));
|
|
2206
2283
|
return;
|
|
2207
2284
|
}
|
|
2208
2285
|
projectId = project.id;
|
|
@@ -2211,7 +2288,7 @@ function chainStart(chainId, taskTitle, opts) {
|
|
|
2211
2288
|
projectId = data.projects[0].id;
|
|
2212
2289
|
}
|
|
2213
2290
|
else {
|
|
2214
|
-
console.log(
|
|
2291
|
+
console.log((0, box_1.renderResult)('error', 'No projects. Create one first: cm init'));
|
|
2215
2292
|
return;
|
|
2216
2293
|
}
|
|
2217
2294
|
const agent = opts.agent || 'antigravity';
|
|
@@ -2230,18 +2307,16 @@ function chainStart(chainId, taskTitle, opts) {
|
|
|
2230
2307
|
});
|
|
2231
2308
|
(0, data_1.saveData)(data);
|
|
2232
2309
|
const project = data.projects.find(p => p.id === projectId);
|
|
2233
|
-
console.log(
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
console.log(
|
|
2242
|
-
console.log();
|
|
2243
|
-
console.log(chalk_1.default.gray(` Next: cm chain advance ${(0, data_1.shortId)(execution.id)} "output summary"`));
|
|
2244
|
-
console.log();
|
|
2310
|
+
console.log((0, box_1.renderResult)('success', 'Chain started!', [
|
|
2311
|
+
(0, theme_1.dim)(`Chain: ${chain.icon} ${chain.name}`),
|
|
2312
|
+
(0, theme_1.dim)(`Task: ${taskTitle}`),
|
|
2313
|
+
(0, theme_1.dim)(`Project: ${(project === null || project === void 0 ? void 0 : project.name) || 'β'}`),
|
|
2314
|
+
(0, theme_1.dim)(`Agent: ${agent}`),
|
|
2315
|
+
(0, theme_1.dim)(`Steps: ${chain.steps.length}`),
|
|
2316
|
+
(0, theme_1.dim)(`Exec ID: ${(0, data_1.shortId)(execution.id)}`),
|
|
2317
|
+
]));
|
|
2318
|
+
console.log((0, theme_1.brand)(` βΆ Current step: ${(_b = execution.steps[0]) === null || _b === void 0 ? void 0 : _b.skill} β ${(_c = execution.steps[0]) === null || _c === void 0 ? void 0 : _c.description}`));
|
|
2319
|
+
console.log((0, theme_1.dim)(`\n Next: cm chain advance ${(0, data_1.shortId)(execution.id)} "output summary"\n`));
|
|
2245
2320
|
}
|
|
2246
2321
|
function chainStatus(execIdPrefix) {
|
|
2247
2322
|
const data = (0, data_1.loadData)();
|
|
@@ -2249,7 +2324,7 @@ function chainStatus(execIdPrefix) {
|
|
|
2249
2324
|
// Show specific execution
|
|
2250
2325
|
const exec = data.chainExecutions.find(e => e.id === execIdPrefix || e.id.startsWith(execIdPrefix));
|
|
2251
2326
|
if (!exec) {
|
|
2252
|
-
console.log(
|
|
2327
|
+
console.log((0, box_1.renderResult)('error', `Chain execution not found: ${execIdPrefix}`));
|
|
2253
2328
|
return;
|
|
2254
2329
|
}
|
|
2255
2330
|
console.log();
|
|
@@ -2260,34 +2335,33 @@ function chainStatus(execIdPrefix) {
|
|
|
2260
2335
|
// Show all active executions
|
|
2261
2336
|
const active = data.chainExecutions.filter(e => e.status === 'running' || e.status === 'paused');
|
|
2262
2337
|
if (active.length === 0) {
|
|
2263
|
-
console.log(
|
|
2264
|
-
console.log(
|
|
2338
|
+
console.log(`\n ${(0, theme_1.dim)('No active chain executions.')}`);
|
|
2339
|
+
console.log(` ${(0, theme_1.dim)('Start one with: cm chain auto "task description"')}\n`);
|
|
2265
2340
|
return;
|
|
2266
2341
|
}
|
|
2267
|
-
console.log(
|
|
2342
|
+
console.log((0, box_1.renderCommandHeader)(`Active Chains (${active.length})`, 'π'));
|
|
2268
2343
|
for (const exec of active) {
|
|
2269
2344
|
const project = data.projects.find(p => p.id === exec.projectId);
|
|
2270
2345
|
const currentSkill = (0, skill_chain_1.getCurrentSkill)(exec);
|
|
2271
2346
|
const progressBar = (0, skill_chain_1.formatChainProgressBar)(exec);
|
|
2272
|
-
console.log(` ${
|
|
2273
|
-
console.log(
|
|
2274
|
-
console.log(
|
|
2275
|
-
console.log();
|
|
2347
|
+
console.log(` ${(0, theme_1.brand)(exec.chainName)} β "${exec.taskTitle}"`);
|
|
2348
|
+
console.log((0, theme_1.dim)(` ${progressBar} | Step ${exec.currentStepIndex + 1}/${exec.steps.length}: ${currentSkill || 'done'}`));
|
|
2349
|
+
console.log((0, theme_1.dim)(` ID: ${(0, data_1.shortId)(exec.id)} | Agent: ${exec.agent} | Project: ${(project === null || project === void 0 ? void 0 : project.name) || 'β'}\n`));
|
|
2276
2350
|
}
|
|
2277
2351
|
}
|
|
2278
2352
|
function chainAdvance(execIdPrefix, output) {
|
|
2279
2353
|
if (!execIdPrefix) {
|
|
2280
|
-
console.log(
|
|
2354
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain advance <exec-id> ["output summary"]'));
|
|
2281
2355
|
return;
|
|
2282
2356
|
}
|
|
2283
2357
|
const data = (0, data_1.loadData)();
|
|
2284
2358
|
const exec = data.chainExecutions.find(e => e.id === execIdPrefix || e.id.startsWith(execIdPrefix));
|
|
2285
2359
|
if (!exec) {
|
|
2286
|
-
console.log(
|
|
2360
|
+
console.log((0, box_1.renderResult)('error', `Chain execution not found: ${execIdPrefix}`));
|
|
2287
2361
|
return;
|
|
2288
2362
|
}
|
|
2289
2363
|
if (exec.status !== 'running') {
|
|
2290
|
-
console.log(
|
|
2364
|
+
console.log((0, box_1.renderResult)('warning', `Chain is ${exec.status}, cannot advance.`));
|
|
2291
2365
|
return;
|
|
2292
2366
|
}
|
|
2293
2367
|
const completedStep = exec.steps[exec.currentStepIndex];
|
|
@@ -2307,10 +2381,10 @@ function chainAdvance(execIdPrefix, output) {
|
|
|
2307
2381
|
executionId: exec.id, totalSteps: exec.steps.length,
|
|
2308
2382
|
});
|
|
2309
2383
|
(0, data_1.saveData)(data);
|
|
2310
|
-
console.log(
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2384
|
+
console.log((0, box_1.renderResult)('success', `Chain completed! All ${exec.steps.length} steps done.`, [
|
|
2385
|
+
(0, theme_1.dim)(`Chain: ${exec.chainName}`),
|
|
2386
|
+
(0, theme_1.dim)(`Task: ${exec.taskTitle}`),
|
|
2387
|
+
]));
|
|
2314
2388
|
}
|
|
2315
2389
|
else {
|
|
2316
2390
|
(0, data_1.logActivity)(data, 'chain_step_completed', `Chain step completed: ${completedStep === null || completedStep === void 0 ? void 0 : completedStep.skill} β next: ${result.nextSkill}`, exec.projectId, exec.agent, {
|
|
@@ -2318,52 +2392,51 @@ function chainAdvance(execIdPrefix, output) {
|
|
|
2318
2392
|
});
|
|
2319
2393
|
(0, data_1.saveData)(data);
|
|
2320
2394
|
const nextStep = exec.steps[exec.currentStepIndex];
|
|
2321
|
-
console.log(
|
|
2322
|
-
console.log(
|
|
2323
|
-
console.log(
|
|
2324
|
-
console.log();
|
|
2395
|
+
console.log((0, box_1.renderResult)('success', `Step completed: ${completedStep === null || completedStep === void 0 ? void 0 : completedStep.skill}`));
|
|
2396
|
+
console.log((0, theme_1.brand)(` βΆ Next step: ${result.nextSkill} β ${nextStep === null || nextStep === void 0 ? void 0 : nextStep.description}`));
|
|
2397
|
+
console.log((0, theme_1.dim)(` Progress: ${(0, skill_chain_1.formatChainProgressBar)(exec)}\n`));
|
|
2325
2398
|
}
|
|
2326
2399
|
}
|
|
2327
2400
|
function chainSkip(execIdPrefix, reason) {
|
|
2328
2401
|
if (!execIdPrefix) {
|
|
2329
|
-
console.log(
|
|
2402
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain skip <exec-id> ["reason"]'));
|
|
2330
2403
|
return;
|
|
2331
2404
|
}
|
|
2332
2405
|
const data = (0, data_1.loadData)();
|
|
2333
2406
|
const exec = data.chainExecutions.find(e => e.id === execIdPrefix || e.id.startsWith(execIdPrefix));
|
|
2334
2407
|
if (!exec) {
|
|
2335
|
-
console.log(
|
|
2408
|
+
console.log((0, box_1.renderResult)('error', `Chain execution not found: ${execIdPrefix}`));
|
|
2336
2409
|
return;
|
|
2337
2410
|
}
|
|
2338
2411
|
if (exec.status !== 'running') {
|
|
2339
|
-
console.log(
|
|
2412
|
+
console.log((0, box_1.renderResult)('warning', `Chain is ${exec.status}, cannot skip.`));
|
|
2340
2413
|
return;
|
|
2341
2414
|
}
|
|
2342
2415
|
const skippedStep = exec.steps[exec.currentStepIndex];
|
|
2343
2416
|
const result = (0, skill_chain_1.skipChainStep)(exec, reason);
|
|
2344
2417
|
(0, data_1.saveData)(data);
|
|
2345
|
-
console.log(
|
|
2418
|
+
console.log((0, theme_1.warning)(` βοΈ Skipped: ${skippedStep === null || skippedStep === void 0 ? void 0 : skippedStep.skill}`));
|
|
2346
2419
|
if (result.completed) {
|
|
2347
|
-
console.log(
|
|
2420
|
+
console.log((0, theme_1.success)(` β
Chain completed!`));
|
|
2348
2421
|
}
|
|
2349
2422
|
else {
|
|
2350
|
-
console.log(
|
|
2423
|
+
console.log((0, theme_1.brand)(` βΆ Next: ${result.nextSkill}`));
|
|
2351
2424
|
}
|
|
2352
2425
|
console.log();
|
|
2353
2426
|
}
|
|
2354
2427
|
function chainAbort(execIdPrefix, reason) {
|
|
2355
2428
|
if (!execIdPrefix) {
|
|
2356
|
-
console.log(
|
|
2429
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain abort <exec-id> ["reason"]'));
|
|
2357
2430
|
return;
|
|
2358
2431
|
}
|
|
2359
2432
|
const data = (0, data_1.loadData)();
|
|
2360
2433
|
const exec = data.chainExecutions.find(e => e.id === execIdPrefix || e.id.startsWith(execIdPrefix));
|
|
2361
2434
|
if (!exec) {
|
|
2362
|
-
console.log(
|
|
2435
|
+
console.log((0, box_1.renderResult)('error', `Chain execution not found: ${execIdPrefix}`));
|
|
2363
2436
|
return;
|
|
2364
2437
|
}
|
|
2365
2438
|
if (exec.status !== 'running' && exec.status !== 'paused') {
|
|
2366
|
-
console.log(
|
|
2439
|
+
console.log((0, box_1.renderResult)('warning', `Chain already ${exec.status}.`));
|
|
2367
2440
|
return;
|
|
2368
2441
|
}
|
|
2369
2442
|
(0, skill_chain_1.abortChain)(exec, reason);
|
|
@@ -2371,30 +2444,25 @@ function chainAbort(execIdPrefix, reason) {
|
|
|
2371
2444
|
executionId: exec.id,
|
|
2372
2445
|
});
|
|
2373
2446
|
(0, data_1.saveData)(data);
|
|
2374
|
-
console.log(
|
|
2375
|
-
if (reason)
|
|
2376
|
-
console.log(chalk_1.default.gray(` Reason: ${reason}`));
|
|
2377
|
-
console.log();
|
|
2447
|
+
console.log((0, box_1.renderResult)('error', `Chain aborted: ${exec.chainName}`, reason ? [(0, theme_1.dim)(`Reason: ${reason}`)] : []));
|
|
2378
2448
|
}
|
|
2379
2449
|
function chainAuto(taskTitle, opts) {
|
|
2380
2450
|
if (!taskTitle) {
|
|
2381
|
-
console.log(
|
|
2382
|
-
console.log(chalk_1.default.gray(' Example: cm chain auto "Build user authentication"'));
|
|
2451
|
+
console.log((0, box_1.renderResult)('error', 'Usage: cm chain auto "task description"', [(0, theme_1.dim)('Example: cm chain auto "Build user authentication"')]));
|
|
2383
2452
|
return;
|
|
2384
2453
|
}
|
|
2385
2454
|
const chain = (0, skill_chain_1.matchChain)(taskTitle);
|
|
2386
2455
|
if (!chain) {
|
|
2387
|
-
|
|
2388
|
-
console.log(
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2456
|
+
const listHint = (0, skill_chain_1.listChains)().map(c => ` ${c.icon} ${c.id}: ${c.triggers.slice(0, 3).join(', ')}...`);
|
|
2457
|
+
console.log((0, box_1.renderResult)('warning', `No matching chain found for: "${taskTitle}"`, [
|
|
2458
|
+
(0, theme_1.dim)('Available chains:'),
|
|
2459
|
+
...listHint.map(l => (0, theme_1.dim)(l)),
|
|
2460
|
+
(0, theme_1.dim)('\n Use "cm chain start <chain-id> <title>" to start manually.'),
|
|
2461
|
+
]));
|
|
2393
2462
|
return;
|
|
2394
2463
|
}
|
|
2395
|
-
console.log(
|
|
2396
|
-
console.log(
|
|
2397
|
-
console.log();
|
|
2464
|
+
console.log((0, box_1.renderCommandHeader)(`Auto-detected chain: ${chain.name}`, chain.icon));
|
|
2465
|
+
console.log((0, theme_1.dim)(` Matched from: "${taskTitle}"\n`));
|
|
2398
2466
|
// Delegate to chainStart
|
|
2399
2467
|
chainStart(chain.id, taskTitle, opts);
|
|
2400
2468
|
}
|
|
@@ -2402,21 +2470,21 @@ function chainHistory() {
|
|
|
2402
2470
|
const data = (0, data_1.loadData)();
|
|
2403
2471
|
const execs = data.chainExecutions;
|
|
2404
2472
|
if (execs.length === 0) {
|
|
2405
|
-
console.log(
|
|
2473
|
+
console.log(`\n ${(0, theme_1.dim)('No chain executions yet.')}\n`);
|
|
2406
2474
|
return;
|
|
2407
2475
|
}
|
|
2408
2476
|
const STATUS_ICONS = {
|
|
2409
2477
|
pending: 'βͺ', running: 'π΅', paused: 'βΈοΈ', completed: 'β
', failed: 'β', aborted: 'π',
|
|
2410
2478
|
};
|
|
2411
|
-
console.log(
|
|
2412
|
-
console.log(
|
|
2413
|
-
console.log(
|
|
2479
|
+
console.log((0, box_1.renderCommandHeader)(`Chain History (${execs.length})`, 'π'));
|
|
2480
|
+
console.log((0, theme_1.dim)(' ' + padRight('Status', 8) + padRight('Chain', 24) + padRight('Task', 30) + padRight('Progress', 14) + 'Time'));
|
|
2481
|
+
console.log((0, theme_1.dim)(' ' + 'β'.repeat(86)));
|
|
2414
2482
|
for (const exec of execs.slice(0, 20)) {
|
|
2415
2483
|
const icon = STATUS_ICONS[exec.status] || 'β';
|
|
2416
2484
|
const completed = exec.steps.filter(s => s.status === 'completed' || s.status === 'skipped').length;
|
|
2417
2485
|
const progress = `${completed}/${exec.steps.length} steps`;
|
|
2418
2486
|
const time = formatTimeAgoCli(exec.startedAt);
|
|
2419
|
-
console.log(' ' + padRight(icon, 8) + padRight(exec.chainName.substring(0, 22), 24) + padRight(exec.taskTitle.substring(0, 28), 30) +
|
|
2487
|
+
console.log(' ' + padRight(icon, 8) + (0, theme_1.brand)(padRight(exec.chainName.substring(0, 22), 24)) + padRight(exec.taskTitle.substring(0, 28), 30) + (0, theme_1.dim)(padRight(progress, 14)) + (0, theme_1.dim)(time));
|
|
2420
2488
|
}
|
|
2421
2489
|
console.log();
|
|
2422
2490
|
}
|
|
@@ -2431,4 +2499,6 @@ if (!SKIP_DASHBOARD_CMDS.has(firstArg) && firstArg !== '' && !firstArg.startsWit
|
|
|
2431
2499
|
(0, dashboard_1.launchDashboard)(data_1.DEFAULT_PORT, true);
|
|
2432
2500
|
}
|
|
2433
2501
|
}
|
|
2502
|
+
// Kick off update check (non-blocking)
|
|
2503
|
+
checkForUpdates().catch(() => { });
|
|
2434
2504
|
program.parse(process.argv);
|