From eff80e1dabfa5ecd68d65577760cff592ecb0094 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Thu, 23 Jan 2025 15:16:35 +0100 Subject: [PATCH 01/11] Add experimental support for repomix --- Claudette.py | 3 + Claudette.sublime-settings | 3 + Default.sublime-commands | 12 +++ Main.sublime-menu | 17 +++ Side Bar.sublime-menu | 21 ++++ api/api.py | 35 +++++- chat/chat_history.py | 14 +-- chat/chat_view.py | 25 +++++ repomix/add_repomix.py | 214 +++++++++++++++++++++++++++++++++++++ repomix/clear_repomix.py | 38 +++++++ repomix/show_repomix.py | 38 +++++++ 11 files changed, 407 insertions(+), 13 deletions(-) create mode 100644 Side Bar.sublime-menu create mode 100644 repomix/add_repomix.py create mode 100644 repomix/clear_repomix.py create mode 100644 repomix/show_repomix.py diff --git a/Claudette.py b/Claudette.py index 41fc166..ac9a164 100644 --- a/Claudette.py +++ b/Claudette.py @@ -11,6 +11,9 @@ from .chat.chat_view import ClaudetteChatViewListener from .chat.ask_question import ClaudetteAskQuestionCommand, ClaudetteAskNewQuestionCommand from .chat.chat_history import ClaudetteClearChatHistoryCommand, ClaudetteExportChatHistoryCommand, ClaudetteImportChatHistoryCommand +from .repomix.add_repomix import ClaudetteAddRepomixCommand +from .repomix.clear_repomix import ClaudetteClearRepomixCommand +from .repomix.show_repomix import ClaudetteShowRepomixCommand from .settings.select_model_panel import ClaudetteSelectModelPanelCommand from .settings.select_system_message_panel import ClaudetteSelectSystemMessagePanelCommand from .statusbar.spinner import Spinner diff --git a/Claudette.sublime-settings b/Claudette.sublime-settings index dc75aec..b83dd26 100644 --- a/Claudette.sublime-settings +++ b/Claudette.sublime-settings @@ -20,5 +20,8 @@ "rulers": false, // If set_scratch is set to true, the chat view will be closed without prompting to save. "set_scratch": true + }, + "repomix": { + "executable": "repomix" } } diff --git a/Default.sublime-commands b/Default.sublime-commands index 11d9b66..c41112f 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -27,4 +27,16 @@ "caption": "Claude: Switch System Prompt", "command": "claudette_select_system_message_panel" }, + { + "caption": "Claude: Repomix Run", + "command": "claudette_add_repomix" + }, + { + "caption": "Claude: Repomix Show Content", + "command": "claudette_show_repomix" + }, + { + "caption": "Claude: Repomix Clear Content", + "command": "claudette_clear_repomix" + }, ] diff --git a/Main.sublime-menu b/Main.sublime-menu index 9d536da..c64e0d1 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -22,6 +22,23 @@ "caption": "Switch System Message", "command": "claudette_select_system_message_panel" }, + { + "caption": "Repomix", + "children": [ + { + "caption": "Run Repomix", + "command": "claudette_add_repomix" + }, + { + "caption": "Show Content", + "command": "claudette_show_repomix" + }, + { + "caption": "Clear Content", + "command": "claudette_clear_repomix" + } + ] + }, { "caption": "Chat History", "children": [ diff --git a/Side Bar.sublime-menu b/Side Bar.sublime-menu new file mode 100644 index 0000000..047e32a --- /dev/null +++ b/Side Bar.sublime-menu @@ -0,0 +1,21 @@ +[ + { + "caption": "-", + "id": "side-bar-files-separator" + }, + { + "caption": "Claudette", + "children": [ + { + "caption": "Repomix Run", + "command": "claudette_add_repomix", + "args": {"paths": []}, + }, + { + "caption": "Repomix Clear", + "command": "claudette_clear_repomix", + } + ], + "id": "side-bar-claudette" + } +] diff --git a/api/api.py b/api/api.py index 451b38b..eb24211 100644 --- a/api/api.py +++ b/api/api.py @@ -1,10 +1,17 @@ +# api/api.py import sublime import json import urllib.request import urllib.parse import urllib.error -from ..constants import ANTHROPIC_VERSION, DEFAULT_MODEL, MAX_TOKENS, SETTINGS_FILE from ..statusbar.spinner import Spinner +from ..constants import ANTHROPIC_VERSION, DEFAULT_MODEL, MAX_TOKENS, SETTINGS_FILE + +CACHE_SUPPORTED_MODEL_PREFIXES = { + 'claude-3-opus', + 'claude-3-sonnet', + 'claude-3-haiku' +} class ClaudeAPI: BASE_URL = 'https://api.anthropic.com/v1/' @@ -27,6 +34,14 @@ def get_valid_temperature(temp): except (TypeError, ValueError): return 1.0 + @staticmethod + def should_use_cache_control(model): + """Determine if cache control should be used based on model.""" + if not model: + return False + # Check if the model name starts with any of the supported prefixes + return any(model.startswith(prefix) for prefix in CACHE_SUPPORTED_MODEL_PREFIXES) + def stream_response(self, chunk_callback, messages): """Stream API response for the given messages.""" if not messages or not any(msg.get('content', '').strip() for msg in messages): @@ -97,6 +112,24 @@ def handle_error(error_msg): "text": selected_message.strip() }) + # Add repomix content as system message if available + window = sublime.active_window() + if window: + current_view = window.active_view() + if current_view and current_view.settings().get('claudette_is_chat_view'): + repomix_content = current_view.settings().get('claudette_repomix') + if repomix_content: + system_message = { + "type": "text", + "text": repomix_content.strip() + } + + # Add cache control if model supports it + if self.should_use_cache_control(self.model): + system_message["cache_control"] = {"type": "ephemeral"} + + data['system'].append(system_message) + req = urllib.request.Request( urllib.parse.urljoin(self.BASE_URL, 'messages'), data=json.dumps(data).encode('utf-8'), diff --git a/chat/chat_history.py b/chat/chat_history.py index b2bb829..4a81edd 100644 --- a/chat/chat_history.py +++ b/chat/chat_history.py @@ -225,18 +225,8 @@ def run(self, edit): if current_chat_view: current_chat_view.settings().set('claudette_conversation_json', '[]') - current_chat_view.set_read_only(False) - - end_point = current_chat_view.size() - - if end_point > 0: - current_chat_view.insert(edit, end_point, "\n\n") - end_point += 2 - - clear_message = "⚠️ Chat history cleared" - current_chat_view.insert(edit, end_point, clear_message) - current_chat_view.set_read_only(True) - current_chat_view.show(current_chat_view.size()) + current_chat_view.settings().erase('claudette_repomix') + current_chat_view.settings().erase('claudette_repomix_tokens') claudette_chat_status_message(window, "Chat history cleared", prefix="✅") sublime.status_message("Chat history cleared") diff --git a/chat/chat_view.py b/chat/chat_view.py index 9534386..ae38987 100644 --- a/chat/chat_view.py +++ b/chat/chat_view.py @@ -333,3 +333,28 @@ def destroy(self): del self._instances[window_id] self.view = None + + def status_message(self, message: str, prefix: str = "", scroll_to_end: bool = True) -> None: + """ + Display a status message in the chat view without adding it to the conversation history. + + Args: + message (str): The status message to display + prefix (str, optional): Icon or text prefix for the message. + scroll_to_end (bool, optional): Whether to scroll to the end after displaying. Defaults to True + """ + if not self.view: + return + + if self.get_size() > 0: + message = f"\n\n{prefix} {message}\n" + else: + message = f"{prefix} {message}\n" + + self.view.set_read_only(False) + self.view.run_command('append', { + 'characters': message, + 'force': True, + 'scroll_to_end': scroll_to_end + }) + self.view.set_read_only(True) diff --git a/repomix/add_repomix.py b/repomix/add_repomix.py new file mode 100644 index 0000000..8f5dbf3 --- /dev/null +++ b/repomix/add_repomix.py @@ -0,0 +1,214 @@ +import sublime +import sublime_plugin +import os +import subprocess +import re +import json +import tempfile +from ..constants import PLUGIN_NAME, SETTINGS_FILE +from ..utils import claudette_chat_status_message +from ..chat.ask_question import ClaudetteAskQuestionCommand + +class ClaudetteAddRepomixCommand(sublime_plugin.WindowCommand): + def is_visible(self): + # Show if there's either a folder open or files selected in sidebar + if hasattr(self, 'paths'): + return bool(self.paths) + return bool(self.window.folders()) + + def is_enabled(self): + return self.is_visible() + + def get_active_chat_view(self): + """Get the current chat view or create a new one""" + # First try to find an existing active chat view + existing_view = None + for view in self.window.views(): + if (view.settings().get('claudette_is_chat_view', False) and + view.settings().get('claudette_is_current_chat', False)): + existing_view = view + return existing_view, False + + # If no active chat view found, create a new one + ask_cmd = ClaudetteAskQuestionCommand(self.window.active_view()) + ask_cmd.load_settings() + new_view = ask_cmd.create_chat_panel(force_new=True) + return new_view, True + + def extract_token_count(self, output): + """Extract token count from repomix output using regex.""" + # Look for patterns like "Total Tokens: 12,868 tokens" + # First capture the number including any commas + match = re.search(r'(?:token count|tokens):\s*([\d,]+)', output, re.IGNORECASE) + if match: + # Remove commas and convert to int + token_count = match.group(1).replace(',', '') + return int(token_count) + return None + + def format_include_paths(self, paths, base_dir): + """Format file paths into repomix include pattern.""" + if not paths: + return None + + # Convert absolute paths to relative paths from base_dir + relative_paths = [] + for path in paths: + if os.path.isfile(path): + rel_path = os.path.relpath(path, base_dir) + # Replace backslashes with forward slashes for consistency + rel_path = rel_path.replace('\\', '/') + relative_paths.append(rel_path) + + if relative_paths: + # Join all paths with commas + return ','.join(relative_paths) + return None + + def run(self, paths=None): + # Get or create chat view first, and track if it's new + chat_view, is_new_view = self.get_active_chat_view() + if not chat_view: + sublime.error_message("Could not create chat view") + return + + self.paths = paths + settings = sublime.load_settings(SETTINGS_FILE) + repomix_settings = settings.get('repomix', {}) + executable = repomix_settings.get('executable', 'repomix') + + # Use selected paths if provided, otherwise use first folder + target_paths = paths if paths else [self.window.folders()[0]] + if not target_paths: + sublime.error_message("Please select a folder or files in the sidebar") + return + + # Get the working directory (use first folder if files selected) + if paths and all(os.path.isfile(p) for p in paths): + # All selected items are files, use their common parent directory + target_folder = os.path.dirname(paths[0]) + else: + # At least one folder selected, use the first folder + target_folder = next((p for p in target_paths if os.path.isdir(p)), None) + if not target_folder: + sublime.error_message("No valid folder found") + return + + # Look for config file in project root + config_file = None + project_root = self._find_project_root(target_folder) + + if project_root: + potential_config = os.path.join(project_root, 'repomix.config.json') + if os.path.exists(potential_config): + config_file = potential_config + + # Create temporary output file in Sublime's cache directory + cache_dir = os.path.join(sublime.cache_path(), PLUGIN_NAME) + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + output_file = os.path.join(cache_dir, f'repomix-output-{os.urandom(4).hex()}.xml') + + try: + cmd = [executable] + + if config_file: + cmd.extend(['--config', config_file]) + + # Add output file flag + cmd.extend(['--output', output_file]) + + # Add include pattern for selected files + if paths and any(os.path.isfile(p) for p in paths): + include_pattern = self.format_include_paths(paths, target_folder) + if include_pattern: + cmd.extend(['--include', include_pattern]) + + # Print command being run + print(f"\n{PLUGIN_NAME}: Running command:", ' '.join(cmd)) + print(f"{PLUGIN_NAME}: Working directory:", target_folder) + + # Run repomix + process = subprocess.Popen( + cmd, + cwd=target_folder, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True if os.name == 'nt' else False, + text=True + ) + + stdout, stderr = process.communicate() + + if process.returncode != 0: + print(f"Repomix Error: {stderr}") + sublime.status_message('Repomix error.') + return + + # Read the output file + if not os.path.exists(output_file): + raise FileNotFoundError(f"Output file not found: {output_file}") + + with open(output_file, 'r', encoding='utf-8') as f: + file_content = f.read() + + # Store the file content in the chat view's settings + chat_view.settings().set('claudette_repomix', file_content) + + # Extract token count from stdout and create status message + token_count = self.extract_token_count(stdout) + status_msg = "Repomix completed successfully" + if token_count is not None: + status_msg += f" ({token_count:,} tokens)" + chat_view.settings().set('claudette_repomix_tokens', token_count) + + # Show success message in chat view + claudette_chat_status_message(self.window, status_msg, prefix="✅") + + # Print success message to console + print(f"\n{PLUGIN_NAME}: {status_msg}") + print("\nOutput stored in chat view settings") + + sublime.status_message(f"{PLUGIN_NAME}: {status_msg}") + + # Only open input panel if this is a new view + if is_new_view: + def show_input_panel(): + self.window.run_command('claudette_ask_question') + + # Slight delay to ensure status messages are visible + sublime.set_timeout(show_input_panel, 100) + + except FileNotFoundError as e: + if 'repomix' in str(e): + error_msg = ( + f"Could not find repomix executable. Please ensure repomix is installed and " + f"configured correctly in Package Settings > Claudette > Settings" + ) + else: + error_msg = str(e) + print(f"\n{PLUGIN_NAME} Error:", error_msg) + sublime.error_message(error_msg) + except Exception as e: + print(f"\n{PLUGIN_NAME} Error:", str(e)) + sublime.error_message(f"Error running repomix: {str(e)}") + finally: + # Clean up output file + if os.path.exists(output_file): + try: + os.remove(output_file) + except Exception as e: + print(f"{PLUGIN_NAME} Warning: Could not remove output file: {str(e)}") + + def _find_project_root(self, start_path): + """Walk up directories looking for repomix config files""" + current = start_path + while True: + if os.path.exists(os.path.join(current, 'repomix.config.json')): + return current + + parent = os.path.dirname(current) + if parent == current: + return None + current = parent diff --git a/repomix/clear_repomix.py b/repomix/clear_repomix.py new file mode 100644 index 0000000..17afc98 --- /dev/null +++ b/repomix/clear_repomix.py @@ -0,0 +1,38 @@ +import sublime +import sublime_plugin +from ..utils import claudette_chat_status_message + +class ClaudetteClearRepomixCommand(sublime_plugin.WindowCommand): + """Command to clear Repomix content from the active chat view.""" + + def get_active_chat_view(self): + """Get the current active chat view.""" + for view in self.window.views(): + if (view.settings().get('claudette_is_chat_view', False) and + view.settings().get('claudette_is_current_chat', False)): + return view + return None + + def is_visible(self): + """Always show the command in menus.""" + return True + + def is_enabled(self): + """Enable command only if there's Repomix content to clear.""" + chat_view = self.get_active_chat_view() + if not chat_view: + return False + return chat_view.settings().get('claudette_repomix') is not None + + def run(self): + """Clear Repomix content from the active chat view.""" + chat_view = self.get_active_chat_view() + if not chat_view: + sublime.status_message("No active chat view found") + return + + chat_view.settings().erase('claudette_repomix') + chat_view.settings().erase('claudette_repomix_tokens') + + claudette_chat_status_message(window, "Repomix content cleared", prefix="✅") + sublime.status_message("Repomix content cleared") diff --git a/repomix/show_repomix.py b/repomix/show_repomix.py new file mode 100644 index 0000000..cd9f235 --- /dev/null +++ b/repomix/show_repomix.py @@ -0,0 +1,38 @@ +import sublime +import sublime_plugin + +class ClaudetteShowRepomixCommand(sublime_plugin.WindowCommand): + def get_active_chat_view(self): + for view in self.window.views(): + if (view.settings().get('claudette_is_chat_view', False) and + view.settings().get('claudette_is_current_chat', False)): + return view + return None + + def is_visible(self): + return self.get_active_chat_view() is not None + + def run(self): + chat_view = self.get_active_chat_view() + if not chat_view: + sublime.message_dialog("No active chat view found") + return + + repomix_content = chat_view.settings().get('claudette_repomix') + if not repomix_content: + sublime.message_dialog("No Repomix content available for the active chat view") + return + + # Create a new scratch view for the repomix content + repomix_view = self.window.new_file() + repomix_view.set_name("Repomix Output") + repomix_view.set_scratch(True) + + # Insert the content + repomix_view.run_command('append', { + 'characters': repomix_content, + 'force': True + }) + + # Set syntax to markdown since repomix output uses markdown formatting + repomix_view.assign_syntax('Packages/Markdown/Markdown.sublime-syntax') From 90c0cc7ee87bba9a34f75da7321b350f98eb18d9 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Thu, 23 Jan 2025 15:19:17 +0100 Subject: [PATCH 02/11] Fix indentation --- Main.sublime-menu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Main.sublime-menu b/Main.sublime-menu index c64e0d1..d41b38d 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -34,8 +34,8 @@ "command": "claudette_show_repomix" }, { - "caption": "Clear Content", - "command": "claudette_clear_repomix" + "caption": "Clear Content", + "command": "claudette_clear_repomix" } ] }, From aaa095e7cf55d3d5a94089280b4c1922f78c435c Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Fri, 24 Jan 2025 11:59:20 +0100 Subject: [PATCH 03/11] Update command name Rename add_repomix to run_repomix --- Claudette.py | 2 +- Default.sublime-commands | 2 +- Main.sublime-menu | 2 +- Side Bar.sublime-menu | 2 +- repomix/{add_repomix.py => run_repomix.py} | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename repomix/{add_repomix.py => run_repomix.py} (99%) diff --git a/Claudette.py b/Claudette.py index ac9a164..a88da9a 100644 --- a/Claudette.py +++ b/Claudette.py @@ -11,7 +11,7 @@ from .chat.chat_view import ClaudetteChatViewListener from .chat.ask_question import ClaudetteAskQuestionCommand, ClaudetteAskNewQuestionCommand from .chat.chat_history import ClaudetteClearChatHistoryCommand, ClaudetteExportChatHistoryCommand, ClaudetteImportChatHistoryCommand -from .repomix.add_repomix import ClaudetteAddRepomixCommand +from .repomix.run_repomix import ClaudetteRunRepomixCommand from .repomix.clear_repomix import ClaudetteClearRepomixCommand from .repomix.show_repomix import ClaudetteShowRepomixCommand from .settings.select_model_panel import ClaudetteSelectModelPanelCommand diff --git a/Default.sublime-commands b/Default.sublime-commands index c41112f..ab3381a 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -29,7 +29,7 @@ }, { "caption": "Claude: Repomix Run", - "command": "claudette_add_repomix" + "command": "claudette_run_repomix" }, { "caption": "Claude: Repomix Show Content", diff --git a/Main.sublime-menu b/Main.sublime-menu index d41b38d..a2de1b5 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -27,7 +27,7 @@ "children": [ { "caption": "Run Repomix", - "command": "claudette_add_repomix" + "command": "claudette_run_repomix" }, { "caption": "Show Content", diff --git a/Side Bar.sublime-menu b/Side Bar.sublime-menu index 047e32a..f230593 100644 --- a/Side Bar.sublime-menu +++ b/Side Bar.sublime-menu @@ -8,7 +8,7 @@ "children": [ { "caption": "Repomix Run", - "command": "claudette_add_repomix", + "command": "claudette_run_repomix", "args": {"paths": []}, }, { diff --git a/repomix/add_repomix.py b/repomix/run_repomix.py similarity index 99% rename from repomix/add_repomix.py rename to repomix/run_repomix.py index 8f5dbf3..8408309 100644 --- a/repomix/add_repomix.py +++ b/repomix/run_repomix.py @@ -9,7 +9,7 @@ from ..utils import claudette_chat_status_message from ..chat.ask_question import ClaudetteAskQuestionCommand -class ClaudetteAddRepomixCommand(sublime_plugin.WindowCommand): +class ClaudetteRunRepomixCommand(sublime_plugin.WindowCommand): def is_visible(self): # Show if there's either a folder open or files selected in sidebar if hasattr(self, 'paths'): From 3eb322f5254b99c26942cb02e195b7f12aa8c9ee Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Fri, 24 Jan 2025 11:59:49 +0100 Subject: [PATCH 04/11] Update setting repomix content in api.py --- api/api.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/api/api.py b/api/api.py index 1fe3654..73d07a8 100644 --- a/api/api.py +++ b/api/api.py @@ -96,19 +96,24 @@ def handle_error(error_msg): "text": selected_message.strip() }) - # Add repomix content as system message if available + # @todo It's likely better to pass along the system message to stream_response() + # Find the active chat view window = sublime.active_window() if window: - current_view = window.active_view() - if current_view and current_view.settings().get('claudette_is_chat_view'): - repomix_content = current_view.settings().get('claudette_repomix') + current_chat_view = None + for view in window.views(): + if (view.settings().get('claudette_is_chat_view', False) and + view.settings().get('claudette_is_current_chat', False)): + current_chat_view = view + + if current_chat_view: + repomix_content = current_chat_view.settings().get('claudette_repomix') if repomix_content: system_message = { "type": "text", "text": repomix_content.strip() } - # Add cache control if model supports it if self.should_use_cache_control(self.model): system_message["cache_control"] = {"type": "ephemeral"} @@ -121,6 +126,8 @@ def handle_error(error_msg): method='POST' ) + print("System messages being sent:", json.dumps(data['system'], indent=2)) + try: with urllib.request.urlopen(req) as response: for line in response: From 19a8ef330cc211a2434463e9aac9e5e9dee9f481 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 26 Jan 2025 12:08:59 +0100 Subject: [PATCH 05/11] Update repomix config --- repomix.config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/repomix.config.json b/repomix.config.json index 0ee797d..00991c2 100644 --- a/repomix.config.json +++ b/repomix.config.json @@ -5,8 +5,8 @@ "parsableStyle": false, "fileSummary": true, "directoryStructure": true, - "removeComments": false, - "removeEmptyLines": false, + "removeComments": true, + "removeEmptyLines": true, "topFilesLength": 5, "showLineNumbers": false, "copyToClipboard": false @@ -18,7 +18,7 @@ "customPatterns": [] }, "security": { - "enableSecurityCheck": true + "enableSecurityCheck": false }, "tokenCount": { "encoding": "o200k_base" From 9aca90f612dc1f4f5484118bfbb514d2d619f45c Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 26 Jan 2025 12:21:14 +0100 Subject: [PATCH 06/11] Add token usage display with caching info in status bar --- api/api.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/api.py b/api/api.py index 73d07a8..f9602c5 100644 --- a/api/api.py +++ b/api/api.py @@ -145,6 +145,14 @@ def handle_error(error_msg): data = json.loads(chunk) if 'delta' in data and 'text' in data['delta']: + # Extract usage info if present + usage_info = "" + if 'usage' in data: + usage = data['usage'] + cache_info = " (cached)" if usage.get('cached', False) else "" + usage_info = f"Tokens: {usage.get('input_tokens', 0)} in, {usage.get('output_tokens', 0)} out{cache_info}" + sublime.status_message(usage_info) + sublime.set_timeout( lambda text=data['delta']['text']: chunk_callback(text), 0 From b7e81caa30103dbc326f92285e030f3ad5e8a8fb Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 26 Jan 2025 18:19:08 +0100 Subject: [PATCH 07/11] Fix usage logging --- api/api.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/api/api.py b/api/api.py index f9602c5..448c1c3 100644 --- a/api/api.py +++ b/api/api.py @@ -145,16 +145,16 @@ def handle_error(error_msg): data = json.loads(chunk) if 'delta' in data and 'text' in data['delta']: - # Extract usage info if present - usage_info = "" - if 'usage' in data: - usage = data['usage'] - cache_info = " (cached)" if usage.get('cached', False) else "" - usage_info = f"Tokens: {usage.get('input_tokens', 0)} in, {usage.get('output_tokens', 0)} out{cache_info}" - sublime.status_message(usage_info) - sublime.set_timeout( - lambda text=data['delta']['text']: chunk_callback(text), + lambda text=data['delta']['text']: chunk_callback(text, is_done=False), + 0 + ) + elif 'usage' in data: + usage = data['usage'] + cache_info = " (cached)" if usage.get('cached', False) else "" + usage_info = f"\n\nTokens: {usage.get('input_tokens', 0)} sent, {usage.get('output_tokens', 0)}{cache_info} received." + sublime.set_timeout( + lambda msg=usage_info: chunk_callback(msg, is_done=True), 0 ) except Exception: From fbea9915b81c2d3c4baace73317e68a03bcff3b9 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 26 Jan 2025 18:19:16 +0100 Subject: [PATCH 08/11] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cc6ab5e..c49bea9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ repomix-output.* +.aider* From 393b8891476157e0821e5a5d72ca8ba970227cb9 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 26 Jan 2025 18:19:25 +0100 Subject: [PATCH 09/11] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ffe9bd9..3fea62b 100644 --- a/README.md +++ b/README.md @@ -79,4 +79,10 @@ For Linux and Windows: 2. Get an API key from [Anthropic](https://console.anthropic.com/) 3. Configure API key in *Preferences > Package Settings > Claudette > Settings* +## Privacy & Legal + +Note that this package interacts with the Anthropic Claude API and thus the code that you share with the API will be sent to Anthropic's servers. For information about Anthropic's privacy practices, data processing, and legal compliance, please visit the [Privacy & Legal documentation](https://support.anthropic.com/en/collections/4078534-privacy-legal). + +## Credits + The package is for the most part written by Claude AI itself! From f8d36029173f8c463aced551bacc80042d99a393 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 9 Feb 2025 13:42:45 +0100 Subject: [PATCH 10/11] Fix indentation --- api/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/api.py b/api/api.py index e434abb..9d6b47a 100644 --- a/api/api.py +++ b/api/api.py @@ -112,7 +112,7 @@ def handle_error(error_msg): system_messages.append(system_message) - repomix_content = chat_view.settings().get('claudette_repomix') + repomix_content = chat_view.settings().get('claudette_repomix') if repomix_content: system_message = { "type": "text", From 21871b8ea0c9fd4c52e161c5f41f8f771eded0d2 Mon Sep 17 00:00:00 2001 From: Barry Ceelen Date: Sun, 9 Feb 2025 17:45:20 +0100 Subject: [PATCH 11/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c1003e..c7b5089 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ For Linux and Windows: ## Privacy & legal -Note that this package interacts directly with the Anthropic Claude API. All code that you share via the API, e.g. by including it in a chat, will be sent to Anthropic's servers. For information about Anthropic's privacy practices, data processing, and legal compliance, please visit the [Privacy & Legal documentation](https://support.anthropic.com/en/collections/4078534-privacy-legal). +All code that you share with the Anthropic Claude API, for example by including it in a chat, will be sent to Anthropic's servers. For information about Anthropic's privacy practices, data processing, and legal compliance, please visit the [Privacy & Legal documentation](https://support.anthropic.com/en/collections/4078534-privacy-legal). ## Credits