@@ -48,16 +48,16 @@ export class SettingsView {
4848 this . _extensionContext = context ;
4949
5050 // Initial content
51- this . _update ( ) ;
51+ this . _update ( ) . catch ( err => console . error ( 'Error updating settings view:' , err ) ) ;
5252
5353 // Listen for when the panel is disposed
5454 this . _panel . onDidDispose ( ( ) => this . dispose ( ) , null , this . _disposables ) ;
5555
5656 // Update the content when the view changes
5757 this . _panel . onDidChangeViewState (
58- e => {
58+ async e => {
5959 if ( this . _panel . visible ) {
60- this . _update ( ) ;
60+ await this . _update ( ) ;
6161 }
6262 } ,
6363 null ,
@@ -83,6 +83,9 @@ export class SettingsView {
8383 case 'saveAxiomSettings' :
8484 await this . _saveAxiomSettings ( message . apiKey , message . dataset , message . query ) ;
8585 break ;
86+ case 'saveClaudeApiKey' :
87+ await this . _saveClaudeApiKey ( message . apiKey ) ;
88+ break ;
8689 case 'selectRepository' :
8790 await this . _selectRepository ( ) ;
8891 break ;
@@ -302,6 +305,42 @@ export class SettingsView {
302305 } ) ;
303306 }
304307 }
308+
309+ /**
310+ * Save Claude API key to workspace configuration
311+ */
312+ private async _saveClaudeApiKey ( apiKey : string ) {
313+ if ( ! apiKey || apiKey . trim ( ) . length === 0 ) {
314+ vscode . window . showWarningMessage ( 'Please enter a valid Claude API key' ) ;
315+ return ;
316+ }
317+
318+ try {
319+ // Store the API key in the secure storage
320+ await vscode . workspace . getConfiguration ( 'traceback' ) . update ( 'claudeApiKey' , apiKey , true ) ;
321+
322+ // Also update the ClaudeService instance
323+ const claudeService = ( await import ( './claudeService' ) ) . ClaudeService . getInstance ( ) ;
324+ await claudeService . setApiKey ( apiKey ) ;
325+
326+ // Notify webview of success
327+ this . _panel . webview . postMessage ( {
328+ command : 'updateStatus' ,
329+ message : 'Claude API key saved successfully'
330+ } ) ;
331+
332+ // Update the API key input field placeholder to indicate it's set
333+ this . _panel . webview . postMessage ( {
334+ command : 'updateClaudeApiKey' ,
335+ isSet : true
336+ } ) ;
337+
338+ vscode . window . showInformationMessage ( 'Claude API key saved successfully' ) ;
339+ } catch ( error ) {
340+ console . error ( 'Error saving Claude API key:' , error ) ;
341+ vscode . window . showErrorMessage ( `Failed to save Claude API key: ${ error } ` ) ;
342+ }
343+ }
305344
306345 /**
307346 * Handle repository selection
@@ -333,9 +372,27 @@ export class SettingsView {
333372 /**
334373 * Update webview content
335374 */
336- private _update ( ) {
375+ private async _update ( ) {
337376 this . _panel . title = 'TraceBack Settings' ;
377+
378+ // Check if Claude API key is set
379+ const config = vscode . workspace . getConfiguration ( 'traceback' ) ;
380+ const claudeApiKey = config . get ( 'claudeApiKey' ) ;
381+ const isApiKeySet = ! ! claudeApiKey ;
382+
383+ // Store the state so we can use it in the HTML template
384+ await this . _extensionContext . workspaceState . update ( 'claudeApiKeySet' , isApiKeySet ) ;
385+
386+ // Generate and set the webview HTML
338387 this . _panel . webview . html = this . _getHtmlForWebview ( ) ;
388+
389+ // Update the Claude API key status in the webview after it's loaded
390+ setTimeout ( ( ) => {
391+ this . _panel . webview . postMessage ( {
392+ command : 'updateClaudeApiKey' ,
393+ isSet : isApiKeySet
394+ } ) ;
395+ } , 500 ) ;
339396 }
340397
341398 /**
@@ -465,7 +522,7 @@ export class SettingsView {
465522 <h1>TraceBack Settings</h1>
466523 </header>
467524
468- <h2>Choose Data Source</h2>
525+ <h2>1. Choose Data Source</h2>
469526
470527 <div class="setting-group">
471528 <h3>Paste Rust Logs</h3>
@@ -482,13 +539,25 @@ export class SettingsView {
482539 </div>
483540 </div>
484541
485- <h2>Select Repository</h2>
542+ <h2>2. Select Repository</h2>
486543 <div class="setting-group">
487544 <button id="selectRepo">Select Repository</button>
488545 <div class="current-setting" id="currentRepoPath">
489546 ${ repoPath ? `Current: ${ repoPath } ` : 'No repository selected' }
490547 </div>
491548 </div>
549+
550+ <h2>3. Add API key</h2>
551+ <div class="setting-group">
552+ <div id="claudeSettings">
553+ <label for="claudeApiKey">Claude API Key:</label>
554+ <input type="password" id="claudeApiKey" placeholder="sk-ant-api03-...">
555+ <button id="saveClaudeApiKey">Save API Key</button>
556+ <div class="current-setting" id="claudeApiKeyStatus">
557+ ${ this . _extensionContext . workspaceState . get ( 'claudeApiKeySet' ) ? 'API key is set' : 'No API key set' }
558+ </div>
559+ </div>
560+ </div>
492561
493562 <div id="statusMessage" class="status"></div>
494563
@@ -525,6 +594,17 @@ export class SettingsView {
525594 document.getElementById('selectRepo').addEventListener('click', () => {
526595 vscode.postMessage({ command: 'selectRepository' });
527596 });
597+
598+ document.getElementById('saveClaudeApiKey').addEventListener('click', () => {
599+ const apiKey = document.getElementById('claudeApiKey').value;
600+ if (!apiKey) {
601+ showStatus('Please enter a Claude API key');
602+ return;
603+ }
604+ vscode.postMessage({ command: 'saveClaudeApiKey', apiKey });
605+ // Clear the input field after sending
606+ document.getElementById('claudeApiKey').value = '';
607+ });
528608
529609 // Clear placeholder when focusing on textarea
530610 const rustLogText = document.getElementById('rustLogText');
@@ -551,6 +631,16 @@ export class SettingsView {
551631 case 'updateStatus':
552632 showStatus(message.message);
553633 break;
634+ case 'updateClaudeApiKey':
635+ const apiKeyInput = document.getElementById('claudeApiKey');
636+ if (message.isSet) {
637+ apiKeyInput.placeholder = '********** (API key is set)';
638+ document.getElementById('claudeApiKeyStatus').textContent = 'API key is set';
639+ } else {
640+ apiKeyInput.placeholder = 'sk-ant-api03-...';
641+ document.getElementById('claudeApiKeyStatus').textContent = 'No API key set';
642+ }
643+ break;
554644 }
555645 });
556646
0 commit comments