@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.
Files changed (155) hide show
  1. package/README.md +164 -0
  2. package/dist/.build-info.json +9 -0
  3. package/dist/build-config.d.ts +25 -0
  4. package/dist/build-config.d.ts.map +1 -0
  5. package/dist/build-config.js +27 -0
  6. package/dist/build-config.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +246 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/handlers/auth.handlers.d.ts +13 -0
  12. package/dist/handlers/auth.handlers.d.ts.map +1 -0
  13. package/dist/handlers/auth.handlers.js +99 -0
  14. package/dist/handlers/auth.handlers.js.map +1 -0
  15. package/dist/handlers/index.d.ts +11 -0
  16. package/dist/handlers/index.d.ts.map +1 -0
  17. package/dist/handlers/index.js +11 -0
  18. package/dist/handlers/index.js.map +1 -0
  19. package/dist/handlers/project.handlers.d.ts +29 -0
  20. package/dist/handlers/project.handlers.d.ts.map +1 -0
  21. package/dist/handlers/project.handlers.js +200 -0
  22. package/dist/handlers/project.handlers.js.map +1 -0
  23. package/dist/handlers/requirement.handlers.d.ts +32 -0
  24. package/dist/handlers/requirement.handlers.d.ts.map +1 -0
  25. package/dist/handlers/requirement.handlers.js +234 -0
  26. package/dist/handlers/requirement.handlers.js.map +1 -0
  27. package/dist/handlers/status.handlers.d.ts +12 -0
  28. package/dist/handlers/status.handlers.d.ts.map +1 -0
  29. package/dist/handlers/status.handlers.js +209 -0
  30. package/dist/handlers/status.handlers.js.map +1 -0
  31. package/dist/handlers/task.handlers.d.ts +29 -0
  32. package/dist/handlers/task.handlers.d.ts.map +1 -0
  33. package/dist/handlers/task.handlers.js +272 -0
  34. package/dist/handlers/task.handlers.js.map +1 -0
  35. package/dist/handlers/types.d.ts +10 -0
  36. package/dist/handlers/types.d.ts.map +1 -0
  37. package/dist/handlers/types.js +5 -0
  38. package/dist/handlers/types.js.map +1 -0
  39. package/dist/services/auth.d.ts +41 -0
  40. package/dist/services/auth.d.ts.map +1 -0
  41. package/dist/services/auth.js +498 -0
  42. package/dist/services/auth.js.map +1 -0
  43. package/dist/services/claude.d.ts +18 -0
  44. package/dist/services/claude.d.ts.map +1 -0
  45. package/dist/services/claude.js +164 -0
  46. package/dist/services/claude.js.map +1 -0
  47. package/dist/services/context-manager.d.ts +170 -0
  48. package/dist/services/context-manager.d.ts.map +1 -0
  49. package/dist/services/context-manager.js +261 -0
  50. package/dist/services/context-manager.js.map +1 -0
  51. package/dist/services/credential-store.d.ts +47 -0
  52. package/dist/services/credential-store.d.ts.map +1 -0
  53. package/dist/services/credential-store.js +88 -0
  54. package/dist/services/credential-store.js.map +1 -0
  55. package/dist/services/oauth2-auth.d.ts +60 -0
  56. package/dist/services/oauth2-auth.d.ts.map +1 -0
  57. package/dist/services/oauth2-auth.js +377 -0
  58. package/dist/services/oauth2-auth.js.map +1 -0
  59. package/dist/services/project-service.d.ts +22 -0
  60. package/dist/services/project-service.d.ts.map +1 -0
  61. package/dist/services/project-service.js +52 -0
  62. package/dist/services/project-service.js.map +1 -0
  63. package/dist/services/requirement-service.d.ts +32 -0
  64. package/dist/services/requirement-service.d.ts.map +1 -0
  65. package/dist/services/requirement-service.js +91 -0
  66. package/dist/services/requirement-service.js.map +1 -0
  67. package/dist/services/task-service.d.ts +22 -0
  68. package/dist/services/task-service.d.ts.map +1 -0
  69. package/dist/services/task-service.js +52 -0
  70. package/dist/services/task-service.js.map +1 -0
  71. package/dist/test/setup.d.ts +2 -0
  72. package/dist/test/setup.d.ts.map +1 -0
  73. package/dist/test/setup.js +40 -0
  74. package/dist/test/setup.js.map +1 -0
  75. package/dist/types/api.d.ts +16 -0
  76. package/dist/types/api.d.ts.map +1 -0
  77. package/dist/types/api.js +5 -0
  78. package/dist/types/api.js.map +1 -0
  79. package/dist/types/auth.d.ts +68 -0
  80. package/dist/types/auth.d.ts.map +1 -0
  81. package/dist/types/auth.js +2 -0
  82. package/dist/types/auth.js.map +1 -0
  83. package/dist/types/claude.d.ts +22 -0
  84. package/dist/types/claude.d.ts.map +1 -0
  85. package/dist/types/claude.js +2 -0
  86. package/dist/types/claude.js.map +1 -0
  87. package/dist/types/project.d.ts +32 -0
  88. package/dist/types/project.d.ts.map +1 -0
  89. package/dist/types/project.js +5 -0
  90. package/dist/types/project.js.map +1 -0
  91. package/dist/types/requirement.d.ts +69 -0
  92. package/dist/types/requirement.d.ts.map +1 -0
  93. package/dist/types/requirement.js +5 -0
  94. package/dist/types/requirement.js.map +1 -0
  95. package/dist/types/task.d.ts +44 -0
  96. package/dist/types/task.d.ts.map +1 -0
  97. package/dist/types/task.js +5 -0
  98. package/dist/types/task.js.map +1 -0
  99. package/dist/utils/axios-retry.d.ts +25 -0
  100. package/dist/utils/axios-retry.d.ts.map +1 -0
  101. package/dist/utils/axios-retry.js +174 -0
  102. package/dist/utils/axios-retry.js.map +1 -0
  103. package/dist/utils/axios-with-auth.d.ts +10 -0
  104. package/dist/utils/axios-with-auth.d.ts.map +1 -0
  105. package/dist/utils/axios-with-auth.js +118 -0
  106. package/dist/utils/axios-with-auth.js.map +1 -0
  107. package/dist/utils/cli-tools.d.ts +30 -0
  108. package/dist/utils/cli-tools.d.ts.map +1 -0
  109. package/dist/utils/cli-tools.js +131 -0
  110. package/dist/utils/cli-tools.js.map +1 -0
  111. package/dist/utils/command-execution.d.ts +30 -0
  112. package/dist/utils/command-execution.d.ts.map +1 -0
  113. package/dist/utils/command-execution.js +264 -0
  114. package/dist/utils/command-execution.js.map +1 -0
  115. package/dist/utils/command-parser.d.ts +85 -0
  116. package/dist/utils/command-parser.d.ts.map +1 -0
  117. package/dist/utils/command-parser.js +287 -0
  118. package/dist/utils/command-parser.js.map +1 -0
  119. package/dist/utils/config.d.ts +9 -0
  120. package/dist/utils/config.d.ts.map +1 -0
  121. package/dist/utils/config.js +59 -0
  122. package/dist/utils/config.js.map +1 -0
  123. package/dist/utils/error-formatter.d.ts +17 -0
  124. package/dist/utils/error-formatter.d.ts.map +1 -0
  125. package/dist/utils/error-formatter.js +115 -0
  126. package/dist/utils/error-formatter.js.map +1 -0
  127. package/dist/utils/formatting.d.ts +10 -0
  128. package/dist/utils/formatting.d.ts.map +1 -0
  129. package/dist/utils/formatting.js +122 -0
  130. package/dist/utils/formatting.js.map +1 -0
  131. package/dist/utils/git.d.ts +55 -0
  132. package/dist/utils/git.d.ts.map +1 -0
  133. package/dist/utils/git.js +131 -0
  134. package/dist/utils/git.js.map +1 -0
  135. package/dist/utils/jwt.d.ts +45 -0
  136. package/dist/utils/jwt.d.ts.map +1 -0
  137. package/dist/utils/jwt.js +64 -0
  138. package/dist/utils/jwt.js.map +1 -0
  139. package/dist/utils/logger.d.ts +36 -0
  140. package/dist/utils/logger.d.ts.map +1 -0
  141. package/dist/utils/logger.js +176 -0
  142. package/dist/utils/logger.js.map +1 -0
  143. package/dist/utils/requirements.d.ts +28 -0
  144. package/dist/utils/requirements.d.ts.map +1 -0
  145. package/dist/utils/requirements.js +54 -0
  146. package/dist/utils/requirements.js.map +1 -0
  147. package/dist/utils/status-parser.d.ts +95 -0
  148. package/dist/utils/status-parser.d.ts.map +1 -0
  149. package/dist/utils/status-parser.js +189 -0
  150. package/dist/utils/status-parser.js.map +1 -0
  151. package/dist/utils/tasks.d.ts +9 -0
  152. package/dist/utils/tasks.d.ts.map +1 -0
  153. package/dist/utils/tasks.js +38 -0
  154. package/dist/utils/tasks.js.map +1 -0
  155. package/package.json +101 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Credential Store - Encrypted credential storage using conf
3
+ *
4
+ * Provides a keytar-compatible API for storing credentials securely
5
+ * using file-based encrypted storage.
6
+ *
7
+ * Storage locations:
8
+ * - macOS: ~/Library/Preferences/BrainGrid/config.json
9
+ * - Linux: ~/.config/BrainGrid/config.json
10
+ * - Windows: %APPDATA%\BrainGrid\config.json
11
+ *
12
+ * Security:
13
+ * - Encrypted using AES-256-CBC
14
+ * - Encryption key derived from machine ID + app salt
15
+ * - File permissions automatically set to 0600 on Unix systems
16
+ */
17
+ import Conf from 'conf';
18
+ import machineId from 'node-machine-id';
19
+ import crypto from 'crypto';
20
+ // App-specific salt for key derivation
21
+ const APP_SALT = 'braingrid-cli-v1-credentials';
22
+ // Derive encryption key from machine ID + salt
23
+ // This makes the encryption key machine-specific
24
+ function deriveEncryptionKey() {
25
+ try {
26
+ const id = machineId.machineIdSync();
27
+ return crypto
28
+ .createHash('sha256')
29
+ .update(id + APP_SALT)
30
+ .digest('hex')
31
+ .substring(0, 32); // 32 bytes for AES-256
32
+ }
33
+ catch {
34
+ // Fallback if machine ID fails (unlikely)
35
+ // This is still better than plain text
36
+ console.warn('⚠️ Could not derive machine-specific encryption key, using fallback');
37
+ return crypto.createHash('sha256').update(APP_SALT).digest('hex').substring(0, 32);
38
+ }
39
+ }
40
+ // Initialize encrypted configuration store
41
+ const store = new Conf({
42
+ projectName: 'BrainGrid',
43
+ encryptionKey: deriveEncryptionKey(),
44
+ clearInvalidConfig: true, // Clear config if decryption fails
45
+ });
46
+ /**
47
+ * Credential store with keytar-compatible API
48
+ */
49
+ export const credentialStore = {
50
+ /**
51
+ * Get a stored password/credential
52
+ * @param service Service name (e.g., 'braingrid-cli')
53
+ * @param account Account name (e.g., 'session', 'refresh-token')
54
+ * @returns The stored credential or null if not found
55
+ */
56
+ async getPassword(service, account) {
57
+ const key = `${service}.${account}`;
58
+ const value = store.get(key);
59
+ return value !== undefined ? String(value) : null;
60
+ },
61
+ /**
62
+ * Store a password/credential
63
+ * @param service Service name
64
+ * @param account Account name
65
+ * @param password The credential to store
66
+ */
67
+ async setPassword(service, account, password) {
68
+ const key = `${service}.${account}`;
69
+ store.set(key, password);
70
+ },
71
+ /**
72
+ * Delete a stored password/credential
73
+ * @param service Service name
74
+ * @param account Account name
75
+ */
76
+ async deletePassword(service, account) {
77
+ const key = `${service}.${account}`;
78
+ store.delete(key);
79
+ },
80
+ /**
81
+ * Get the path to the encrypted config file
82
+ * Useful for informing users where credentials are stored
83
+ */
84
+ getStoragePath() {
85
+ return store.path;
86
+ },
87
+ };
88
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/services/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,SAAS,MAAM,iBAAiB,CAAC;AACxC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,uCAAuC;AACvC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;AAEhD,+CAA+C;AAC/C,iDAAiD;AACjD,SAAS,mBAAmB;IAC3B,IAAI,CAAC;QACJ,MAAM,EAAE,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC;QACrC,OAAO,MAAM;aACX,UAAU,CAAC,QAAQ,CAAC;aACpB,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC;aACrB,MAAM,CAAC,KAAK,CAAC;aACb,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,uBAAuB;IAC5C,CAAC;IAAC,MAAM,CAAC;QACR,0CAA0C;QAC1C,uCAAuC;QACvC,OAAO,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACrF,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;AACF,CAAC;AAED,2CAA2C;AAC3C,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC;IACtB,WAAW,EAAE,WAAW;IACxB,aAAa,EAAE,mBAAmB,EAAE;IACpC,kBAAkB,EAAE,IAAI,EAAE,mCAAmC;CAC7D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,OAAe;QACjD,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,OAAe,EAAE,QAAgB;QACnE,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;QACpC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,OAAe;QACpD,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;QACpC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,cAAc;QACb,OAAO,KAAK,CAAC,IAAI,CAAC;IACnB,CAAC;CACD,CAAC"}
@@ -0,0 +1,60 @@
1
+ export interface OAuth2AuthResult {
2
+ accessToken: string;
3
+ refreshToken?: string;
4
+ idToken?: string;
5
+ expiresIn?: number;
6
+ tokenType?: string;
7
+ }
8
+ export declare class OAuth2Handler {
9
+ private abortController?;
10
+ private onAuthCodeReceived?;
11
+ private server?;
12
+ private authorizationCode?;
13
+ private authError?;
14
+ private state?;
15
+ /**
16
+ * Set callback for when auth URL is ready
17
+ */
18
+ setAuthUrlCallback(callback: (authUrl: string) => void): void;
19
+ /**
20
+ * Generate PKCE challenge for OAuth2 flow
21
+ */
22
+ private generatePKCEChallenge;
23
+ /**
24
+ * Generate a cryptographically secure state parameter
25
+ */
26
+ private generateState;
27
+ /**
28
+ * Get the fixed port for the callback server
29
+ */
30
+ private getCallbackPort;
31
+ /**
32
+ * Start local HTTP server to handle OAuth callback
33
+ */
34
+ private startCallbackServer;
35
+ /**
36
+ * Build the authorization URL with PKCE parameters
37
+ */
38
+ private buildAuthorizationUrl;
39
+ /**
40
+ * Exchange authorization code for tokens
41
+ */
42
+ private exchangeCodeForTokens;
43
+ /**
44
+ * Wait for the authorization code from the callback
45
+ */
46
+ private waitForAuthorizationCode;
47
+ /**
48
+ * Initiates the OAuth2 authorization code flow with PKCE
49
+ */
50
+ authenticate(): Promise<OAuth2AuthResult>;
51
+ /**
52
+ * Refresh an access token using a refresh token
53
+ */
54
+ refreshToken(refreshToken: string): Promise<OAuth2AuthResult>;
55
+ /**
56
+ * Abort any ongoing authentication
57
+ */
58
+ abort(): void;
59
+ }
60
+ //# sourceMappingURL=oauth2-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2-auth.d.ts","sourceRoot":"","sources":["../../src/services/oauth2-auth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,gBAAgB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,qBAAa,aAAa;IACzB,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,kBAAkB,CAAC,CAA4B;IACvD,OAAO,CAAC,MAAM,CAAC,CAAkC;IACjD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAC,CAAS;IAEvB;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI7D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;YACW,mBAAmB;IAyHjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;YACW,qBAAqB;IA+CnC;;OAEG;YACW,wBAAwB;IAqCtC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAwE/C;;OAEG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4CnE;;OAEG;IACH,KAAK,IAAI,IAAI;CAWb"}
@@ -0,0 +1,377 @@
1
+ import { createHash, randomBytes } from 'crypto';
2
+ import { createServer } from 'http';
3
+ import open from 'open';
4
+ import axios, { AxiosError } from 'axios';
5
+ import { getConfig } from '../utils/config.js';
6
+ import { getLogger } from '../utils/logger.js';
7
+ const logger = getLogger();
8
+ export class OAuth2Handler {
9
+ /**
10
+ * Set callback for when auth URL is ready
11
+ */
12
+ setAuthUrlCallback(callback) {
13
+ this.onAuthCodeReceived = callback;
14
+ }
15
+ /**
16
+ * Generate PKCE challenge for OAuth2 flow
17
+ */
18
+ generatePKCEChallenge() {
19
+ // Generate a cryptographically secure random verifier (43-128 chars)
20
+ const verifier = randomBytes(32).toString('base64url');
21
+ // Create challenge from verifier using SHA256
22
+ const challenge = createHash('sha256').update(verifier).digest('base64url');
23
+ return {
24
+ verifier,
25
+ challenge,
26
+ method: 'S256',
27
+ };
28
+ }
29
+ /**
30
+ * Generate a cryptographically secure state parameter
31
+ */
32
+ generateState() {
33
+ return randomBytes(32).toString('base64url');
34
+ }
35
+ /**
36
+ * Get the fixed port for the callback server
37
+ */
38
+ getCallbackPort() {
39
+ // Use fixed port 34536 for OAuth callback
40
+ return 34536;
41
+ }
42
+ /**
43
+ * Start local HTTP server to handle OAuth callback
44
+ */
45
+ async startCallbackServer(port) {
46
+ return new Promise(resolve => {
47
+ this.server = createServer((req, res) => {
48
+ const url = new URL(req.url || '', `http://127.0.0.1:${port}`);
49
+ // Handle OAuth callback
50
+ if (url.pathname === '/callback') {
51
+ const code = url.searchParams.get('code');
52
+ const error = url.searchParams.get('error');
53
+ const state = url.searchParams.get('state');
54
+ // Validate state parameter
55
+ if (state !== this.state) {
56
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
57
+ res.end(`
58
+ <html>
59
+ <body>
60
+ <h1>Authentication Failed</h1>
61
+ <p>Invalid state parameter. Please try again.</p>
62
+ <script>window.setTimeout(() => window.close(), 3000);</script>
63
+ </body>
64
+ </html>
65
+ `);
66
+ this.authError = 'Invalid state parameter';
67
+ return;
68
+ }
69
+ if (error) {
70
+ // Handle error response
71
+ const errorDescription = url.searchParams.get('error_description') || 'Unknown error';
72
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
73
+ res.end(`
74
+ <html>
75
+ <body>
76
+ <h1>Authentication Failed</h1>
77
+ <p>${errorDescription}</p>
78
+ <script>window.setTimeout(() => window.close(), 3000);</script>
79
+ </body>
80
+ </html>
81
+ `);
82
+ this.authError = errorDescription;
83
+ }
84
+ else if (code) {
85
+ // Success! Store the code
86
+ this.authorizationCode = code;
87
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
88
+ res.end(`
89
+ <html>
90
+ <head>
91
+ <style>
92
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
93
+ .container { background: white; padding: 2rem; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); text-align: center; }
94
+ h1 { color: #2d3748; margin-bottom: 1rem; }
95
+ p { color: #718096; }
96
+ .success-icon { font-size: 3rem; margin-bottom: 1rem; }
97
+ </style>
98
+ </head>
99
+ <body>
100
+ <div class="container">
101
+ <div class="success-icon">✅</div>
102
+ <h1>Authentication Successful!</h1>
103
+ <p>You can now close this window and return to the CLI.</p>
104
+ <script>window.setTimeout(() => window.close(), 2000);</script>
105
+ </div>
106
+ </body>
107
+ </html>
108
+ `);
109
+ }
110
+ else {
111
+ // No code or error
112
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
113
+ res.end(`
114
+ <html>
115
+ <body>
116
+ <h1>Authentication Failed</h1>
117
+ <p>No authorization code received.</p>
118
+ <script>window.setTimeout(() => window.close(), 3000);</script>
119
+ </body>
120
+ </html>
121
+ `);
122
+ this.authError = 'No authorization code received';
123
+ }
124
+ // Close the server after handling the callback
125
+ setTimeout(() => {
126
+ if (this.server) {
127
+ this.server.close();
128
+ this.server = undefined;
129
+ }
130
+ }, 500);
131
+ }
132
+ else {
133
+ // Handle other routes (redirect to /callback or show waiting page)
134
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
135
+ res.end(`
136
+ <html>
137
+ <head>
138
+ <style>
139
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
140
+ .container { background: white; padding: 2rem; border-radius: 10px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); text-align: center; }
141
+ h1 { color: #2d3748; }
142
+ .spinner { border: 3px solid #f3f4f6; border-top: 3px solid #667eea; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 1rem auto; }
143
+ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
144
+ </style>
145
+ </head>
146
+ <body>
147
+ <div class="container">
148
+ <h1>Waiting for authentication...</h1>
149
+ <div class="spinner"></div>
150
+ <p>Please complete the authentication in your browser.</p>
151
+ </div>
152
+ </body>
153
+ </html>
154
+ `);
155
+ }
156
+ });
157
+ this.server.listen(port, '127.0.0.1', () => {
158
+ logger.debug(`Callback server listening on http://127.0.0.1:${port}`);
159
+ resolve();
160
+ });
161
+ });
162
+ }
163
+ /**
164
+ * Build the authorization URL with PKCE parameters
165
+ */
166
+ buildAuthorizationUrl(pkce, redirectUri) {
167
+ const config = getConfig();
168
+ // Use WorkOS AuthKit directly like the MCP server does
169
+ const authUrl = config.getWorkOSAuthUrl();
170
+ // Generate state for CSRF protection
171
+ this.state = this.generateState();
172
+ const params = new URLSearchParams({
173
+ client_id: config.oauthClientId || 'braingrid-cli',
174
+ redirect_uri: redirectUri,
175
+ response_type: 'code',
176
+ scope: 'openid email profile offline_access',
177
+ state: this.state,
178
+ code_challenge: pkce.challenge,
179
+ code_challenge_method: pkce.method,
180
+ });
181
+ return `${authUrl}/oauth2/authorize?${params.toString()}`;
182
+ }
183
+ /**
184
+ * Exchange authorization code for tokens
185
+ */
186
+ async exchangeCodeForTokens(code, verifier, redirectUri) {
187
+ const config = getConfig();
188
+ // Use WorkOS AuthKit token endpoint
189
+ const tokenUrl = `${config.getWorkOSAuthUrl()}/oauth2/token`;
190
+ const params = new URLSearchParams({
191
+ grant_type: 'authorization_code',
192
+ client_id: config.oauthClientId || 'braingrid-cli',
193
+ code: code,
194
+ redirect_uri: redirectUri,
195
+ code_verifier: verifier,
196
+ });
197
+ logger.debug('Exchanging authorization code for tokens', { tokenUrl });
198
+ try {
199
+ const response = await axios.post(tokenUrl, params.toString(), {
200
+ headers: {
201
+ 'Content-Type': 'application/x-www-form-urlencoded',
202
+ },
203
+ });
204
+ logger.debug('Token exchange successful', {
205
+ hasAccessToken: !!response.data.access_token,
206
+ hasRefreshToken: !!response.data.refresh_token,
207
+ });
208
+ return response.data;
209
+ }
210
+ catch (error) {
211
+ if (error instanceof AxiosError && error.response) {
212
+ const errorData = error.response.data;
213
+ logger.error('Token exchange failed', {
214
+ status: error.response.status,
215
+ error: errorData,
216
+ });
217
+ throw new Error(`Token exchange failed: ${errorData.error_description || errorData.error}`);
218
+ }
219
+ throw new Error(`Token exchange failed: ${error instanceof Error ? error.message : String(error)}`);
220
+ }
221
+ }
222
+ /**
223
+ * Wait for the authorization code from the callback
224
+ */
225
+ async waitForAuthorizationCode(timeoutMs = 300000) {
226
+ // 5 minutes timeout
227
+ return new Promise((resolve, reject) => {
228
+ const startTime = Date.now();
229
+ const checkInterval = setInterval(() => {
230
+ // Check if we should abort
231
+ if (this.abortController?.signal.aborted) {
232
+ clearInterval(checkInterval);
233
+ reject(new Error('Authentication cancelled'));
234
+ return;
235
+ }
236
+ // Check for error
237
+ if (this.authError) {
238
+ clearInterval(checkInterval);
239
+ reject(new Error(this.authError));
240
+ return;
241
+ }
242
+ // Check for success
243
+ if (this.authorizationCode) {
244
+ clearInterval(checkInterval);
245
+ resolve(this.authorizationCode);
246
+ return;
247
+ }
248
+ // Check for timeout
249
+ if (Date.now() - startTime > timeoutMs) {
250
+ clearInterval(checkInterval);
251
+ reject(new Error('Authentication timeout - no response received'));
252
+ return;
253
+ }
254
+ }, 500); // Check every 500ms
255
+ });
256
+ }
257
+ /**
258
+ * Initiates the OAuth2 authorization code flow with PKCE
259
+ */
260
+ async authenticate() {
261
+ logger.info('Starting OAuth2 authentication flow with PKCE');
262
+ // Create new AbortController for this authentication session
263
+ this.abortController = new AbortController();
264
+ // Reset state
265
+ this.authorizationCode = undefined;
266
+ this.authError = undefined;
267
+ this.state = undefined;
268
+ try {
269
+ // Step 1: Generate PKCE challenge
270
+ const pkce = this.generatePKCEChallenge();
271
+ logger.debug('PKCE challenge generated');
272
+ // Step 2: Use fixed port and start callback server
273
+ const port = this.getCallbackPort();
274
+ const redirectUri = `http://127.0.0.1:${port}/callback`;
275
+ logger.info('Starting callback server', { port, redirectUri });
276
+ await this.startCallbackServer(port);
277
+ // Step 3: Build authorization URL
278
+ const authUrl = this.buildAuthorizationUrl(pkce, redirectUri);
279
+ logger.info('Authorization URL ready', { authUrl });
280
+ // Notify callback if set
281
+ if (this.onAuthCodeReceived) {
282
+ this.onAuthCodeReceived(authUrl);
283
+ }
284
+ // Step 4: Open browser
285
+ try {
286
+ logger.debug('Opening browser for authentication');
287
+ await open(authUrl);
288
+ logger.info('Browser opened automatically');
289
+ }
290
+ catch (error) {
291
+ logger.warn('Failed to open browser automatically', { error });
292
+ logger.info(`Please open the following URL manually:\n${authUrl}`);
293
+ }
294
+ // Step 5: Wait for authorization code
295
+ logger.info('Waiting for user to complete authentication...');
296
+ const code = await this.waitForAuthorizationCode();
297
+ logger.info('Authorization code received');
298
+ // Step 6: Exchange code for tokens
299
+ const tokens = await this.exchangeCodeForTokens(code, pkce.verifier, redirectUri);
300
+ logger.info('Authentication successful');
301
+ // Step 7: Return token info
302
+ return {
303
+ accessToken: tokens.access_token,
304
+ refreshToken: tokens.refresh_token,
305
+ idToken: tokens.id_token,
306
+ expiresIn: tokens.expires_in,
307
+ tokenType: tokens.token_type,
308
+ };
309
+ }
310
+ catch (error) {
311
+ // Abort any ongoing operations
312
+ this.abort();
313
+ throw error;
314
+ }
315
+ finally {
316
+ // Clean up server if still running
317
+ if (this.server) {
318
+ this.server.close();
319
+ this.server = undefined;
320
+ }
321
+ }
322
+ }
323
+ /**
324
+ * Refresh an access token using a refresh token
325
+ */
326
+ async refreshToken(refreshToken) {
327
+ const config = getConfig();
328
+ // Use WorkOS AuthKit token endpoint for refresh
329
+ const tokenUrl = `${config.getWorkOSAuthUrl()}/oauth2/token`;
330
+ const params = new URLSearchParams({
331
+ grant_type: 'refresh_token',
332
+ client_id: config.oauthClientId || 'braingrid-cli',
333
+ refresh_token: refreshToken,
334
+ });
335
+ logger.debug('Refreshing access token');
336
+ try {
337
+ const response = await axios.post(tokenUrl, params.toString(), {
338
+ headers: {
339
+ 'Content-Type': 'application/x-www-form-urlencoded',
340
+ },
341
+ });
342
+ logger.debug('Token refresh successful');
343
+ return {
344
+ accessToken: response.data.access_token,
345
+ refreshToken: response.data.refresh_token,
346
+ idToken: response.data.id_token,
347
+ expiresIn: response.data.expires_in,
348
+ tokenType: response.data.token_type,
349
+ };
350
+ }
351
+ catch (error) {
352
+ if (error instanceof AxiosError && error.response) {
353
+ const errorData = error.response.data;
354
+ logger.error('Token refresh failed', {
355
+ status: error.response.status,
356
+ error: errorData,
357
+ });
358
+ throw new Error(`Token refresh failed: ${errorData.error_description || errorData.error}`);
359
+ }
360
+ throw new Error(`Token refresh failed: ${error instanceof Error ? error.message : String(error)}`);
361
+ }
362
+ }
363
+ /**
364
+ * Abort any ongoing authentication
365
+ */
366
+ abort() {
367
+ if (this.abortController) {
368
+ this.abortController.abort();
369
+ this.abortController = undefined;
370
+ }
371
+ if (this.server) {
372
+ this.server.close();
373
+ this.server = undefined;
374
+ }
375
+ }
376
+ }
377
+ //# sourceMappingURL=oauth2-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2-auth.js","sourceRoot":"","sources":["../../src/services/oauth2-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Project Service
3
+ * Handles all API interactions for projects
4
+ */
5
+ import { BraingridAuth } from './auth.js';
6
+ import { Project, CreateProjectRequest, UpdateProjectRequest, ListProjectsResponse } from '../types/project.js';
7
+ export declare class ProjectService {
8
+ private baseUrl;
9
+ private auth;
10
+ private axios;
11
+ constructor(baseUrl: string, auth: BraingridAuth);
12
+ private getHeaders;
13
+ listProjects(params: {
14
+ page?: number;
15
+ limit?: number;
16
+ }): Promise<ListProjectsResponse>;
17
+ getProject(projectId: string): Promise<Project>;
18
+ createProject(data: CreateProjectRequest): Promise<Project>;
19
+ updateProject(projectId: string, data: UpdateProjectRequest): Promise<Project>;
20
+ deleteProject(projectId: string): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=project-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-service.d.ts","sourceRoot":"","sources":["../../src/services/project-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACN,OAAO,EACP,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,cAAc;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,KAAK,CAAgB;gBAEjB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa;IAMhD,OAAO,CAAC,UAAU;IAMZ,YAAY,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAYtF,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ/C,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ3D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ9E,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMrD"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Project Service
3
+ * Handles all API interactions for projects
4
+ */
5
+ import { createAuthenticatedAxios } from '../utils/axios-with-auth.js';
6
+ export class ProjectService {
7
+ constructor(baseUrl, auth) {
8
+ this.baseUrl = baseUrl;
9
+ this.auth = auth;
10
+ this.axios = createAuthenticatedAxios(auth);
11
+ }
12
+ getHeaders() {
13
+ return {
14
+ 'Content-Type': 'application/json',
15
+ };
16
+ }
17
+ async listProjects(params) {
18
+ const queryParams = new URLSearchParams();
19
+ if (params.page)
20
+ queryParams.append('page', params.page.toString());
21
+ if (params.limit)
22
+ queryParams.append('limit', params.limit.toString());
23
+ const url = `${this.baseUrl}/api/v1/projects?${queryParams.toString()}`;
24
+ const headers = this.getHeaders();
25
+ const response = await this.axios.get(url, { headers });
26
+ return response.data;
27
+ }
28
+ async getProject(projectId) {
29
+ const url = `${this.baseUrl}/api/v1/projects/${projectId}`;
30
+ const headers = this.getHeaders();
31
+ const response = await this.axios.get(url, { headers });
32
+ return response.data;
33
+ }
34
+ async createProject(data) {
35
+ const url = `${this.baseUrl}/api/v1/projects`;
36
+ const headers = this.getHeaders();
37
+ const response = await this.axios.post(url, data, { headers });
38
+ return response.data;
39
+ }
40
+ async updateProject(projectId, data) {
41
+ const url = `${this.baseUrl}/api/v1/projects/${projectId}`;
42
+ const headers = this.getHeaders();
43
+ const response = await this.axios.patch(url, data, { headers });
44
+ return response.data;
45
+ }
46
+ async deleteProject(projectId) {
47
+ const url = `${this.baseUrl}/api/v1/projects/${projectId}`;
48
+ const headers = this.getHeaders();
49
+ await this.axios.delete(url, { headers });
50
+ }
51
+ }
52
+ //# sourceMappingURL=project-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-service.js","sourceRoot":"","sources":["../../src/services/project-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAQvE,MAAM,OAAO,cAAc;IAK1B,YAAY,OAAe,EAAE,IAAmB;QAC/C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAEO,UAAU;QACjB,OAAO;YACN,cAAc,EAAE,kBAAkB;SAClC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAyC;QAC3D,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI;YAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,KAAK;YAAE,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,oBAAoB,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC;QACxE,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9E,OAAO,QAAQ,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QACjC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,oBAAoB,SAAS,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAU,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAA0B;QAC7C,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,kBAAkB,CAAC;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAU,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACxE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB,EAAE,IAA0B;QAChE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,oBAAoB,SAAS,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAU,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACzE,OAAO,QAAQ,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACpC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,oBAAoB,SAAS,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;CACD"}