@kodus/cli 0.0.11 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +387 -0
  2. package/dist/cli.d.ts +4 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +26 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/auth/index.d.ts +3 -0
  7. package/dist/commands/auth/index.d.ts.map +1 -0
  8. package/dist/commands/auth/index.js +36 -0
  9. package/dist/commands/auth/index.js.map +1 -0
  10. package/dist/commands/auth/login.d.ts +7 -0
  11. package/dist/commands/auth/login.d.ts.map +1 -0
  12. package/dist/commands/auth/login.js +97 -0
  13. package/dist/commands/auth/login.js.map +1 -0
  14. package/dist/commands/auth/logout.d.ts +2 -0
  15. package/dist/commands/auth/logout.d.ts.map +1 -0
  16. package/dist/commands/auth/logout.js +24 -0
  17. package/dist/commands/auth/logout.js.map +1 -0
  18. package/dist/commands/auth/signup.d.ts +2 -0
  19. package/dist/commands/auth/signup.d.ts.map +1 -0
  20. package/dist/commands/auth/signup.js +74 -0
  21. package/dist/commands/auth/signup.js.map +1 -0
  22. package/dist/commands/auth/status.d.ts +2 -0
  23. package/dist/commands/auth/status.d.ts.map +1 -0
  24. package/dist/commands/auth/status.js +91 -0
  25. package/dist/commands/auth/status.js.map +1 -0
  26. package/dist/commands/auth/team-key.d.ts +5 -0
  27. package/dist/commands/auth/team-key.d.ts.map +1 -0
  28. package/dist/commands/auth/team-key.js +59 -0
  29. package/dist/commands/auth/team-key.js.map +1 -0
  30. package/dist/commands/auth/token.d.ts +2 -0
  31. package/dist/commands/auth/token.d.ts.map +1 -0
  32. package/dist/commands/auth/token.js +31 -0
  33. package/dist/commands/auth/token.js.map +1 -0
  34. package/dist/commands/config.d.ts +3 -0
  35. package/dist/commands/config.d.ts.map +1 -0
  36. package/dist/commands/config.js +47 -0
  37. package/dist/commands/config.js.map +1 -0
  38. package/dist/commands/pr.d.ts +3 -0
  39. package/dist/commands/pr.d.ts.map +1 -0
  40. package/dist/commands/pr.js +75 -0
  41. package/dist/commands/pr.js.map +1 -0
  42. package/dist/commands/review.d.ts +3 -0
  43. package/dist/commands/review.d.ts.map +1 -0
  44. package/dist/commands/review.js +245 -0
  45. package/dist/commands/review.js.map +1 -0
  46. package/dist/commands/telemetry.d.ts +3 -0
  47. package/dist/commands/telemetry.d.ts.map +1 -0
  48. package/dist/commands/telemetry.js +76 -0
  49. package/dist/commands/telemetry.js.map +1 -0
  50. package/dist/commands/upgrade.d.ts +3 -0
  51. package/dist/commands/upgrade.d.ts.map +1 -0
  52. package/dist/commands/upgrade.js +35 -0
  53. package/dist/commands/upgrade.js.map +1 -0
  54. package/dist/constants.d.ts +3 -0
  55. package/dist/constants.d.ts.map +1 -0
  56. package/dist/constants.js +3 -0
  57. package/dist/constants.js.map +1 -0
  58. package/dist/formatters/json.d.ts +7 -0
  59. package/dist/formatters/json.d.ts.map +1 -0
  60. package/dist/formatters/json.js +7 -0
  61. package/dist/formatters/json.js.map +1 -0
  62. package/dist/formatters/markdown.d.ts +7 -0
  63. package/dist/formatters/markdown.d.ts.map +1 -0
  64. package/dist/formatters/markdown.js +93 -0
  65. package/dist/formatters/markdown.js.map +1 -0
  66. package/dist/formatters/prompt.d.ts +12 -0
  67. package/dist/formatters/prompt.d.ts.map +1 -0
  68. package/dist/formatters/prompt.js +90 -0
  69. package/dist/formatters/prompt.js.map +1 -0
  70. package/dist/formatters/terminal.d.ts +7 -0
  71. package/dist/formatters/terminal.d.ts.map +1 -0
  72. package/dist/formatters/terminal.js +127 -0
  73. package/dist/formatters/terminal.js.map +1 -0
  74. package/dist/index.d.ts +3 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +4 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/services/api/api.interface.d.ts +46 -0
  79. package/dist/services/api/api.interface.d.ts.map +1 -0
  80. package/dist/services/api/api.interface.js +2 -0
  81. package/dist/services/api/api.interface.js.map +1 -0
  82. package/dist/services/api/api.mock.d.ts +8 -0
  83. package/dist/services/api/api.mock.d.ts.map +1 -0
  84. package/dist/services/api/api.mock.js +249 -0
  85. package/dist/services/api/api.mock.js.map +1 -0
  86. package/dist/services/api/api.real.d.ts +8 -0
  87. package/dist/services/api/api.real.d.ts.map +1 -0
  88. package/dist/services/api/api.real.js +253 -0
  89. package/dist/services/api/api.real.js.map +1 -0
  90. package/dist/services/api/index.d.ts +4 -0
  91. package/dist/services/api/index.d.ts.map +1 -0
  92. package/dist/services/api/index.js +9 -0
  93. package/dist/services/api/index.js.map +1 -0
  94. package/dist/services/auth.service.d.ts +19 -0
  95. package/dist/services/auth.service.d.ts.map +1 -0
  96. package/dist/services/auth.service.js +90 -0
  97. package/dist/services/auth.service.js.map +1 -0
  98. package/dist/services/context.service.d.ts +22 -0
  99. package/dist/services/context.service.d.ts.map +1 -0
  100. package/dist/services/context.service.js +104 -0
  101. package/dist/services/context.service.js.map +1 -0
  102. package/dist/services/fix.service.d.ts +31 -0
  103. package/dist/services/fix.service.d.ts.map +1 -0
  104. package/dist/services/fix.service.js +120 -0
  105. package/dist/services/fix.service.js.map +1 -0
  106. package/dist/services/git.service.d.ts +32 -0
  107. package/dist/services/git.service.d.ts.map +1 -0
  108. package/dist/services/git.service.js +261 -0
  109. package/dist/services/git.service.js.map +1 -0
  110. package/dist/services/review.service.d.ts +26 -0
  111. package/dist/services/review.service.d.ts.map +1 -0
  112. package/dist/services/review.service.js +82 -0
  113. package/dist/services/review.service.js.map +1 -0
  114. package/dist/services/telemetry.service.d.ts +73 -0
  115. package/dist/services/telemetry.service.d.ts.map +1 -0
  116. package/dist/services/telemetry.service.js +229 -0
  117. package/dist/services/telemetry.service.js.map +1 -0
  118. package/dist/types/index.d.ts +143 -0
  119. package/dist/types/index.d.ts.map +1 -0
  120. package/dist/types/index.js +15 -0
  121. package/dist/types/index.js.map +1 -0
  122. package/dist/ui/interactive.d.ts +26 -0
  123. package/dist/ui/interactive.d.ts.map +1 -0
  124. package/dist/ui/interactive.js +365 -0
  125. package/dist/ui/interactive.js.map +1 -0
  126. package/dist/utils/config.d.ts +10 -0
  127. package/dist/utils/config.d.ts.map +1 -0
  128. package/dist/utils/config.js +54 -0
  129. package/dist/utils/config.js.map +1 -0
  130. package/dist/utils/credentials.d.ts +6 -0
  131. package/dist/utils/credentials.d.ts.map +1 -0
  132. package/dist/utils/credentials.js +54 -0
  133. package/dist/utils/credentials.js.map +1 -0
  134. package/dist/utils/rate-limit.d.ts +5 -0
  135. package/dist/utils/rate-limit.d.ts.map +1 -0
  136. package/dist/utils/rate-limit.js +47 -0
  137. package/dist/utils/rate-limit.js.map +1 -0
  138. package/dist/utils/review-loading.d.ts +19 -0
  139. package/dist/utils/review-loading.d.ts.map +1 -0
  140. package/dist/utils/review-loading.js +140 -0
  141. package/dist/utils/review-loading.js.map +1 -0
  142. package/package.json +39 -33
  143. package/index.js +0 -17
  144. package/license.md +0 -21
  145. package/readme.md +0 -128
  146. package/scripts/setup-db.sh +0 -77
  147. package/src/commands/install.js +0 -324
  148. package/src/config/default.js +0 -66
  149. package/src/utils/helpers.js +0 -118
  150. package/templates/docker-compose.yml +0 -139
@@ -0,0 +1,253 @@
1
+ import { ApiError } from '../../types/index.js';
2
+ /**
3
+ * Validates and returns the API base URL
4
+ * Prevents URL injection attacks by validating custom API URLs
5
+ */
6
+ function getApiBaseUrl() {
7
+ const customUrl = process.env.KODUS_API_URL;
8
+ const defaultUrl = 'https://api.kodus.io';
9
+ if (!customUrl) {
10
+ return defaultUrl;
11
+ }
12
+ try {
13
+ const url = new URL(customUrl);
14
+ // Only allow HTTPS (except localhost for development)
15
+ const isLocalhost = url.hostname === 'localhost' || url.hostname === '127.0.0.1';
16
+ if (url.protocol !== 'https:' && !isLocalhost) {
17
+ console.error('Security Error: KODUS_API_URL must use HTTPS protocol');
18
+ console.error(`Falling back to default: ${defaultUrl}`);
19
+ return defaultUrl;
20
+ }
21
+ // Warn about non-standard API URLs
22
+ const standardDomains = ['api.kodus.io', 'localhost', '127.0.0.1'];
23
+ const isStandard = standardDomains.some(domain => url.hostname === domain || url.hostname.endsWith(`.${domain}`));
24
+ if (!isStandard && process.env.KODUS_VERBOSE) {
25
+ console.warn(`Warning: Using non-standard API URL: ${url.hostname}`);
26
+ }
27
+ return customUrl;
28
+ }
29
+ catch (error) {
30
+ console.error('Invalid KODUS_API_URL format:', customUrl);
31
+ console.error(`Falling back to default: ${defaultUrl}`);
32
+ return defaultUrl;
33
+ }
34
+ }
35
+ const API_BASE_URL = getApiBaseUrl();
36
+ async function request(endpoint, options = {}) {
37
+ const url = `${API_BASE_URL}${endpoint}`;
38
+ const response = await fetch(url, {
39
+ ...options,
40
+ headers: {
41
+ 'Content-Type': 'application/json',
42
+ ...options.headers,
43
+ },
44
+ });
45
+ if (!response.ok) {
46
+ const errorData = await response.json().catch(() => ({ message: 'Request failed' }));
47
+ const errorMessage = errorData.message || `Request failed with status ${response.status}`;
48
+ if (process.env.KODUS_VERBOSE) {
49
+ console.error('API Error:', { status: response.status, url, errorData });
50
+ }
51
+ throw new ApiError(response.status, errorMessage);
52
+ }
53
+ const json = await response.json();
54
+ // API retorna { data: {...}, statusCode, type }
55
+ // Extrair apenas o .data se existir
56
+ if (json && typeof json === 'object' && 'data' in json) {
57
+ return json.data;
58
+ }
59
+ return json;
60
+ }
61
+ class RealAuthApi {
62
+ async login(email, password) {
63
+ const response = await request('/auth/login', {
64
+ method: 'POST',
65
+ body: JSON.stringify({ email, password }),
66
+ });
67
+ // Mapear resposta da API para formato esperado pelo CLI
68
+ return {
69
+ accessToken: response.accessToken,
70
+ refreshToken: response.refreshToken,
71
+ expiresIn: 3600, // Default: 1 hora
72
+ user: {
73
+ id: 'unknown', // API não retorna user info no login
74
+ email,
75
+ orgs: [],
76
+ },
77
+ };
78
+ }
79
+ async signup(email, password) {
80
+ // Signup não é permitido via CLI - só via app.kodus.io
81
+ throw new Error('Signup is not available via CLI. Please sign up at https://app.kodus.io');
82
+ }
83
+ async refresh(refreshToken) {
84
+ return request('/auth/refresh', {
85
+ method: 'POST',
86
+ body: JSON.stringify({ refreshToken }),
87
+ });
88
+ }
89
+ async logout(accessToken) {
90
+ await request('/auth/logout', {
91
+ method: 'POST',
92
+ headers: {
93
+ Authorization: `Bearer ${accessToken}`,
94
+ },
95
+ });
96
+ }
97
+ async generateCIToken(accessToken) {
98
+ const response = await request('/auth/ci-token', {
99
+ method: 'POST',
100
+ headers: {
101
+ Authorization: `Bearer ${accessToken}`,
102
+ },
103
+ });
104
+ return response.token;
105
+ }
106
+ async verify(accessToken) {
107
+ // SECURITY NOTE: This performs basic client-side JWT validation without signature verification.
108
+ // This is acceptable for a CLI client where:
109
+ // 1. The token is securely stored locally and only accessed by the user
110
+ // 2. The API validates the token signature on every request
111
+ // 3. We only check format and expiration to avoid unnecessary API calls
112
+ //
113
+ // For production security, all authorization decisions MUST be made by the API
114
+ // after validating the token signature.
115
+ if (!accessToken || !accessToken.startsWith('eyJ')) {
116
+ return { valid: false };
117
+ }
118
+ try {
119
+ // Decode JWT payload (without signature validation)
120
+ const parts = accessToken.split('.');
121
+ if (parts.length !== 3) {
122
+ return { valid: false };
123
+ }
124
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString());
125
+ // Check expiration
126
+ if (payload.exp && payload.exp * 1000 < Date.now()) {
127
+ return { valid: false };
128
+ }
129
+ return {
130
+ valid: true,
131
+ user: {
132
+ id: payload.sub || 'unknown',
133
+ email: payload.email || 'unknown',
134
+ orgs: [],
135
+ },
136
+ };
137
+ }
138
+ catch (error) {
139
+ if (process.env.KODUS_VERBOSE) {
140
+ console.error('Token verification failed:', error);
141
+ }
142
+ return { valid: false };
143
+ }
144
+ }
145
+ }
146
+ class RealReviewApi {
147
+ async analyze(diff, accessToken, config) {
148
+ const isTeamKey = accessToken.startsWith('kodus_');
149
+ if (isTeamKey) {
150
+ return request('/cli/review', {
151
+ method: 'POST',
152
+ headers: {
153
+ 'X-Team-Key': accessToken,
154
+ },
155
+ body: JSON.stringify({ diff, config }),
156
+ });
157
+ }
158
+ let teamId;
159
+ try {
160
+ const payload = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString());
161
+ teamId = payload.organizationId;
162
+ }
163
+ catch (error) {
164
+ // Ignore if cannot decode
165
+ }
166
+ const endpoint = teamId ? `/cli/review?teamId=${encodeURIComponent(teamId)}` : '/cli/review';
167
+ return request(endpoint, {
168
+ method: 'POST',
169
+ headers: {
170
+ Authorization: `Bearer ${accessToken}`,
171
+ },
172
+ body: JSON.stringify({ diff, config }),
173
+ });
174
+ }
175
+ async analyzeWithMetrics(diff, accessToken, config, metrics) {
176
+ const isTeamKey = accessToken.startsWith('kodus_');
177
+ if (isTeamKey) {
178
+ return request('/cli/review', {
179
+ method: 'POST',
180
+ headers: {
181
+ 'X-Team-Key': accessToken,
182
+ },
183
+ body: JSON.stringify({
184
+ diff,
185
+ config,
186
+ ...metrics,
187
+ }),
188
+ });
189
+ }
190
+ return this.analyze(diff, accessToken, config);
191
+ }
192
+ async getPullRequestSuggestions(accessToken, params) {
193
+ const query = new URLSearchParams();
194
+ if (params.prUrl) {
195
+ query.set('prUrl', params.prUrl);
196
+ }
197
+ if (params.prNumber !== undefined) {
198
+ query.set('prNumber', params.prNumber.toString());
199
+ }
200
+ if (params.repositoryId) {
201
+ query.set('repositoryId', params.repositoryId);
202
+ }
203
+ if (params.format) {
204
+ query.set('format', params.format);
205
+ }
206
+ if (params.severity) {
207
+ query.set('severity', params.severity);
208
+ }
209
+ if (params.category) {
210
+ query.set('category', params.category);
211
+ }
212
+ const queryString = query.toString();
213
+ const endpoint = `/pull-requests/suggestions${queryString ? `?${queryString}` : ''}`;
214
+ return request(endpoint, {
215
+ headers: {
216
+ Authorization: `Bearer ${accessToken}`,
217
+ },
218
+ });
219
+ }
220
+ async trialAnalyze(diff, fingerprint) {
221
+ return request('/cli/trial/review', {
222
+ method: 'POST',
223
+ body: JSON.stringify({ diff, fingerprint }),
224
+ });
225
+ }
226
+ }
227
+ class RealConfigApi {
228
+ async get(accessToken, org, repo) {
229
+ const params = new URLSearchParams();
230
+ if (org)
231
+ params.set('org', org);
232
+ if (repo)
233
+ params.set('repo', repo);
234
+ const query = params.toString() ? `?${params.toString()}` : '';
235
+ return request(`/cli/config${query}`, {
236
+ headers: {
237
+ Authorization: `Bearer ${accessToken}`,
238
+ },
239
+ });
240
+ }
241
+ }
242
+ class RealTrialApi {
243
+ async getStatus(fingerprint) {
244
+ return request(`/cli/trial/status?fingerprint=${fingerprint}`);
245
+ }
246
+ }
247
+ export class RealApi {
248
+ auth = new RealAuthApi();
249
+ review = new RealReviewApi();
250
+ config = new RealConfigApi();
251
+ trial = new RealTrialApi();
252
+ }
253
+ //# sourceMappingURL=api.real.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.real.js","sourceRoot":"","sources":["../../../src/services/api/api.real.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { IKodusApi } from './api.interface.js';
2
+ export type { IKodusApi } from './api.interface.js';
3
+ export declare const api: IKodusApi;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIpD,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAUpD,eAAO,MAAM,GAAG,WAAc,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { MockApi } from './api.mock.js';
2
+ import { RealApi } from './api.real.js';
3
+ function createApi() {
4
+ const useMock = process.env.KODUS_MOCK === 'true' ||
5
+ (!process.env.KODUS_API_URL && process.env.NODE_ENV !== 'production');
6
+ return useMock ? new MockApi() : new RealApi();
7
+ }
8
+ export const api = createApi();
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/api/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAIxC,SAAS,SAAS;IAChB,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,MAAM;QACjC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;IAExE,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { StoredCredentials } from '../types/index.js';
2
+ declare class AuthService {
3
+ private cachedCredentials;
4
+ login(email: string, password: string): Promise<void>;
5
+ signup(email: string, password: string): Promise<void>;
6
+ logout(): Promise<void>;
7
+ isAuthenticated(): Promise<boolean>;
8
+ getCredentials(): Promise<StoredCredentials | null>;
9
+ getValidToken(): Promise<string>;
10
+ generateCIToken(): Promise<string>;
11
+ verifyToken(): Promise<{
12
+ valid: boolean;
13
+ user?: any;
14
+ }>;
15
+ private storeAuthResponse;
16
+ }
17
+ export declare const authService: AuthService;
18
+ export {};
19
+ //# sourceMappingURL=auth.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,mBAAmB,CAAC;AAKzE,cAAM,WAAW;IACf,OAAO,CAAC,iBAAiB,CAAkC;IAErD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAevB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAQnC,cAAc,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IASnD,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IA6BhC,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAKlC,WAAW,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;YAU9C,iBAAiB;CAWhC;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { api } from './api/index.js';
2
+ import { loadCredentials, saveCredentials, clearCredentials, } from '../utils/credentials.js';
3
+ import { loadConfig } from '../utils/config.js';
4
+ import { AuthError } from '../types/index.js';
5
+ const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
6
+ class AuthService {
7
+ cachedCredentials = null;
8
+ async login(email, password) {
9
+ const response = await api.auth.login(email, password);
10
+ await this.storeAuthResponse(response);
11
+ }
12
+ async signup(email, password) {
13
+ const response = await api.auth.signup(email, password);
14
+ await this.storeAuthResponse(response);
15
+ }
16
+ async logout() {
17
+ const credentials = await this.getCredentials();
18
+ if (credentials) {
19
+ try {
20
+ await api.auth.logout(credentials.accessToken);
21
+ }
22
+ catch {
23
+ // Ignore logout errors
24
+ }
25
+ }
26
+ await clearCredentials();
27
+ this.cachedCredentials = null;
28
+ }
29
+ async isAuthenticated() {
30
+ const credentials = await this.getCredentials();
31
+ if (credentials !== null)
32
+ return true;
33
+ const config = await loadConfig();
34
+ return !!config?.teamKey;
35
+ }
36
+ async getCredentials() {
37
+ if (this.cachedCredentials) {
38
+ return this.cachedCredentials;
39
+ }
40
+ this.cachedCredentials = await loadCredentials();
41
+ return this.cachedCredentials;
42
+ }
43
+ async getValidToken() {
44
+ const config = await loadConfig();
45
+ if (config?.teamKey) {
46
+ return config.teamKey;
47
+ }
48
+ const credentials = await this.getCredentials();
49
+ if (!credentials) {
50
+ throw new AuthError('Not authenticated. Run: kodus auth login or kodus auth team-key --key <your-key>');
51
+ }
52
+ const isExpired = Date.now() > credentials.expiresAt - TOKEN_REFRESH_BUFFER_MS;
53
+ if (isExpired) {
54
+ try {
55
+ const response = await api.auth.refresh(credentials.refreshToken);
56
+ await this.storeAuthResponse(response);
57
+ return response.accessToken;
58
+ }
59
+ catch (error) {
60
+ await clearCredentials();
61
+ this.cachedCredentials = null;
62
+ throw new AuthError('Session expired. Run: kodus auth login');
63
+ }
64
+ }
65
+ return credentials.accessToken;
66
+ }
67
+ async generateCIToken() {
68
+ const token = await this.getValidToken();
69
+ return api.auth.generateCIToken(token);
70
+ }
71
+ async verifyToken() {
72
+ const credentials = await this.getCredentials();
73
+ if (!credentials) {
74
+ return { valid: false };
75
+ }
76
+ return api.auth.verify(credentials.accessToken);
77
+ }
78
+ async storeAuthResponse(response) {
79
+ const credentials = {
80
+ accessToken: response.accessToken,
81
+ refreshToken: response.refreshToken,
82
+ expiresAt: Date.now() + response.expiresIn * 1000,
83
+ user: response.user,
84
+ };
85
+ await saveCredentials(credentials);
86
+ this.cachedCredentials = credentials;
87
+ }
88
+ }
89
+ export const authService = new AuthService();
90
+ //# sourceMappingURL=auth.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ProjectContext } from '../types/index.js';
2
+ /**
3
+ * Context Service - Reads project context files
4
+ * Similar to CodeRabbit CLI reading .cursorrules, claude.md, etc.
5
+ */
6
+ declare class ContextService {
7
+ private fileExists;
8
+ private readFile;
9
+ private getRepoRoot;
10
+ readProjectContext(customContextPath?: string): Promise<ProjectContext>;
11
+ /**
12
+ * Formats project context for inclusion in review requests
13
+ */
14
+ formatContextForReview(context: ProjectContext): string;
15
+ /**
16
+ * Enriches diff with project context
17
+ */
18
+ enrichDiffWithContext(diff: string, customContextPath?: string): Promise<string>;
19
+ }
20
+ export declare const contextService: ContextService;
21
+ export {};
22
+ //# sourceMappingURL=context.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.service.d.ts","sourceRoot":"","sources":["../../src/services/context.service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;GAGG;AACH,cAAM,cAAc;YACJ,UAAU;YASV,QAAQ;YAYR,WAAW;IAWnB,kBAAkB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6B7E;;OAEG;IACH,sBAAsB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IA8BvD;;OAEG;IACG,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAUvF;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
@@ -0,0 +1,104 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { simpleGit } from 'simple-git';
4
+ /**
5
+ * Context Service - Reads project context files
6
+ * Similar to CodeRabbit CLI reading .cursorrules, claude.md, etc.
7
+ */
8
+ class ContextService {
9
+ async fileExists(filePath) {
10
+ try {
11
+ await fs.access(filePath);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ async readFile(filePath) {
19
+ try {
20
+ const exists = await this.fileExists(filePath);
21
+ if (!exists)
22
+ return undefined;
23
+ const content = await fs.readFile(filePath, 'utf-8');
24
+ return content.trim();
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ async getRepoRoot() {
31
+ try {
32
+ const git = simpleGit();
33
+ const root = await git.revparse(['--show-toplevel']);
34
+ return root.trim();
35
+ }
36
+ catch {
37
+ // Fallback to current directory
38
+ return process.cwd();
39
+ }
40
+ }
41
+ async readProjectContext(customContextPath) {
42
+ const repoRoot = await this.getRepoRoot();
43
+ const context = {};
44
+ // Read .cursorrules
45
+ const cursorRulesPath = path.join(repoRoot, '.cursorrules');
46
+ context.cursorRules = await this.readFile(cursorRulesPath);
47
+ // Read claude.md or .claude.md
48
+ const claudeMdPath = path.join(repoRoot, 'claude.md');
49
+ const dotClaudeMdPath = path.join(repoRoot, '.claude.md');
50
+ context.claudeRules = await this.readFile(claudeMdPath) || await this.readFile(dotClaudeMdPath);
51
+ // Read .kodus.md or .kodus/rules.md
52
+ const kodusMdPath = path.join(repoRoot, '.kodus.md');
53
+ const kodusRulesPath = path.join(repoRoot, '.kodus', 'rules.md');
54
+ context.kodusRules = await this.readFile(kodusMdPath) || await this.readFile(kodusRulesPath);
55
+ // Read custom context file if specified
56
+ if (customContextPath) {
57
+ const customPath = path.isAbsolute(customContextPath)
58
+ ? customContextPath
59
+ : path.join(repoRoot, customContextPath);
60
+ context.customContext = await this.readFile(customPath);
61
+ }
62
+ return context;
63
+ }
64
+ /**
65
+ * Formats project context for inclusion in review requests
66
+ */
67
+ formatContextForReview(context) {
68
+ const parts = [];
69
+ if (context.cursorRules) {
70
+ parts.push('=== Cursor Rules (.cursorrules) ===');
71
+ parts.push(context.cursorRules);
72
+ parts.push('');
73
+ }
74
+ if (context.claudeRules) {
75
+ parts.push('=== Claude Rules (claude.md) ===');
76
+ parts.push(context.claudeRules);
77
+ parts.push('');
78
+ }
79
+ if (context.kodusRules) {
80
+ parts.push('=== Kodus Rules (.kodus.md) ===');
81
+ parts.push(context.kodusRules);
82
+ parts.push('');
83
+ }
84
+ if (context.customContext) {
85
+ parts.push('=== Custom Context ===');
86
+ parts.push(context.customContext);
87
+ parts.push('');
88
+ }
89
+ return parts.join('\n');
90
+ }
91
+ /**
92
+ * Enriches diff with project context
93
+ */
94
+ async enrichDiffWithContext(diff, customContextPath) {
95
+ const context = await this.readProjectContext(customContextPath);
96
+ const formattedContext = this.formatContextForReview(context);
97
+ if (!formattedContext) {
98
+ return diff;
99
+ }
100
+ return `${formattedContext}\n=== Code Changes ===\n${diff}`;
101
+ }
102
+ }
103
+ export const contextService = new ContextService();
104
+ //# sourceMappingURL=context.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.service.js","sourceRoot":"","sources":["../../src/services/context.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { ReviewIssue } from '../types/index.js';
2
+ /**
3
+ * Fix Service - Applies code fixes to files
4
+ */
5
+ declare class FixService {
6
+ /**
7
+ * Applies a single fix to a file
8
+ */
9
+ applyFix(issue: ReviewIssue): Promise<void>;
10
+ /**
11
+ * Applies multiple fixes to files
12
+ */
13
+ applyFixes(issues: ReviewIssue[]): Promise<{
14
+ applied: number;
15
+ failed: number;
16
+ }>;
17
+ /**
18
+ * Generates a preview diff for a fix
19
+ */
20
+ generatePreview(issue: ReviewIssue): string;
21
+ private applyReplace;
22
+ private applyInsert;
23
+ private applyDelete;
24
+ /**
25
+ * Checks if a fix can be safely applied
26
+ */
27
+ canApplyFix(issue: ReviewIssue): Promise<boolean>;
28
+ }
29
+ export declare const fixService: FixService;
30
+ export {};
31
+ //# sourceMappingURL=fix.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.service.d.ts","sourceRoot":"","sources":["../../src/services/fix.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAW,MAAM,mBAAmB,CAAC;AAE9D;;GAEG;AACH,cAAM,UAAU;IACd;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAmCrF;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;YAoB7B,YAAY;YAcZ,WAAW;YASX,WAAW;IASzB;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CAaxD;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}