@@ -3,65 +3,129 @@ import * as vscode from 'vscode'
3
3
import { ChatViewProvider } from './chat/view'
4
4
import { WSChatClient } from './chat/ws'
5
5
import { WSCompletionsClient , fetchAndShowCompletions } from './completions'
6
+ import { Configuration , ConfigurationUseContext , getConfiguration } from './configuration'
6
7
import { CompletionsDocumentProvider } from './docprovider'
7
8
import { EmbeddingsClient } from './embeddings-client'
8
9
import { History } from './history'
9
10
10
- const CODY_ENDPOINT = 'cody.sgdev.org'
11
11
const CODY_ACCESS_TOKEN_SECRET = 'cody.access-token'
12
12
13
13
export async function activate ( context : vscode . ExtensionContext ) : Promise < void > {
14
14
console . log ( 'Cody extension activated' )
15
- const isDevelopment = process . env . NODE_ENV === 'development'
16
15
17
- const settings = vscode . workspace . getConfiguration ( )
18
- const documentProvider = new CompletionsDocumentProvider ( )
19
- const history = new History ( )
20
- history . register ( context )
16
+ context . subscriptions . push (
17
+ vscode . commands . registerCommand ( 'sourcegraph.cody.toggleEnabled' , async ( ) => {
18
+ const config = vscode . workspace . getConfiguration ( )
19
+ await config . update (
20
+ 'sourcegraph.cody.enable' ,
21
+ ! config . get ( 'sourcegraph.cody.enable' ) ,
22
+ vscode . ConfigurationTarget . Global
23
+ )
24
+ } ) ,
25
+ vscode . commands . registerCommand ( 'cody.set-access-token' , async ( ) => {
26
+ const tokenInput = await vscode . window . showInputBox ( )
27
+ if ( tokenInput === undefined || tokenInput === '' ) {
28
+ return
29
+ }
30
+ await context . secrets . store ( CODY_ACCESS_TOKEN_SECRET , tokenInput )
31
+ } ) ,
32
+ vscode . commands . registerCommand ( 'cody.delete-access-token' , async ( ) =>
33
+ context . secrets . delete ( CODY_ACCESS_TOKEN_SECRET )
34
+ )
35
+ )
21
36
22
- const serverAddr = settings . get ( 'cody.serverEndpoint' ) || CODY_ENDPOINT
23
- const wsUrl = `${ isDevelopment ? 'ws' : 'wss' } ://${ serverAddr } `
24
- const httpUrl = `${ isDevelopment ? 'http' : 'https' } ://${ serverAddr } `
37
+ let disposable : vscode . Disposable | undefined
38
+ context . subscriptions . push ( {
39
+ dispose : ( ) => disposable ?. dispose ( ) ,
40
+ } )
41
+ const doConfigure = async ( ) : Promise < void > => {
42
+ disposable ?. dispose ( )
43
+ const config = getConfiguration ( vscode . workspace . getConfiguration ( ) )
44
+ const accessToken = ( await context . secrets . get ( CODY_ACCESS_TOKEN_SECRET ) ) ?? null
45
+ disposable = configure ( context , config , accessToken )
46
+ }
25
47
26
- const embeddingsAddr = settings . get ( 'cody.embeddingsEndpoint' ) || CODY_ENDPOINT
27
- const embeddingsUrl = `${ isDevelopment ? 'http' : 'https' } ://${ embeddingsAddr } `
48
+ // Watch all relevant configuration and secrets for changes.
49
+ context . subscriptions . push (
50
+ vscode . workspace . onDidChangeConfiguration ( async event => {
51
+ if ( event . affectsConfiguration ( 'cody' ) || event . affectsConfiguration ( 'sourcegraph' ) ) {
52
+ await doConfigure ( )
53
+ }
54
+ } )
55
+ )
56
+ context . subscriptions . push (
57
+ context . secrets . onDidChange ( async event => {
58
+ if ( event . key === CODY_ACCESS_TOKEN_SECRET ) {
59
+ await doConfigure ( )
60
+ }
61
+ } )
62
+ )
28
63
29
- const codebaseId : string = settings . get ( 'cody.codebase' , '' )
64
+ await doConfigure ( )
65
+ }
30
66
31
- const accessToken = ( await context . secrets . get ( 'cody.access-token' ) ) ?? ''
32
- if ( ! accessToken ) {
33
- vscode . window . showWarningMessage (
34
- 'Cody needs an access token to work. Please set the token using the "Cody: Set access token" command and reload the editor.'
35
- )
67
+ function configure (
68
+ context : Pick < vscode . ExtensionContext , 'extensionPath' | 'secrets' > ,
69
+ config : Configuration ,
70
+ accessToken : string | null
71
+ ) : vscode . Disposable {
72
+ if ( ! config . enable || ! accessToken ) {
73
+ if ( config . enable ) {
74
+ const SET_ACCESS_TOKEN_ITEM = 'Set Access Token' as const
75
+ vscode . window
76
+ . showWarningMessage ( 'Cody requires an access token.' , SET_ACCESS_TOKEN_ITEM )
77
+ . then ( async item => {
78
+ if ( item === SET_ACCESS_TOKEN_ITEM ) {
79
+ await vscode . commands . executeCommand ( 'cody.set-access-token' )
80
+ }
81
+ } , undefined )
82
+ }
83
+ setContextActivated ( false )
84
+ return NOOP_DISPOSABLE
36
85
}
37
86
87
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
+ const subscriptions : { dispose ( ) : any } [ ] = [ ]
89
+
90
+ const isDevelopment = process . env . NODE_ENV === 'development'
91
+
92
+ const documentProvider = new CompletionsDocumentProvider ( )
93
+ const history = new History ( )
94
+ subscriptions . push ( history )
95
+
96
+ const wsUrl = `${ isDevelopment ? 'ws' : 'wss' } ://${ config . serverEndpoint } `
97
+ const httpUrl = `${ isDevelopment ? 'http' : 'https' } ://${ config . serverEndpoint } `
98
+
99
+ const embeddingsUrl = `${ isDevelopment ? 'http' : 'https' } ://${ config . embeddingsEndpoint } `
100
+
38
101
const wsCompletionsClient = WSCompletionsClient . new ( `${ wsUrl } /completions` , accessToken )
39
102
const wsChatClient = WSChatClient . new ( `${ wsUrl } /chat` , accessToken )
40
- const embeddingsClient = codebaseId ? new EmbeddingsClient ( embeddingsUrl , accessToken , codebaseId ) : null
103
+ const embeddingsClient = config . codebase ? new EmbeddingsClient ( embeddingsUrl , accessToken , config . codebase ) : null
41
104
42
- let contextType : 'embeddings' | 'keyword' | 'none' = settings . get ( 'cody.useContext' ) || 'embeddings'
43
- if ( ! embeddingsClient && contextType === 'embeddings' ) {
105
+ let useContext : ConfigurationUseContext = config . useContext
106
+ if ( ! embeddingsClient && config . useContext === 'embeddings' ) {
107
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
44
108
vscode . window . showInformationMessage (
45
109
'Embeddings were not available (is `cody.codebase` set?), falling back to keyword context'
46
110
)
47
- contextType = 'keyword'
111
+ useContext = 'keyword'
48
112
}
49
113
50
114
const chatProvider = new ChatViewProvider (
51
115
context . extensionPath ,
52
116
httpUrl ,
53
117
wsChatClient ,
54
118
embeddingsClient ,
55
- contextType ,
56
- settings . get ( 'cody. debug' ) || false
119
+ useContext ,
120
+ config . debug
57
121
)
58
122
59
- const executeRecipe = async ( recipe : string ) => {
123
+ const executeRecipe = async ( recipe : string ) : Promise < void > => {
60
124
await vscode . commands . executeCommand ( 'cody.chat.focus' )
61
- return chatProvider . executeRecipe ( recipe )
125
+ await chatProvider . executeRecipe ( recipe )
62
126
}
63
127
64
- context . subscriptions . push (
128
+ subscriptions . push (
65
129
vscode . workspace . registerTextDocumentContentProvider ( 'codegen' , documentProvider ) ,
66
130
vscode . languages . registerHoverProvider ( { scheme : 'codegen' } , documentProvider ) ,
67
131
@@ -78,30 +142,30 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
78
142
vscode . commands . registerCommand ( 'cody.recipe.translate-to-language' , async ( ) =>
79
143
executeRecipe ( 'translateToLanguage' )
80
144
) ,
81
- vscode . commands . registerCommand ( 'cody.recipe.git-history' , async => executeRecipe ( 'gitHistory' ) ) ,
82
-
83
- vscode . window . registerWebviewViewProvider ( 'cody.chat' , chatProvider ) ,
145
+ vscode . commands . registerCommand ( 'cody.recipe.git-history' , ( ) => executeRecipe ( 'gitHistory' ) ) ,
84
146
85
- vscode . commands . registerCommand ( 'cody.set-access-token' , async ( ) => {
86
- const tokenInput = await vscode . window . showInputBox ( )
87
- if ( tokenInput === undefined ) {
88
- return
89
- }
90
- return context . secrets . store ( CODY_ACCESS_TOKEN_SECRET , tokenInput )
91
- } ) ,
92
-
93
- vscode . commands . registerCommand ( 'cody.delete-access-token' , async ( ) =>
94
- context . secrets . delete ( CODY_ACCESS_TOKEN_SECRET )
95
- )
147
+ vscode . window . registerWebviewViewProvider ( 'cody.chat' , chatProvider )
96
148
)
97
149
98
- if ( settings . get ( 'cody.experimental.suggest' ) ) {
99
- context . subscriptions . push (
150
+ if ( config . experimentalSuggest ) {
151
+ subscriptions . push (
100
152
vscode . commands . registerCommand ( 'cody.experimental.suggest' , async ( ) => {
101
153
await fetchAndShowCompletions ( wsCompletionsClient , documentProvider , history )
102
154
} )
103
155
)
104
156
}
157
+
158
+ setContextActivated ( true )
159
+
160
+ return vscode . Disposable . from ( ...subscriptions )
105
161
}
106
162
107
- export function deactivate ( ) { }
163
+ const NOOP_DISPOSABLE : vscode . Disposable = {
164
+ dispose : ( ) => {
165
+ /* noop */
166
+ } ,
167
+ }
168
+
169
+ function setContextActivated ( activated : boolean ) : void {
170
+ vscode . commands . executeCommand ( 'setContext' , 'sourcegraph.cody.activated' , activated ) . then ( undefined , undefined )
171
+ }
0 commit comments