@@ -15,6 +15,7 @@ import { sanitizeCommitMessage } from './utils/sanitizeCommitMessage.js'
1515let openai
1616let model = 'gpt-4o' // Default model
1717let language = 'English' // Default language
18+ let apiKey = null // Store API key from config
1819// Define prefixState using closure for safer state management
1920const prefixState = ( ( ) => {
2021 let enabled = true // Default is enabled
@@ -59,19 +60,43 @@ function loadConfig() {
5960 if ( config . prefixEnabled !== undefined ) {
6061 prefixState . setEnabled ( config . prefixEnabled )
6162 }
63+ if ( config . apiKey ) {
64+ apiKey = config . apiKey
65+ }
6266 }
6367 } catch ( error ) {
6468 console . error ( 'Error loading configuration:' , error )
6569 // Continue with default model if there's an error
6670 }
6771}
6872
73+ // Mask API key for display
74+ function maskApiKey ( key ) {
75+ if ( ! key ) return 'none'
76+ // Show only first 4 and last 4 characters
77+ return `${ key . substring ( 0 , 4 ) } ...${ key . substring ( key . length - 4 ) } `
78+ }
79+
6980export async function getGitSummary ( ) {
7081 try {
71- const dotenv = await import ( 'dotenv' )
72- const envPath = path . join ( process . cwd ( ) , '.env' )
73- dotenv . config ( { path : envPath } )
74- openai = new OpenAI ( { apiKey : process . env . OPENAI_API_KEY } )
82+ // If no API key in config, try to load from .env
83+ if ( ! apiKey ) {
84+ const dotenv = await import ( 'dotenv' )
85+ const envPath = path . join ( process . cwd ( ) , '.env' )
86+ dotenv . config ( { path : envPath } )
87+ }
88+
89+ // Use API key from config if available, otherwise use from .env
90+ const openaiApiKey = apiKey || process . env . OPENAI_API_KEY
91+
92+ if ( ! openaiApiKey ) {
93+ console . error (
94+ 'No OpenAI API key found. Please set it using "git gpt open-api-key add".' ,
95+ )
96+ process . exit ( 1 )
97+ }
98+
99+ openai = new OpenAI ( { apiKey : openaiApiKey } )
75100
76101 const exec = promisify ( originalExec )
77102 const { stdout } = await exec (
@@ -236,6 +261,80 @@ const gitExtension = (_args) => {
236261 )
237262 } )
238263
264+ program
265+ . command ( 'open-api-key' )
266+ . description ( 'Manage your OpenAI API key' )
267+ . action ( async ( ) => {
268+ // Show select menu for actions
269+ const actionResponse = await prompts ( {
270+ type : 'select' ,
271+ name : 'value' ,
272+ message : 'What would you like to do with your OpenAI API key?' ,
273+ choices : [
274+ { title : 'Add or update API key' , value : 'add' } ,
275+ { title : 'Show API key (masked)' , value : 'show' } ,
276+ { title : 'Delete API key' , value : 'delete' } ,
277+ ] ,
278+ initial : 0 ,
279+ } )
280+
281+ // If user cancelled the selection
282+ if ( ! actionResponse . value ) {
283+ console . log ( 'Action cancelled.' )
284+ return
285+ }
286+
287+ const action = actionResponse . value
288+
289+ switch ( action ) {
290+ case 'add' :
291+ const response = await prompts ( {
292+ type : 'password' ,
293+ name : 'value' ,
294+ message : 'Enter your OpenAI API key' ,
295+ } )
296+
297+ if ( response . value ) {
298+ saveConfig ( { apiKey : response . value } )
299+ apiKey = response . value
300+ console . log ( 'API key saved to configuration.' )
301+ } else {
302+ console . log ( 'Action cancelled.' )
303+ }
304+ break
305+
306+ case 'delete' :
307+ const confirmDelete = await prompts ( {
308+ type : 'confirm' ,
309+ name : 'value' ,
310+ message : 'Are you sure you want to delete your stored API key?' ,
311+ initial : false ,
312+ } )
313+
314+ if ( confirmDelete . value ) {
315+ // Load current config, delete apiKey, and save back
316+ let existingConfig = { }
317+ if ( fs . existsSync ( CONFIG_FILE ) ) {
318+ existingConfig = JSON . parse ( fs . readFileSync ( CONFIG_FILE , 'utf8' ) )
319+ delete existingConfig . apiKey
320+ fs . writeFileSync (
321+ CONFIG_FILE ,
322+ JSON . stringify ( existingConfig , null , 2 ) ,
323+ )
324+ apiKey = null
325+ console . log ( 'API key deleted from configuration.' )
326+ }
327+ } else {
328+ console . log ( 'Action cancelled.' )
329+ }
330+ break
331+
332+ case 'show' :
333+ console . log ( `OpenAI API key: ${ maskApiKey ( apiKey ) } ` )
334+ break
335+ }
336+ } )
337+
239338 program
240339 . command ( 'config' )
241340 . description ( 'Show current configuration' )
@@ -245,6 +344,7 @@ const gitExtension = (_args) => {
245344 )
246345 console . log ( ` model: ${ model } ` )
247346 console . log ( ` lang: ${ language } ` )
347+ console . log ( ` apikey: ${ maskApiKey ( apiKey ) } ` )
248348 console . log ( ` path: ${ CONFIG_FILE } ` )
249349 } )
250350
0 commit comments