Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions lab_notebook_intelligence/ai_service_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,14 @@
)
from lab_notebook_intelligence.base_chat_participant import BaseChatParticipant
from lab_notebook_intelligence.config import NBIConfig
from lab_notebook_intelligence.github_copilot_chat_participant import (
GithubCopilotChatParticipant,
)
from lab_notebook_intelligence.github_copilot_chat_participant import GithubCopilotChatParticipant
from lab_notebook_intelligence.llm_providers.github_copilot_llm_provider import (
GitHubCopilotLLMProvider,
)
from lab_notebook_intelligence.llm_providers.litellm_compatible_llm_provider import (
LiteLLMCompatibleLLMProvider,
)
from lab_notebook_intelligence.llm_providers.ollama_llm_provider import (
OllamaLLMProvider,
)
from lab_notebook_intelligence.llm_providers.ollama_llm_provider import OllamaLLMProvider
from lab_notebook_intelligence.llm_providers.openai_compatible_llm_provider import (
OpenAICompatibleLLMProvider,
)
Expand Down
35 changes: 25 additions & 10 deletions lab_notebook_intelligence/github_copilot.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@
websocket_connector: ThreadSafeWebSocketConnector = None
github_login_status_change_updater_enabled = False

deprecated_user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi-data.json")
user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi", "user-data.json")
access_token_password = os.getenv("NBI_GH_ACCESS_TOKEN_PASSWORD", "nbi-access-token-password")


def get_gh_access_token_from_env() -> str:
access_token = os.environ.get("NBI_GH_ACCESS_TOKEN_ENCRYPTED")
if access_token is not None:
try:
base64_bytes = base64.b64decode(access_token.encode("utf-8"))
return decrypt_with_password(access_token_password, base64_bytes).decode("utf-8")
except Exception as e:
log.error(f"Failed to decrypt GitHub access token from environment variable: {e}")
return None


def enable_github_login_status_change_updater(enabled: bool):
global github_login_status_change_updater_enabled
Expand Down Expand Up @@ -109,11 +124,6 @@ def get_login_status():
return response


deprecated_user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi-data.json")
user_data_file = os.path.join(os.path.expanduser("~"), ".jupyter", "nbi", "user-data.json")
access_token_password = os.getenv("NBI_GH_ACCESS_TOKEN_PASSWORD", "nbi-access-token-password")


def read_stored_github_access_token() -> str:
try:
if os.path.exists(user_data_file):
Expand Down Expand Up @@ -186,7 +196,12 @@ def login_with_existing_credentials(store_access_token: bool):
if github_auth["status"] is not LoginStatus.NOT_LOGGED_IN:
return

if store_access_token:
# Check for GitHub access token in environment variable
github_access_token_provided = get_gh_access_token_from_env()
if github_access_token_provided:
log.info("Using GitHub access token from environment variable")
remember_github_access_token = False # Do not store the token if it's from the environment
elif store_access_token:
github_access_token_provided = read_stored_github_access_token()
remember_github_access_token = True
else:
Expand Down Expand Up @@ -331,8 +346,7 @@ def wait_for_user_access_token_thread_func():

def get_token():
global github_auth, github_access_token_provided, API_ENDPOINT, PROXY_ENDPOINT, TOKEN_REFRESH_INTERVAL
access_token = github_auth["access_token"]

access_token = get_gh_access_token_from_env() or github_auth["access_token"]
if access_token is None:
return

Expand All @@ -351,7 +365,6 @@ def get_token():
)

resp_json = resp.json()

if resp.status_code == 401:
github_access_token_provided = None
logout()
Expand Down Expand Up @@ -393,7 +406,9 @@ def get_token_thread_func():
return
token = github_auth["token"]
# update token if 10 seconds or less left to expiration
if github_auth["access_token"] is not None and (
access_token = get_gh_access_token_from_env() or github_auth["access_token"]

if access_token and (
token is None
or (dt.datetime.now() - github_auth["token_expires_at"]).total_seconds() > -10
):
Expand Down
4 changes: 1 addition & 3 deletions src/chat-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@
const [ghLoginStatus, setGHLoginStatus] = useState(
GitHubCopilotLoginStatus.NotLoggedIn
);
const [loginClickCount, _setLoginClickCount] = useState(0);

Check warning on line 725 in src/chat-sidebar.tsx

View workflow job for this annotation

GitHub Actions / Check Code Formatting

'_setLoginClickCount' is assigned a value but never used
const [copilotRequestInProgress, setCopilotRequestInProgress] =
useState(false);
const [showPopover, setShowPopover] = useState(false);
Expand Down Expand Up @@ -1323,7 +1323,7 @@
}

setCopilotRequestInProgress(true);

console.log('Request triggered on input - ', prompt);
const activeDocInfo: IActiveDocumentInfo = props.getActiveDocumentInfo();
const extractedPrompt = prompt;
const contents: IChatMessageContent[] = [];
Expand Down Expand Up @@ -1363,8 +1363,6 @@
}
}

console.log('Complete context : ', additionalContext);

submitCompletionRequest(
{
messageId: lastMessageId.current,
Expand Down Expand Up @@ -2438,7 +2436,7 @@
const [ghLoginStatus, setGHLoginStatus] = useState(
GitHubCopilotLoginStatus.NotLoggedIn
);
const [loginClickCount, _setLoginClickCount] = useState(0);

Check warning on line 2439 in src/chat-sidebar.tsx

View workflow job for this annotation

GitHub Actions / Check Code Formatting

'_setLoginClickCount' is assigned a value but never used

useEffect(() => {
const fetchData = () => {
Expand Down
34 changes: 30 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ class NBIInlineCompletionProvider
get schema(): ISettingRegistry.IProperty {
return {
default: {
debouncerDelay: 200,
debouncerDelay: 100,
timeout: 15000
}
};
Expand Down Expand Up @@ -438,7 +438,6 @@ class NBIInlineCompletionProvider
editorType
}
});

return new Promise((resolve, reject) => {
const items: IInlineCompletionItem[] = [];

Expand All @@ -453,11 +452,36 @@ class NBIInlineCompletionProvider
RequestDataType.CancelInlineCompletionRequest,
{ chatId: this._lastRequestInfo.chatId }
);

// TODO: handle fast-typers
if (
this._lastRequestInfo.completion &&
preCursor.length > 0 &&
preCursor[preCursor.length - 1] ===
this._lastRequestInfo.completion[0]
) {
// if the last element of the preCursor is the first element of the completion
// we do not need to make a completion request on the assumption that the
// user is about to type the rest of the completion
resolve({
items: [
{ insertText: this._lastRequestInfo.completion.substring(1) }
]
});
this._lastRequestInfo.completion =
this._lastRequestInfo.completion.substring(1);
return;
}
}

const messageId = UUID.uuid4();
const chatId = UUID.uuid4();
this._lastRequestInfo = { chatId, messageId, requestTime: new Date() };
this._lastRequestInfo = {
chatId,
messageId,
completion: '',
requestTime: new Date()
};

NBIAPI.inlineCompletionsRequest(
chatId,
Expand All @@ -475,6 +499,7 @@ class NBIInlineCompletionProvider
items.push({
insertText: response.data.completions
});
this._lastRequestInfo.completion = response.data.completions;

const timeElapsed =
(new Date().getTime() -
Expand Down Expand Up @@ -518,6 +543,7 @@ class NBIInlineCompletionProvider
private _lastRequestInfo: {
chatId: string;
messageId: string;
completion: string;
requestTime: Date;
} = null;
private _telemetryEmitter: TelemetryEmitter;
Expand Down Expand Up @@ -721,7 +747,7 @@ const plugin: JupyterFrontEndPlugin<INotebookIntelligence> = {
})
.catch(reason => {
console.error(
'Failed to load settings for @notebook-intelligence/lab-notebook-intelligence.',
'Failed to load settings for @lab-notebook-intelligence/lab-notebook-intelligence.',
reason
);
});
Expand Down
2 changes: 1 addition & 1 deletion style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
.sidebar {
display: flex;
flex-direction: column;
min-width: 40%;
min-width: 50%;
height: 100%;
}

Expand Down