popeye-cli 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 (209) hide show
  1. package/.env.example +25 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +320 -0
  4. package/dist/adapters/claude.d.ts +82 -0
  5. package/dist/adapters/claude.d.ts.map +1 -0
  6. package/dist/adapters/claude.js +230 -0
  7. package/dist/adapters/claude.js.map +1 -0
  8. package/dist/adapters/openai.d.ts +48 -0
  9. package/dist/adapters/openai.d.ts.map +1 -0
  10. package/dist/adapters/openai.js +257 -0
  11. package/dist/adapters/openai.js.map +1 -0
  12. package/dist/auth/claude.d.ts +44 -0
  13. package/dist/auth/claude.d.ts.map +1 -0
  14. package/dist/auth/claude.js +139 -0
  15. package/dist/auth/claude.js.map +1 -0
  16. package/dist/auth/index.d.ts +61 -0
  17. package/dist/auth/index.d.ts.map +1 -0
  18. package/dist/auth/index.js +141 -0
  19. package/dist/auth/index.js.map +1 -0
  20. package/dist/auth/keychain.d.ts +66 -0
  21. package/dist/auth/keychain.d.ts.map +1 -0
  22. package/dist/auth/keychain.js +125 -0
  23. package/dist/auth/keychain.js.map +1 -0
  24. package/dist/auth/openai-entry.d.ts +9 -0
  25. package/dist/auth/openai-entry.d.ts.map +1 -0
  26. package/dist/auth/openai-entry.js +410 -0
  27. package/dist/auth/openai-entry.js.map +1 -0
  28. package/dist/auth/openai.d.ts +71 -0
  29. package/dist/auth/openai.d.ts.map +1 -0
  30. package/dist/auth/openai.js +212 -0
  31. package/dist/auth/openai.js.map +1 -0
  32. package/dist/auth/server.d.ts +32 -0
  33. package/dist/auth/server.d.ts.map +1 -0
  34. package/dist/auth/server.js +213 -0
  35. package/dist/auth/server.js.map +1 -0
  36. package/dist/cli/commands/auth.d.ts +10 -0
  37. package/dist/cli/commands/auth.d.ts.map +1 -0
  38. package/dist/cli/commands/auth.js +162 -0
  39. package/dist/cli/commands/auth.js.map +1 -0
  40. package/dist/cli/commands/config.d.ts +10 -0
  41. package/dist/cli/commands/config.d.ts.map +1 -0
  42. package/dist/cli/commands/config.js +215 -0
  43. package/dist/cli/commands/config.js.map +1 -0
  44. package/dist/cli/commands/create.d.ts +10 -0
  45. package/dist/cli/commands/create.d.ts.map +1 -0
  46. package/dist/cli/commands/create.js +240 -0
  47. package/dist/cli/commands/create.js.map +1 -0
  48. package/dist/cli/commands/index.d.ts +10 -0
  49. package/dist/cli/commands/index.d.ts.map +1 -0
  50. package/dist/cli/commands/index.js +10 -0
  51. package/dist/cli/commands/index.js.map +1 -0
  52. package/dist/cli/commands/resume.d.ts +18 -0
  53. package/dist/cli/commands/resume.d.ts.map +1 -0
  54. package/dist/cli/commands/resume.js +241 -0
  55. package/dist/cli/commands/resume.js.map +1 -0
  56. package/dist/cli/commands/status.d.ts +18 -0
  57. package/dist/cli/commands/status.d.ts.map +1 -0
  58. package/dist/cli/commands/status.js +154 -0
  59. package/dist/cli/commands/status.js.map +1 -0
  60. package/dist/cli/index.d.ts +17 -0
  61. package/dist/cli/index.d.ts.map +1 -0
  62. package/dist/cli/index.js +71 -0
  63. package/dist/cli/index.js.map +1 -0
  64. package/dist/cli/interactive.d.ts +9 -0
  65. package/dist/cli/interactive.d.ts.map +1 -0
  66. package/dist/cli/interactive.js +330 -0
  67. package/dist/cli/interactive.js.map +1 -0
  68. package/dist/cli/output.d.ts +182 -0
  69. package/dist/cli/output.d.ts.map +1 -0
  70. package/dist/cli/output.js +355 -0
  71. package/dist/cli/output.js.map +1 -0
  72. package/dist/config/defaults.d.ts +57 -0
  73. package/dist/config/defaults.d.ts.map +1 -0
  74. package/dist/config/defaults.js +103 -0
  75. package/dist/config/defaults.js.map +1 -0
  76. package/dist/config/index.d.ts +138 -0
  77. package/dist/config/index.d.ts.map +1 -0
  78. package/dist/config/index.js +244 -0
  79. package/dist/config/index.js.map +1 -0
  80. package/dist/config/schema.d.ts +220 -0
  81. package/dist/config/schema.d.ts.map +1 -0
  82. package/dist/config/schema.js +141 -0
  83. package/dist/config/schema.js.map +1 -0
  84. package/dist/generators/index.d.ts +101 -0
  85. package/dist/generators/index.d.ts.map +1 -0
  86. package/dist/generators/index.js +200 -0
  87. package/dist/generators/index.js.map +1 -0
  88. package/dist/generators/python.d.ts +48 -0
  89. package/dist/generators/python.d.ts.map +1 -0
  90. package/dist/generators/python.js +262 -0
  91. package/dist/generators/python.js.map +1 -0
  92. package/dist/generators/templates/index.d.ts +6 -0
  93. package/dist/generators/templates/index.d.ts.map +1 -0
  94. package/dist/generators/templates/index.js +6 -0
  95. package/dist/generators/templates/index.js.map +1 -0
  96. package/dist/generators/templates/python.d.ts +53 -0
  97. package/dist/generators/templates/python.d.ts.map +1 -0
  98. package/dist/generators/templates/python.js +454 -0
  99. package/dist/generators/templates/python.js.map +1 -0
  100. package/dist/generators/templates/typescript.d.ts +53 -0
  101. package/dist/generators/templates/typescript.d.ts.map +1 -0
  102. package/dist/generators/templates/typescript.js +394 -0
  103. package/dist/generators/templates/typescript.js.map +1 -0
  104. package/dist/generators/typescript.d.ts +64 -0
  105. package/dist/generators/typescript.d.ts.map +1 -0
  106. package/dist/generators/typescript.js +271 -0
  107. package/dist/generators/typescript.js.map +1 -0
  108. package/dist/index.d.ts +7 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +12 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/state/index.d.ts +168 -0
  113. package/dist/state/index.d.ts.map +1 -0
  114. package/dist/state/index.js +338 -0
  115. package/dist/state/index.js.map +1 -0
  116. package/dist/state/persistence.d.ts +91 -0
  117. package/dist/state/persistence.d.ts.map +1 -0
  118. package/dist/state/persistence.js +201 -0
  119. package/dist/state/persistence.js.map +1 -0
  120. package/dist/types/cli.d.ts +132 -0
  121. package/dist/types/cli.d.ts.map +1 -0
  122. package/dist/types/cli.js +17 -0
  123. package/dist/types/cli.js.map +1 -0
  124. package/dist/types/consensus.d.ts +111 -0
  125. package/dist/types/consensus.d.ts.map +1 -0
  126. package/dist/types/consensus.js +29 -0
  127. package/dist/types/consensus.js.map +1 -0
  128. package/dist/types/index.d.ts +9 -0
  129. package/dist/types/index.d.ts.map +1 -0
  130. package/dist/types/index.js +13 -0
  131. package/dist/types/index.js.map +1 -0
  132. package/dist/types/project.d.ts +73 -0
  133. package/dist/types/project.d.ts.map +1 -0
  134. package/dist/types/project.js +55 -0
  135. package/dist/types/project.js.map +1 -0
  136. package/dist/types/workflow.d.ts +236 -0
  137. package/dist/types/workflow.d.ts.map +1 -0
  138. package/dist/types/workflow.js +74 -0
  139. package/dist/types/workflow.js.map +1 -0
  140. package/dist/workflow/consensus.d.ts +89 -0
  141. package/dist/workflow/consensus.d.ts.map +1 -0
  142. package/dist/workflow/consensus.js +220 -0
  143. package/dist/workflow/consensus.js.map +1 -0
  144. package/dist/workflow/execution-mode.d.ts +82 -0
  145. package/dist/workflow/execution-mode.d.ts.map +1 -0
  146. package/dist/workflow/execution-mode.js +346 -0
  147. package/dist/workflow/execution-mode.js.map +1 -0
  148. package/dist/workflow/index.d.ts +110 -0
  149. package/dist/workflow/index.d.ts.map +1 -0
  150. package/dist/workflow/index.js +283 -0
  151. package/dist/workflow/index.js.map +1 -0
  152. package/dist/workflow/plan-mode.d.ts +83 -0
  153. package/dist/workflow/plan-mode.d.ts.map +1 -0
  154. package/dist/workflow/plan-mode.js +241 -0
  155. package/dist/workflow/plan-mode.js.map +1 -0
  156. package/dist/workflow/test-runner.d.ts +87 -0
  157. package/dist/workflow/test-runner.d.ts.map +1 -0
  158. package/dist/workflow/test-runner.js +273 -0
  159. package/dist/workflow/test-runner.js.map +1 -0
  160. package/eslint.config.js +25 -0
  161. package/package.json +66 -0
  162. package/src/adapters/claude.ts +298 -0
  163. package/src/adapters/openai.ts +300 -0
  164. package/src/auth/claude.ts +166 -0
  165. package/src/auth/index.ts +171 -0
  166. package/src/auth/keychain.ts +138 -0
  167. package/src/auth/openai-entry.ts +410 -0
  168. package/src/auth/openai.ts +260 -0
  169. package/src/auth/server.ts +252 -0
  170. package/src/cli/commands/auth.ts +194 -0
  171. package/src/cli/commands/config.ts +241 -0
  172. package/src/cli/commands/create.ts +308 -0
  173. package/src/cli/commands/index.ts +10 -0
  174. package/src/cli/commands/resume.ts +304 -0
  175. package/src/cli/commands/status.ts +189 -0
  176. package/src/cli/index.ts +90 -0
  177. package/src/cli/interactive.ts +418 -0
  178. package/src/cli/output.ts +410 -0
  179. package/src/config/defaults.ts +114 -0
  180. package/src/config/index.ts +315 -0
  181. package/src/config/schema.ts +164 -0
  182. package/src/generators/index.ts +251 -0
  183. package/src/generators/python.ts +318 -0
  184. package/src/generators/templates/index.ts +6 -0
  185. package/src/generators/templates/python.ts +465 -0
  186. package/src/generators/templates/typescript.ts +417 -0
  187. package/src/generators/typescript.ts +340 -0
  188. package/src/index.ts +13 -0
  189. package/src/state/index.ts +454 -0
  190. package/src/state/persistence.ts +230 -0
  191. package/src/types/cli.ts +146 -0
  192. package/src/types/consensus.ts +116 -0
  193. package/src/types/index.ts +64 -0
  194. package/src/types/project.ts +85 -0
  195. package/src/types/workflow.ts +149 -0
  196. package/src/workflow/consensus.ts +299 -0
  197. package/src/workflow/execution-mode.ts +517 -0
  198. package/src/workflow/index.ts +396 -0
  199. package/src/workflow/plan-mode.ts +356 -0
  200. package/src/workflow/test-runner.ts +345 -0
  201. package/tests/adapters/openai.test.ts +145 -0
  202. package/tests/config/config.test.ts +208 -0
  203. package/tests/generators/generators.test.ts +185 -0
  204. package/tests/types/consensus.test.ts +152 -0
  205. package/tests/types/project.test.ts +134 -0
  206. package/tests/workflow/consensus.test.ts +221 -0
  207. package/tests/workflow/test-runner.test.ts +214 -0
  208. package/tsconfig.json +25 -0
  209. package/vitest.config.ts +22 -0
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Authentication orchestration module
3
+ * Coordinates authentication for both Claude CLI and OpenAI API
4
+ */
5
+ import { checkClaudeCLIAuth, authenticateClaude, logoutClaude } from './claude.js';
6
+ import { checkOpenAIAuth, authenticateOpenAI, logoutOpenAI } from './openai.js';
7
+ import { clearAllCredentials } from './keychain.js';
8
+ // Re-export individual auth modules
9
+ export * from './claude.js';
10
+ export * from './openai.js';
11
+ export * from './keychain.js';
12
+ export * from './server.js';
13
+ /**
14
+ * Get the authentication status for both services
15
+ */
16
+ export async function getAuthStatus() {
17
+ const [claudeStatus, openaiStatus] = await Promise.all([
18
+ checkClaudeCLIAuth(),
19
+ checkOpenAIAuth(),
20
+ ]);
21
+ return {
22
+ claude: claudeStatus,
23
+ openai: openaiStatus,
24
+ fullyAuthenticated: claudeStatus.authenticated && openaiStatus.authenticated,
25
+ };
26
+ }
27
+ /**
28
+ * Get auth status formatted for CLI display
29
+ */
30
+ export async function getAuthStatusForDisplay() {
31
+ const status = await getAuthStatus();
32
+ return {
33
+ claude: {
34
+ authenticated: status.claude.authenticated,
35
+ user: status.claude.user,
36
+ expires: status.claude.expires,
37
+ },
38
+ openai: {
39
+ authenticated: status.openai.authenticated,
40
+ keyLastFour: status.openai.keyLastFour,
41
+ modelAccess: status.openai.modelAccess,
42
+ },
43
+ };
44
+ }
45
+ /**
46
+ * Ensure both services are authenticated
47
+ * Prompts for authentication if either is missing
48
+ *
49
+ * @returns True if both services are authenticated
50
+ */
51
+ export async function ensureAuthenticated() {
52
+ const status = await getAuthStatus();
53
+ if (status.fullyAuthenticated) {
54
+ return true;
55
+ }
56
+ let success = true;
57
+ // Authenticate Claude if needed
58
+ if (!status.claude.authenticated) {
59
+ console.log('\n--- Claude CLI Authentication ---\n');
60
+ const claudeSuccess = await authenticateClaude();
61
+ if (!claudeSuccess) {
62
+ success = false;
63
+ }
64
+ }
65
+ // Authenticate OpenAI if needed
66
+ if (!status.openai.authenticated) {
67
+ console.log('\n--- OpenAI API Authentication ---\n');
68
+ const openaiSuccess = await authenticateOpenAI();
69
+ if (!openaiSuccess) {
70
+ success = false;
71
+ }
72
+ }
73
+ return success;
74
+ }
75
+ /**
76
+ * Authenticate a specific service
77
+ *
78
+ * @param service - The service to authenticate ('claude', 'openai', or 'all')
79
+ * @returns True if authentication was successful
80
+ */
81
+ export async function authenticateService(service) {
82
+ switch (service) {
83
+ case 'claude':
84
+ return authenticateClaude();
85
+ case 'openai':
86
+ return authenticateOpenAI();
87
+ case 'all':
88
+ return ensureAuthenticated();
89
+ }
90
+ }
91
+ /**
92
+ * Logout from a specific service or all services
93
+ *
94
+ * @param service - The service to logout from ('claude', 'openai', or 'all')
95
+ */
96
+ export async function logout(service) {
97
+ switch (service) {
98
+ case 'claude':
99
+ await logoutClaude();
100
+ break;
101
+ case 'openai':
102
+ await logoutOpenAI();
103
+ break;
104
+ case 'all':
105
+ await clearAllCredentials();
106
+ console.log('All credentials removed.');
107
+ break;
108
+ }
109
+ }
110
+ /**
111
+ * Check if a specific service is authenticated
112
+ *
113
+ * @param service - The service to check
114
+ * @returns True if the service is authenticated
115
+ */
116
+ export async function isAuthenticated(service) {
117
+ const status = await getAuthStatus();
118
+ switch (service) {
119
+ case 'claude':
120
+ return status.claude.authenticated;
121
+ case 'openai':
122
+ return status.openai.authenticated;
123
+ case 'both':
124
+ return status.fullyAuthenticated;
125
+ }
126
+ }
127
+ /**
128
+ * Require authentication, throwing an error if not authenticated
129
+ *
130
+ * @throws Error if not authenticated
131
+ */
132
+ export async function requireAuth() {
133
+ const status = await getAuthStatus();
134
+ if (!status.claude.authenticated) {
135
+ throw new Error('Claude CLI authentication required. Run: popeye-cli auth claude');
136
+ }
137
+ if (!status.openai.authenticated) {
138
+ throw new Error('OpenAI API authentication required. Run: popeye-cli auth openai');
139
+ }
140
+ }
141
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,YAAY,EAAyB,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAyB,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,oCAAoC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAW5B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACrD,kBAAkB,EAAE;QACpB,eAAe,EAAE;KAClB,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,YAAY;QACpB,kBAAkB,EAAE,YAAY,CAAC,aAAa,IAAI,YAAY,CAAC,aAAa;KAC7E,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IAErC,OAAO;QACL,MAAM,EAAE;YACN,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;YAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;YACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;SAC/B;QACD,MAAM,EAAE;YACN,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;YAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;YACtC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;SACvC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IAErC,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,gCAAgC;IAChC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACjD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACjD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAoC;IAEpC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,kBAAkB,EAAE,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,kBAAkB,EAAE,CAAC;QAC9B,KAAK,KAAK;YACR,OAAO,mBAAmB,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAoC;IAC/D,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,MAAM,YAAY,EAAE,CAAC;YACrB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,YAAY,EAAE,CAAC;YACrB,MAAM;QACR,KAAK,KAAK;YACR,MAAM,mBAAmB,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,MAAM;IACV,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAqC;IACzE,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IAErC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;QACrC,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;QACrC,KAAK,MAAM;YACT,OAAO,MAAM,CAAC,kBAAkB,CAAC;IACrC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IAErC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;AACH,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Keychain wrapper for secure credential storage
3
+ * Uses keytar for cross-platform keychain access (macOS Keychain, Windows Credential Vault, Linux Secret Service)
4
+ */
5
+ /**
6
+ * Get a credential from the system keychain
7
+ * Falls back to environment variable if keychain is unavailable
8
+ *
9
+ * @param account - The account name (e.g., 'claude-cli', 'openai-api')
10
+ * @returns The stored credential or null if not found
11
+ */
12
+ export declare function getCredential(account: string): Promise<string | null>;
13
+ /**
14
+ * Store a credential in the system keychain
15
+ *
16
+ * @param account - The account name
17
+ * @param password - The credential to store
18
+ */
19
+ export declare function setCredential(account: string, password: string): Promise<void>;
20
+ /**
21
+ * Delete a credential from the system keychain
22
+ *
23
+ * @param account - The account name
24
+ * @returns True if the credential was deleted, false if it didn't exist
25
+ */
26
+ export declare function deleteCredential(account: string): Promise<boolean>;
27
+ /**
28
+ * Check if a credential exists in the keychain
29
+ *
30
+ * @param account - The account name
31
+ * @returns True if the credential exists
32
+ */
33
+ export declare function hasCredential(account: string): Promise<boolean>;
34
+ /**
35
+ * Get the Claude CLI credential
36
+ */
37
+ export declare function getClaudeCredential(): Promise<string | null>;
38
+ /**
39
+ * Set the Claude CLI credential
40
+ */
41
+ export declare function setClaudeCredential(token: string): Promise<void>;
42
+ /**
43
+ * Delete the Claude CLI credential
44
+ */
45
+ export declare function deleteClaudeCredential(): Promise<boolean>;
46
+ /**
47
+ * Get the OpenAI API credential
48
+ */
49
+ export declare function getOpenAICredential(): Promise<string | null>;
50
+ /**
51
+ * Set the OpenAI API credential
52
+ */
53
+ export declare function setOpenAICredential(apiKey: string): Promise<void>;
54
+ /**
55
+ * Delete the OpenAI API credential
56
+ */
57
+ export declare function deleteOpenAICredential(): Promise<boolean>;
58
+ /**
59
+ * Clear all stored credentials
60
+ */
61
+ export declare function clearAllCredentials(): Promise<void>;
62
+ /**
63
+ * Get the last 4 characters of a credential for display purposes
64
+ */
65
+ export declare function maskCredential(credential: string): string;
66
+ //# sourceMappingURL=keychain.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Keychain wrapper for secure credential storage
3
+ * Uses keytar for cross-platform keychain access (macOS Keychain, Windows Credential Vault, Linux Secret Service)
4
+ */
5
+ import * as keytar from 'keytar';
6
+ import { SERVICE_NAME, KEYCHAIN_ACCOUNTS, ENV_VARS } from '../config/defaults.js';
7
+ /**
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
13
+ */
14
+ export async function getCredential(account) {
15
+ try {
16
+ const password = await keytar.getPassword(SERVICE_NAME, account);
17
+ if (password) {
18
+ return password;
19
+ }
20
+ }
21
+ catch {
22
+ // Keychain unavailable, fall back to environment variables
23
+ console.warn(`Keychain unavailable for ${account}, checking environment variables`);
24
+ }
25
+ // Fallback to environment variables
26
+ if (account === KEYCHAIN_ACCOUNTS.OPENAI) {
27
+ return process.env[ENV_VARS.OPENAI_KEY] || null;
28
+ }
29
+ if (account === KEYCHAIN_ACCOUNTS.CLAUDE) {
30
+ return process.env[ENV_VARS.ANTHROPIC_KEY] || null;
31
+ }
32
+ return null;
33
+ }
34
+ /**
35
+ * Store a credential in the system keychain
36
+ *
37
+ * @param account - The account name
38
+ * @param password - The credential to store
39
+ */
40
+ 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
+ }
47
+ }
48
+ /**
49
+ * Delete a credential from the system keychain
50
+ *
51
+ * @param account - The account name
52
+ * @returns True if the credential was deleted, false if it didn't exist
53
+ */
54
+ 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;
61
+ }
62
+ }
63
+ /**
64
+ * Check if a credential exists in the keychain
65
+ *
66
+ * @param account - The account name
67
+ * @returns True if the credential exists
68
+ */
69
+ export async function hasCredential(account) {
70
+ const credential = await getCredential(account);
71
+ return credential !== null;
72
+ }
73
+ /**
74
+ * Get the Claude CLI credential
75
+ */
76
+ export async function getClaudeCredential() {
77
+ return getCredential(KEYCHAIN_ACCOUNTS.CLAUDE);
78
+ }
79
+ /**
80
+ * Set the Claude CLI credential
81
+ */
82
+ export async function setClaudeCredential(token) {
83
+ return setCredential(KEYCHAIN_ACCOUNTS.CLAUDE, token);
84
+ }
85
+ /**
86
+ * Delete the Claude CLI credential
87
+ */
88
+ export async function deleteClaudeCredential() {
89
+ return deleteCredential(KEYCHAIN_ACCOUNTS.CLAUDE);
90
+ }
91
+ /**
92
+ * Get the OpenAI API credential
93
+ */
94
+ export async function getOpenAICredential() {
95
+ return getCredential(KEYCHAIN_ACCOUNTS.OPENAI);
96
+ }
97
+ /**
98
+ * Set the OpenAI API credential
99
+ */
100
+ export async function setOpenAICredential(apiKey) {
101
+ return setCredential(KEYCHAIN_ACCOUNTS.OPENAI, apiKey);
102
+ }
103
+ /**
104
+ * Delete the OpenAI API credential
105
+ */
106
+ export async function deleteOpenAICredential() {
107
+ return deleteCredential(KEYCHAIN_ACCOUNTS.OPENAI);
108
+ }
109
+ /**
110
+ * Clear all stored credentials
111
+ */
112
+ export async function clearAllCredentials() {
113
+ await deleteClaudeCredential();
114
+ await deleteOpenAICredential();
115
+ }
116
+ /**
117
+ * Get the last 4 characters of a credential for display purposes
118
+ */
119
+ export function maskCredential(credential) {
120
+ if (credential.length <= 4) {
121
+ return '****';
122
+ }
123
+ return `****${credential.slice(-4)}`;
124
+ }
125
+ //# sourceMappingURL=keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/auth/keychain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenAI API key entry HTML page
3
+ * Served by the local auth server for browser-based token entry
4
+ */
5
+ /**
6
+ * Generate the HTML for the OpenAI token entry page
7
+ */
8
+ export declare function getOpenAIEntryHTML(_port: number): string;
9
+ //# sourceMappingURL=openai-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-entry.d.ts","sourceRoot":"","sources":["../../src/auth/openai-entry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiZxD"}