@claudecam/cli 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cam-hook.d.ts +8 -0
- package/dist/cam-hook.d.ts.map +1 -0
- package/dist/cam-hook.js +8 -0
- package/dist/cam-hook.js.map +1 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +218 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hooks.d.ts +3 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +106 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +576 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/progress.d.ts +3 -0
- package/dist/commands/progress.d.ts.map +1 -0
- package/dist/commands/progress.js +157 -0
- package/dist/commands/progress.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +203 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/sessions.d.ts +3 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +105 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/sprint.d.ts +3 -0
- package/dist/commands/sprint.d.ts.map +1 -0
- package/dist/commands/sprint.js +552 -0
- package/dist/commands/sprint.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +216 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +178 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tasks.d.ts +3 -0
- package/dist/commands/tasks.d.ts.map +1 -0
- package/dist/commands/tasks.js +176 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/commands/theme.d.ts +3 -0
- package/dist/commands/theme.d.ts.map +1 -0
- package/dist/commands/theme.js +63 -0
- package/dist/commands/theme.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config.d.ts +18 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +74 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/hooks-config.d.ts +28 -0
- package/dist/utils/hooks-config.d.ts.map +1 -0
- package/dist/utils/hooks-config.js +120 -0
- package/dist/utils/hooks-config.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +39 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sprint-parser.d.ts +32 -0
- package/dist/utils/sprint-parser.d.ts.map +1 -0
- package/dist/utils/sprint-parser.js +115 -0
- package/dist/utils/sprint-parser.js.map +1 -0
- package/package.json +47 -20
- package/index.js +0 -6
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { DEFAULT_SERVER_PORT } from '@claudecam/shared';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { readConfig, writeConfig } from '../utils/config.js';
|
|
6
|
+
const VALID_THEMES = ['pixel', 'modern', 'terminal'];
|
|
7
|
+
export const themeCommand = new Command('theme')
|
|
8
|
+
.description('Switch dashboard theme')
|
|
9
|
+
.argument('[name]', 'Theme name: pixel, modern, terminal')
|
|
10
|
+
.action(async (name) => {
|
|
11
|
+
logger.blank();
|
|
12
|
+
if (!name) {
|
|
13
|
+
// Show current theme and available themes
|
|
14
|
+
const config = readConfig();
|
|
15
|
+
logger.section('Dashboard Theme');
|
|
16
|
+
logger.blank();
|
|
17
|
+
logger.keyValue('Current', chalk.cyan(config.theme));
|
|
18
|
+
logger.blank();
|
|
19
|
+
logger.section('Available themes:');
|
|
20
|
+
for (const theme of VALID_THEMES) {
|
|
21
|
+
const marker = theme === config.theme ? chalk.green(' (active)') : '';
|
|
22
|
+
const description = getThemeDescription(theme);
|
|
23
|
+
logger.item(`${chalk.white(theme)}${marker} ${chalk.gray(`- ${description}`)}`);
|
|
24
|
+
}
|
|
25
|
+
logger.blank();
|
|
26
|
+
logger.info(`Usage: ${chalk.cyan('cam theme <name>')}`);
|
|
27
|
+
logger.blank();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!VALID_THEMES.includes(name)) {
|
|
31
|
+
logger.error(`Invalid theme: "${name}"`);
|
|
32
|
+
logger.info(`Valid themes: ${VALID_THEMES.map((t) => chalk.cyan(t)).join(', ')}`);
|
|
33
|
+
logger.blank();
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
writeConfig({ theme: name });
|
|
37
|
+
logger.success(`Theme set to ${chalk.cyan(name)}`);
|
|
38
|
+
// Try to notify the server about theme change
|
|
39
|
+
const config = readConfig();
|
|
40
|
+
try {
|
|
41
|
+
await fetch(`http://localhost:${config.serverPort || DEFAULT_SERVER_PORT}/api/config`, {
|
|
42
|
+
method: 'PATCH',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' },
|
|
44
|
+
body: JSON.stringify({ theme: name }),
|
|
45
|
+
});
|
|
46
|
+
logger.info('Dashboard will update automatically.');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
logger.info('Theme will be applied on next server start.');
|
|
50
|
+
}
|
|
51
|
+
logger.blank();
|
|
52
|
+
});
|
|
53
|
+
function getThemeDescription(theme) {
|
|
54
|
+
switch (theme) {
|
|
55
|
+
case 'pixel':
|
|
56
|
+
return 'Retro pixel art RPG style with sprites and animations';
|
|
57
|
+
case 'modern':
|
|
58
|
+
return 'Clean, minimal dashboard inspired by Linear/Vercel';
|
|
59
|
+
case 'terminal':
|
|
60
|
+
return 'Hacker-style terminal with keyboard navigation';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/commands/theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAG9D,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,wBAAwB,CAAC;KACrC,QAAQ,CAAC,QAAQ,EAAE,qCAAqC,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,IAAa,EAAE,EAAE;IAC9B,MAAM,CAAC,KAAK,EAAE,CAAC;IAEf,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,0CAA0C;QAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,WAAW,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAa,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,GAAG,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,iBAAiB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,WAAW,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7B,MAAM,CAAC,OAAO,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEnD,8CAA8C;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,oBAAoB,MAAM,CAAC,UAAU,IAAI,mBAAmB,aAAa,EAAE;YACrF,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SACtC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AAEL,SAAS,mBAAmB,CAAC,KAAY;IACvC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,uDAAuD,CAAC;QACjE,KAAK,QAAQ;YACX,OAAO,oDAAoD,CAAC;QAC9D,KAAK,UAAU;YACb,OAAO,gDAAgD,CAAC;IAC5D,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { initCommand } from "./commands/init.js";
|
|
4
|
+
import { startCommand } from "./commands/start.js";
|
|
5
|
+
import { statusCommand } from "./commands/status.js";
|
|
6
|
+
import { sessionsCommand } from "./commands/sessions.js";
|
|
7
|
+
import { hooksCommand } from "./commands/hooks.js";
|
|
8
|
+
import { themeCommand } from "./commands/theme.js";
|
|
9
|
+
import { projectCommand } from "./commands/project.js";
|
|
10
|
+
import { sprintCommand } from "./commands/sprint.js";
|
|
11
|
+
import { tasksCommand } from "./commands/tasks.js";
|
|
12
|
+
import { progressCommand } from "./commands/progress.js";
|
|
13
|
+
import { doctorCommand } from "./commands/doctor.js";
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name("cam")
|
|
17
|
+
.description("Claude Agent Monitor - Mission Control for Claude Code agents")
|
|
18
|
+
.version("1.0.0");
|
|
19
|
+
program.addCommand(initCommand);
|
|
20
|
+
program.addCommand(startCommand);
|
|
21
|
+
program.addCommand(statusCommand);
|
|
22
|
+
program.addCommand(sessionsCommand);
|
|
23
|
+
program.addCommand(hooksCommand);
|
|
24
|
+
program.addCommand(themeCommand);
|
|
25
|
+
program.addCommand(projectCommand);
|
|
26
|
+
program.addCommand(sprintCommand);
|
|
27
|
+
program.addCommand(tasksCommand);
|
|
28
|
+
program.addCommand(progressCommand);
|
|
29
|
+
program.addCommand(doctorCommand);
|
|
30
|
+
program.parse();
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,+DAA+D,CAAC;KAC5E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CamConfig {
|
|
2
|
+
serverPort: number;
|
|
3
|
+
dashboardPort: number;
|
|
4
|
+
theme: string;
|
|
5
|
+
activeProjectId?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function getProjectRoot(): string;
|
|
8
|
+
export declare function getClaudeDir(): string;
|
|
9
|
+
export declare function getClaudeSettingsPath(): string;
|
|
10
|
+
export declare function claudeSettingsExist(): boolean;
|
|
11
|
+
export declare function ensureClaudeDir(): void;
|
|
12
|
+
export declare function readClaudeSettings(): Record<string, unknown>;
|
|
13
|
+
export declare function writeClaudeSettings(settings: Record<string, unknown>): void;
|
|
14
|
+
export declare function getConfigPath(): string;
|
|
15
|
+
export declare function readConfig(): CamConfig;
|
|
16
|
+
export declare function writeConfig(config: Partial<CamConfig>): void;
|
|
17
|
+
export declare function resolveFilePath(filePath: string): string;
|
|
18
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAW5D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAI3E;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,IAAI,SAAS,CAmBtC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAK5D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { DEFAULT_SERVER_PORT, DEFAULT_DASHBOARD_PORT } from '@claudecam/shared';
|
|
4
|
+
const CONFIG_FILE_NAME = 'cam.config.json';
|
|
5
|
+
const CLAUDE_DIR = '.claude';
|
|
6
|
+
const CLAUDE_SETTINGS_FILE = 'settings.json';
|
|
7
|
+
export function getProjectRoot() {
|
|
8
|
+
return process.cwd();
|
|
9
|
+
}
|
|
10
|
+
export function getClaudeDir() {
|
|
11
|
+
return join(getProjectRoot(), CLAUDE_DIR);
|
|
12
|
+
}
|
|
13
|
+
export function getClaudeSettingsPath() {
|
|
14
|
+
return join(getClaudeDir(), CLAUDE_SETTINGS_FILE);
|
|
15
|
+
}
|
|
16
|
+
export function claudeSettingsExist() {
|
|
17
|
+
return existsSync(getClaudeSettingsPath());
|
|
18
|
+
}
|
|
19
|
+
export function ensureClaudeDir() {
|
|
20
|
+
const dir = getClaudeDir();
|
|
21
|
+
if (!existsSync(dir)) {
|
|
22
|
+
mkdirSync(dir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function readClaudeSettings() {
|
|
26
|
+
const settingsPath = getClaudeSettingsPath();
|
|
27
|
+
if (!existsSync(settingsPath)) {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const raw = readFileSync(settingsPath, 'utf-8');
|
|
32
|
+
return JSON.parse(raw);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function writeClaudeSettings(settings) {
|
|
39
|
+
ensureClaudeDir();
|
|
40
|
+
const settingsPath = getClaudeSettingsPath();
|
|
41
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
export function getConfigPath() {
|
|
44
|
+
return join(getProjectRoot(), CONFIG_FILE_NAME);
|
|
45
|
+
}
|
|
46
|
+
export function readConfig() {
|
|
47
|
+
const configPath = getConfigPath();
|
|
48
|
+
const defaults = {
|
|
49
|
+
serverPort: DEFAULT_SERVER_PORT,
|
|
50
|
+
dashboardPort: DEFAULT_DASHBOARD_PORT,
|
|
51
|
+
theme: 'modern',
|
|
52
|
+
};
|
|
53
|
+
if (!existsSync(configPath)) {
|
|
54
|
+
return defaults;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
return { ...defaults, ...parsed };
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return defaults;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function writeConfig(config) {
|
|
66
|
+
const current = readConfig();
|
|
67
|
+
const merged = { ...current, ...config };
|
|
68
|
+
const configPath = getConfigPath();
|
|
69
|
+
writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
export function resolveFilePath(filePath) {
|
|
72
|
+
return resolve(getProjectRoot(), filePath);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface HookHandler {
|
|
2
|
+
type: "command";
|
|
3
|
+
command: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface HookEntry {
|
|
7
|
+
matcher?: string;
|
|
8
|
+
hooks: HookHandler[];
|
|
9
|
+
}
|
|
10
|
+
export interface HooksConfig {
|
|
11
|
+
PreToolUse: HookEntry[];
|
|
12
|
+
PostToolUse: HookEntry[];
|
|
13
|
+
Notification: HookEntry[];
|
|
14
|
+
Stop: HookEntry[];
|
|
15
|
+
SubagentStop: HookEntry[];
|
|
16
|
+
PreCompact: HookEntry[];
|
|
17
|
+
PostCompact: HookEntry[];
|
|
18
|
+
}
|
|
19
|
+
export declare function generateHooksConfig(): HooksConfig;
|
|
20
|
+
export declare function mergeHooks(existing: Record<string, unknown>, camHooks: HooksConfig): Record<string, unknown>;
|
|
21
|
+
export declare function removeCamHooks(settings: Record<string, unknown>): Record<string, unknown>;
|
|
22
|
+
export declare function isCamHook(entry: HookEntry): boolean;
|
|
23
|
+
export declare function listConfiguredCamHooks(settings: Record<string, unknown>): Array<{
|
|
24
|
+
hookType: string;
|
|
25
|
+
command: string;
|
|
26
|
+
}>;
|
|
27
|
+
export declare const HOOK_TYPE_DESCRIPTIONS: Record<string, string>;
|
|
28
|
+
//# sourceMappingURL=hooks-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-config.d.ts","sourceRoot":"","sources":["../../src/utils/hooks-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,WAAW,EAAE,SAAS,EAAE,CAAC;CAC1B;AAID,wBAAgB,mBAAmB,IAAI,WAAW,CAyCjD;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,WAAW,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBzB;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmBzB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAanD;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB9C;AAED,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQzD,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const CAM_HOOK_MARKER = "cam-hook";
|
|
2
|
+
export function generateHooksConfig() {
|
|
3
|
+
return {
|
|
4
|
+
PreToolUse: [
|
|
5
|
+
{
|
|
6
|
+
matcher: "*",
|
|
7
|
+
hooks: [{ type: "command", command: "cam-hook pre-tool-use" }],
|
|
8
|
+
},
|
|
9
|
+
],
|
|
10
|
+
PostToolUse: [
|
|
11
|
+
{
|
|
12
|
+
matcher: "*",
|
|
13
|
+
hooks: [{ type: "command", command: "cam-hook post-tool-use" }],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
Notification: [
|
|
17
|
+
{
|
|
18
|
+
matcher: "*",
|
|
19
|
+
hooks: [{ type: "command", command: "cam-hook notification" }],
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
Stop: [
|
|
23
|
+
{
|
|
24
|
+
hooks: [{ type: "command", command: "cam-hook stop" }],
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
SubagentStop: [
|
|
28
|
+
{
|
|
29
|
+
hooks: [{ type: "command", command: "cam-hook subagent-stop" }],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
PreCompact: [
|
|
33
|
+
{
|
|
34
|
+
hooks: [{ type: "command", command: "cam-hook pre-compact" }],
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
PostCompact: [
|
|
38
|
+
{
|
|
39
|
+
hooks: [{ type: "command", command: "cam-hook post-compact" }],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function mergeHooks(existing, camHooks) {
|
|
45
|
+
const existingHooks = (existing.hooks ?? {});
|
|
46
|
+
const merged = {};
|
|
47
|
+
for (const [hookType, entries] of Object.entries(camHooks)) {
|
|
48
|
+
const existingEntries = existingHooks[hookType] ?? [];
|
|
49
|
+
// Filter out any existing CAM hooks to avoid duplicates
|
|
50
|
+
const nonCamEntries = existingEntries.filter((entry) => !isCamHook(entry));
|
|
51
|
+
// Append CAM hooks at the end
|
|
52
|
+
merged[hookType] = [...nonCamEntries, ...entries];
|
|
53
|
+
}
|
|
54
|
+
// Preserve hook types not managed by CAM
|
|
55
|
+
for (const [hookType, entries] of Object.entries(existingHooks)) {
|
|
56
|
+
if (!(hookType in camHooks)) {
|
|
57
|
+
merged[hookType] = entries;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
...existing,
|
|
62
|
+
hooks: merged,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function removeCamHooks(settings) {
|
|
66
|
+
const hooks = (settings.hooks ?? {});
|
|
67
|
+
const cleaned = {};
|
|
68
|
+
for (const [hookType, entries] of Object.entries(hooks)) {
|
|
69
|
+
const nonCamEntries = entries.filter((entry) => !isCamHook(entry));
|
|
70
|
+
if (nonCamEntries.length > 0) {
|
|
71
|
+
cleaned[hookType] = nonCamEntries;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const result = { ...settings };
|
|
75
|
+
if (Object.keys(cleaned).length > 0) {
|
|
76
|
+
result.hooks = cleaned;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
delete result.hooks;
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
export function isCamHook(entry) {
|
|
84
|
+
// Check new format: hooks array with command containing marker
|
|
85
|
+
if (entry.hooks && Array.isArray(entry.hooks)) {
|
|
86
|
+
return entry.hooks.some((h) => h.type === "command" && h.command.includes(CAM_HOOK_MARKER));
|
|
87
|
+
}
|
|
88
|
+
// Legacy format fallback: direct command field
|
|
89
|
+
const legacy = entry;
|
|
90
|
+
if (typeof legacy["command"] === "string") {
|
|
91
|
+
return legacy["command"].includes(CAM_HOOK_MARKER);
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
export function listConfiguredCamHooks(settings) {
|
|
96
|
+
const hooks = (settings.hooks ?? {});
|
|
97
|
+
const result = [];
|
|
98
|
+
for (const [hookType, entries] of Object.entries(hooks)) {
|
|
99
|
+
for (const entry of entries) {
|
|
100
|
+
if (isCamHook(entry)) {
|
|
101
|
+
// Extract command from hooks array
|
|
102
|
+
const cmd = entry.hooks?.find((h) => h.type === "command" && h.command.includes(CAM_HOOK_MARKER));
|
|
103
|
+
if (cmd) {
|
|
104
|
+
result.push({ hookType, command: cmd.command });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
export const HOOK_TYPE_DESCRIPTIONS = {
|
|
112
|
+
PreToolUse: "Before each tool call (all tools)",
|
|
113
|
+
PostToolUse: "After each tool call (all tools)",
|
|
114
|
+
Notification: "When Claude Code sends a notification",
|
|
115
|
+
Stop: "When the main agent stops",
|
|
116
|
+
SubagentStop: "When a sub-agent (teammate) stops",
|
|
117
|
+
PreCompact: "Before context compaction",
|
|
118
|
+
PostCompact: "After context compaction",
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=hooks-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-config.js","sourceRoot":"","sources":["../../src/utils/hooks-config.ts"],"names":[],"mappings":"AAqBA,MAAM,eAAe,GAAG,UAAU,CAAC;AAEnC,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,UAAU,EAAE;YACV;gBACE,OAAO,EAAE,GAAG;gBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;aAC/D;SACF;QACD,WAAW,EAAE;YACX;gBACE,OAAO,EAAE,GAAG;gBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;aAChE;SACF;QACD,YAAY,EAAE;YACZ;gBACE,OAAO,EAAE,GAAG;gBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;aAC/D;SACF;QACD,IAAI,EAAE;YACJ;gBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;aACvD;SACF;QACD,YAAY,EAAE;YACZ;gBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;aAChE;SACF;QACD,UAAU,EAAE;YACV;gBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;aAC9D;SACF;QACD,WAAW,EAAE;YACX;gBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;aAC/D;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,QAAiC,EACjC,QAAqB;IAErB,MAAM,aAAa,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAgC,CAAC;IAC5E,MAAM,MAAM,GAAgC,EAAE,CAAC;IAE/C,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,MAAM,eAAe,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEtD,wDAAwD;QACxD,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAE3E,8BAA8B;QAC9B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE,MAAM;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,QAAiC;IAEjC,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAgC,CAAC;IACpE,MAAM,OAAO,GAAgC,EAAE,CAAC;IAEhD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC;QACpC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC/B,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAgB;IACxC,+DAA+D;IAC/D,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CACnE,CAAC;IACJ,CAAC;IACD,+CAA+C;IAC/C,MAAM,MAAM,GAAG,KAA0C,CAAC;IAC1D,IAAI,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAAiC;IAEjC,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAgC,CAAC;IACpE,MAAM,MAAM,GAAiD,EAAE,CAAC;IAEhE,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrB,mCAAmC;gBACnC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,CAC3B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CACnE,CAAC;gBACF,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAA2B;IAC5D,UAAU,EAAE,mCAAmC;IAC/C,WAAW,EAAE,kCAAkC;IAC/C,YAAY,EAAE,uCAAuC;IACrD,IAAI,EAAE,2BAA2B;IACjC,YAAY,EAAE,mCAAmC;IACjD,UAAU,EAAE,2BAA2B;IACvC,WAAW,EAAE,0BAA0B;CACxC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
info(message: string): void;
|
|
3
|
+
success(message: string): void;
|
|
4
|
+
warning(message: string): void;
|
|
5
|
+
error(message: string): void;
|
|
6
|
+
item(message: string): void;
|
|
7
|
+
blank(): void;
|
|
8
|
+
banner(): void;
|
|
9
|
+
section(title: string): void;
|
|
10
|
+
keyValue(key: string, value: string): void;
|
|
11
|
+
table(rows: Array<{
|
|
12
|
+
label: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}>): void;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;kBACH,MAAM,GAAG,IAAI;qBAIV,MAAM,GAAG,IAAI;qBAIb,MAAM,GAAG,IAAI;mBAIf,MAAM,GAAG,IAAI;kBAId,MAAM,GAAG,IAAI;aAIlB,IAAI;cAIH,IAAI;mBAMC,MAAM,GAAG,IAAI;kBAId,MAAM,SAAS,MAAM,GAAG,IAAI;gBAI9B,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;CAM3D,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const logger = {
|
|
3
|
+
info(message) {
|
|
4
|
+
console.log(chalk.blue(' info'), message);
|
|
5
|
+
},
|
|
6
|
+
success(message) {
|
|
7
|
+
console.log(chalk.green(' done'), message);
|
|
8
|
+
},
|
|
9
|
+
warning(message) {
|
|
10
|
+
console.log(chalk.yellow(' warn'), message);
|
|
11
|
+
},
|
|
12
|
+
error(message) {
|
|
13
|
+
console.error(chalk.red(' error'), message);
|
|
14
|
+
},
|
|
15
|
+
item(message) {
|
|
16
|
+
console.log(chalk.gray(' -'), message);
|
|
17
|
+
},
|
|
18
|
+
blank() {
|
|
19
|
+
console.log();
|
|
20
|
+
},
|
|
21
|
+
banner() {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(chalk.bold.cyan(' Claude Agent Monitor') + chalk.gray(' v1.0.0'));
|
|
24
|
+
console.log();
|
|
25
|
+
},
|
|
26
|
+
section(title) {
|
|
27
|
+
console.log(chalk.bold(` ${title}`));
|
|
28
|
+
},
|
|
29
|
+
keyValue(key, value) {
|
|
30
|
+
console.log(` ${chalk.gray(key + ':')} ${value}`);
|
|
31
|
+
},
|
|
32
|
+
table(rows) {
|
|
33
|
+
const maxLabel = Math.max(...rows.map((r) => r.label.length));
|
|
34
|
+
for (const row of rows) {
|
|
35
|
+
console.log(` ${chalk.gray(row.label.padEnd(maxLabel))} ${row.value}`);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,CAAC,OAAe;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,CAAC,OAAe;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,OAAe;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAe;QACnB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK;QACH,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,MAAM;QACJ,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,KAAa;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,GAAW,EAAE,KAAa;QACjC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,IAA6C;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint Markdown Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses sprint markdown files in the format:
|
|
5
|
+
*
|
|
6
|
+
* # Sprint X - Name
|
|
7
|
+
* Status: completed | active | planned
|
|
8
|
+
*
|
|
9
|
+
* ## Section Name
|
|
10
|
+
* - [x] Task title (completed)
|
|
11
|
+
* - [ ] Task title (planned)
|
|
12
|
+
* Priority: high | medium | low
|
|
13
|
+
* Tags: tag1, tag2
|
|
14
|
+
* Description: Brief description
|
|
15
|
+
*/
|
|
16
|
+
export interface ParsedSprintTask {
|
|
17
|
+
title: string;
|
|
18
|
+
completed: boolean;
|
|
19
|
+
priority: string;
|
|
20
|
+
tags: string[];
|
|
21
|
+
description: string;
|
|
22
|
+
files: string[];
|
|
23
|
+
section: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ParsedSprint {
|
|
26
|
+
name: string;
|
|
27
|
+
status: string;
|
|
28
|
+
sections: string[];
|
|
29
|
+
tasks: ParsedSprintTask[];
|
|
30
|
+
}
|
|
31
|
+
export declare function parseSprintMarkdown(content: string): ParsedSprint;
|
|
32
|
+
//# sourceMappingURL=sprint-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprint-parser.d.ts","sourceRoot":"","sources":["../../src/utils/sprint-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA6GjE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint Markdown Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses sprint markdown files in the format:
|
|
5
|
+
*
|
|
6
|
+
* # Sprint X - Name
|
|
7
|
+
* Status: completed | active | planned
|
|
8
|
+
*
|
|
9
|
+
* ## Section Name
|
|
10
|
+
* - [x] Task title (completed)
|
|
11
|
+
* - [ ] Task title (planned)
|
|
12
|
+
* Priority: high | medium | low
|
|
13
|
+
* Tags: tag1, tag2
|
|
14
|
+
* Description: Brief description
|
|
15
|
+
*/
|
|
16
|
+
const VALID_STATUSES = ['completed', 'active', 'planned'];
|
|
17
|
+
const VALID_PRIORITIES = ['critical', 'high', 'medium', 'low'];
|
|
18
|
+
export function parseSprintMarkdown(content) {
|
|
19
|
+
const lines = content.split('\n');
|
|
20
|
+
let name = '';
|
|
21
|
+
let status = 'planned';
|
|
22
|
+
let currentSection = '';
|
|
23
|
+
const sections = [];
|
|
24
|
+
const tasks = [];
|
|
25
|
+
let currentTask = null;
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
const trimmed = line.trim();
|
|
28
|
+
// Parse sprint title: # Sprint X - Name
|
|
29
|
+
const titleMatch = trimmed.match(/^#\s+(.+)$/);
|
|
30
|
+
if (titleMatch && !trimmed.startsWith('##')) {
|
|
31
|
+
name = titleMatch[1].trim();
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// Parse status line: Status: completed | active | planned
|
|
35
|
+
const statusMatch = trimmed.match(/^Status:\s*(.+)$/i);
|
|
36
|
+
if (statusMatch) {
|
|
37
|
+
const parsed = statusMatch[1].trim().toLowerCase();
|
|
38
|
+
if (VALID_STATUSES.includes(parsed)) {
|
|
39
|
+
status = parsed;
|
|
40
|
+
}
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Parse section heading: ## Section Name
|
|
44
|
+
const sectionMatch = trimmed.match(/^##\s+(.+)$/);
|
|
45
|
+
if (sectionMatch) {
|
|
46
|
+
// Save any pending task
|
|
47
|
+
if (currentTask) {
|
|
48
|
+
tasks.push(currentTask);
|
|
49
|
+
currentTask = null;
|
|
50
|
+
}
|
|
51
|
+
currentSection = sectionMatch[1].trim();
|
|
52
|
+
if (!sections.includes(currentSection)) {
|
|
53
|
+
sections.push(currentSection);
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// Parse task line: - [x] Task title OR - [ ] Task title
|
|
58
|
+
const taskMatch = trimmed.match(/^-\s+\[([ xX])\]\s+(.+)$/);
|
|
59
|
+
if (taskMatch) {
|
|
60
|
+
// Save any pending task
|
|
61
|
+
if (currentTask) {
|
|
62
|
+
tasks.push(currentTask);
|
|
63
|
+
}
|
|
64
|
+
const completed = taskMatch[1].toLowerCase() === 'x';
|
|
65
|
+
currentTask = {
|
|
66
|
+
title: taskMatch[2].trim(),
|
|
67
|
+
completed,
|
|
68
|
+
priority: 'medium',
|
|
69
|
+
tags: [],
|
|
70
|
+
description: '',
|
|
71
|
+
files: [],
|
|
72
|
+
section: currentSection,
|
|
73
|
+
};
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Parse task metadata (indented lines after a task)
|
|
77
|
+
if (currentTask) {
|
|
78
|
+
const priorityMatch = trimmed.match(/^Priority:\s*(.+)$/i);
|
|
79
|
+
if (priorityMatch) {
|
|
80
|
+
const p = priorityMatch[1].trim().toLowerCase();
|
|
81
|
+
if (VALID_PRIORITIES.includes(p)) {
|
|
82
|
+
currentTask.priority = p;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const tagsMatch = trimmed.match(/^Tags:\s*(.+)$/i);
|
|
87
|
+
if (tagsMatch) {
|
|
88
|
+
currentTask.tags = tagsMatch[1]
|
|
89
|
+
.split(',')
|
|
90
|
+
.map((t) => t.trim())
|
|
91
|
+
.filter((t) => t.length > 0);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const descMatch = trimmed.match(/^Description:\s*(.+)$/i);
|
|
95
|
+
if (descMatch) {
|
|
96
|
+
currentTask.description = descMatch[1].trim();
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const filesMatch = trimmed.match(/^Files:\s*(.+)$/i);
|
|
100
|
+
if (filesMatch) {
|
|
101
|
+
currentTask.files = filesMatch[1]
|
|
102
|
+
.split(',')
|
|
103
|
+
.map((f) => f.trim())
|
|
104
|
+
.filter((f) => f.length > 0);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Save final pending task
|
|
110
|
+
if (currentTask) {
|
|
111
|
+
tasks.push(currentTask);
|
|
112
|
+
}
|
|
113
|
+
return { name, status, sections, tasks };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=sprint-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprint-parser.js","sourceRoot":"","sources":["../../src/utils/sprint-parser.ts"],"names":[],"mappings":"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"}
|