diff --git a/.gitignore b/.gitignore index eafa699..5272430 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.codegraph/ .DS_Store .venv/ __pycache__/ diff --git a/plugin/commands.py b/plugin/commands.py index 8e53ce1..6d9a93f 100644 --- a/plugin/commands.py +++ b/plugin/commands.py @@ -568,10 +568,58 @@ def _on_result_conversation_preconditions( session: Session, payload: CopilotPayloadConversationPreconditions, initial_message: str, + ) -> None: + if not self.view.window(): + return + + session.send_request( + Request(REQ_COPILOT_MODELS, {}), + lambda models: self._on_result_copilot_models_for_create(plugin, session, models, initial_message), + ) + + def _on_result_copilot_models_for_create( + self, + plugin: CopilotPlugin, + session: Session, + models: list[CopilotModel], + initial_message: str, ) -> None: if not (window := self.view.window()): return + chat_models = [model for model in models if "chat-panel" in model["scopes"]] + if not chat_models: + status_message("No chat models available", icon="❌") + return + + default_index = next((i for i, model in enumerate(chat_models) if model["isChatDefault"]), 0) + window.show_quick_panel( + [ + sublime.QuickPanelItem( + trigger=model["modelName"], + details=model["modelFamily"], + annotation="Default" if model["isChatDefault"] else "", + ) + for model in chat_models + ], + lambda index: self._on_result_model_selected(plugin, session, chat_models, index, initial_message), + selected_index=default_index, + placeholder="Select a model for this conversation", + ) + + def _on_result_model_selected( + self, + plugin: CopilotPlugin, + session: Session, + models: list[CopilotModel], + index: int, + initial_message: str, + ) -> None: + if index == -1: + return + if not (window := self.view.window()): + return + wcm = WindowConversationManager(window) if not (view := find_view_by_id(wcm.last_active_view_id)): return @@ -589,6 +637,7 @@ def _on_result_conversation_preconditions( "hideText": False, "warnings": [], }) + wcm.model_id = models[index]["id"] req_params: dict[str, Any] = { "turns": [{"request": msg}], "capabilities": { @@ -598,6 +647,7 @@ def _on_result_conversation_preconditions( "workDoneToken": f"copilot_chat://{window.id()}", "computeSuggestions": True, "source": "panel", + "modelInfo": {"id": wcm.model_id}, } session.send_request( Request(REQ_CONVERSATION_CREATE, req_params), @@ -634,7 +684,11 @@ def _on_prompt(self, plugin: CopilotPlugin, session: Session, msg: str): user_prompts: list[CopilotUserDefinedPromptTemplates] = session.config.settings.get("prompts") or [] is_template, msg = preprocess_chat_message(view, msg, user_prompts) views = [sv.view for sv in session.session_views_async() if sv.view.id() != view.id()] - if not (request := prepare_conversation_turn_request(wcm.conversation_id, wcm.window.id(), msg, view, views)): + if not ( + request := prepare_conversation_turn_request( + wcm.conversation_id, wcm.window.id(), msg, view, views, wcm.model_id + ) + ): return wcm.append_conversation_entry({ diff --git a/plugin/helpers.py b/plugin/helpers.py index 9b5800a..88ce280 100644 --- a/plugin/helpers.py +++ b/plugin/helpers.py @@ -228,6 +228,7 @@ def prepare_conversation_turn_request( message: str, view: sublime.View, views: list[sublime.View], + model_id: str, source: Literal["panel", "inline"] = "panel", ) -> CopilotRequestConversationTurn | None: if not (doc := prepare_completion_request_doc(view)): @@ -260,6 +261,7 @@ def prepare_conversation_turn_request( "computeSuggestions": True, "references": references, "source": source, + "modelInfo": {"id": model_id}, } diff --git a/plugin/types.py b/plugin/types.py index 7486670..f890654 100644 --- a/plugin/types.py +++ b/plugin/types.py @@ -220,6 +220,10 @@ class CopilotPayloadConversationTemplate(TypedDict, total=True): scopes: list[str] +class CopilotModelInfo(TypedDict, total=True): + id: str + + class CopilotRequestConversationTurn(TypedDict, total=True): conversationId: str message: str @@ -228,6 +232,7 @@ class CopilotRequestConversationTurn(TypedDict, total=True): computeSuggestions: bool references: list[CopilotRequestConversationTurnReference | CopilotGitHubWebSearch] source: Literal["panel", "inline"] + modelInfo: CopilotModelInfo class CopilotRequestConversationTurnReference(TypedDict, total=True): @@ -309,6 +314,7 @@ class CopilotModel(TypedDict, total=True): modelFamily: str modelName: str scopes: list[str] + isChatDefault: bool # --------------------------- # diff --git a/plugin/ui/chat.py b/plugin/ui/chat.py index 3483b47..10a6717 100644 --- a/plugin/ui/chat.py +++ b/plugin/ui/chat.py @@ -243,6 +243,14 @@ def last_active_view_id(self) -> int: def last_active_view_id(self, value: int) -> None: self._set_setting("last_active_view_id", value) + @property + def model_id(self) -> str: + return self._get_setting("model_id", "") + + @model_id.setter + def model_id(self, value: str) -> None: + self._set_setting("model_id", value) + @property def suggested_title(self) -> str: return self._get_setting("suggested_title", "") @@ -289,6 +297,7 @@ def reset(self) -> None: """Reset all chat conversation settings.""" self.reset_base_settings() self.last_active_view_id = -1 + self.model_id = "" self.suggested_title = "" self.follow_up = "" self.code_block_index = {}