Skip to content

Commit 136a8f9

Browse files
feat: Add OpenAI API key management functionality
- Introduced a new feature to manage the OpenAI API key within the application. - Added the ability to add update show masked and delete the API key through a new command
1 parent 009713c commit 136a8f9

File tree

1 file changed

+104
-4
lines changed

1 file changed

+104
-4
lines changed

index.js

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { sanitizeCommitMessage } from './utils/sanitizeCommitMessage.js'
1515
let openai
1616
let model = 'gpt-4o' // Default model
1717
let language = 'English' // Default language
18+
let apiKey = null // Store API key from config
1819
// Define prefixState using closure for safer state management
1920
const 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+
6980
export 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

Comments
 (0)