@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,25 @@
1
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ export interface RetryOptions {
3
+ maxRetries?: number;
4
+ initialDelay?: number;
5
+ maxDelay?: number;
6
+ backoffMultiplier?: number;
7
+ retryableStatuses?: number[];
8
+ onRetry?: (attempt: number, delay: number, error: unknown) => void;
9
+ }
10
+ export declare function sleep(ms: number): Promise<void>;
11
+ export declare function calculateDelay(attempt: number, initialDelay: number, maxDelay: number, backoffMultiplier: number): number;
12
+ export declare function isRetryableError(error: unknown, retryableStatuses: number[]): boolean;
13
+ export declare const axiosInstance: AxiosInstance;
14
+ export declare function axiosWithRetry<T = unknown>(config: AxiosRequestConfig, options?: RetryOptions): Promise<AxiosResponse<T>>;
15
+ export declare class RetryableHttpClient {
16
+ private defaultOptions;
17
+ constructor(defaultOptions?: RetryOptions);
18
+ get<T = unknown>(url: string, config?: AxiosRequestConfig, options?: RetryOptions): Promise<AxiosResponse<T>>;
19
+ post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig, options?: RetryOptions): Promise<AxiosResponse<T>>;
20
+ patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig, options?: RetryOptions): Promise<AxiosResponse<T>>;
21
+ delete<T = unknown>(url: string, config?: AxiosRequestConfig, options?: RetryOptions): Promise<AxiosResponse<T>>;
22
+ }
23
+ export declare const retryableHttpClient: RetryableHttpClient;
24
+ export declare function createAxiosConfig(init?: RequestInit): AxiosRequestConfig;
25
+ //# sourceMappingURL=axios-retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-retry.d.ts","sourceRoot":"","sources":["../../src/utils/axios-retry.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnE;AAWD,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAgB,cAAc,CAC7B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,GACvB,MAAM,CAIR;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,OAAO,CAmCrF;AAGD,eAAO,MAAM,aAAa,EAAE,aAO1B,CAAC;AAEH,wBAAsB,cAAc,CAAC,CAAC,GAAG,OAAO,EAC/C,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CA8C3B;AAGD,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,cAAc,CAAe;gBAEzB,cAAc,CAAC,EAAE,YAAY;IAInC,GAAG,CAAC,CAAC,GAAG,OAAO,EACpB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAOtB,IAAI,CAAC,CAAC,GAAG,OAAO,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAgBtB,KAAK,CAAC,CAAC,GAAG,OAAO,EACtB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,MAAM,CAAC,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAgBtB,MAAM,CAAC,CAAC,GAAG,OAAO,EACvB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAM5B;AAGD,eAAO,MAAM,mBAAmB,qBAK9B,CAAC;AAGH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,kBAAkB,CAwCxE"}
@@ -0,0 +1,174 @@
1
+ import axios from 'axios';
2
+ const DEFAULT_OPTIONS = {
3
+ maxRetries: 3,
4
+ initialDelay: 1000, // 1 second
5
+ maxDelay: 30000, // 30 seconds
6
+ backoffMultiplier: 2,
7
+ retryableStatuses: [408, 429, 500, 502, 503, 504], // Timeout, Too Many Requests, Server Errors
8
+ onRetry: () => { }, // No-op by default
9
+ };
10
+ export async function sleep(ms) {
11
+ return new Promise(resolve => setTimeout(resolve, ms));
12
+ }
13
+ export function calculateDelay(attempt, initialDelay, maxDelay, backoffMultiplier) {
14
+ const exponentialDelay = initialDelay * Math.pow(backoffMultiplier, attempt - 1);
15
+ const jitteredDelay = exponentialDelay * (0.5 + Math.random() * 0.5); // Add jitter
16
+ return Math.min(jitteredDelay, maxDelay);
17
+ }
18
+ export function isRetryableError(error, retryableStatuses) {
19
+ // Type guard to check if error has expected properties
20
+ const hasErrorCode = (err) => typeof err === 'object' && err !== null && 'code' in err;
21
+ const hasErrorMessage = (err) => typeof err === 'object' && err !== null;
22
+ const hasResponseStatus = (err) => typeof err === 'object' && err !== null && 'response' in err;
23
+ // Network errors are always retryable
24
+ if (hasErrorCode(error)) {
25
+ if (error.code === 'ECONNRESET' ||
26
+ error.code === 'ETIMEDOUT' ||
27
+ error.code === 'ENOTFOUND' ||
28
+ error.code === 'ECONNREFUSED' ||
29
+ error.code === 'ECONNABORTED') {
30
+ return true;
31
+ }
32
+ }
33
+ if (hasErrorMessage(error) && error.message) {
34
+ if (error.message.includes('network') || error.message.includes('Network')) {
35
+ return true;
36
+ }
37
+ }
38
+ // Check if it's an HTTP error with a retryable status
39
+ if (hasResponseStatus(error) && error.response?.status) {
40
+ if (retryableStatuses.includes(error.response.status)) {
41
+ return true;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ // Create axios instance with default config
47
+ export const axiosInstance = axios.create({
48
+ timeout: 120000, // 2 minutes default timeout
49
+ headers: {
50
+ 'User-Agent': 'Braingrid-CLI',
51
+ },
52
+ // Don't throw on any status to handle errors ourselves
53
+ validateStatus: () => true,
54
+ });
55
+ export async function axiosWithRetry(config, options) {
56
+ const opts = { ...DEFAULT_OPTIONS, ...options };
57
+ let lastError;
58
+ for (let attempt = 1; attempt <= opts.maxRetries + 1; attempt++) {
59
+ try {
60
+ const response = await axiosInstance.request(config);
61
+ // Check if the response status is retryable
62
+ if (response.status >= 400 &&
63
+ opts.retryableStatuses.includes(response.status) &&
64
+ attempt <= opts.maxRetries) {
65
+ const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
66
+ error.response = response;
67
+ error.status = response.status;
68
+ throw error;
69
+ }
70
+ return response;
71
+ }
72
+ catch (error) {
73
+ lastError = error;
74
+ // Check if we should retry
75
+ if (attempt <= opts.maxRetries && isRetryableError(error, opts.retryableStatuses)) {
76
+ const delay = calculateDelay(attempt, opts.initialDelay, opts.maxDelay, opts.backoffMultiplier);
77
+ opts.onRetry(attempt, delay, error);
78
+ await sleep(delay);
79
+ continue;
80
+ }
81
+ // If not retryable or max retries exceeded, throw the error
82
+ throw error;
83
+ }
84
+ }
85
+ // This should never be reached, but just in case
86
+ throw lastError || new Error('Unexpected error in axiosWithRetry');
87
+ }
88
+ // Enhanced wrapper for common use cases
89
+ export class RetryableHttpClient {
90
+ constructor(defaultOptions) {
91
+ this.defaultOptions = defaultOptions || {};
92
+ }
93
+ async get(url, config, options) {
94
+ return axiosWithRetry({ ...config, method: 'GET', url }, { ...this.defaultOptions, ...options });
95
+ }
96
+ async post(url, data, config, options) {
97
+ return axiosWithRetry({
98
+ ...config,
99
+ method: 'POST',
100
+ url,
101
+ data,
102
+ headers: {
103
+ 'Content-Type': 'application/json',
104
+ ...config?.headers,
105
+ },
106
+ }, { ...this.defaultOptions, ...options });
107
+ }
108
+ async patch(url, data, config, options) {
109
+ return axiosWithRetry({
110
+ ...config,
111
+ method: 'PATCH',
112
+ url,
113
+ data,
114
+ headers: {
115
+ 'Content-Type': 'application/json',
116
+ ...config?.headers,
117
+ },
118
+ }, { ...this.defaultOptions, ...options });
119
+ }
120
+ async delete(url, config, options) {
121
+ return axiosWithRetry({ ...config, method: 'DELETE', url }, { ...this.defaultOptions, ...options });
122
+ }
123
+ }
124
+ // Export a default instance for convenience
125
+ export const retryableHttpClient = new RetryableHttpClient({
126
+ onRetry: (attempt, delay, error) => {
127
+ const errorMessage = error instanceof Error ? error.message : String(error);
128
+ console.warn(`Retry attempt ${attempt} after ${delay}ms due to:`, errorMessage);
129
+ },
130
+ });
131
+ // Helper function to convert headers for cookie support
132
+ export function createAxiosConfig(init) {
133
+ const config = {};
134
+ if (init) {
135
+ // Convert method
136
+ if (init.method)
137
+ config.method = init.method;
138
+ // Convert headers
139
+ if (init.headers) {
140
+ const headers = {};
141
+ if (init.headers instanceof Headers) {
142
+ init.headers.forEach((value, key) => {
143
+ headers[key] = value;
144
+ });
145
+ config.headers = headers;
146
+ }
147
+ else if (Array.isArray(init.headers)) {
148
+ init.headers.forEach(([key, value]) => {
149
+ headers[key] = value;
150
+ });
151
+ config.headers = headers;
152
+ }
153
+ else {
154
+ config.headers = init.headers;
155
+ }
156
+ }
157
+ // Convert body to data
158
+ if (init.body) {
159
+ if (typeof init.body === 'string') {
160
+ try {
161
+ config.data = JSON.parse(init.body);
162
+ }
163
+ catch {
164
+ config.data = init.body;
165
+ }
166
+ }
167
+ else {
168
+ config.data = init.body;
169
+ }
170
+ }
171
+ }
172
+ return config;
173
+ }
174
+ //# sourceMappingURL=axios-retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-retry.js","sourceRoot":"","sources":["../../src/utils/axios-retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAWhF,MAAM,eAAe,GAA2B;IAC/C,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,IAAI,EAAE,WAAW;IAC/B,QAAQ,EAAE,KAAK,EAAE,aAAa;IAC9B,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,4CAA4C;IAC/F,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,mBAAmB;CACtC,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,EAAU;IACrC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,OAAe,EACf,YAAoB,EACpB,QAAgB,EAChB,iBAAyB;IAEzB,MAAM,gBAAgB,GAAG,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,aAAa,GAAG,gBAAgB,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa;IACnF,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,iBAA2B;IAC3E,uDAAuD;IACvD,MAAM,YAAY,GAAG,CAAC,GAAY,EAA2B,EAAE,CAC9D,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;IAC1D,MAAM,eAAe,GAAG,CAAC,GAAY,EAA+B,EAAE,CACrE,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC;IACzC,MAAM,iBAAiB,GAAG,CAAC,GAAY,EAA4C,EAAE,CACpF,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI,GAAG,CAAC;IAC9D,sCAAsC;IACtC,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IACC,KAAK,CAAC,IAAI,KAAK,YAAY;YAC3B,KAAK,CAAC,IAAI,KAAK,WAAW;YAC1B,KAAK,CAAC,IAAI,KAAK,WAAW;YAC1B,KAAK,CAAC,IAAI,KAAK,cAAc;YAC7B,KAAK,CAAC,IAAI,KAAK,cAAc,EAC5B,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5E,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,sDAAsD;IACtD,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACxD,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAkB,KAAK,CAAC,MAAM,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,4BAA4B;IAC7C,OAAO,EAAE;QACR,YAAY,EAAE,eAAe;KAC7B;IACD,uDAAuD;IACvD,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;CAC1B,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,MAA0B,EAC1B,OAAsB;IAEtB,MAAM,IAAI,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;IAChD,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QACjE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAAI,MAAM,CAAC,CAAC;YAExD,4CAA4C;YAC5C,IACC,QAAQ,CAAC,MAAM,IAAI,GAAG;gBACtB,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAChD,OAAO,IAAI,IAAI,CAAC,UAAU,EACzB,CAAC;gBACF,MAAM,KAAK,GAA6D,IAAI,KAAK,CAChF,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CACjD,CAAC;gBACF,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAC1B,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;gBAC/B,MAAM,KAAK,CAAC;YACb,CAAC;YAED,OAAO,QAAQ,CAAC;QACjB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,SAAS,GAAG,KAAK,CAAC;YAElB,2BAA2B;YAC3B,IAAI,OAAO,IAAI,IAAI,CAAC,UAAU,IAAI,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACnF,MAAM,KAAK,GAAG,cAAc,CAC3B,OAAO,EACP,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,iBAAiB,CACtB,CAAC;gBACF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;gBACpC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnB,SAAS;YACV,CAAC;YAED,4DAA4D;YAC5D,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED,iDAAiD;IACjD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACpE,CAAC;AAED,wCAAwC;AACxC,MAAM,OAAO,mBAAmB;IAG/B,YAAY,cAA6B;QACxC,IAAI,CAAC,cAAc,GAAG,cAAc,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,GAAG,CACR,GAAW,EACX,MAA2B,EAC3B,OAAsB;QAEtB,OAAO,cAAc,CACpB,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EACjC,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,CACtC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CACT,GAAW,EACX,IAAc,EACd,MAA2B,EAC3B,OAAsB;QAEtB,OAAO,cAAc,CACpB;YACC,GAAG,MAAM;YACT,MAAM,EAAE,MAAM;YACd,GAAG;YACH,IAAI;YACJ,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,GAAG,MAAM,EAAE,OAAO;aAClB;SACD,EACD,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,CACtC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CACV,GAAW,EACX,IAAc,EACd,MAA2B,EAC3B,OAAsB;QAEtB,OAAO,cAAc,CACpB;YACC,GAAG,MAAM;YACT,MAAM,EAAE,OAAO;YACf,GAAG;YACH,IAAI;YACJ,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,GAAG,MAAM,EAAE,OAAO;aAClB;SACD,EACD,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,CACtC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CACX,GAAW,EACX,MAA2B,EAC3B,OAAsB;QAEtB,OAAO,cAAc,CACpB,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,EACpC,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,CACtC,CAAC;IACH,CAAC;CACD;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,CAAC;IAC1D,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAClC,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,iBAAiB,OAAO,UAAU,KAAK,YAAY,EAAE,YAAY,CAAC,CAAC;IACjF,CAAC;CACD,CAAC,CAAC;AAEH,wDAAwD;AACxD,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IACnD,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,IAAI,IAAI,EAAE,CAAC;QACV,iBAAiB;QACjB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE7C,kBAAkB;QAClB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,OAAO,YAAY,OAAO,EAAE,CAAC;gBACrC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACnC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YAC1B,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;oBACrC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACtB,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAiC,CAAC;YACzD,CAAC;QACF,CAAC;QAED,uBAAuB;QACvB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACJ,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACR,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACzB,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACzB,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Axios instance with authentication and automatic token refresh
3
+ */
4
+ import { AxiosInstance } from 'axios';
5
+ import { BraingridAuth } from '../services/auth.js';
6
+ /**
7
+ * Create an axios instance with automatic token refresh on 401 errors and auth redirects
8
+ */
9
+ export declare function createAuthenticatedAxios(auth: BraingridAuth): AxiosInstance;
10
+ //# sourceMappingURL=axios-with-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-with-auth.d.ts","sourceRoot":"","sources":["../../src/utils/axios-with-auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAc,EAAE,aAAa,EAA0C,MAAM,OAAO,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA+BpD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CA2G3E"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Axios instance with authentication and automatic token refresh
3
+ */
4
+ import axios from 'axios';
5
+ import { getLogger } from './logger.js';
6
+ const logger = getLogger();
7
+ /**
8
+ * Check if a response is a redirect to an auth endpoint
9
+ */
10
+ function isAuthRedirect(error) {
11
+ const status = error.response?.status;
12
+ if (!status || (status !== 302 && status !== 307 && status !== 303)) {
13
+ return false;
14
+ }
15
+ const location = error.response?.headers?.location;
16
+ if (!location) {
17
+ return false;
18
+ }
19
+ // Check if redirecting to auth endpoints (WorkOS, AuthKit, etc.)
20
+ const authPatterns = [
21
+ '/auth/',
22
+ '/oauth2/',
23
+ 'workos.com',
24
+ 'authkit.app',
25
+ '/user_management/authorize',
26
+ ];
27
+ return authPatterns.some(pattern => location.toLowerCase().includes(pattern));
28
+ }
29
+ /**
30
+ * Create an axios instance with automatic token refresh on 401 errors and auth redirects
31
+ */
32
+ export function createAuthenticatedAxios(auth) {
33
+ const instance = axios.create({
34
+ maxRedirects: 0, // Don't follow redirects - treat them as errors
35
+ validateStatus: status => status >= 200 && status < 300, // Only accept 2xx as success
36
+ });
37
+ // Request interceptor to add auth headers
38
+ instance.interceptors.request.use(async (config) => {
39
+ const session = await auth.getStoredSession();
40
+ if (session) {
41
+ config.headers.Authorization = `Bearer ${session.sealed_session}`;
42
+ }
43
+ return config;
44
+ }, error => Promise.reject(error));
45
+ // Response interceptor to handle 401 errors, auth redirects, and refresh token
46
+ instance.interceptors.response.use(response => {
47
+ // Log successful API calls for debugging/testing
48
+ const method = response.config.method?.toUpperCase() || 'UNKNOWN';
49
+ const url = response.config.url || 'unknown';
50
+ const status = response.status;
51
+ logger.debug(`[API] ${method} ${url} -> ${status}`);
52
+ return response;
53
+ }, async (error) => {
54
+ const originalRequest = error.config;
55
+ // Log API error details for debugging/testing
56
+ const method = error.config?.method?.toUpperCase() || 'UNKNOWN';
57
+ const url = error.config?.url || 'unknown';
58
+ const status = error.response?.status || 'NO_RESPONSE';
59
+ // Extract request params (query params or request body)
60
+ let params = '';
61
+ if (error.config?.params) {
62
+ params = JSON.stringify(error.config.params);
63
+ }
64
+ else if (error.config?.data) {
65
+ try {
66
+ const data = typeof error.config.data === 'string'
67
+ ? JSON.parse(error.config.data)
68
+ : error.config.data;
69
+ // Truncate long prompts for readability
70
+ if (data.prompt && data.prompt.length > 100) {
71
+ data.prompt = data.prompt.substring(0, 100) + '...';
72
+ }
73
+ params = JSON.stringify(data);
74
+ }
75
+ catch {
76
+ params = String(error.config.data).substring(0, 200);
77
+ }
78
+ }
79
+ logger.debug(`[API] ${method} ${url} -> ${status}`, { params });
80
+ // Check if this is an auth failure (401 or redirect to auth)
81
+ const is401 = error.response?.status === 401;
82
+ const isRedirectToAuth = isAuthRedirect(error);
83
+ // If auth failure and we haven't retried yet, attempt token refresh
84
+ if ((is401 || isRedirectToAuth) && !originalRequest._retry) {
85
+ originalRequest._retry = true;
86
+ if (isRedirectToAuth) {
87
+ logger.debug('[AUTH] Received redirect to auth endpoint - token likely expired');
88
+ }
89
+ else {
90
+ logger.debug('[AUTH] Received 401 error - attempting token refresh');
91
+ }
92
+ // Attempt to refresh the token
93
+ const refreshed = await auth.refreshSession();
94
+ if (refreshed) {
95
+ logger.debug('[AUTH] Token refreshed - retrying request');
96
+ // Get the new session and update the request headers
97
+ const session = await auth.getStoredSession();
98
+ if (session && originalRequest.headers) {
99
+ originalRequest.headers.Authorization = `Bearer ${session.sealed_session}`;
100
+ }
101
+ // Retry the original request with the new token
102
+ return instance(originalRequest);
103
+ }
104
+ else {
105
+ logger.warn('[AUTH] Token refresh failed - clearing session');
106
+ // Refresh failed, clear the session
107
+ await auth.clearSession();
108
+ // Return a more user-friendly error
109
+ const authError = new Error('Authentication expired. Please run "braingrid login" to re-authenticate.');
110
+ return Promise.reject(authError);
111
+ }
112
+ }
113
+ // For all other errors or if retry already happened, just reject
114
+ return Promise.reject(error);
115
+ });
116
+ return instance;
117
+ }
118
+ //# sourceMappingURL=axios-with-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-with-auth.js","sourceRoot":"","sources":["../../src/utils/axios-with-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * CLI Tools Detection Utilities
3
+ *
4
+ * Detects installed AI coding tools and CLI utilities:
5
+ * - Checks if common AI IDE CLIs are installed
6
+ * - Gets version information where available
7
+ * - Cross-platform support (macOS, Linux, Windows)
8
+ */
9
+ export interface CliToolInfo {
10
+ name: string;
11
+ command: string;
12
+ installed: boolean;
13
+ version?: string;
14
+ }
15
+ /**
16
+ * Check if a CLI command is installed
17
+ * Uses user's shell to access PATH (supports shell-installed CLIs)
18
+ */
19
+ export declare function isCliInstalled(command: string): Promise<boolean>;
20
+ /**
21
+ * Get the version of a CLI tool
22
+ * Returns null if version cannot be determined
23
+ */
24
+ export declare function getCliVersion(command: string, versionFlag?: string, parser?: (output: string) => string | null): Promise<string | null>;
25
+ /**
26
+ * Check all configured CLI tools in parallel
27
+ * Returns array of CLI tool information
28
+ */
29
+ export declare function checkInstalledCliTools(): Promise<CliToolInfo[]>;
30
+ //# sourceMappingURL=cli-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-tools.d.ts","sourceRoot":"","sources":["../../src/utils/cli-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AA+BD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAatE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAoB,EACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACxC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAqCD;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAarE"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * CLI Tools Detection Utilities
3
+ *
4
+ * Detects installed AI coding tools and CLI utilities:
5
+ * - Checks if common AI IDE CLIs are installed
6
+ * - Gets version information where available
7
+ * - Cross-platform support (macOS, Linux, Windows)
8
+ */
9
+ import { exec } from 'child_process';
10
+ import { promisify } from 'util';
11
+ const execAsync = promisify(exec);
12
+ const CLI_TOOLS = [
13
+ {
14
+ name: 'GitHub CLI',
15
+ command: 'gh',
16
+ versionFlag: '--version',
17
+ versionParser: output => {
18
+ const match = output.match(/gh version ([\d.]+)/);
19
+ return match ? match[1] : null;
20
+ },
21
+ },
22
+ {
23
+ name: 'Claude Code',
24
+ command: 'claude',
25
+ versionFlag: '--version',
26
+ versionParser: output => {
27
+ // Output format: "2.0.1 (Claude Code)"
28
+ const match = output.match(/([\d.]+)/);
29
+ return match ? match[1] : null;
30
+ },
31
+ },
32
+ ];
33
+ /**
34
+ * Check if a CLI command is installed
35
+ * Uses user's shell to access PATH (supports shell-installed CLIs)
36
+ */
37
+ export async function isCliInstalled(command) {
38
+ try {
39
+ if (process.platform === 'win32') {
40
+ await execAsync(`where ${command}`, { timeout: 2000 });
41
+ }
42
+ else {
43
+ // Use interactive shell to access user's PATH (loads shell rc files)
44
+ const shell = process.env.SHELL || '/bin/zsh';
45
+ await execAsync(`${shell} -i -c "which ${command}" 2>/dev/null`, { timeout: 2000 });
46
+ }
47
+ return true;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ /**
54
+ * Get the version of a CLI tool
55
+ * Returns null if version cannot be determined
56
+ */
57
+ export async function getCliVersion(command, versionFlag = '--version', parser) {
58
+ try {
59
+ let stdout, stderr;
60
+ if (process.platform === 'win32') {
61
+ const result = await execAsync(`${command} ${versionFlag}`, { timeout: 2000 });
62
+ stdout = result.stdout;
63
+ stderr = result.stderr;
64
+ }
65
+ else {
66
+ // Use interactive shell to access user's PATH (loads shell rc files)
67
+ const shell = process.env.SHELL || '/bin/zsh';
68
+ const result = await execAsync(`${shell} -i -c "${command} ${versionFlag}" 2>&1`, {
69
+ timeout: 2000,
70
+ });
71
+ stdout = result.stdout;
72
+ stderr = result.stderr;
73
+ }
74
+ const output = stdout || stderr;
75
+ if (parser) {
76
+ return parser(output);
77
+ }
78
+ // Default: return first line, trimmed
79
+ return output.trim().split('\n')[0] || null;
80
+ }
81
+ catch {
82
+ return null;
83
+ }
84
+ }
85
+ /**
86
+ * Check a single CLI tool (installed status and version)
87
+ */
88
+ async function checkCliTool(config) {
89
+ const installed = await isCliInstalled(config.command);
90
+ if (!installed) {
91
+ return {
92
+ name: config.name,
93
+ command: config.command,
94
+ installed: false,
95
+ };
96
+ }
97
+ // Try to get version if tool is installed
98
+ let version;
99
+ if (config.versionFlag) {
100
+ const versionStr = await getCliVersion(config.command, config.versionFlag, config.versionParser);
101
+ if (versionStr) {
102
+ version = versionStr;
103
+ }
104
+ }
105
+ return {
106
+ name: config.name,
107
+ command: config.command,
108
+ installed: true,
109
+ version,
110
+ };
111
+ }
112
+ /**
113
+ * Check all configured CLI tools in parallel
114
+ * Returns array of CLI tool information
115
+ */
116
+ export async function checkInstalledCliTools() {
117
+ try {
118
+ const results = await Promise.all(CLI_TOOLS.map(config => checkCliTool(config)));
119
+ return results;
120
+ }
121
+ catch {
122
+ // If something goes catastrophically wrong, return empty array
123
+ // This ensures status command never fails due to CLI detection
124
+ return CLI_TOOLS.map(config => ({
125
+ name: config.name,
126
+ command: config.command,
127
+ installed: false,
128
+ }));
129
+ }
130
+ }
131
+ //# sourceMappingURL=cli-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-tools.js","sourceRoot":"","sources":["../../src/utils/cli-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export interface ExecResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ }
5
+ export interface ExecOptions {
6
+ maxBuffer?: number;
7
+ timeout?: number;
8
+ cwd?: string;
9
+ env?: NodeJS.ProcessEnv;
10
+ }
11
+ /**
12
+ * Execute a command asynchronously with proper buffer limits and timeout handling
13
+ */
14
+ export declare function execAsync(command: string, options?: ExecOptions, isTestMode?: boolean, mockExecHandler?: (command: string) => Promise<ExecResult>): Promise<ExecResult>;
15
+ /**
16
+ * Execute a command with streaming output support
17
+ */
18
+ export declare function execStreamAsync(command: string, onOutput?: (chunk: string) => void, isTestMode?: boolean, mockExecHandler?: (command: string) => Promise<ExecResult>, options?: {
19
+ timeout?: number;
20
+ inactivityTimeout?: number;
21
+ }): Promise<ExecResult>;
22
+ /**
23
+ * Execute git commit with smart timeout handling for pre-commit hooks
24
+ */
25
+ export declare function execGitCommitAsync(commitMessage: string, onOutput?: (chunk: string) => void, isTestMode?: boolean, mockExecHandler?: (command: string) => Promise<ExecResult>): Promise<ExecResult>;
26
+ /**
27
+ * Mock execution handler for testing
28
+ */
29
+ export declare function createMockExecHandler(addMessage?: (type: 'info' | 'error' | 'system', content: string) => void): Promise<(command: string) => Promise<ExecResult>>;
30
+ //# sourceMappingURL=command-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-execution.d.ts","sourceRoot":"","sources":["../../src/utils/command-execution.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAID;;GAEG;AACH,wBAAsB,SAAS,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,EACrB,UAAU,GAAE,OAAe,EAC3B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GACxD,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAClC,UAAU,GAAE,OAAe,EAC3B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,EAC1D,OAAO,CAAC,EAAE;IACT,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B,GACC,OAAO,CAAC,UAAU,CAAC,CA6IrB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACvC,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAClC,UAAU,GAAE,OAAe,EAC3B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GACxD,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAC1C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACvE,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CA+FnD"}