@chrishdx/llm-dev-server 1.0.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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +164 -0
  3. package/backend/bin/llm-dev-server.js +3 -0
  4. package/backend/dist/cli.d.ts +15 -0
  5. package/backend/dist/cli.d.ts.map +1 -0
  6. package/backend/dist/cli.js +326 -0
  7. package/backend/dist/cli.js.map +1 -0
  8. package/backend/dist/config/database.d.ts +10 -0
  9. package/backend/dist/config/database.d.ts.map +1 -0
  10. package/backend/dist/config/database.js +61 -0
  11. package/backend/dist/config/database.js.map +1 -0
  12. package/backend/dist/config/environment.d.ts +20 -0
  13. package/backend/dist/config/environment.d.ts.map +1 -0
  14. package/backend/dist/config/environment.js +77 -0
  15. package/backend/dist/config/environment.js.map +1 -0
  16. package/backend/dist/controllers/AuthController.d.ts +18 -0
  17. package/backend/dist/controllers/AuthController.d.ts.map +1 -0
  18. package/backend/dist/controllers/AuthController.js +282 -0
  19. package/backend/dist/controllers/AuthController.js.map +1 -0
  20. package/backend/dist/controllers/ConversationController.d.ts +44 -0
  21. package/backend/dist/controllers/ConversationController.d.ts.map +1 -0
  22. package/backend/dist/controllers/ConversationController.js +193 -0
  23. package/backend/dist/controllers/ConversationController.js.map +1 -0
  24. package/backend/dist/controllers/JobController.d.ts +49 -0
  25. package/backend/dist/controllers/JobController.d.ts.map +1 -0
  26. package/backend/dist/controllers/JobController.js +227 -0
  27. package/backend/dist/controllers/JobController.js.map +1 -0
  28. package/backend/dist/index.d.ts +2 -0
  29. package/backend/dist/index.d.ts.map +1 -0
  30. package/backend/dist/index.js +160 -0
  31. package/backend/dist/index.js.map +1 -0
  32. package/backend/dist/middleware/auth.middleware.d.ts +25 -0
  33. package/backend/dist/middleware/auth.middleware.d.ts.map +1 -0
  34. package/backend/dist/middleware/auth.middleware.js +116 -0
  35. package/backend/dist/middleware/auth.middleware.js.map +1 -0
  36. package/backend/dist/middleware/authelia.middleware.d.ts +26 -0
  37. package/backend/dist/middleware/authelia.middleware.d.ts.map +1 -0
  38. package/backend/dist/middleware/authelia.middleware.js +165 -0
  39. package/backend/dist/middleware/authelia.middleware.js.map +1 -0
  40. package/backend/dist/middleware/error.middleware.d.ts +23 -0
  41. package/backend/dist/middleware/error.middleware.d.ts.map +1 -0
  42. package/backend/dist/middleware/error.middleware.js +59 -0
  43. package/backend/dist/middleware/error.middleware.js.map +1 -0
  44. package/backend/dist/models/AuthToken.d.ts +42 -0
  45. package/backend/dist/models/AuthToken.d.ts.map +1 -0
  46. package/backend/dist/models/AuthToken.js +97 -0
  47. package/backend/dist/models/AuthToken.js.map +1 -0
  48. package/backend/dist/models/Conversation.d.ts +36 -0
  49. package/backend/dist/models/Conversation.d.ts.map +1 -0
  50. package/backend/dist/models/Conversation.js +100 -0
  51. package/backend/dist/models/Conversation.js.map +1 -0
  52. package/backend/dist/models/FileOperation.d.ts +36 -0
  53. package/backend/dist/models/FileOperation.d.ts.map +1 -0
  54. package/backend/dist/models/FileOperation.js +117 -0
  55. package/backend/dist/models/FileOperation.js.map +1 -0
  56. package/backend/dist/models/Job.d.ts +48 -0
  57. package/backend/dist/models/Job.d.ts.map +1 -0
  58. package/backend/dist/models/Job.js +87 -0
  59. package/backend/dist/models/Job.js.map +1 -0
  60. package/backend/dist/models/Message.d.ts +38 -0
  61. package/backend/dist/models/Message.d.ts.map +1 -0
  62. package/backend/dist/models/Message.js +87 -0
  63. package/backend/dist/models/Message.js.map +1 -0
  64. package/backend/dist/models/User.d.ts +26 -0
  65. package/backend/dist/models/User.d.ts.map +1 -0
  66. package/backend/dist/models/User.js +67 -0
  67. package/backend/dist/models/User.js.map +1 -0
  68. package/backend/dist/models/index.d.ts +13 -0
  69. package/backend/dist/models/index.d.ts.map +1 -0
  70. package/backend/dist/models/index.js +24 -0
  71. package/backend/dist/models/index.js.map +1 -0
  72. package/backend/dist/routes/auth.routes.d.ts +3 -0
  73. package/backend/dist/routes/auth.routes.d.ts.map +1 -0
  74. package/backend/dist/routes/auth.routes.js +27 -0
  75. package/backend/dist/routes/auth.routes.js.map +1 -0
  76. package/backend/dist/routes/conversation.routes.d.ts +3 -0
  77. package/backend/dist/routes/conversation.routes.d.ts.map +1 -0
  78. package/backend/dist/routes/conversation.routes.js +17 -0
  79. package/backend/dist/routes/conversation.routes.js.map +1 -0
  80. package/backend/dist/routes/filesystem.routes.d.ts +3 -0
  81. package/backend/dist/routes/filesystem.routes.d.ts.map +1 -0
  82. package/backend/dist/routes/filesystem.routes.js +64 -0
  83. package/backend/dist/routes/filesystem.routes.js.map +1 -0
  84. package/backend/dist/routes/index.d.ts +3 -0
  85. package/backend/dist/routes/index.d.ts.map +1 -0
  86. package/backend/dist/routes/index.js +27 -0
  87. package/backend/dist/routes/index.js.map +1 -0
  88. package/backend/dist/routes/job.routes.d.ts +3 -0
  89. package/backend/dist/routes/job.routes.d.ts.map +1 -0
  90. package/backend/dist/routes/job.routes.js +18 -0
  91. package/backend/dist/routes/job.routes.js.map +1 -0
  92. package/backend/dist/services/auth/BaseAuthService.d.ts +49 -0
  93. package/backend/dist/services/auth/BaseAuthService.d.ts.map +1 -0
  94. package/backend/dist/services/auth/BaseAuthService.js +97 -0
  95. package/backend/dist/services/auth/BaseAuthService.js.map +1 -0
  96. package/backend/dist/services/auth/ClaudeAuthService.d.ts +69 -0
  97. package/backend/dist/services/auth/ClaudeAuthService.d.ts.map +1 -0
  98. package/backend/dist/services/auth/ClaudeAuthService.js +401 -0
  99. package/backend/dist/services/auth/ClaudeAuthService.js.map +1 -0
  100. package/backend/dist/services/auth/CodexAuthService.d.ts +37 -0
  101. package/backend/dist/services/auth/CodexAuthService.d.ts.map +1 -0
  102. package/backend/dist/services/auth/CodexAuthService.js +186 -0
  103. package/backend/dist/services/auth/CodexAuthService.js.map +1 -0
  104. package/backend/dist/services/auth/GeminiAuthService.d.ts +50 -0
  105. package/backend/dist/services/auth/GeminiAuthService.d.ts.map +1 -0
  106. package/backend/dist/services/auth/GeminiAuthService.js +284 -0
  107. package/backend/dist/services/auth/GeminiAuthService.js.map +1 -0
  108. package/backend/dist/services/auth/JwtService.d.ts +27 -0
  109. package/backend/dist/services/auth/JwtService.d.ts.map +1 -0
  110. package/backend/dist/services/auth/JwtService.js +65 -0
  111. package/backend/dist/services/auth/JwtService.js.map +1 -0
  112. package/backend/dist/services/auth/TokenRefreshService.d.ts +36 -0
  113. package/backend/dist/services/auth/TokenRefreshService.d.ts.map +1 -0
  114. package/backend/dist/services/auth/TokenRefreshService.js +178 -0
  115. package/backend/dist/services/auth/TokenRefreshService.js.map +1 -0
  116. package/backend/dist/services/conversation/ConversationService.d.ts +89 -0
  117. package/backend/dist/services/conversation/ConversationService.d.ts.map +1 -0
  118. package/backend/dist/services/conversation/ConversationService.js +255 -0
  119. package/backend/dist/services/conversation/ConversationService.js.map +1 -0
  120. package/backend/dist/services/job/JobService.d.ts +83 -0
  121. package/backend/dist/services/job/JobService.d.ts.map +1 -0
  122. package/backend/dist/services/job/JobService.js +213 -0
  123. package/backend/dist/services/job/JobService.js.map +1 -0
  124. package/backend/dist/services/job/WorkingDirectoryService.d.ts +73 -0
  125. package/backend/dist/services/job/WorkingDirectoryService.d.ts.map +1 -0
  126. package/backend/dist/services/job/WorkingDirectoryService.js +289 -0
  127. package/backend/dist/services/job/WorkingDirectoryService.js.map +1 -0
  128. package/backend/dist/services/llm/ClaudeProvider.d.ts +16 -0
  129. package/backend/dist/services/llm/ClaudeProvider.d.ts.map +1 -0
  130. package/backend/dist/services/llm/ClaudeProvider.js +229 -0
  131. package/backend/dist/services/llm/ClaudeProvider.js.map +1 -0
  132. package/backend/dist/services/llm/CodexProvider.d.ts +15 -0
  133. package/backend/dist/services/llm/CodexProvider.d.ts.map +1 -0
  134. package/backend/dist/services/llm/CodexProvider.js +301 -0
  135. package/backend/dist/services/llm/CodexProvider.js.map +1 -0
  136. package/backend/dist/services/llm/GeminiProvider.d.ts +17 -0
  137. package/backend/dist/services/llm/GeminiProvider.d.ts.map +1 -0
  138. package/backend/dist/services/llm/GeminiProvider.js +190 -0
  139. package/backend/dist/services/llm/GeminiProvider.js.map +1 -0
  140. package/backend/dist/services/llm/LLMProviderBase.d.ts +76 -0
  141. package/backend/dist/services/llm/LLMProviderBase.d.ts.map +1 -0
  142. package/backend/dist/services/llm/LLMProviderBase.js +34 -0
  143. package/backend/dist/services/llm/LLMProviderBase.js.map +1 -0
  144. package/backend/dist/services/llm/ProviderFactory.d.ts +17 -0
  145. package/backend/dist/services/llm/ProviderFactory.d.ts.map +1 -0
  146. package/backend/dist/services/llm/ProviderFactory.js +58 -0
  147. package/backend/dist/services/llm/ProviderFactory.js.map +1 -0
  148. package/backend/dist/utils/crypto.d.ts +33 -0
  149. package/backend/dist/utils/crypto.d.ts.map +1 -0
  150. package/backend/dist/utils/crypto.js +165 -0
  151. package/backend/dist/utils/crypto.js.map +1 -0
  152. package/backend/dist/utils/logger.d.ts +4 -0
  153. package/backend/dist/utils/logger.d.ts.map +1 -0
  154. package/backend/dist/utils/logger.js +44 -0
  155. package/backend/dist/utils/logger.js.map +1 -0
  156. package/backend/dist/utils/validators.d.ts +22 -0
  157. package/backend/dist/utils/validators.d.ts.map +1 -0
  158. package/backend/dist/utils/validators.js +127 -0
  159. package/backend/dist/utils/validators.js.map +1 -0
  160. package/backend/package.json +45 -0
  161. package/backend/public/assets/index-C207-KqP.js +188 -0
  162. package/backend/public/index.html +12 -0
  163. package/package.json +96 -0
  164. package/shared/dist/index.d.ts +5 -0
  165. package/shared/dist/index.d.ts.map +1 -0
  166. package/shared/dist/index.js +25 -0
  167. package/shared/dist/index.js.map +1 -0
  168. package/shared/dist/types/api.d.ts +27 -0
  169. package/shared/dist/types/api.d.ts.map +1 -0
  170. package/shared/dist/types/api.js +3 -0
  171. package/shared/dist/types/api.js.map +1 -0
  172. package/shared/dist/types/auth.d.ts +62 -0
  173. package/shared/dist/types/auth.d.ts.map +1 -0
  174. package/shared/dist/types/auth.js +3 -0
  175. package/shared/dist/types/auth.js.map +1 -0
  176. package/shared/dist/types/conversation.d.ts +98 -0
  177. package/shared/dist/types/conversation.d.ts.map +1 -0
  178. package/shared/dist/types/conversation.js +3 -0
  179. package/shared/dist/types/conversation.js.map +1 -0
  180. package/shared/dist/types/job.d.ts +93 -0
  181. package/shared/dist/types/job.d.ts.map +1 -0
  182. package/shared/dist/types/job.js +3 -0
  183. package/shared/dist/types/job.js.map +1 -0
  184. package/shared/package.json +15 -0
@@ -0,0 +1,401 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ClaudeAuthService = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const BaseAuthService_1 = require("./BaseAuthService");
11
+ const models_1 = require("../../models");
12
+ const crypto_2 = require("../../utils/crypto");
13
+ const environment_1 = __importDefault(require("../../config/environment"));
14
+ const logger_1 = __importDefault(require("../../utils/logger"));
15
+ const CLAUDE_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
16
+ const CLAUDE_SCOPES = [
17
+ 'org:create_api_key',
18
+ 'user:profile',
19
+ 'user:inference',
20
+ 'user:sessions:claude_code',
21
+ ];
22
+ const CLAUDE_TOKEN_URL = 'https://console.anthropic.com/v1/oauth/token';
23
+ const CLAUDE_PROFILE_URL = 'https://api.anthropic.com/api/oauth/profile';
24
+ const MANUAL_REDIRECT_URL = 'https://console.anthropic.com/oauth/code/callback';
25
+ const CLAUDE_AI_AUTHORIZE_URL = 'https://claude.ai/oauth/authorize';
26
+ const CONSOLE_AUTHORIZE_URL = 'https://console.anthropic.com/oauth/authorize';
27
+ class ClaudeAuthService extends BaseAuthService_1.BaseAuthService {
28
+ constructor() {
29
+ super('claude');
30
+ this.claudeConfigDir = path_1.default.join(environment_1.default.DATA_DIR, 'claude');
31
+ }
32
+ /**
33
+ * Parse various callback input formats (URL, query params, or raw code)
34
+ * Based on n8n plugin implementation
35
+ */
36
+ static parseCallbackInput(input) {
37
+ const trimmed = input.trim();
38
+ if (!trimmed)
39
+ return {};
40
+ let code;
41
+ let state;
42
+ const trySet = (maybeCode, maybeState) => {
43
+ const trimmedCode = maybeCode?.trim() || '';
44
+ const trimmedState = maybeState?.trim() || '';
45
+ if (!code && trimmedCode)
46
+ code = trimmedCode;
47
+ if (!state && trimmedState)
48
+ state = trimmedState;
49
+ };
50
+ // Try parsing as URL
51
+ try {
52
+ const url = new URL(trimmed);
53
+ trySet(url.searchParams.get('code'), url.searchParams.get('state'));
54
+ const hash = url.hash.startsWith('#') ? url.hash.slice(1) : url.hash;
55
+ if (hash) {
56
+ if (hash.includes('=')) {
57
+ const hashParams = new URLSearchParams(hash);
58
+ trySet(hashParams.get('code'), hashParams.get('state'));
59
+ }
60
+ else if (!state) {
61
+ state = hash.trim();
62
+ }
63
+ }
64
+ if (code || state)
65
+ return { code, state };
66
+ }
67
+ catch {
68
+ // Fall through to non-URL parsing
69
+ }
70
+ // Parse as query string or hash fragments
71
+ const [beforeHash, ...hashParts] = trimmed.split('#');
72
+ const hashPart = hashParts.join('#');
73
+ if (beforeHash.includes('?')) {
74
+ const params = new URLSearchParams(beforeHash.slice(beforeHash.indexOf('?') + 1));
75
+ trySet(params.get('code'), params.get('state'));
76
+ }
77
+ if (beforeHash.includes('code=')) {
78
+ const params = new URLSearchParams(beforeHash);
79
+ trySet(params.get('code'), params.get('state'));
80
+ }
81
+ // If still no code, treat entire input as code
82
+ if (!code && beforeHash && !beforeHash.includes('?') && !beforeHash.includes('=')) {
83
+ code = beforeHash.trim();
84
+ }
85
+ if (hashPart) {
86
+ if (hashPart.includes('=')) {
87
+ const hashParams = new URLSearchParams(hashPart);
88
+ trySet(hashParams.get('code'), hashParams.get('state'));
89
+ }
90
+ else if (!state) {
91
+ state = hashPart.trim();
92
+ }
93
+ }
94
+ return { code, state };
95
+ }
96
+ /**
97
+ * Start Claude OAuth login flow
98
+ */
99
+ async startLogin(options) {
100
+ const codeVerifier = (0, crypto_2.generateCodeVerifier)();
101
+ const codeChallenge = (0, crypto_2.generateCodeChallenge)(codeVerifier);
102
+ const state = crypto_1.default.randomUUID();
103
+ const baseUrl = options.loginWithClaudeAi
104
+ ? 'https://claude.ai/oauth/authorize'
105
+ : 'https://console.anthropic.com/oauth/authorize';
106
+ const redirectUri = 'http://localhost:3000/oauth/callback';
107
+ const url = new URL(baseUrl);
108
+ url.searchParams.set('client_id', CLAUDE_CLIENT_ID);
109
+ url.searchParams.set('response_type', 'code');
110
+ url.searchParams.set('redirect_uri', redirectUri);
111
+ url.searchParams.set('scope', CLAUDE_SCOPES.join(' '));
112
+ url.searchParams.set('code_challenge', codeChallenge);
113
+ url.searchParams.set('code_challenge_method', 'S256');
114
+ url.searchParams.set('state', state);
115
+ const sessionId = crypto_1.default.randomUUID();
116
+ await this.storeLoginSession({
117
+ sessionId,
118
+ state,
119
+ codeVerifier: this.encrypt(codeVerifier),
120
+ provider: 'claude',
121
+ redirectUri,
122
+ expiresAt: new Date(Date.now() + 15 * 60 * 1000),
123
+ });
124
+ logger_1.default.info('Claude OAuth login started', { sessionId, baseUrl: baseUrl });
125
+ return {
126
+ loginUrl: url.toString(),
127
+ sessionId,
128
+ state,
129
+ };
130
+ }
131
+ /**
132
+ * Complete Claude OAuth login flow
133
+ */
134
+ async completeLogin(params) {
135
+ // Validate session
136
+ const session = await this.getLoginSession(params.sessionId);
137
+ if (!session || session.state !== params.state) {
138
+ throw new Error('Invalid OAuth state');
139
+ }
140
+ const codeVerifier = this.decrypt(session.codeVerifier);
141
+ // Exchange code for tokens
142
+ const tokenResponse = await fetch(CLAUDE_TOKEN_URL, {
143
+ method: 'POST',
144
+ headers: { 'Content-Type': 'application/json' },
145
+ body: JSON.stringify({
146
+ grant_type: 'authorization_code',
147
+ code: params.code,
148
+ redirect_uri: session.redirectUri || 'http://localhost:3000/oauth/callback',
149
+ client_id: CLAUDE_CLIENT_ID,
150
+ code_verifier: codeVerifier,
151
+ }),
152
+ });
153
+ if (!tokenResponse.ok) {
154
+ const error = await tokenResponse.text();
155
+ throw new Error(`Token exchange failed: ${error}`);
156
+ }
157
+ const tokens = (await tokenResponse.json());
158
+ // Fetch user profile
159
+ const profileResponse = await fetch(CLAUDE_PROFILE_URL, {
160
+ headers: { Authorization: `Bearer ${tokens.access_token}` },
161
+ });
162
+ const profile = profileResponse.ok
163
+ ? (await profileResponse.json())
164
+ : {};
165
+ // 1. Create directory structure
166
+ await promises_1.default.mkdir(this.claudeConfigDir, { recursive: true, mode: 0o700 });
167
+ // 2. Write credentials to file (like native Claude CLI)
168
+ const credentialsPath = path_1.default.join(this.claudeConfigDir, '.credentials.json');
169
+ const credentialsData = {
170
+ accessToken: tokens.access_token,
171
+ refreshToken: tokens.refresh_token,
172
+ expiresAt: Date.now() + tokens.expires_in * 1000,
173
+ issuedAt: Date.now(),
174
+ scopes: tokens.scope?.split(' '),
175
+ subscriptionType: profile.organization?.organization_type,
176
+ rateLimitTier: profile.rate_limit_tier,
177
+ };
178
+ await promises_1.default.writeFile(credentialsPath, JSON.stringify(credentialsData, null, 2), { encoding: 'utf8', mode: 0o600 });
179
+ logger_1.default.info('Claude credentials written to file');
180
+ // 3. Store in database (for UI/management)
181
+ const authToken = await models_1.AuthToken.create({
182
+ provider: 'claude',
183
+ accessToken: this.encrypt(tokens.access_token),
184
+ refreshToken: tokens.refresh_token ? this.encrypt(tokens.refresh_token) : undefined,
185
+ tokenType: tokens.token_type,
186
+ expiresAt: new Date(Date.now() + tokens.expires_in * 1000),
187
+ issuedAt: new Date(),
188
+ scopes: tokens.scope?.split(' '),
189
+ email: profile.account?.email,
190
+ organization: profile.organization?.name,
191
+ isActive: true,
192
+ });
193
+ // Cleanup session
194
+ await this.deleteLoginSession(params.sessionId);
195
+ logger_1.default.info('Claude OAuth login completed', { tokenId: authToken.id });
196
+ return authToken;
197
+ }
198
+ /**
199
+ * Load credentials from file on server startup
200
+ */
201
+ async loadFromFile() {
202
+ const credentialsPath = path_1.default.join(this.claudeConfigDir, '.credentials.json');
203
+ try {
204
+ const content = await promises_1.default.readFile(credentialsPath, 'utf8');
205
+ const creds = JSON.parse(content);
206
+ // Check if already in database
207
+ let authToken = await models_1.AuthToken.findOne({
208
+ where: { provider: 'claude', isActive: true },
209
+ });
210
+ if (!authToken) {
211
+ // Create from file
212
+ authToken = await models_1.AuthToken.create({
213
+ provider: 'claude',
214
+ accessToken: this.encrypt(creds.accessToken),
215
+ refreshToken: creds.refreshToken ? this.encrypt(creds.refreshToken) : undefined,
216
+ tokenType: 'Bearer',
217
+ expiresAt: new Date(creds.expiresAt),
218
+ issuedAt: new Date(creds.issuedAt),
219
+ scopes: creds.scopes,
220
+ isActive: true,
221
+ });
222
+ logger_1.default.info('Claude credentials loaded from file and synced to database');
223
+ }
224
+ return authToken;
225
+ }
226
+ catch (error) {
227
+ if (error instanceof Error && error.code !== 'ENOENT') {
228
+ logger_1.default.warn('Failed to load Claude credentials from file:', error.message);
229
+ }
230
+ return null;
231
+ }
232
+ }
233
+ /**
234
+ * Refresh Claude access token
235
+ */
236
+ async refreshToken(token) {
237
+ if (!token.refreshToken) {
238
+ throw new Error('No refresh token available');
239
+ }
240
+ const refreshTokenDecrypted = this.decrypt(token.refreshToken);
241
+ const tokenResponse = await fetch(CLAUDE_TOKEN_URL, {
242
+ method: 'POST',
243
+ headers: { 'Content-Type': 'application/json' },
244
+ body: JSON.stringify({
245
+ grant_type: 'refresh_token',
246
+ refresh_token: refreshTokenDecrypted,
247
+ client_id: CLAUDE_CLIENT_ID,
248
+ }),
249
+ });
250
+ if (!tokenResponse.ok) {
251
+ const error = await tokenResponse.text();
252
+ throw new Error(`Token refresh failed: ${error}`);
253
+ }
254
+ const tokens = (await tokenResponse.json());
255
+ logger_1.default.info('Claude token refreshed successfully');
256
+ return {
257
+ accessToken: tokens.access_token,
258
+ refreshToken: tokens.refresh_token,
259
+ expiresAt: new Date(Date.now() + tokens.expires_in * 1000),
260
+ };
261
+ }
262
+ /**
263
+ * Get current authentication status
264
+ */
265
+ async getStatus() {
266
+ const token = await this.getActiveToken();
267
+ if (!token) {
268
+ return { loggedIn: false };
269
+ }
270
+ return {
271
+ loggedIn: true,
272
+ tokenId: token.id,
273
+ email: token.email,
274
+ expiresAt: token.expiresAt,
275
+ hasInferenceScope: token.scopes?.includes('user:inference') || false,
276
+ };
277
+ }
278
+ /**
279
+ * Start Claude OAuth login flow for manual code entry
280
+ * Uses official Anthropic static callback page for displaying authorization code
281
+ */
282
+ async startLoginWithRedirect(_redirectUri, loginWithClaudeAi = true) {
283
+ const codeVerifier = (0, crypto_2.generateCodeVerifier)();
284
+ const codeChallenge = (0, crypto_2.generateCodeChallenge)(codeVerifier);
285
+ const state = crypto_1.default.randomUUID();
286
+ // Use static manual redirect URI (official Anthropic page)
287
+ const manualRedirectUri = MANUAL_REDIRECT_URL;
288
+ // Choose authorization endpoint
289
+ const baseUrl = loginWithClaudeAi ? CLAUDE_AI_AUTHORIZE_URL : CONSOLE_AUTHORIZE_URL;
290
+ const url = new URL(baseUrl);
291
+ url.searchParams.set('client_id', CLAUDE_CLIENT_ID);
292
+ url.searchParams.set('response_type', 'code');
293
+ url.searchParams.set('redirect_uri', manualRedirectUri);
294
+ url.searchParams.set('scope', CLAUDE_SCOPES.join(' '));
295
+ url.searchParams.set('code_challenge', codeChallenge);
296
+ url.searchParams.set('code_challenge_method', 'S256');
297
+ url.searchParams.set('state', state);
298
+ // Store session in memory (state is sessionId)
299
+ await this.storeLoginSession({
300
+ sessionId: state,
301
+ state,
302
+ codeVerifier: this.encrypt(codeVerifier),
303
+ provider: 'claude',
304
+ redirectUri: manualRedirectUri,
305
+ expiresAt: new Date(Date.now() + 15 * 60 * 1000),
306
+ });
307
+ logger_1.default.info('Claude OAuth manual login started', { baseUrl, state });
308
+ return {
309
+ loginUrl: url.toString(),
310
+ state,
311
+ };
312
+ }
313
+ /**
314
+ * Complete Claude OAuth login with manual code entry
315
+ * Accepts full callback URL or just the authorization code
316
+ */
317
+ async completeLoginFromCallback(code, state) {
318
+ // 1. Validate session
319
+ const session = await this.getLoginSession(state);
320
+ if (!session) {
321
+ throw new Error('Login session expired or not found. Please restart the login process.');
322
+ }
323
+ if (session.state !== state) {
324
+ await this.deleteLoginSession(state);
325
+ throw new Error('Invalid authentication state. Please restart the login process.');
326
+ }
327
+ // 2. Validate code
328
+ if (!code || code.trim().length === 0) {
329
+ await this.deleteLoginSession(state);
330
+ throw new Error('Invalid authorization code. Please copy the full callback URL.');
331
+ }
332
+ const codeVerifier = this.decrypt(session.codeVerifier);
333
+ // 3. Exchange code for tokens (with error handling)
334
+ try {
335
+ const tokenResponse = await fetch(CLAUDE_TOKEN_URL, {
336
+ method: 'POST',
337
+ headers: { 'Content-Type': 'application/json' },
338
+ body: JSON.stringify({
339
+ grant_type: 'authorization_code',
340
+ code: code.trim(),
341
+ redirect_uri: session.redirectUri || MANUAL_REDIRECT_URL,
342
+ client_id: CLAUDE_CLIENT_ID,
343
+ code_verifier: codeVerifier,
344
+ state: state, // WICHTIG: State muss auch beim Token-Exchange mitgesendet werden!
345
+ }),
346
+ });
347
+ if (!tokenResponse.ok) {
348
+ const error = await tokenResponse.text();
349
+ throw new Error(`Token exchange failed: ${error}`);
350
+ }
351
+ const tokens = (await tokenResponse.json());
352
+ // 4. Fetch user profile
353
+ const profileResponse = await fetch(CLAUDE_PROFILE_URL, {
354
+ headers: { Authorization: `Bearer ${tokens.access_token}` },
355
+ });
356
+ const profile = profileResponse.ok
357
+ ? (await profileResponse.json())
358
+ : {};
359
+ // 5. Create directory structure
360
+ await promises_1.default.mkdir(this.claudeConfigDir, { recursive: true, mode: 0o700 });
361
+ // 6. Write credentials to file (like native Claude CLI)
362
+ const credentialsPath = path_1.default.join(this.claudeConfigDir, '.credentials.json');
363
+ const credentialsData = {
364
+ accessToken: tokens.access_token,
365
+ refreshToken: tokens.refresh_token,
366
+ expiresAt: Date.now() + tokens.expires_in * 1000,
367
+ issuedAt: Date.now(),
368
+ scopes: tokens.scope?.split(' '),
369
+ subscriptionType: profile.organization?.organization_type,
370
+ rateLimitTier: profile.rate_limit_tier,
371
+ };
372
+ await promises_1.default.writeFile(credentialsPath, JSON.stringify(credentialsData, null, 2), { encoding: 'utf8', mode: 0o600 });
373
+ logger_1.default.info('Claude credentials written to file');
374
+ // 7. Store in database
375
+ const authToken = await models_1.AuthToken.create({
376
+ provider: 'claude',
377
+ accessToken: this.encrypt(tokens.access_token),
378
+ refreshToken: tokens.refresh_token ? this.encrypt(tokens.refresh_token) : undefined,
379
+ tokenType: tokens.token_type,
380
+ expiresAt: new Date(Date.now() + tokens.expires_in * 1000),
381
+ issuedAt: new Date(),
382
+ scopes: tokens.scope?.split(' '),
383
+ email: profile.account?.email,
384
+ organization: profile.organization?.name,
385
+ isActive: true,
386
+ });
387
+ // 8. Cleanup session
388
+ await this.deleteLoginSession(state);
389
+ logger_1.default.info('Claude OAuth manual login completed', { tokenId: authToken.id });
390
+ return authToken;
391
+ }
392
+ catch (error) {
393
+ // Cleanup session on failure
394
+ await this.deleteLoginSession(state);
395
+ throw error;
396
+ }
397
+ }
398
+ }
399
+ exports.ClaudeAuthService = ClaudeAuthService;
400
+ exports.default = ClaudeAuthService;
401
+ //# sourceMappingURL=ClaudeAuthService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClaudeAuthService.js","sourceRoot":"","sources":["../../../src/services/auth/ClaudeAuthService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { BaseAuthService } from './BaseAuthService';
2
+ import { AuthToken } from '../../models';
3
+ export declare class CodexAuthService extends BaseAuthService {
4
+ private codexHome;
5
+ constructor();
6
+ /**
7
+ * Start Codex Device Auth flow
8
+ */
9
+ startLogin(): Promise<{
10
+ deviceAuthId: string;
11
+ userCode: string;
12
+ verificationUrl: string;
13
+ intervalSeconds: number;
14
+ expiresIn: number;
15
+ }>;
16
+ /**
17
+ * Poll for device auth token
18
+ */
19
+ pollForToken(params: {
20
+ deviceAuthId: string;
21
+ userCode: string;
22
+ }): Promise<AuthToken>;
23
+ /**
24
+ * Load credentials from file on server startup
25
+ */
26
+ loadFromFile(): Promise<AuthToken | null>;
27
+ /**
28
+ * Get current authentication status
29
+ */
30
+ getStatus(): Promise<{
31
+ loggedIn: boolean;
32
+ tokenId?: string;
33
+ email?: string;
34
+ }>;
35
+ }
36
+ export default CodexAuthService;
37
+ //# sourceMappingURL=CodexAuthService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodexAuthService.d.ts","sourceRoot":"","sources":["../../../src/services/auth/CodexAuthService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAmCzC,qBAAa,gBAAiB,SAAQ,eAAe;IACnD,OAAO,CAAC,SAAS,CAAS;;IAO1B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,EAAE,MAAM,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAmCF;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,SAAS,CAAC;IA6FtB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAmC/C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CAaH;AAED,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CodexAuthService = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const BaseAuthService_1 = require("./BaseAuthService");
10
+ const models_1 = require("../../models");
11
+ const crypto_1 = require("../../utils/crypto");
12
+ const environment_1 = __importDefault(require("../../config/environment"));
13
+ const logger_1 = __importDefault(require("../../utils/logger"));
14
+ const CODEX_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';
15
+ const CODEX_ISSUER = 'https://auth.openai.com';
16
+ /**
17
+ * Construct the verification URL for device auth
18
+ */
19
+ function getVerificationUrl(issuer) {
20
+ const normalized = issuer.replace(/\/+$/g, '');
21
+ return `${normalized}/codex/device`;
22
+ }
23
+ class CodexAuthService extends BaseAuthService_1.BaseAuthService {
24
+ constructor() {
25
+ super('codex');
26
+ this.codexHome = path_1.default.join(environment_1.default.DATA_DIR, 'codex');
27
+ }
28
+ /**
29
+ * Start Codex Device Auth flow
30
+ */
31
+ async startLogin() {
32
+ const response = await fetch(`${CODEX_ISSUER}/api/accounts/deviceauth/usercode`, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify({
36
+ client_id: CODEX_CLIENT_ID,
37
+ }),
38
+ });
39
+ if (!response.ok) {
40
+ const error = await response.text();
41
+ throw new Error(`Failed to start device auth: ${error}`);
42
+ }
43
+ const data = (await response.json());
44
+ const verificationUrl = getVerificationUrl(CODEX_ISSUER);
45
+ // OpenAI doesn't return expires_in, so we use a default of 15 minutes
46
+ const expiresIn = data.expires_in || (15 * 60);
47
+ logger_1.default.info('Codex device auth started', {
48
+ userCode: data.user_code,
49
+ expiresIn,
50
+ verificationUrl
51
+ });
52
+ return {
53
+ deviceAuthId: data.device_auth_id,
54
+ userCode: data.user_code,
55
+ verificationUrl,
56
+ intervalSeconds: parseInt(data.interval) || 5,
57
+ expiresIn,
58
+ };
59
+ }
60
+ /**
61
+ * Poll for device auth token
62
+ */
63
+ async pollForToken(params) {
64
+ // Poll device token endpoint
65
+ const deviceTokenResponse = await fetch(`${CODEX_ISSUER}/api/accounts/deviceauth/token`, {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': 'application/json' },
68
+ body: JSON.stringify({
69
+ device_auth_id: params.deviceAuthId,
70
+ user_code: params.userCode,
71
+ }),
72
+ });
73
+ logger_1.default.debug('Device token poll response', {
74
+ status: deviceTokenResponse.status,
75
+ ok: deviceTokenResponse.ok
76
+ });
77
+ if (!deviceTokenResponse.ok) {
78
+ // OpenAI returns 403 or 404 when device auth is pending
79
+ if (deviceTokenResponse.status === 400 || deviceTokenResponse.status === 403 || deviceTokenResponse.status === 404) {
80
+ throw new Error('Device auth not yet approved');
81
+ }
82
+ const error = await deviceTokenResponse.text();
83
+ logger_1.default.error('Device token poll failed', { status: deviceTokenResponse.status, error });
84
+ throw new Error(`Failed to poll device token: ${error}`);
85
+ }
86
+ const deviceTokens = (await deviceTokenResponse.json());
87
+ // Exchange for OAuth tokens
88
+ // OAuth token endpoints expect application/x-www-form-urlencoded
89
+ const tokenBody = new URLSearchParams();
90
+ tokenBody.set('grant_type', 'authorization_code');
91
+ tokenBody.set('code', deviceTokens.authorization_code);
92
+ tokenBody.set('redirect_uri', `${CODEX_ISSUER}/deviceauth/callback`);
93
+ tokenBody.set('client_id', CODEX_CLIENT_ID);
94
+ tokenBody.set('code_verifier', deviceTokens.code_verifier);
95
+ const tokenResponse = await fetch(`${CODEX_ISSUER}/oauth/token`, {
96
+ method: 'POST',
97
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
98
+ body: tokenBody.toString(),
99
+ });
100
+ if (!tokenResponse.ok) {
101
+ const error = await tokenResponse.text();
102
+ logger_1.default.error('Token exchange failed', { status: tokenResponse.status, error });
103
+ throw new Error(`Failed to exchange tokens: ${error}`);
104
+ }
105
+ const tokens = (await tokenResponse.json());
106
+ // Decode JWT for user info
107
+ const claims = (0, crypto_1.decodeJWT)(tokens.id_token);
108
+ // 1. Create directory structure
109
+ await promises_1.default.mkdir(this.codexHome, { recursive: true, mode: 0o700 });
110
+ // 2. Write auth.json (like native Codex CLI)
111
+ const authPath = path_1.default.join(this.codexHome, 'auth.json');
112
+ const authData = {
113
+ tokens: {
114
+ id_token: tokens.id_token,
115
+ access_token: tokens.access_token,
116
+ refresh_token: tokens.refresh_token,
117
+ account_id: claims.account_id || claims.sub,
118
+ },
119
+ last_refresh: new Date().toISOString(),
120
+ };
121
+ await promises_1.default.writeFile(authPath, JSON.stringify(authData, null, 2), { encoding: 'utf8', mode: 0o600 });
122
+ logger_1.default.info('Codex credentials written to file');
123
+ // 3. Store in database
124
+ const authToken = await models_1.AuthToken.create({
125
+ provider: 'codex',
126
+ accessToken: this.encrypt(tokens.access_token),
127
+ refreshToken: this.encrypt(tokens.refresh_token),
128
+ tokenType: 'Bearer',
129
+ issuedAt: new Date(),
130
+ email: claims.email,
131
+ isActive: true,
132
+ });
133
+ logger_1.default.info('Codex device auth completed', { tokenId: authToken.id });
134
+ return authToken;
135
+ }
136
+ /**
137
+ * Load credentials from file on server startup
138
+ */
139
+ async loadFromFile() {
140
+ const authPath = path_1.default.join(this.codexHome, 'auth.json');
141
+ try {
142
+ const content = await promises_1.default.readFile(authPath, 'utf8');
143
+ const auth = JSON.parse(content);
144
+ // Check if already in database
145
+ let authToken = await models_1.AuthToken.findOne({
146
+ where: { provider: 'codex', isActive: true },
147
+ });
148
+ if (!authToken) {
149
+ // Create from file
150
+ authToken = await models_1.AuthToken.create({
151
+ provider: 'codex',
152
+ accessToken: this.encrypt(auth.tokens.access_token),
153
+ refreshToken: this.encrypt(auth.tokens.refresh_token),
154
+ tokenType: 'Bearer',
155
+ issuedAt: new Date(auth.last_refresh),
156
+ isActive: true,
157
+ });
158
+ logger_1.default.info('Codex credentials loaded from file and synced to database');
159
+ }
160
+ return authToken;
161
+ }
162
+ catch (error) {
163
+ if (error instanceof Error && error.code !== 'ENOENT') {
164
+ logger_1.default.warn('Failed to load Codex credentials from file:', error.message);
165
+ }
166
+ return null;
167
+ }
168
+ }
169
+ /**
170
+ * Get current authentication status
171
+ */
172
+ async getStatus() {
173
+ const token = await this.getActiveToken();
174
+ if (!token) {
175
+ return { loggedIn: false };
176
+ }
177
+ return {
178
+ loggedIn: true,
179
+ tokenId: token.id,
180
+ email: token.email,
181
+ };
182
+ }
183
+ }
184
+ exports.CodexAuthService = CodexAuthService;
185
+ exports.default = CodexAuthService;
186
+ //# sourceMappingURL=CodexAuthService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodexAuthService.js","sourceRoot":"","sources":["../../../src/services/auth/CodexAuthService.ts"],"names":[],"mappings":"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"}