Skip to content

Commit fb2bc25

Browse files
authored
Add copilot auto login through env vars and restrict inline completions(#6)
* add copilot auto login through env vars * restrict inline completions * add todo
1 parent b454076 commit fb2bc25

File tree

5 files changed

+59
-24
lines changed

5 files changed

+59
-24
lines changed

lab_notebook_intelligence/ai_service_manager.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,14 @@
3131
)
3232
from lab_notebook_intelligence.base_chat_participant import BaseChatParticipant
3333
from lab_notebook_intelligence.config import NBIConfig
34-
from lab_notebook_intelligence.github_copilot_chat_participant import (
35-
GithubCopilotChatParticipant,
36-
)
34+
from lab_notebook_intelligence.github_copilot_chat_participant import GithubCopilotChatParticipant
3735
from lab_notebook_intelligence.llm_providers.github_copilot_llm_provider import (
3836
GitHubCopilotLLMProvider,
3937
)
4038
from lab_notebook_intelligence.llm_providers.litellm_compatible_llm_provider import (
4139
LiteLLMCompatibleLLMProvider,
4240
)
43-
from lab_notebook_intelligence.llm_providers.ollama_llm_provider import (
44-
OllamaLLMProvider,
45-
)
41+
from lab_notebook_intelligence.llm_providers.ollama_llm_provider import OllamaLLMProvider
4642
from lab_notebook_intelligence.llm_providers.openai_compatible_llm_provider import (
4743
OpenAICompatibleLLMProvider,
4844
)

lab_notebook_intelligence/github_copilot.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@
7878
websocket_connector: ThreadSafeWebSocketConnector = None
7979
github_login_status_change_updater_enabled = False
8080

81+
deprecated_user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi-data.json")
82+
user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi", "user-data.json")
83+
access_token_password = os.getenv("NBI_GH_ACCESS_TOKEN_PASSWORD", "nbi-access-token-password")
84+
85+
86+
def get_gh_access_token_from_env() -> str:
87+
access_token = os.environ.get("NBI_GH_ACCESS_TOKEN_ENCRYPTED")
88+
if access_token is not None:
89+
try:
90+
base64_bytes = base64.b64decode(access_token.encode("utf-8"))
91+
return decrypt_with_password(access_token_password, base64_bytes).decode("utf-8")
92+
except Exception as e:
93+
log.error(f"Failed to decrypt GitHub access token from environment variable: {e}")
94+
return None
95+
8196

8297
def enable_github_login_status_change_updater(enabled: bool):
8398
global github_login_status_change_updater_enabled
@@ -109,11 +124,6 @@ def get_login_status():
109124
return response
110125

111126

112-
deprecated_user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi-data.json")
113-
user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi", "user-data.json")
114-
access_token_password = os.getenv("NBI_GH_ACCESS_TOKEN_PASSWORD", "nbi-access-token-password")
115-
116-
117127
def read_stored_github_access_token() -> str:
118128
try:
119129
if os.path.exists(user_data_file):
@@ -186,7 +196,12 @@ def login_with_existing_credentials(store_access_token: bool):
186196
if github_auth["status"] is not LoginStatus.NOT_LOGGED_IN:
187197
return
188198

189-
if store_access_token:
199+
# Check for GitHub access token in environment variable
200+
github_access_token_provided = get_gh_access_token_from_env()
201+
if github_access_token_provided:
202+
log.info("Using GitHub access token from environment variable")
203+
remember_github_access_token = False # Do not store the token if it's from the environment
204+
elif store_access_token:
190205
github_access_token_provided = read_stored_github_access_token()
191206
remember_github_access_token = True
192207
else:
@@ -331,8 +346,7 @@ def wait_for_user_access_token_thread_func():
331346

332347
def get_token():
333348
global github_auth, github_access_token_provided, API_ENDPOINT, PROXY_ENDPOINT, TOKEN_REFRESH_INTERVAL
334-
access_token = github_auth["access_token"]
335-
349+
access_token = get_gh_access_token_from_env() or github_auth["access_token"]
336350
if access_token is None:
337351
return
338352

@@ -351,7 +365,6 @@ def get_token():
351365
)
352366

353367
resp_json = resp.json()
354-
355368
if resp.status_code == 401:
356369
github_access_token_provided = None
357370
logout()
@@ -393,7 +406,9 @@ def get_token_thread_func():
393406
return
394407
token = github_auth["token"]
395408
# update token if 10 seconds or less left to expiration
396-
if github_auth["access_token"] is not None and (
409+
access_token = get_gh_access_token_from_env() or github_auth["access_token"]
410+
411+
if access_token and (
397412
token is None
398413
or (dt.datetime.now() - github_auth["token_expires_at"]).total_seconds() > -10
399414
):

src/chat-sidebar.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ function SidebarComponent(props: any) {
13231323
}
13241324

13251325
setCopilotRequestInProgress(true);
1326-
1326+
console.log('Request triggered on input - ', prompt);
13271327
const activeDocInfo: IActiveDocumentInfo = props.getActiveDocumentInfo();
13281328
const extractedPrompt = prompt;
13291329
const contents: IChatMessageContent[] = [];
@@ -1363,8 +1363,6 @@ function SidebarComponent(props: any) {
13631363
}
13641364
}
13651365

1366-
console.log('Complete context : ', additionalContext);
1367-
13681366
submitCompletionRequest(
13691367
{
13701368
messageId: lastMessageId.current,

src/index.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ class NBIInlineCompletionProvider
345345
get schema(): ISettingRegistry.IProperty {
346346
return {
347347
default: {
348-
debouncerDelay: 200,
348+
debouncerDelay: 100,
349349
timeout: 15000
350350
}
351351
};
@@ -438,7 +438,6 @@ class NBIInlineCompletionProvider
438438
editorType
439439
}
440440
});
441-
442441
return new Promise((resolve, reject) => {
443442
const items: IInlineCompletionItem[] = [];
444443

@@ -453,11 +452,36 @@ class NBIInlineCompletionProvider
453452
RequestDataType.CancelInlineCompletionRequest,
454453
{ chatId: this._lastRequestInfo.chatId }
455454
);
455+
456+
// TODO: handle fast-typers
457+
if (
458+
this._lastRequestInfo.completion &&
459+
preCursor.length > 0 &&
460+
preCursor[preCursor.length - 1] ===
461+
this._lastRequestInfo.completion[0]
462+
) {
463+
// if the last element of the preCursor is the first element of the completion
464+
// we do not need to make a completion request on the assumption that the
465+
// user is about to type the rest of the completion
466+
resolve({
467+
items: [
468+
{ insertText: this._lastRequestInfo.completion.substring(1) }
469+
]
470+
});
471+
this._lastRequestInfo.completion =
472+
this._lastRequestInfo.completion.substring(1);
473+
return;
474+
}
456475
}
457476

458477
const messageId = UUID.uuid4();
459478
const chatId = UUID.uuid4();
460-
this._lastRequestInfo = { chatId, messageId, requestTime: new Date() };
479+
this._lastRequestInfo = {
480+
chatId,
481+
messageId,
482+
completion: '',
483+
requestTime: new Date()
484+
};
461485

462486
NBIAPI.inlineCompletionsRequest(
463487
chatId,
@@ -475,6 +499,7 @@ class NBIInlineCompletionProvider
475499
items.push({
476500
insertText: response.data.completions
477501
});
502+
this._lastRequestInfo.completion = response.data.completions;
478503

479504
const timeElapsed =
480505
(new Date().getTime() -
@@ -518,6 +543,7 @@ class NBIInlineCompletionProvider
518543
private _lastRequestInfo: {
519544
chatId: string;
520545
messageId: string;
546+
completion: string;
521547
requestTime: Date;
522548
} = null;
523549
private _telemetryEmitter: TelemetryEmitter;
@@ -721,7 +747,7 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
721747
})
722748
.catch(reason => {
723749
console.error(
724-
'Failed to load settings for @notebook-intelligence/lab-notebook-intelligence.',
750+
'Failed to load settings for @lab-notebook-intelligence/lab-notebook-intelligence.',
725751
reason
726752
);
727753
});

style/base.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
.sidebar {
99
display: flex;
1010
flex-direction: column;
11-
min-width: 40%;
11+
min-width: 50%;
1212
height: 100%;
1313
}
1414

0 commit comments

Comments
 (0)