@braingrid/cli 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -0
- package/dist/.build-info.json +9 -0
- package/dist/build-config.d.ts +25 -0
- package/dist/build-config.d.ts.map +1 -0
- package/dist/build-config.js +27 -0
- package/dist/build-config.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +246 -0
- package/dist/cli.js.map +1 -0
- package/dist/handlers/auth.handlers.d.ts +13 -0
- package/dist/handlers/auth.handlers.d.ts.map +1 -0
- package/dist/handlers/auth.handlers.js +99 -0
- package/dist/handlers/auth.handlers.js.map +1 -0
- package/dist/handlers/index.d.ts +11 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +11 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/project.handlers.d.ts +29 -0
- package/dist/handlers/project.handlers.d.ts.map +1 -0
- package/dist/handlers/project.handlers.js +200 -0
- package/dist/handlers/project.handlers.js.map +1 -0
- package/dist/handlers/requirement.handlers.d.ts +32 -0
- package/dist/handlers/requirement.handlers.d.ts.map +1 -0
- package/dist/handlers/requirement.handlers.js +234 -0
- package/dist/handlers/requirement.handlers.js.map +1 -0
- package/dist/handlers/status.handlers.d.ts +12 -0
- package/dist/handlers/status.handlers.d.ts.map +1 -0
- package/dist/handlers/status.handlers.js +209 -0
- package/dist/handlers/status.handlers.js.map +1 -0
- package/dist/handlers/task.handlers.d.ts +29 -0
- package/dist/handlers/task.handlers.d.ts.map +1 -0
- package/dist/handlers/task.handlers.js +272 -0
- package/dist/handlers/task.handlers.js.map +1 -0
- package/dist/handlers/types.d.ts +10 -0
- package/dist/handlers/types.d.ts.map +1 -0
- package/dist/handlers/types.js +5 -0
- package/dist/handlers/types.js.map +1 -0
- package/dist/services/auth.d.ts +41 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +498 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/services/claude.d.ts +18 -0
- package/dist/services/claude.d.ts.map +1 -0
- package/dist/services/claude.js +164 -0
- package/dist/services/claude.js.map +1 -0
- package/dist/services/context-manager.d.ts +170 -0
- package/dist/services/context-manager.d.ts.map +1 -0
- package/dist/services/context-manager.js +261 -0
- package/dist/services/context-manager.js.map +1 -0
- package/dist/services/credential-store.d.ts +47 -0
- package/dist/services/credential-store.d.ts.map +1 -0
- package/dist/services/credential-store.js +88 -0
- package/dist/services/credential-store.js.map +1 -0
- package/dist/services/oauth2-auth.d.ts +60 -0
- package/dist/services/oauth2-auth.d.ts.map +1 -0
- package/dist/services/oauth2-auth.js +377 -0
- package/dist/services/oauth2-auth.js.map +1 -0
- package/dist/services/project-service.d.ts +22 -0
- package/dist/services/project-service.d.ts.map +1 -0
- package/dist/services/project-service.js +52 -0
- package/dist/services/project-service.js.map +1 -0
- package/dist/services/requirement-service.d.ts +32 -0
- package/dist/services/requirement-service.d.ts.map +1 -0
- package/dist/services/requirement-service.js +91 -0
- package/dist/services/requirement-service.js.map +1 -0
- package/dist/services/task-service.d.ts +22 -0
- package/dist/services/task-service.d.ts.map +1 -0
- package/dist/services/task-service.js +52 -0
- package/dist/services/task-service.js.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +40 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/types/api.d.ts +16 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +5 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/auth.d.ts +68 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +2 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/claude.d.ts +22 -0
- package/dist/types/claude.d.ts.map +1 -0
- package/dist/types/claude.js +2 -0
- package/dist/types/claude.js.map +1 -0
- package/dist/types/project.d.ts +32 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +5 -0
- package/dist/types/project.js.map +1 -0
- package/dist/types/requirement.d.ts +69 -0
- package/dist/types/requirement.d.ts.map +1 -0
- package/dist/types/requirement.js +5 -0
- package/dist/types/requirement.js.map +1 -0
- package/dist/types/task.d.ts +44 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +5 -0
- package/dist/types/task.js.map +1 -0
- package/dist/utils/axios-retry.d.ts +25 -0
- package/dist/utils/axios-retry.d.ts.map +1 -0
- package/dist/utils/axios-retry.js +174 -0
- package/dist/utils/axios-retry.js.map +1 -0
- package/dist/utils/axios-with-auth.d.ts +10 -0
- package/dist/utils/axios-with-auth.d.ts.map +1 -0
- package/dist/utils/axios-with-auth.js +118 -0
- package/dist/utils/axios-with-auth.js.map +1 -0
- package/dist/utils/cli-tools.d.ts +30 -0
- package/dist/utils/cli-tools.d.ts.map +1 -0
- package/dist/utils/cli-tools.js +131 -0
- package/dist/utils/cli-tools.js.map +1 -0
- package/dist/utils/command-execution.d.ts +30 -0
- package/dist/utils/command-execution.d.ts.map +1 -0
- package/dist/utils/command-execution.js +264 -0
- package/dist/utils/command-execution.js.map +1 -0
- package/dist/utils/command-parser.d.ts +85 -0
- package/dist/utils/command-parser.d.ts.map +1 -0
- package/dist/utils/command-parser.js +287 -0
- package/dist/utils/command-parser.js.map +1 -0
- package/dist/utils/config.d.ts +9 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +59 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/error-formatter.d.ts +17 -0
- package/dist/utils/error-formatter.d.ts.map +1 -0
- package/dist/utils/error-formatter.js +115 -0
- package/dist/utils/error-formatter.js.map +1 -0
- package/dist/utils/formatting.d.ts +10 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/formatting.js +122 -0
- package/dist/utils/formatting.js.map +1 -0
- package/dist/utils/git.d.ts +55 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +131 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/jwt.d.ts +45 -0
- package/dist/utils/jwt.d.ts.map +1 -0
- package/dist/utils/jwt.js +64 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +176 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/requirements.d.ts +28 -0
- package/dist/utils/requirements.d.ts.map +1 -0
- package/dist/utils/requirements.js +54 -0
- package/dist/utils/requirements.js.map +1 -0
- package/dist/utils/status-parser.d.ts +95 -0
- package/dist/utils/status-parser.d.ts.map +1 -0
- package/dist/utils/status-parser.js +189 -0
- package/dist/utils/status-parser.js.map +1 -0
- package/dist/utils/tasks.d.ts +9 -0
- package/dist/utils/tasks.d.ts.map +1 -0
- package/dist/utils/tasks.js +38 -0
- package/dist/utils/tasks.js.map +1 -0
- package/package.json +101 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT utility functions
|
|
3
|
+
* Note: This is basic JWT decoding without signature verification
|
|
4
|
+
* The server validates the token signature when we make API calls
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Decode a JWT token to extract the payload
|
|
8
|
+
* Note: This does NOT verify the signature - that's the server's job
|
|
9
|
+
*/
|
|
10
|
+
export function decodeJWT(token) {
|
|
11
|
+
try {
|
|
12
|
+
// JWT format: header.payload.signature
|
|
13
|
+
const parts = token.split('.');
|
|
14
|
+
if (parts.length !== 3) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
// Decode the payload (base64url)
|
|
18
|
+
const payload = parts[1];
|
|
19
|
+
// Replace URL-safe characters with standard base64 characters
|
|
20
|
+
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
|
|
21
|
+
// Add padding if necessary
|
|
22
|
+
const padded = base64 + '=='.substring(0, (4 - (base64.length % 4)) % 4);
|
|
23
|
+
const decoded = Buffer.from(padded, 'base64').toString('utf-8');
|
|
24
|
+
return JSON.parse(decoded);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Invalid token format or JSON
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if a JWT token is expired
|
|
33
|
+
*/
|
|
34
|
+
export function isJWTExpired(token) {
|
|
35
|
+
const payload = decodeJWT(token);
|
|
36
|
+
if (!payload || !payload.exp) {
|
|
37
|
+
// If we can't decode or no expiry, assume it's invalid
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// exp is in seconds, Date.now() is in milliseconds
|
|
41
|
+
return Date.now() >= payload.exp * 1000;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract user information from JWT payload
|
|
45
|
+
*/
|
|
46
|
+
export function extractUserFromJWT(payload) {
|
|
47
|
+
return {
|
|
48
|
+
id: payload.sub || '',
|
|
49
|
+
email: payload.email || '',
|
|
50
|
+
// Try different naming conventions for first name
|
|
51
|
+
firstName: payload.firstName ||
|
|
52
|
+
payload.first_name ||
|
|
53
|
+
payload.given_name ||
|
|
54
|
+
(payload.name ? payload.name.split(' ')[0] : ''),
|
|
55
|
+
// Try different naming conventions for last name
|
|
56
|
+
lastName: payload.lastName ||
|
|
57
|
+
payload.last_name ||
|
|
58
|
+
payload.family_name ||
|
|
59
|
+
(payload.name ? payload.name.split(' ').slice(1).join(' ') : ''),
|
|
60
|
+
// Try different naming conventions for organization
|
|
61
|
+
organizationId: payload.organizationId || payload.organization_id || payload.org || 'default',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACtC,IAAI,CAAC;QACJ,uCAAuC;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,iCAAiC;QACjC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,8DAA8D;QAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC7D,2BAA2B;QAC3B,MAAM,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACR,+BAA+B;QAC/B,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC9B,uDAAuD;QACvD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,mDAAmD;IACnD,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAmB;IAOrD,OAAO;QACN,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;QACrB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,kDAAkD;QAClD,SAAS,EACR,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,UAAU;YAClB,OAAO,CAAC,UAAU;YAClB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,iDAAiD;QACjD,QAAQ,EACP,OAAO,CAAC,QAAQ;YAChB,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,WAAW;YACnB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,oDAAoD;QACpD,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,IAAI,SAAS;KAC7F,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
+
export type MessageType = 'user' | 'system' | 'error' | 'info' | 'debug';
|
|
3
|
+
interface LoggerConfig {
|
|
4
|
+
logToFile: boolean;
|
|
5
|
+
logLevel: LogLevel;
|
|
6
|
+
logFilePath?: string;
|
|
7
|
+
maxFileSize: number;
|
|
8
|
+
maxFiles: number;
|
|
9
|
+
consoleOutput: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare class Logger {
|
|
12
|
+
private config;
|
|
13
|
+
private logFilePath;
|
|
14
|
+
constructor(config?: Partial<LoggerConfig>);
|
|
15
|
+
private ensureLogDirectory;
|
|
16
|
+
private shouldLog;
|
|
17
|
+
private formatLogEntry;
|
|
18
|
+
private writeToFile;
|
|
19
|
+
private rotateLogFile;
|
|
20
|
+
private log;
|
|
21
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
22
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
23
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
24
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
25
|
+
userMessage(message: string, context?: Record<string, unknown>): void;
|
|
26
|
+
systemMessage(message: string, context?: Record<string, unknown>): void;
|
|
27
|
+
streamOutput(message: string, isError?: boolean): void;
|
|
28
|
+
updateConfig(newConfig: Partial<LoggerConfig>): void;
|
|
29
|
+
getLogFilePath(): string;
|
|
30
|
+
getLogFileSize(): number;
|
|
31
|
+
clearLogFile(): void;
|
|
32
|
+
}
|
|
33
|
+
export declare function getLogger(config?: Partial<LoggerConfig>): Logger;
|
|
34
|
+
export declare function initializeLogger(config: Partial<LoggerConfig>): Logger;
|
|
35
|
+
export { Logger };
|
|
36
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAUzE,UAAU,YAAY;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,cAAM,MAAM;IACX,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAmB9C,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,GAAG;IA2BX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIrE,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKvE,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,IAAI;IAKpD,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAapD,cAAc,IAAI,MAAM;IAKxB,cAAc,IAAI,MAAM;IAaxB,YAAY,IAAI,IAAI;CAUpB;AAKD,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAKhE;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAGtE;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
class Logger {
|
|
5
|
+
constructor(config = {}) {
|
|
6
|
+
const isDebugMode = process.env.DEBUG === 'true';
|
|
7
|
+
this.config = {
|
|
8
|
+
logToFile: false,
|
|
9
|
+
logLevel: isDebugMode ? 'debug' : 'info', // Set log level to debug when DEBUG=true
|
|
10
|
+
maxFileSize: 10 * 1024 * 1024, // 10MB
|
|
11
|
+
maxFiles: 5,
|
|
12
|
+
consoleOutput: isDebugMode, // Enable console output when DEBUG=true
|
|
13
|
+
...config,
|
|
14
|
+
};
|
|
15
|
+
this.logFilePath =
|
|
16
|
+
this.config.logFilePath || path.join(os.homedir(), '.braingrid', 'logs', 'braingrid-cli.log');
|
|
17
|
+
if (this.config.logToFile) {
|
|
18
|
+
this.ensureLogDirectory();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
ensureLogDirectory() {
|
|
22
|
+
const logDir = path.dirname(this.logFilePath);
|
|
23
|
+
if (!fs.existsSync(logDir)) {
|
|
24
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
shouldLog(level) {
|
|
28
|
+
const levels = ['debug', 'info', 'warn', 'error'];
|
|
29
|
+
return levels.indexOf(level) >= levels.indexOf(this.config.logLevel);
|
|
30
|
+
}
|
|
31
|
+
formatLogEntry(entry) {
|
|
32
|
+
const timestamp = entry.timestamp.toISOString();
|
|
33
|
+
const level = entry.level.toUpperCase().padEnd(5);
|
|
34
|
+
const type = entry.type.toUpperCase().padEnd(7);
|
|
35
|
+
const contextStr = entry.context ? ` | ${JSON.stringify(entry.context)}` : '';
|
|
36
|
+
return `[${timestamp}] ${level} [${type}] ${entry.message}${contextStr}`;
|
|
37
|
+
}
|
|
38
|
+
writeToFile(entry) {
|
|
39
|
+
if (!this.config.logToFile)
|
|
40
|
+
return;
|
|
41
|
+
try {
|
|
42
|
+
const logLine = this.formatLogEntry(entry) + '\n';
|
|
43
|
+
// Check file size and rotate if necessary
|
|
44
|
+
if (fs.existsSync(this.logFilePath)) {
|
|
45
|
+
const stats = fs.statSync(this.logFilePath);
|
|
46
|
+
if (stats.size > this.config.maxFileSize) {
|
|
47
|
+
this.rotateLogFile();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
fs.appendFileSync(this.logFilePath, logLine);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error('Failed to write to log file:', error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
rotateLogFile() {
|
|
57
|
+
try {
|
|
58
|
+
// Rotate log files
|
|
59
|
+
for (let i = this.config.maxFiles - 1; i >= 1; i--) {
|
|
60
|
+
const oldFile = `${this.logFilePath}.${i}`;
|
|
61
|
+
const newFile = `${this.logFilePath}.${i + 1}`;
|
|
62
|
+
if (fs.existsSync(oldFile)) {
|
|
63
|
+
if (i === this.config.maxFiles - 1) {
|
|
64
|
+
fs.unlinkSync(oldFile); // Delete oldest file
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
fs.renameSync(oldFile, newFile);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Move current log to .1
|
|
72
|
+
if (fs.existsSync(this.logFilePath)) {
|
|
73
|
+
fs.renameSync(this.logFilePath, `${this.logFilePath}.1`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('Failed to rotate log file:', error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
log(level, type, message, context) {
|
|
81
|
+
if (!this.shouldLog(level))
|
|
82
|
+
return;
|
|
83
|
+
const entry = {
|
|
84
|
+
timestamp: new Date(),
|
|
85
|
+
level,
|
|
86
|
+
type,
|
|
87
|
+
message,
|
|
88
|
+
context,
|
|
89
|
+
};
|
|
90
|
+
// Write to file if enabled
|
|
91
|
+
this.writeToFile(entry);
|
|
92
|
+
// Write to console if enabled and it's a debug message
|
|
93
|
+
if (this.config.consoleOutput && level === 'debug') {
|
|
94
|
+
const contextStr = context ? ` ${JSON.stringify(context)}` : '';
|
|
95
|
+
// Write to stderr so it doesn't interfere with CLI output
|
|
96
|
+
console.error(`${message}${contextStr}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
debug(message, context) {
|
|
100
|
+
this.log('debug', 'debug', message, context);
|
|
101
|
+
}
|
|
102
|
+
info(message, context) {
|
|
103
|
+
this.log('info', 'info', message, context);
|
|
104
|
+
}
|
|
105
|
+
warn(message, context) {
|
|
106
|
+
this.log('warn', 'info', message, context);
|
|
107
|
+
}
|
|
108
|
+
error(message, context) {
|
|
109
|
+
this.log('error', 'error', message, context);
|
|
110
|
+
}
|
|
111
|
+
userMessage(message, context) {
|
|
112
|
+
this.log('info', 'user', message, context);
|
|
113
|
+
}
|
|
114
|
+
systemMessage(message, context) {
|
|
115
|
+
this.log('info', 'system', message, context);
|
|
116
|
+
}
|
|
117
|
+
// Log streaming output with full content
|
|
118
|
+
streamOutput(message, isError = false) {
|
|
119
|
+
this.log(isError ? 'error' : 'info', isError ? 'error' : 'system', message);
|
|
120
|
+
}
|
|
121
|
+
// Update configuration
|
|
122
|
+
updateConfig(newConfig) {
|
|
123
|
+
const wasLoggingToFile = this.config.logToFile;
|
|
124
|
+
this.config = { ...this.config, ...newConfig };
|
|
125
|
+
if (this.config.logToFile && !wasLoggingToFile) {
|
|
126
|
+
this.ensureLogDirectory();
|
|
127
|
+
this.info('File logging enabled', { logFilePath: this.logFilePath });
|
|
128
|
+
}
|
|
129
|
+
else if (!this.config.logToFile && wasLoggingToFile) {
|
|
130
|
+
this.info('File logging disabled');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Get current log file path
|
|
134
|
+
getLogFilePath() {
|
|
135
|
+
return this.logFilePath;
|
|
136
|
+
}
|
|
137
|
+
// Get log file size in MB
|
|
138
|
+
getLogFileSize() {
|
|
139
|
+
try {
|
|
140
|
+
if (fs.existsSync(this.logFilePath)) {
|
|
141
|
+
const stats = fs.statSync(this.logFilePath);
|
|
142
|
+
return stats.size / (1024 * 1024);
|
|
143
|
+
}
|
|
144
|
+
return 0;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Clear log file
|
|
151
|
+
clearLogFile() {
|
|
152
|
+
try {
|
|
153
|
+
if (fs.existsSync(this.logFilePath)) {
|
|
154
|
+
fs.unlinkSync(this.logFilePath);
|
|
155
|
+
this.info('Log file cleared');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error('Failed to clear log file:', error);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Create singleton logger instance
|
|
164
|
+
let loggerInstance = null;
|
|
165
|
+
export function getLogger(config) {
|
|
166
|
+
if (!loggerInstance) {
|
|
167
|
+
loggerInstance = new Logger(config);
|
|
168
|
+
}
|
|
169
|
+
return loggerInstance;
|
|
170
|
+
}
|
|
171
|
+
export function initializeLogger(config) {
|
|
172
|
+
loggerInstance = new Logger(config);
|
|
173
|
+
return loggerInstance;
|
|
174
|
+
}
|
|
175
|
+
export { Logger };
|
|
176
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Requirement } from '../types/requirement.js';
|
|
2
|
+
/**
|
|
3
|
+
* Format a requirement with friendly REQ-<number> format
|
|
4
|
+
* Note: short_id already contains "REQ-123" format
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatRequirementId(requirement: Requirement): string;
|
|
7
|
+
/**
|
|
8
|
+
* Parse a requirement ID from various formats:
|
|
9
|
+
* - "REQ-123" -> { type: 'req_id', value: 123 }
|
|
10
|
+
* - "123" -> { type: 'req_id', value: 123 }
|
|
11
|
+
* - "uuid-string" -> { type: 'uuid', value: 'uuid-string' }
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseRequirementId(input: string): {
|
|
14
|
+
type: 'req_id' | 'uuid';
|
|
15
|
+
value: string | number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Find a requirement by either req_id or UUID
|
|
19
|
+
*/
|
|
20
|
+
export declare function findRequirementById(requirements: Requirement[], identifier: string): Requirement | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Get query parameters for API calls based on identifier type
|
|
23
|
+
* Note: API doesn't support req_id parameter, so we only return id for UUIDs
|
|
24
|
+
*/
|
|
25
|
+
export declare function getRequirementQueryParams(identifier: string): {
|
|
26
|
+
id?: string;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=requirements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../src/utils/requirements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAClD,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAeA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,YAAY,EAAE,WAAW,EAAE,EAC3B,UAAU,EAAE,MAAM,GAChB,WAAW,GAAG,SAAS,CAQzB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAS7E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a requirement with friendly REQ-<number> format
|
|
3
|
+
* Note: short_id already contains "REQ-123" format
|
|
4
|
+
*/
|
|
5
|
+
export function formatRequirementId(requirement) {
|
|
6
|
+
return requirement.short_id || `REQ-${requirement.req_id || 0}`;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse a requirement ID from various formats:
|
|
10
|
+
* - "REQ-123" -> { type: 'req_id', value: 123 }
|
|
11
|
+
* - "123" -> { type: 'req_id', value: 123 }
|
|
12
|
+
* - "uuid-string" -> { type: 'uuid', value: 'uuid-string' }
|
|
13
|
+
*/
|
|
14
|
+
export function parseRequirementId(input) {
|
|
15
|
+
// Handle REQ-123 format
|
|
16
|
+
const reqMatch = input.match(/^REQ-(\d+)$/i);
|
|
17
|
+
if (reqMatch) {
|
|
18
|
+
return { type: 'req_id', value: parseInt(reqMatch[1], 10) };
|
|
19
|
+
}
|
|
20
|
+
// Handle plain number format
|
|
21
|
+
const numberMatch = input.match(/^\d+$/);
|
|
22
|
+
if (numberMatch) {
|
|
23
|
+
return { type: 'req_id', value: parseInt(input, 10) };
|
|
24
|
+
}
|
|
25
|
+
// Assume it's a UUID
|
|
26
|
+
return { type: 'uuid', value: input };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Find a requirement by either req_id or UUID
|
|
30
|
+
*/
|
|
31
|
+
export function findRequirementById(requirements, identifier) {
|
|
32
|
+
const parsed = parseRequirementId(identifier);
|
|
33
|
+
if (parsed.type === 'req_id') {
|
|
34
|
+
return requirements.find(req => req.short_id === `REQ-${parsed.value}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return requirements.find(req => req.id === parsed.value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get query parameters for API calls based on identifier type
|
|
42
|
+
* Note: API doesn't support req_id parameter, so we only return id for UUIDs
|
|
43
|
+
*/
|
|
44
|
+
export function getRequirementQueryParams(identifier) {
|
|
45
|
+
const parsed = parseRequirementId(identifier);
|
|
46
|
+
if (parsed.type === 'uuid') {
|
|
47
|
+
return { id: parsed.value };
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// For req_id, we'll need to search differently
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../src/utils/requirements.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAwB;IAC3D,OAAO,WAAW,CAAC,QAAQ,IAAI,OAAO,WAAW,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAI/C,wBAAwB;IACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED,6BAA6B;IAC7B,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,qBAAqB;IACrB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAClC,YAA2B,EAC3B,UAAkB;IAElB,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACP,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAe,EAAE,CAAC;IACvC,CAAC;SAAM,CAAC;QACP,+CAA+C;QAC/C,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { RequirementStatus } from '../types/requirement.js';
|
|
2
|
+
import type { TaskStatus } from '../types/task.js';
|
|
3
|
+
export type Status = RequirementStatus | TaskStatus;
|
|
4
|
+
/**
|
|
5
|
+
* Maps natural language keywords to Status enum values
|
|
6
|
+
*/
|
|
7
|
+
export declare const StatusKeywordMap: Record<string, Status>;
|
|
8
|
+
/**
|
|
9
|
+
* Result of status parsing operation
|
|
10
|
+
*/
|
|
11
|
+
export interface StatusParsingResult {
|
|
12
|
+
/**
|
|
13
|
+
* Successfully parsed status values
|
|
14
|
+
*/
|
|
15
|
+
statuses: Status[];
|
|
16
|
+
/**
|
|
17
|
+
* Invalid keywords that couldn't be parsed
|
|
18
|
+
*/
|
|
19
|
+
invalid: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Whether parsing encountered any errors
|
|
22
|
+
*/
|
|
23
|
+
hasErrors: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Error message if any invalid keywords were found
|
|
26
|
+
*/
|
|
27
|
+
errorMessage?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parses a comma-separated string of status keywords into Status values
|
|
31
|
+
*
|
|
32
|
+
* @param input - Comma-separated status keywords (e.g., "todo,doing" or "done")
|
|
33
|
+
* @returns Array of Status values
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* parseStatusKeywords("todo,doing") // Returns ["PLANNED", "IN_PROGRESS"]
|
|
37
|
+
* parseStatusKeywords("done") // Returns ["COMPLETED"]
|
|
38
|
+
* parseStatusKeywords("") // Returns [] (all statuses)
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseStatusKeywords(input: string): Status[];
|
|
41
|
+
/**
|
|
42
|
+
* Validates status keywords and returns both valid and invalid ones
|
|
43
|
+
*
|
|
44
|
+
* @param keywords - Array of status keywords to validate
|
|
45
|
+
* @returns Object containing valid statuses and invalid keywords
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* validateStatusKeywords(["todo", "invalid"])
|
|
49
|
+
* // Returns { valid: ["PLANNED"], invalid: ["invalid"] }
|
|
50
|
+
*/
|
|
51
|
+
export declare function validateStatusKeywords(keywords: string[]): {
|
|
52
|
+
valid: Status[];
|
|
53
|
+
invalid: string[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Formats an error message for invalid status keywords
|
|
57
|
+
*
|
|
58
|
+
* @param invalidKeywords - Array of invalid keywords
|
|
59
|
+
* @returns Formatted error message with suggestions
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* formatStatusError(["invalid", "unknown"])
|
|
63
|
+
* // Returns detailed error message with valid keyword suggestions
|
|
64
|
+
*/
|
|
65
|
+
export declare function formatStatusError(invalidKeywords: string[]): string;
|
|
66
|
+
/**
|
|
67
|
+
* Parses and validates status keywords, returning a complete result
|
|
68
|
+
*
|
|
69
|
+
* @param input - Comma-separated status keywords
|
|
70
|
+
* @returns StatusParsingResult with parsed statuses and any errors
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* parseAndValidateStatus("todo,invalid")
|
|
74
|
+
* // Returns {
|
|
75
|
+
* // statuses: ["PLANNED"],
|
|
76
|
+
* // invalid: ["invalid"],
|
|
77
|
+
* // hasErrors: true,
|
|
78
|
+
* // errorMessage: "Invalid status keyword: \"invalid\"..."
|
|
79
|
+
* // }
|
|
80
|
+
*/
|
|
81
|
+
export declare function parseAndValidateStatus(input: string): StatusParsingResult;
|
|
82
|
+
/**
|
|
83
|
+
* Gets all valid status keywords grouped by their Status value
|
|
84
|
+
*
|
|
85
|
+
* @returns Object mapping Status to array of keywords
|
|
86
|
+
*/
|
|
87
|
+
export declare function getStatusKeywordsByValue(): Record<Status, string[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Checks if a given string is a valid status keyword
|
|
90
|
+
*
|
|
91
|
+
* @param keyword - The keyword to check
|
|
92
|
+
* @returns true if the keyword is valid, false otherwise
|
|
93
|
+
*/
|
|
94
|
+
export declare function isValidStatusKeyword(keyword: string): boolean;
|
|
95
|
+
//# sourceMappingURL=status-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-parser.d.ts","sourceRoot":"","sources":["../../src/utils/status-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,MAAM,MAAM,GAAG,iBAAiB,GAAG,UAAU,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA+BnD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA4B3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAoBjG;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,MAAM,CAkBnE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAgCzE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAWnE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|