popeye-cli 1.0.1 → 1.2.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 (216) hide show
  1. package/.env.example +24 -1
  2. package/CONTRIBUTING.md +275 -0
  3. package/OPEN_SOURCE_MANIFESTO.md +172 -0
  4. package/README.md +832 -123
  5. package/dist/adapters/claude.d.ts +19 -4
  6. package/dist/adapters/claude.d.ts.map +1 -1
  7. package/dist/adapters/claude.js +908 -42
  8. package/dist/adapters/claude.js.map +1 -1
  9. package/dist/adapters/gemini.d.ts +55 -0
  10. package/dist/adapters/gemini.d.ts.map +1 -0
  11. package/dist/adapters/gemini.js +318 -0
  12. package/dist/adapters/gemini.js.map +1 -0
  13. package/dist/adapters/grok.d.ts +73 -0
  14. package/dist/adapters/grok.d.ts.map +1 -0
  15. package/dist/adapters/grok.js +430 -0
  16. package/dist/adapters/grok.js.map +1 -0
  17. package/dist/adapters/openai.d.ts +1 -1
  18. package/dist/adapters/openai.d.ts.map +1 -1
  19. package/dist/adapters/openai.js +47 -8
  20. package/dist/adapters/openai.js.map +1 -1
  21. package/dist/auth/claude.d.ts +11 -9
  22. package/dist/auth/claude.d.ts.map +1 -1
  23. package/dist/auth/claude.js +107 -71
  24. package/dist/auth/claude.js.map +1 -1
  25. package/dist/auth/gemini.d.ts +58 -0
  26. package/dist/auth/gemini.d.ts.map +1 -0
  27. package/dist/auth/gemini.js +172 -0
  28. package/dist/auth/gemini.js.map +1 -0
  29. package/dist/auth/grok.d.ts +73 -0
  30. package/dist/auth/grok.d.ts.map +1 -0
  31. package/dist/auth/grok.js +211 -0
  32. package/dist/auth/grok.js.map +1 -0
  33. package/dist/auth/index.d.ts +14 -7
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +41 -6
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/keychain.d.ts +20 -7
  38. package/dist/auth/keychain.d.ts.map +1 -1
  39. package/dist/auth/keychain.js +85 -29
  40. package/dist/auth/keychain.js.map +1 -1
  41. package/dist/auth/openai.d.ts +2 -2
  42. package/dist/auth/openai.d.ts.map +1 -1
  43. package/dist/auth/openai.js +30 -32
  44. package/dist/auth/openai.js.map +1 -1
  45. package/dist/cli/commands/auth.d.ts +1 -1
  46. package/dist/cli/commands/auth.d.ts.map +1 -1
  47. package/dist/cli/commands/auth.js +79 -8
  48. package/dist/cli/commands/auth.js.map +1 -1
  49. package/dist/cli/commands/create.d.ts.map +1 -1
  50. package/dist/cli/commands/create.js +15 -4
  51. package/dist/cli/commands/create.js.map +1 -1
  52. package/dist/cli/interactive.d.ts.map +1 -1
  53. package/dist/cli/interactive.js +1494 -114
  54. package/dist/cli/interactive.js.map +1 -1
  55. package/dist/config/defaults.d.ts +9 -1
  56. package/dist/config/defaults.d.ts.map +1 -1
  57. package/dist/config/defaults.js +19 -2
  58. package/dist/config/defaults.js.map +1 -1
  59. package/dist/config/index.d.ts +19 -0
  60. package/dist/config/index.d.ts.map +1 -1
  61. package/dist/config/index.js +33 -1
  62. package/dist/config/index.js.map +1 -1
  63. package/dist/config/schema.d.ts +47 -0
  64. package/dist/config/schema.d.ts.map +1 -1
  65. package/dist/config/schema.js +29 -1
  66. package/dist/config/schema.js.map +1 -1
  67. package/dist/generators/fullstack.d.ts +32 -0
  68. package/dist/generators/fullstack.d.ts.map +1 -0
  69. package/dist/generators/fullstack.js +497 -0
  70. package/dist/generators/fullstack.js.map +1 -0
  71. package/dist/generators/index.d.ts +4 -3
  72. package/dist/generators/index.d.ts.map +1 -1
  73. package/dist/generators/index.js +15 -1
  74. package/dist/generators/index.js.map +1 -1
  75. package/dist/generators/python.d.ts +17 -1
  76. package/dist/generators/python.d.ts.map +1 -1
  77. package/dist/generators/python.js +34 -20
  78. package/dist/generators/python.js.map +1 -1
  79. package/dist/generators/templates/fullstack.d.ts +113 -0
  80. package/dist/generators/templates/fullstack.d.ts.map +1 -0
  81. package/dist/generators/templates/fullstack.js +1004 -0
  82. package/dist/generators/templates/fullstack.js.map +1 -0
  83. package/dist/generators/typescript.d.ts +19 -1
  84. package/dist/generators/typescript.d.ts.map +1 -1
  85. package/dist/generators/typescript.js +37 -20
  86. package/dist/generators/typescript.js.map +1 -1
  87. package/dist/state/index.d.ts +108 -0
  88. package/dist/state/index.d.ts.map +1 -1
  89. package/dist/state/index.js +551 -4
  90. package/dist/state/index.js.map +1 -1
  91. package/dist/state/registry.d.ts +52 -0
  92. package/dist/state/registry.d.ts.map +1 -0
  93. package/dist/state/registry.js +215 -0
  94. package/dist/state/registry.js.map +1 -0
  95. package/dist/types/cli.d.ts +8 -0
  96. package/dist/types/cli.d.ts.map +1 -1
  97. package/dist/types/cli.js.map +1 -1
  98. package/dist/types/consensus.d.ts +186 -4
  99. package/dist/types/consensus.d.ts.map +1 -1
  100. package/dist/types/consensus.js +35 -3
  101. package/dist/types/consensus.js.map +1 -1
  102. package/dist/types/project.d.ts +76 -0
  103. package/dist/types/project.d.ts.map +1 -1
  104. package/dist/types/project.js +1 -1
  105. package/dist/types/project.js.map +1 -1
  106. package/dist/types/workflow.d.ts +217 -16
  107. package/dist/types/workflow.d.ts.map +1 -1
  108. package/dist/types/workflow.js +40 -1
  109. package/dist/types/workflow.js.map +1 -1
  110. package/dist/workflow/auto-fix.d.ts +45 -0
  111. package/dist/workflow/auto-fix.d.ts.map +1 -0
  112. package/dist/workflow/auto-fix.js +274 -0
  113. package/dist/workflow/auto-fix.js.map +1 -0
  114. package/dist/workflow/consensus.d.ts +70 -2
  115. package/dist/workflow/consensus.d.ts.map +1 -1
  116. package/dist/workflow/consensus.js +872 -17
  117. package/dist/workflow/consensus.js.map +1 -1
  118. package/dist/workflow/execution-mode.d.ts +10 -4
  119. package/dist/workflow/execution-mode.d.ts.map +1 -1
  120. package/dist/workflow/execution-mode.js +547 -58
  121. package/dist/workflow/execution-mode.js.map +1 -1
  122. package/dist/workflow/index.d.ts +14 -2
  123. package/dist/workflow/index.d.ts.map +1 -1
  124. package/dist/workflow/index.js +69 -6
  125. package/dist/workflow/index.js.map +1 -1
  126. package/dist/workflow/milestone-workflow.d.ts +34 -0
  127. package/dist/workflow/milestone-workflow.d.ts.map +1 -0
  128. package/dist/workflow/milestone-workflow.js +414 -0
  129. package/dist/workflow/milestone-workflow.js.map +1 -0
  130. package/dist/workflow/plan-mode.d.ts +80 -3
  131. package/dist/workflow/plan-mode.d.ts.map +1 -1
  132. package/dist/workflow/plan-mode.js +767 -49
  133. package/dist/workflow/plan-mode.js.map +1 -1
  134. package/dist/workflow/plan-storage.d.ts +386 -0
  135. package/dist/workflow/plan-storage.d.ts.map +1 -0
  136. package/dist/workflow/plan-storage.js +878 -0
  137. package/dist/workflow/plan-storage.js.map +1 -0
  138. package/dist/workflow/project-verification.d.ts +37 -0
  139. package/dist/workflow/project-verification.d.ts.map +1 -0
  140. package/dist/workflow/project-verification.js +381 -0
  141. package/dist/workflow/project-verification.js.map +1 -0
  142. package/dist/workflow/task-workflow.d.ts +37 -0
  143. package/dist/workflow/task-workflow.d.ts.map +1 -0
  144. package/dist/workflow/task-workflow.js +386 -0
  145. package/dist/workflow/task-workflow.js.map +1 -0
  146. package/dist/workflow/test-runner.d.ts +9 -0
  147. package/dist/workflow/test-runner.d.ts.map +1 -1
  148. package/dist/workflow/test-runner.js +101 -5
  149. package/dist/workflow/test-runner.js.map +1 -1
  150. package/dist/workflow/ui-designer.d.ts +82 -0
  151. package/dist/workflow/ui-designer.d.ts.map +1 -0
  152. package/dist/workflow/ui-designer.js +234 -0
  153. package/dist/workflow/ui-designer.js.map +1 -0
  154. package/dist/workflow/ui-setup.d.ts +58 -0
  155. package/dist/workflow/ui-setup.d.ts.map +1 -0
  156. package/dist/workflow/ui-setup.js +685 -0
  157. package/dist/workflow/ui-setup.js.map +1 -0
  158. package/dist/workflow/ui-verification.d.ts +114 -0
  159. package/dist/workflow/ui-verification.d.ts.map +1 -0
  160. package/dist/workflow/ui-verification.js +258 -0
  161. package/dist/workflow/ui-verification.js.map +1 -0
  162. package/dist/workflow/workflow-logger.d.ts +110 -0
  163. package/dist/workflow/workflow-logger.d.ts.map +1 -0
  164. package/dist/workflow/workflow-logger.js +267 -0
  165. package/dist/workflow/workflow-logger.js.map +1 -0
  166. package/dist/workflow/workspace-manager.d.ts +342 -0
  167. package/dist/workflow/workspace-manager.d.ts.map +1 -0
  168. package/dist/workflow/workspace-manager.js +733 -0
  169. package/dist/workflow/workspace-manager.js.map +1 -0
  170. package/package.json +2 -2
  171. package/src/adapters/claude.ts +1067 -47
  172. package/src/adapters/gemini.ts +373 -0
  173. package/src/adapters/grok.ts +492 -0
  174. package/src/adapters/openai.ts +48 -9
  175. package/src/auth/claude.ts +120 -78
  176. package/src/auth/gemini.ts +207 -0
  177. package/src/auth/grok.ts +255 -0
  178. package/src/auth/index.ts +47 -9
  179. package/src/auth/keychain.ts +95 -28
  180. package/src/auth/openai.ts +29 -36
  181. package/src/cli/commands/auth.ts +89 -10
  182. package/src/cli/commands/create.ts +13 -4
  183. package/src/cli/interactive.ts +1774 -142
  184. package/src/config/defaults.ts +19 -2
  185. package/src/config/index.ts +36 -1
  186. package/src/config/schema.ts +30 -1
  187. package/src/generators/fullstack.ts +551 -0
  188. package/src/generators/index.ts +25 -1
  189. package/src/generators/python.ts +65 -20
  190. package/src/generators/templates/fullstack.ts +1047 -0
  191. package/src/generators/typescript.ts +69 -20
  192. package/src/state/index.ts +713 -4
  193. package/src/state/registry.ts +278 -0
  194. package/src/types/cli.ts +8 -0
  195. package/src/types/consensus.ts +197 -6
  196. package/src/types/project.ts +82 -1
  197. package/src/types/workflow.ts +90 -1
  198. package/src/workflow/auto-fix.ts +340 -0
  199. package/src/workflow/consensus.ts +1180 -16
  200. package/src/workflow/execution-mode.ts +673 -74
  201. package/src/workflow/index.ts +95 -6
  202. package/src/workflow/milestone-workflow.ts +576 -0
  203. package/src/workflow/plan-mode.ts +924 -50
  204. package/src/workflow/plan-storage.ts +1282 -0
  205. package/src/workflow/project-verification.ts +471 -0
  206. package/src/workflow/task-workflow.ts +528 -0
  207. package/src/workflow/test-runner.ts +120 -5
  208. package/src/workflow/ui-designer.ts +337 -0
  209. package/src/workflow/ui-setup.ts +797 -0
  210. package/src/workflow/ui-verification.ts +357 -0
  211. package/src/workflow/workflow-logger.ts +353 -0
  212. package/src/workflow/workspace-manager.ts +912 -0
  213. package/tests/config/config.test.ts +1 -1
  214. package/tests/types/consensus.test.ts +3 -3
  215. package/tests/workflow/plan-mode.test.ts +213 -0
  216. package/tests/workflow/test-runner.test.ts +5 -3
@@ -0,0 +1,211 @@
1
+ /**
2
+ * xAI Grok API authentication module
3
+ * Handles API key validation and storage
4
+ */
5
+ import * as readline from 'node:readline';
6
+ import OpenAI from 'openai';
7
+ import { getCredential, setCredential, deleteCredential, maskCredential, } from './keychain.js';
8
+ import { ENV_VARS } from '../config/defaults.js';
9
+ /**
10
+ * Grok API URL (OpenAI-compatible)
11
+ */
12
+ export const GROK_API_URL = 'https://api.x.ai/v1';
13
+ /**
14
+ * Keychain account for Grok
15
+ */
16
+ const GROK_ACCOUNT = 'grok-api';
17
+ /**
18
+ * Validate a Grok API key by making a test API call
19
+ *
20
+ * @param apiKey - The API key to validate
21
+ * @returns True if the key is valid
22
+ */
23
+ export async function validateGrokToken(apiKey) {
24
+ try {
25
+ const client = new OpenAI({
26
+ apiKey,
27
+ baseURL: GROK_API_URL,
28
+ });
29
+ // Test the key by making a simple request
30
+ await client.chat.completions.create({
31
+ model: 'grok-3',
32
+ messages: [{ role: 'user', content: 'Say "OK"' }],
33
+ max_tokens: 5,
34
+ });
35
+ return true;
36
+ }
37
+ catch (error) {
38
+ // Check for authentication errors
39
+ const errorMessage = error instanceof Error ? error.message : '';
40
+ if (errorMessage.includes('401') ||
41
+ errorMessage.includes('Invalid API') ||
42
+ errorMessage.includes('Unauthorized')) {
43
+ return false;
44
+ }
45
+ // For other errors (e.g., rate limits), assume the key might be valid
46
+ console.warn('Could not fully validate Grok key:', error);
47
+ return true;
48
+ }
49
+ }
50
+ /**
51
+ * Get the Grok API credential
52
+ */
53
+ export async function getGrokCredential() {
54
+ // First check file storage
55
+ const stored = await getCredential(GROK_ACCOUNT);
56
+ if (stored)
57
+ return stored;
58
+ // Fallback to environment variable
59
+ return process.env[ENV_VARS.GROK_KEY] || null;
60
+ }
61
+ /**
62
+ * Set the Grok API credential
63
+ */
64
+ export async function setGrokCredential(apiKey) {
65
+ return setCredential(GROK_ACCOUNT, apiKey);
66
+ }
67
+ /**
68
+ * Delete the Grok API credential
69
+ */
70
+ export async function deleteGrokCredential() {
71
+ return deleteCredential(GROK_ACCOUNT);
72
+ }
73
+ /**
74
+ * Check if Grok is already authenticated
75
+ */
76
+ export async function checkGrokAuth() {
77
+ try {
78
+ const apiKey = await getGrokCredential();
79
+ if (!apiKey) {
80
+ return { authenticated: false };
81
+ }
82
+ // Validate the key
83
+ const isValid = await validateGrokToken(apiKey);
84
+ if (!isValid) {
85
+ return {
86
+ authenticated: false,
87
+ error: 'Stored API key is invalid',
88
+ };
89
+ }
90
+ return {
91
+ authenticated: true,
92
+ keyLastFour: maskCredential(apiKey),
93
+ };
94
+ }
95
+ catch (error) {
96
+ return {
97
+ authenticated: false,
98
+ error: error instanceof Error ? error.message : 'Unknown error',
99
+ };
100
+ }
101
+ }
102
+ /**
103
+ * Prompt for API key in the terminal
104
+ *
105
+ * @returns The entered API key or null if cancelled
106
+ */
107
+ export async function promptForGrokAPIKey() {
108
+ return new Promise((resolve) => {
109
+ const rl = readline.createInterface({
110
+ input: process.stdin,
111
+ output: process.stdout,
112
+ });
113
+ console.log('\nGet your API key from: https://console.x.ai/\n');
114
+ rl.question('Enter your Grok API key: ', (answer) => {
115
+ rl.close();
116
+ const key = answer.trim();
117
+ if (key) {
118
+ resolve(key);
119
+ }
120
+ else {
121
+ resolve(null);
122
+ }
123
+ });
124
+ });
125
+ }
126
+ /**
127
+ * Authenticate with Grok API
128
+ *
129
+ * @returns True if authentication was successful
130
+ */
131
+ export async function authenticateGrok() {
132
+ // Check if already authenticated
133
+ const existingAuth = await checkGrokAuth();
134
+ if (existingAuth.authenticated) {
135
+ console.log('Already authenticated with Grok API');
136
+ return true;
137
+ }
138
+ console.log('Grok API key required for AI reviews.');
139
+ try {
140
+ // Prompt for the API key
141
+ const apiKey = await promptForGrokAPIKey();
142
+ if (!apiKey) {
143
+ console.error('\nNo API key provided');
144
+ return false;
145
+ }
146
+ // Validate the token
147
+ console.log('\nValidating API key...');
148
+ const isValid = await validateGrokToken(apiKey);
149
+ if (!isValid) {
150
+ console.error('Invalid Grok API key');
151
+ return false;
152
+ }
153
+ // Store the token
154
+ await setGrokCredential(apiKey);
155
+ console.log('Grok API authenticated successfully!\n');
156
+ return true;
157
+ }
158
+ catch (error) {
159
+ console.error(`Authentication error: ${error instanceof Error ? error.message : error}`);
160
+ return false;
161
+ }
162
+ }
163
+ /**
164
+ * Authenticate with a provided API key (for CLI --api-key option)
165
+ *
166
+ * @param apiKey - The API key to use
167
+ * @returns True if authentication was successful
168
+ */
169
+ export async function authenticateGrokWithKey(apiKey) {
170
+ // Validate the token
171
+ const isValid = await validateGrokToken(apiKey);
172
+ if (!isValid) {
173
+ console.error('Invalid Grok API key');
174
+ return false;
175
+ }
176
+ // Store the token
177
+ await setGrokCredential(apiKey);
178
+ console.log('Grok API authenticated successfully!\n');
179
+ return true;
180
+ }
181
+ /**
182
+ * Logout from Grok API
183
+ * Removes stored credentials
184
+ */
185
+ export async function logoutGrok() {
186
+ const deleted = await deleteGrokCredential();
187
+ if (deleted) {
188
+ console.log('Grok API credentials removed.');
189
+ }
190
+ else {
191
+ console.log('No Grok API credentials found.');
192
+ }
193
+ }
194
+ /**
195
+ * Get the Grok API key for API calls
196
+ */
197
+ export async function getGrokToken() {
198
+ return getGrokCredential();
199
+ }
200
+ /**
201
+ * Ensure Grok is authenticated
202
+ * Prompts for authentication if not already authenticated
203
+ */
204
+ export async function ensureGrokAuth() {
205
+ const status = await checkGrokAuth();
206
+ if (status.authenticated) {
207
+ return true;
208
+ }
209
+ return authenticateGrok();
210
+ }
211
+ //# sourceMappingURL=grok.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok.js","sourceRoot":"","sources":["../../src/auth/grok.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,16 @@
1
1
  /**
2
2
  * Authentication orchestration module
3
- * Coordinates authentication for both Claude CLI and OpenAI API
3
+ * Coordinates authentication for Claude CLI, OpenAI API, Gemini API, and Grok API
4
4
  */
5
5
  import { type ClaudeAuthStatus } from './claude.js';
6
6
  import { type OpenAIAuthStatus } from './openai.js';
7
+ import { type GeminiAuthStatus } from './gemini.js';
8
+ import { type GrokAuthStatus } from './grok.js';
7
9
  import type { AuthStatus } from '../types/index.js';
8
10
  export * from './claude.js';
9
11
  export * from './openai.js';
12
+ export * from './gemini.js';
13
+ export * from './grok.js';
10
14
  export * from './keychain.js';
11
15
  export * from './server.js';
12
16
  /**
@@ -15,10 +19,13 @@ export * from './server.js';
15
19
  export interface CombinedAuthStatus {
16
20
  claude: ClaudeAuthStatus;
17
21
  openai: OpenAIAuthStatus;
22
+ gemini: GeminiAuthStatus;
23
+ grok: GrokAuthStatus;
18
24
  fullyAuthenticated: boolean;
25
+ hasArbitrator: boolean;
19
26
  }
20
27
  /**
21
- * Get the authentication status for both services
28
+ * Get the authentication status for all services
22
29
  */
23
30
  export declare function getAuthStatus(): Promise<CombinedAuthStatus>;
24
31
  /**
@@ -35,23 +42,23 @@ export declare function ensureAuthenticated(): Promise<boolean>;
35
42
  /**
36
43
  * Authenticate a specific service
37
44
  *
38
- * @param service - The service to authenticate ('claude', 'openai', or 'all')
45
+ * @param service - The service to authenticate ('claude', 'openai', 'gemini', 'grok', or 'all')
39
46
  * @returns True if authentication was successful
40
47
  */
41
- export declare function authenticateService(service: 'claude' | 'openai' | 'all'): Promise<boolean>;
48
+ export declare function authenticateService(service: 'claude' | 'openai' | 'gemini' | 'grok' | 'all'): Promise<boolean>;
42
49
  /**
43
50
  * Logout from a specific service or all services
44
51
  *
45
- * @param service - The service to logout from ('claude', 'openai', or 'all')
52
+ * @param service - The service to logout from ('claude', 'openai', 'gemini', 'grok', or 'all')
46
53
  */
47
- export declare function logout(service: 'claude' | 'openai' | 'all'): Promise<void>;
54
+ export declare function logout(service: 'claude' | 'openai' | 'gemini' | 'grok' | 'all'): Promise<void>;
48
55
  /**
49
56
  * Check if a specific service is authenticated
50
57
  *
51
58
  * @param service - The service to check
52
59
  * @returns True if the service is authenticated
53
60
  */
54
- export declare function isAuthenticated(service: 'claude' | 'openai' | 'both'): Promise<boolean>;
61
+ export declare function isAuthenticated(service: 'claude' | 'openai' | 'gemini' | 'grok' | 'both' | 'all'): Promise<boolean>;
55
62
  /**
56
63
  * Require authentication, throwing an error if not authenticated
57
64
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAwD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAqD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAWjE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC,CAenE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CA4B5D;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,GACnC,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAahF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW7F;AAED;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAUjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAwD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAqD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAqD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAA+C,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAE7F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAgBjE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC,CAuBnE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CA4B5D;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GACvD,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBpG;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBzH;AAED;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAUjD"}
@@ -1,27 +1,36 @@
1
1
  /**
2
2
  * Authentication orchestration module
3
- * Coordinates authentication for both Claude CLI and OpenAI API
3
+ * Coordinates authentication for Claude CLI, OpenAI API, Gemini API, and Grok API
4
4
  */
5
5
  import { checkClaudeCLIAuth, authenticateClaude, logoutClaude } from './claude.js';
6
6
  import { checkOpenAIAuth, authenticateOpenAI, logoutOpenAI } from './openai.js';
7
- import { clearAllCredentials } from './keychain.js';
7
+ import { checkGeminiAuth, authenticateGemini, logoutGemini } from './gemini.js';
8
+ import { checkGrokAuth, authenticateGrok, logoutGrok } from './grok.js';
9
+ import { clearAllCredentials, deleteCredential } from './keychain.js';
8
10
  // Re-export individual auth modules
9
11
  export * from './claude.js';
10
12
  export * from './openai.js';
13
+ export * from './gemini.js';
14
+ export * from './grok.js';
11
15
  export * from './keychain.js';
12
16
  export * from './server.js';
13
17
  /**
14
- * Get the authentication status for both services
18
+ * Get the authentication status for all services
15
19
  */
16
20
  export async function getAuthStatus() {
17
- const [claudeStatus, openaiStatus] = await Promise.all([
21
+ const [claudeStatus, openaiStatus, geminiStatus, grokStatus] = await Promise.all([
18
22
  checkClaudeCLIAuth(),
19
23
  checkOpenAIAuth(),
24
+ checkGeminiAuth(),
25
+ checkGrokAuth(),
20
26
  ]);
21
27
  return {
22
28
  claude: claudeStatus,
23
29
  openai: openaiStatus,
30
+ gemini: geminiStatus,
31
+ grok: grokStatus,
24
32
  fullyAuthenticated: claudeStatus.authenticated && openaiStatus.authenticated,
33
+ hasArbitrator: geminiStatus.authenticated || openaiStatus.authenticated || grokStatus.authenticated,
25
34
  };
26
35
  }
27
36
  /**
@@ -40,6 +49,14 @@ export async function getAuthStatusForDisplay() {
40
49
  keyLastFour: status.openai.keyLastFour,
41
50
  modelAccess: status.openai.modelAccess,
42
51
  },
52
+ gemini: {
53
+ authenticated: status.gemini.authenticated,
54
+ keyLastFour: status.gemini.keyLastFour,
55
+ },
56
+ grok: {
57
+ authenticated: status.grok.authenticated,
58
+ keyLastFour: status.grok.keyLastFour,
59
+ },
43
60
  };
44
61
  }
45
62
  /**
@@ -75,7 +92,7 @@ export async function ensureAuthenticated() {
75
92
  /**
76
93
  * Authenticate a specific service
77
94
  *
78
- * @param service - The service to authenticate ('claude', 'openai', or 'all')
95
+ * @param service - The service to authenticate ('claude', 'openai', 'gemini', 'grok', or 'all')
79
96
  * @returns True if authentication was successful
80
97
  */
81
98
  export async function authenticateService(service) {
@@ -84,6 +101,10 @@ export async function authenticateService(service) {
84
101
  return authenticateClaude();
85
102
  case 'openai':
86
103
  return authenticateOpenAI();
104
+ case 'gemini':
105
+ return authenticateGemini();
106
+ case 'grok':
107
+ return authenticateGrok();
87
108
  case 'all':
88
109
  return ensureAuthenticated();
89
110
  }
@@ -91,7 +112,7 @@ export async function authenticateService(service) {
91
112
  /**
92
113
  * Logout from a specific service or all services
93
114
  *
94
- * @param service - The service to logout from ('claude', 'openai', or 'all')
115
+ * @param service - The service to logout from ('claude', 'openai', 'gemini', 'grok', or 'all')
95
116
  */
96
117
  export async function logout(service) {
97
118
  switch (service) {
@@ -101,8 +122,16 @@ export async function logout(service) {
101
122
  case 'openai':
102
123
  await logoutOpenAI();
103
124
  break;
125
+ case 'gemini':
126
+ await logoutGemini();
127
+ break;
128
+ case 'grok':
129
+ await logoutGrok();
130
+ break;
104
131
  case 'all':
105
132
  await clearAllCredentials();
133
+ // Also clear grok credential
134
+ await deleteCredential('grok-api');
106
135
  console.log('All credentials removed.');
107
136
  break;
108
137
  }
@@ -120,8 +149,14 @@ export async function isAuthenticated(service) {
120
149
  return status.claude.authenticated;
121
150
  case 'openai':
122
151
  return status.openai.authenticated;
152
+ case 'gemini':
153
+ return status.gemini.authenticated;
154
+ case 'grok':
155
+ return status.grok.authenticated;
123
156
  case 'both':
124
157
  return status.fullyAuthenticated;
158
+ case 'all':
159
+ return status.fullyAuthenticated && status.gemini.authenticated;
125
160
  }
126
161
  }
127
162
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
@@ -1,31 +1,32 @@
1
1
  /**
2
- * Keychain wrapper for secure credential storage
3
- * Uses keytar for cross-platform keychain access (macOS Keychain, Windows Credential Vault, Linux Secret Service)
2
+ * Credential storage module
3
+ * Uses file-based storage in ~/.popeye/ directory
4
+ * Falls back to environment variables
4
5
  */
5
6
  /**
6
- * Get a credential from the system keychain
7
- * Falls back to environment variable if keychain is unavailable
7
+ * Get a credential from storage
8
+ * Falls back to environment variable if not found
8
9
  *
9
10
  * @param account - The account name (e.g., 'claude-cli', 'openai-api')
10
11
  * @returns The stored credential or null if not found
11
12
  */
12
13
  export declare function getCredential(account: string): Promise<string | null>;
13
14
  /**
14
- * Store a credential in the system keychain
15
+ * Store a credential
15
16
  *
16
17
  * @param account - The account name
17
18
  * @param password - The credential to store
18
19
  */
19
20
  export declare function setCredential(account: string, password: string): Promise<void>;
20
21
  /**
21
- * Delete a credential from the system keychain
22
+ * Delete a credential from storage
22
23
  *
23
24
  * @param account - The account name
24
25
  * @returns True if the credential was deleted, false if it didn't exist
25
26
  */
26
27
  export declare function deleteCredential(account: string): Promise<boolean>;
27
28
  /**
28
- * Check if a credential exists in the keychain
29
+ * Check if a credential exists
29
30
  *
30
31
  * @param account - The account name
31
32
  * @returns True if the credential exists
@@ -55,6 +56,18 @@ export declare function setOpenAICredential(apiKey: string): Promise<void>;
55
56
  * Delete the OpenAI API credential
56
57
  */
57
58
  export declare function deleteOpenAICredential(): Promise<boolean>;
59
+ /**
60
+ * Get the Gemini API credential
61
+ */
62
+ export declare function getGeminiCredential(): Promise<string | null>;
63
+ /**
64
+ * Set the Gemini API credential
65
+ */
66
+ export declare function setGeminiCredential(apiKey: string): Promise<void>;
67
+ /**
68
+ * Delete the Gemini API credential
69
+ */
70
+ export declare function deleteGeminiCredential(): Promise<boolean>;
58
71
  /**
59
72
  * Clear all stored credentials
60
73
  */
@@ -1 +1 @@
1
- {"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../src/auth/keychain.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoB3E;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKzD"}
1
+ {"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../src/auth/keychain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA+CH;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqB3E;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpF;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWxE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAElE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKzD"}
@@ -1,26 +1,61 @@
1
1
  /**
2
- * Keychain wrapper for secure credential storage
3
- * Uses keytar for cross-platform keychain access (macOS Keychain, Windows Credential Vault, Linux Secret Service)
2
+ * Credential storage module
3
+ * Uses file-based storage in ~/.popeye/ directory
4
+ * Falls back to environment variables
4
5
  */
5
- import * as keytar from 'keytar';
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import * as os from 'node:os';
6
9
  import { SERVICE_NAME, KEYCHAIN_ACCOUNTS, ENV_VARS } from '../config/defaults.js';
7
10
  /**
8
- * Get a credential from the system keychain
9
- * Falls back to environment variable if keychain is unavailable
10
- *
11
- * @param account - The account name (e.g., 'claude-cli', 'openai-api')
12
- * @returns The stored credential or null if not found
11
+ * Get the credentials file path
13
12
  */
14
- export async function getCredential(account) {
13
+ function getCredentialsPath() {
14
+ const popeyeDir = path.join(os.homedir(), '.popeye');
15
+ // Ensure directory exists
16
+ if (!fs.existsSync(popeyeDir)) {
17
+ fs.mkdirSync(popeyeDir, { mode: 0o700, recursive: true });
18
+ }
19
+ return path.join(popeyeDir, 'credentials.json');
20
+ }
21
+ /**
22
+ * Load credentials from file
23
+ */
24
+ function loadCredentials() {
15
25
  try {
16
- const password = await keytar.getPassword(SERVICE_NAME, account);
17
- if (password) {
18
- return password;
26
+ const filePath = getCredentialsPath();
27
+ if (fs.existsSync(filePath)) {
28
+ const data = fs.readFileSync(filePath, 'utf-8');
29
+ return JSON.parse(data);
19
30
  }
20
31
  }
21
32
  catch {
22
- // Keychain unavailable, fall back to environment variables
23
- console.warn(`Keychain unavailable for ${account}, checking environment variables`);
33
+ // Ignore errors, return empty
34
+ }
35
+ return {};
36
+ }
37
+ /**
38
+ * Save credentials to file
39
+ */
40
+ function saveCredentials(credentials) {
41
+ const filePath = getCredentialsPath();
42
+ fs.writeFileSync(filePath, JSON.stringify(credentials, null, 2), {
43
+ mode: 0o600, // Owner read/write only
44
+ });
45
+ }
46
+ /**
47
+ * Get a credential from storage
48
+ * Falls back to environment variable if not found
49
+ *
50
+ * @param account - The account name (e.g., 'claude-cli', 'openai-api')
51
+ * @returns The stored credential or null if not found
52
+ */
53
+ export async function getCredential(account) {
54
+ // First check file storage
55
+ const credentials = loadCredentials();
56
+ const key = `${SERVICE_NAME}:${account}`;
57
+ if (credentials[key]) {
58
+ return credentials[key];
24
59
  }
25
60
  // Fallback to environment variables
26
61
  if (account === KEYCHAIN_ACCOUNTS.OPENAI) {
@@ -29,39 +64,41 @@ export async function getCredential(account) {
29
64
  if (account === KEYCHAIN_ACCOUNTS.CLAUDE) {
30
65
  return process.env[ENV_VARS.ANTHROPIC_KEY] || null;
31
66
  }
67
+ if (account === KEYCHAIN_ACCOUNTS.GEMINI) {
68
+ return process.env[ENV_VARS.GEMINI_KEY] || null;
69
+ }
32
70
  return null;
33
71
  }
34
72
  /**
35
- * Store a credential in the system keychain
73
+ * Store a credential
36
74
  *
37
75
  * @param account - The account name
38
76
  * @param password - The credential to store
39
77
  */
40
78
  export async function setCredential(account, password) {
41
- try {
42
- await keytar.setPassword(SERVICE_NAME, account, password);
43
- }
44
- catch (error) {
45
- throw new Error(`Failed to store credential in keychain: ${error instanceof Error ? error.message : 'Unknown error'}`);
46
- }
79
+ const credentials = loadCredentials();
80
+ const key = `${SERVICE_NAME}:${account}`;
81
+ credentials[key] = password;
82
+ saveCredentials(credentials);
47
83
  }
48
84
  /**
49
- * Delete a credential from the system keychain
85
+ * Delete a credential from storage
50
86
  *
51
87
  * @param account - The account name
52
88
  * @returns True if the credential was deleted, false if it didn't exist
53
89
  */
54
90
  export async function deleteCredential(account) {
55
- try {
56
- return await keytar.deletePassword(SERVICE_NAME, account);
57
- }
58
- catch (error) {
59
- console.warn(`Failed to delete credential from keychain: ${error}`);
60
- return false;
91
+ const credentials = loadCredentials();
92
+ const key = `${SERVICE_NAME}:${account}`;
93
+ if (credentials[key]) {
94
+ delete credentials[key];
95
+ saveCredentials(credentials);
96
+ return true;
61
97
  }
98
+ return false;
62
99
  }
63
100
  /**
64
- * Check if a credential exists in the keychain
101
+ * Check if a credential exists
65
102
  *
66
103
  * @param account - The account name
67
104
  * @returns True if the credential exists
@@ -106,12 +143,31 @@ export async function setOpenAICredential(apiKey) {
106
143
  export async function deleteOpenAICredential() {
107
144
  return deleteCredential(KEYCHAIN_ACCOUNTS.OPENAI);
108
145
  }
146
+ /**
147
+ * Get the Gemini API credential
148
+ */
149
+ export async function getGeminiCredential() {
150
+ return getCredential(KEYCHAIN_ACCOUNTS.GEMINI);
151
+ }
152
+ /**
153
+ * Set the Gemini API credential
154
+ */
155
+ export async function setGeminiCredential(apiKey) {
156
+ return setCredential(KEYCHAIN_ACCOUNTS.GEMINI, apiKey);
157
+ }
158
+ /**
159
+ * Delete the Gemini API credential
160
+ */
161
+ export async function deleteGeminiCredential() {
162
+ return deleteCredential(KEYCHAIN_ACCOUNTS.GEMINI);
163
+ }
109
164
  /**
110
165
  * Clear all stored credentials
111
166
  */
112
167
  export async function clearAllCredentials() {
113
168
  await deleteClaudeCredential();
114
169
  await deleteOpenAICredential();
170
+ await deleteGeminiCredential();
115
171
  }
116
172
  /**
117
173
  * Get the last 4 characters of a credential for display purposes