meltygui 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meltygui/__init__.py +107 -0
- meltygui/accounts/__init__.py +0 -0
- meltygui/accounts/internet_accounts.py +1355 -0
- meltygui/chat/__init__.py +91 -0
- meltygui/chat/activity.py +75 -0
- meltygui/chat/backends.py +36 -0
- meltygui/chat/chat_interface.py +732 -0
- meltygui/chat/chat_proxy.py +352 -0
- meltygui/chat/codex_proxy.py +592 -0
- meltygui/chat/codex_settings.py +100 -0
- meltygui/chat/codex_transport.py +60 -0
- meltygui/chat/command_parser.py +204 -0
- meltygui/chat/images.py +227 -0
- meltygui/chat/messages.py +417 -0
- meltygui/chat/metadata.py +139 -0
- meltygui/chat/writer_locks.py +64 -0
- meltygui/code/__init__.py +0 -0
- meltygui/code/basic_converters.py +533 -0
- meltygui/code/chain_converters.py +2111 -0
- meltygui/code/code_checks.py +2209 -0
- meltygui/code/core_syntax.py +1430 -0
- meltygui/code/file_converters.py +1933 -0
- meltygui/code/fileref.py +702 -0
- meltygui/code/hotswap_guard.py +144 -0
- meltygui/code/libcst_conversion.py +9724 -0
- meltygui/code/live_instrument.py +392 -0
- meltygui/code/live_view.py +2490 -0
- meltygui/code/melty_scan.py +2684 -0
- meltygui/code/new_codecs.py +1255 -0
- meltygui/code/new_converters.py +3017 -0
- meltygui/code/project_code.py +278 -0
- meltygui/code/source_context.py +63 -0
- meltygui/code/symbol_roster.py +1588 -0
- meltygui/code/syntax_check.py +34 -0
- meltygui/code/syntax_check_worker.py +114 -0
- meltygui/completion/__init__.py +0 -0
- meltygui/completion/fim.py +1232 -0
- meltygui/completion/fim_context.py +481 -0
- meltygui/completion/providers/__init__.py +0 -0
- meltygui/completion/providers/anthropic_oauth.py +446 -0
- meltygui/completion/providers/anthropic_requests.py +69 -0
- meltygui/completion/providers/claude.py +203 -0
- meltygui/completion/providers/claude_usage.py +499 -0
- meltygui/completion/providers/codex_accounts.py +180 -0
- meltygui/completion/providers/copilot.py +617 -0
- meltygui/completion/providers/oauth_popup.py +220 -0
- meltygui/completion/providers/ollama.py +320 -0
- meltygui/completion/providers/profiles.py +23 -0
- meltygui/core/README.md +88 -0
- meltygui/core/__init__.py +1 -0
- meltygui/core/automation/__init__.py +1 -0
- meltygui/core/automation/action_core.py +153 -0
- meltygui/core/automation/collection_action.py +45 -0
- meltygui/core/automation/mcp_eval.py +167 -0
- meltygui/core/automation/mcp_hotswap.py +107 -0
- meltygui/core/automation/mcp_query.py +552 -0
- meltygui/core/automation/mcp_server.py +657 -0
- meltygui/core/automation/orchestration_core.py +2636 -0
- meltygui/core/automation/query_core.py +124 -0
- meltygui/core/automation/search_core.py +26 -0
- meltygui/core/automation/selector_core.py +340 -0
- meltygui/core/automation/value_core.py +1752 -0
- meltygui/core/cache/__init__.py +1 -0
- meltygui/core/cache/cache_diagnostics.py +0 -0
- meltygui/core/cache/invalidation_decoration.py +153 -0
- meltygui/core/cache/invalidation_tracker.py +43 -0
- meltygui/core/cache/tile_cache.py +5968 -0
- meltygui/core/conversion/__init__.py +1 -0
- meltygui/core/conversion/bubbling.py +599 -0
- meltygui/core/conversion/cache_tree.py +188 -0
- meltygui/core/conversion/chain.py +113 -0
- meltygui/core/conversion/converter_register.py +145 -0
- meltygui/core/conversion/data_decoration.py +67 -0
- meltygui/core/conversion/dict_conversion.py +1815 -0
- meltygui/core/conversion/dict_conversion_util.py +177 -0
- meltygui/core/conversion/dynamic_obj.py +89 -0
- meltygui/core/conversion/graph_compare.py +183 -0
- meltygui/core/conversion/load_save_v2.py +1032 -0
- meltygui/core/conversion/missing_saved_class.py +39 -0
- meltygui/core/conversion/path_finder.py +606 -0
- meltygui/core/conversion/render_host.py +1083 -0
- meltygui/core/core_render.py +6537 -0
- meltygui/core/definition_hotswap.py +231 -0
- meltygui/core/diagnostics/__init__.py +1 -0
- meltygui/core/diagnostics/attribute_churn.py +38 -0
- meltygui/core/diagnostics/fps_counter.py +39 -0
- meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
- meltygui/core/diagnostics/inspection_core.py +169 -0
- meltygui/core/diagnostics/monitor_core.py +105 -0
- meltygui/core/diagnostics/notifications.py +706 -0
- meltygui/core/diagnostics/perf_trace.py +281 -0
- meltygui/core/diagnostics/profile_decoration.py +88 -0
- meltygui/core/diagnostics/resize_trace.py +62 -0
- meltygui/core/diagnostics/screenshot_core.py +247 -0
- meltygui/core/diagnostics/session_status.py +98 -0
- meltygui/core/diagnostics/trace_core.py +445 -0
- meltygui/core/files/__init__.py +1 -0
- meltygui/core/files/file_core.py +208 -0
- meltygui/core/files/file_explorer_core.py +104 -0
- meltygui/core/files/file_tree_core.py +198 -0
- meltygui/core/files/file_watch_core.py +43 -0
- meltygui/core/files/import_graph_core.py +43 -0
- meltygui/core/files/metadata_core.py +51 -0
- meltygui/core/graphics/__init__.py +1 -0
- meltygui/core/graphics/cuda_context_core.py +166 -0
- meltygui/core/graphics/cuda_interop_core.py +136 -0
- meltygui/core/graphics/cuda_kernel_core.py +91 -0
- meltygui/core/graphics/framebuffer_recorder.py +337 -0
- meltygui/core/graphics/gl_state.py +658 -0
- meltygui/core/graphics/lut_core.py +52 -0
- meltygui/core/graphics/overlay_renderer.py +984 -0
- meltygui/core/graphics/scene_target.py +180 -0
- meltygui/core/graphics/screenshot.py +439 -0
- meltygui/core/graphics/shader_func.py +478 -0
- meltygui/core/graphics/tensor_core.py +45 -0
- meltygui/core/graphics/text_texture.py +329 -0
- meltygui/core/graphics/wayland_color.py +635 -0
- meltygui/core/input/__init__.py +1 -0
- meltygui/core/input/collision.py +165 -0
- meltygui/core/input/drag_drop_core.py +1525 -0
- meltygui/core/input/hypr_left_drag.py +323 -0
- meltygui/core/input/input_core.py +245 -0
- meltygui/core/input/input_handler.py +1101 -0
- meltygui/core/input/mouse_cursor.py +355 -0
- meltygui/core/input/pynput_backend.py +1054 -0
- meltygui/core/input/space_mouse.py +338 -0
- meltygui/core/input/touchpad_backend.py +393 -0
- meltygui/core/input/view_selection.py +177 -0
- meltygui/core/layout/__init__.py +1 -0
- meltygui/core/layout/column_core.py +2153 -0
- meltygui/core/layout/cursor_core.py +161 -0
- meltygui/core/layout/dropdown_core.py +278 -0
- meltygui/core/layout/edge_constraints.py +155 -0
- meltygui/core/layout/grid_core.py +117 -0
- meltygui/core/layout/header_core.py +23 -0
- meltygui/core/layout/header_runtime.py +67 -0
- meltygui/core/layout/layout_core.py +87 -0
- meltygui/core/layout/tile_manager_core.py +591 -0
- meltygui/core/melty.py +6726 -0
- meltygui/core/module_map.json +896 -0
- meltygui/core/module_names.py +19 -0
- meltygui/core/rendering/__init__.py +1 -0
- meltygui/core/rendering/core_decoration.py +431 -0
- meltygui/core/rendering/core_render_helpers.py +328 -0
- meltygui/core/rendering/func_metadata.py +398 -0
- meltygui/core/rendering/mode.py +818 -0
- meltygui/core/rendering/mode_defaults.py +41 -0
- meltygui/core/rendering/modes.py +136 -0
- meltygui/core/rendering/parameter_core.py +1665 -0
- meltygui/core/rendering/render_dispatch.py +1891 -0
- meltygui/core/rendering/render_funcs.py +273 -0
- meltygui/core/rendering/shaped.py +312 -0
- meltygui/core/rendering/window_decoration.py +25 -0
- meltygui/core/runtime/__init__.py +1 -0
- meltygui/core/runtime/app.py +735 -0
- meltygui/core/runtime/app_session.py +140 -0
- meltygui/core/runtime/background.py +564 -0
- meltygui/core/runtime/extensions.py +53 -0
- meltygui/core/runtime/gc_manager.py +1163 -0
- meltygui/core/runtime/lifecycle.py +21 -0
- meltygui/core/runtime/paths.py +27 -0
- meltygui/core/runtime/settings.py +14 -0
- meltygui/core/runtime/singleton.py +16 -0
- meltygui/core/runtime/thread_safe_bool.py +24 -0
- meltygui/core/runtime/thread_signal.py +30 -0
- meltygui/core/runtime/toggles.py +3115 -0
- meltygui/core/services/__init__.py +1 -0
- meltygui/core/services/account_core.py +10 -0
- meltygui/core/services/chat_core.py +19 -0
- meltygui/core/services/claude_terminal_core.py +346 -0
- meltygui/core/services/terminal_core.py +458 -0
- meltygui/core/services/terminal_runtime.py +78 -0
- meltygui/core/styling/__init__.py +1 -0
- meltygui/core/styling/color_core.py +46 -0
- meltygui/core/styling/fonts.py +639 -0
- meltygui/core/styling/global_style.py +338 -0
- meltygui/core/styling/style.py +198 -0
- meltygui/core/styling/style_core.py +522 -0
- meltygui/core/styling/warm_start.py +149 -0
- meltygui/core/windowing/__init__.py +1 -0
- meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
- meltygui/core/windowing/backends/__init__.py +1 -0
- meltygui/core/windowing/backends/imgui_renderer.py +138 -0
- meltygui/core/windowing/backends/native_wayland.py +850 -0
- meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
- meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
- meltygui/core/windowing/backends/wayland_protocol.py +101 -0
- meltygui/core/windowing/dock_core.py +182 -0
- meltygui/core/windowing/frame_geometry.py +42 -0
- meltygui/core/windowing/geometry_feed.py +864 -0
- meltygui/core/windowing/glfw_utils.py +1343 -0
- meltygui/core/windowing/os_frame.py +1552 -0
- meltygui/core/windowing/surface.py +643 -0
- meltygui/core/windowing/titlebar.py +1560 -0
- meltygui/core/windowing/titlebar_buttons.py +281 -0
- meltygui/core/windowing/wayland_move.py +932 -0
- meltygui/core/windowing/window_api.py +62 -0
- meltygui/core/windowing/window_constants.py +339 -0
- meltygui/core/windowing/window_visibility.py +162 -0
- meltygui/debug/__init__.py +0 -0
- meltygui/debug/app_view_utils.py +9 -0
- meltygui/editor/__init__.py +0 -0
- meltygui/editor/bash_syntax.py +30 -0
- meltygui/editor/code_line_fast.py +152 -0
- meltygui/editor/diff.py +139 -0
- meltygui/editor/external_changes.py +159 -0
- meltygui/editor/file_header.py +41 -0
- meltygui/editor/live_usage.py +169 -0
- meltygui/editor/live_view_views.py +1803 -0
- meltygui/editor/pending_save.py +1351 -0
- meltygui/editor/roster_tints.py +547 -0
- meltygui/editor/source_preview.py +16 -0
- meltygui/editor/source_tools.py +10 -0
- meltygui/editor/source_ui.py +70 -0
- meltygui/editor/spell_check.py +77 -0
- meltygui/editor/text_editor.py +9076 -0
- meltygui/editor/usage_picker.py +538 -0
- meltygui/events/__init__.py +0 -0
- meltygui/events/example.py +118 -0
- meltygui/examples/__init__.py +0 -0
- meltygui/examples/columns_demo.py +33 -0
- meltygui/examples/columns_window_demo.py +60 -0
- meltygui/examples/context_menu_demo.py +24 -0
- meltygui/examples/context_menu_window_demo.py +49 -0
- meltygui/examples/gui_playground.py +127 -0
- meltygui/examples/live_view_playground.py +256 -0
- meltygui/examples/lora.py +43 -0
- meltygui/examples/lora_data.py +59 -0
- meltygui/examples/lora_policies.py +67 -0
- meltygui/examples/mode_demo.py +49 -0
- meltygui/examples/modifies_demo.py +119 -0
- meltygui/examples/scalar_policies.py +60 -0
- meltygui/examples/style_layouts.py +149 -0
- meltygui/examples/tile_manager_demo.py +74 -0
- meltygui/examples/tint_demo.py +160 -0
- meltygui/examples/tint_functions.py +56 -0
- meltygui/examples/trace_demo.py +88 -0
- meltygui/examples/two_windows.py +36 -0
- meltygui/files/__init__.py +0 -0
- meltygui/files/fast_file_explorer.py +439 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
- meltygui/graphics/__init__.py +6 -0
- meltygui/graphics/base.py +85 -0
- meltygui/graphics/examples.py +507 -0
- meltygui/graphics/executor.py +520 -0
- meltygui/graphics/filter.py +667 -0
- meltygui/graphics/filter.pyi +856 -0
- meltygui/graphics/generate_stubs.py +22 -0
- meltygui/graphics/registry.py +203 -0
- meltygui/graphics/shader_compiler.py +155 -0
- meltygui/graphics/shaders.py +1302 -0
- meltygui/graphics/stub_generator.py +250 -0
- meltygui/graphics/texture_manager.py +170 -0
- meltygui/graphics/texture_min_max.py +295 -0
- meltygui/hdr_color.py +757 -0
- meltygui/image_load.py +308 -0
- meltygui/model/__init__.py +1 -0
- meltygui/model/account_model.py +142 -0
- meltygui/model/camera_model.py +159 -0
- meltygui/model/chat_model.py +86 -0
- meltygui/model/code_model.py +62 -0
- meltygui/model/code_proxy_model.py +876 -0
- meltygui/model/collection_model.py +41 -0
- meltygui/model/color_model.py +127 -0
- meltygui/model/cuda_tensor_model.py +36 -0
- meltygui/model/cuda_texture_model.py +149 -0
- meltygui/model/dropdown_model.py +137 -0
- meltygui/model/file_metadata_model.py +73 -0
- meltygui/model/file_model.py +289 -0
- meltygui/model/format_model.py +390 -0
- meltygui/model/graph_model.py +98 -0
- meltygui/model/icon_model.py +1024 -0
- meltygui/model/import_graph_model.py +468 -0
- meltygui/model/layout_model.py +15 -0
- meltygui/model/lut_model.py +266 -0
- meltygui/model/search_model.py +173 -0
- meltygui/model/tensor_model.py +402 -0
- meltygui/model/terminal_model.py +329 -0
- meltygui/model/texture_model.py +146 -0
- meltygui/model/tile_model.py +24 -0
- meltygui/model/trace_model.py +198 -0
- meltygui/model/trace_report_model.py +146 -0
- meltygui/models/__init__.py +0 -0
- meltygui/models/file_meta.py +613 -0
- meltygui/models/function_console.py +184 -0
- meltygui/models/orchestration.py +48 -0
- meltygui/pbr.py +1576 -0
- meltygui/png_unfilter.c +49 -0
- meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
- meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
- meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
- meltygui/resources/dejavu/LICENSE.txt +78 -0
- meltygui/resources/fontawesome-LICENSE.txt +121 -0
- meltygui/resources/fontawesome-webfont.ttf +0 -0
- meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
- meltygui/resources/jetbrains-weights/OFL.txt +93 -0
- meltygui/resources/jetbrains-weights/README.md +2 -0
- meltygui/state/__init__.py +0 -0
- meltygui/state/account_state.py +22 -0
- meltygui/state/animation_state.py +97 -0
- meltygui/state/annotation_state.py +22 -0
- meltygui/state/chat_state.py +36 -0
- meltygui/state/code_state.py +10 -0
- meltygui/state/core_enums.py +59 -0
- meltygui/state/core_markers.py +115 -0
- meltygui/state/core_undo.py +1075 -0
- meltygui/state/file_state.py +75 -0
- meltygui/state/graph_state.py +26 -0
- meltygui/state/inspection_state.py +47 -0
- meltygui/state/menu_state.py +10 -0
- meltygui/state/model_enums.py +11 -0
- meltygui/state/new_core_model.py +2394 -0
- meltygui/state/orchestration_state.py +14 -0
- meltygui/state/query_state.py +24 -0
- meltygui/state/tensor_state.py +10 -0
- meltygui/state/terminal_state.py +23 -0
- meltygui/state/trace_state.py +32 -0
- meltygui/state/voxel_state.py +12 -0
- meltygui/text_index.py +816 -0
- meltygui/utils/__init__.py +0 -0
- meltygui/utils/jump_to_code.py +344 -0
- meltygui/utils/pkl_inspect.py +90 -0
- meltygui/utils/render_utils.py +1419 -0
- meltygui/view/__init__.py +1 -0
- meltygui/view/account_view.py +524 -0
- meltygui/view/action_view.py +73 -0
- meltygui/view/chat_decoration_view.py +112 -0
- meltygui/view/chat_view.py +1703 -0
- meltygui/view/code_view.py +2677 -0
- meltygui/view/collection_view.py +1185 -0
- meltygui/view/color_view.py +824 -0
- meltygui/view/control_view.py +559 -0
- meltygui/view/decoration_view.py +439 -0
- meltygui/view/diagnostic_view.py +177 -0
- meltygui/view/dropdown_view.py +1082 -0
- meltygui/view/file_view.py +1599 -0
- meltygui/view/graph_cuda_view.py +105 -0
- meltygui/view/graph_view.py +882 -0
- meltygui/view/header_view.py +848 -0
- meltygui/view/input_view.py +238 -0
- meltygui/view/inspection_view.py +1783 -0
- meltygui/view/layout_view.py +596 -0
- meltygui/view/lut_view.py +45 -0
- meltygui/view/menu_view.py +212 -0
- meltygui/view/orchestration_view.py +658 -0
- meltygui/view/query_view.py +118 -0
- meltygui/view/search_view.py +342 -0
- meltygui/view/tab_view.py +258 -0
- meltygui/view/tensor_view.py +430 -0
- meltygui/view/terminal_view.py +355 -0
- meltygui/view/text_view.py +8031 -0
- meltygui/view/texture_view.py +480 -0
- meltygui/view/tile_view.py +38 -0
- meltygui/view/trace_view.py +923 -0
- meltygui/view/voxel_cuda_view.py +824 -0
- meltygui/view/voxel_view.py +1860 -0
- meltygui/view/window_view.py +111 -0
- meltygui-0.1.0.dist-info/METADATA +143 -0
- meltygui-0.1.0.dist-info/RECORD +372 -0
- meltygui-0.1.0.dist-info/WHEEL +4 -0
- meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Claude FIM provider — prompt-engineered fill-in-the-middle over the
|
|
2
|
+
Messages API (Claude has no native FIM mode). Prompt layout is cache-
|
|
3
|
+
friendly: a frozen system prompt, then the editor's STABLE context block
|
|
4
|
+
(cache breakpoint), then the RUN block (breakpoint), then the volatile
|
|
5
|
+
file window with a `<|cursor|>` marker. Output is streamed so the first
|
|
6
|
+
line ghosts in while the rest arrives.
|
|
7
|
+
|
|
8
|
+
Session: one `anthropic.Anthropic` client per (api_key_env, base_url) —
|
|
9
|
+
thread-safe, connection-pooled, shared by every editor on that profile.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
from meltygui.completion.fim import FimRequest
|
|
17
|
+
from meltygui.completion.fim import FimResult
|
|
18
|
+
from meltygui.completion.fim import FimSession
|
|
19
|
+
from meltygui.completion.fim import fim_provider
|
|
20
|
+
|
|
21
|
+
SYSTEM = """You are a code completion engine inside an editor. The user message contains:
|
|
22
|
+
1. optional context blocks (other definitions, observed runtime types, values from the last run)
|
|
23
|
+
2. the current file with a <|cursor|> marker where the user is typing.
|
|
24
|
+
|
|
25
|
+
Reply with ONLY the code to insert at <|cursor|> — no explanation, no markdown fences, no echo of the text before or after the cursor.
|
|
26
|
+
Rules:
|
|
27
|
+
- Continue naturally from the exact character before the cursor (respect partial identifiers, open brackets, indentation).
|
|
28
|
+
- Stop where the existing code after the cursor would resume; never repeat it.
|
|
29
|
+
- Match the file's style, names and indentation. Prefer the names/APIs shown in the context blocks.
|
|
30
|
+
- Lines annotated `# ← value` show what that variable held on the last run; use them to pick sensible operations and shapes.
|
|
31
|
+
- If the cursor is mid-statement, finish the statement first. A multi-line completion may continue for several logical lines when the intent is clear.
|
|
32
|
+
- If nothing sensible can be inserted, reply with an empty message."""
|
|
33
|
+
|
|
34
|
+
_FENCE_RE = re.compile(r"^\s*```[a-zA-Z0-9_+-]*\n(.*?)\n?```\s*$", re.S)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def account_client_kwargs(account="default") -> dict:
|
|
38
|
+
"""The `anthropic.Anthropic(...)` kwargs the Internet Accounts entry
|
|
39
|
+
`account` supplies: `api_key` (a pasted key), else `profile` (the
|
|
40
|
+
browser sign-in's SDK profile), plus `base_url`. {} when the entry has
|
|
41
|
+
neither — the SDK's own env / active-profile chain then applies. No
|
|
42
|
+
SDK import, no network."""
|
|
43
|
+
try:
|
|
44
|
+
from meltygui.accounts.internet_accounts import KINDS
|
|
45
|
+
from meltygui.accounts.internet_accounts import account as account_entry
|
|
46
|
+
entry = account_entry("anthropic", account)
|
|
47
|
+
except Exception:
|
|
48
|
+
return {}
|
|
49
|
+
if entry is None:
|
|
50
|
+
return {}
|
|
51
|
+
return KINDS["anthropic"].client_kwargs(entry)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def has_credentials(account="default") -> bool:
|
|
55
|
+
"""True when Claude can be reached at all: an account key or browser
|
|
56
|
+
sign-in, an ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN env var, or an
|
|
57
|
+
ACTIVE `ant auth login` profile on disk (the one a bare client picks
|
|
58
|
+
up). Cheap — filesystem + env only, no import, no network."""
|
|
59
|
+
kwargs = account_client_kwargs(account)
|
|
60
|
+
if kwargs.get("api_key") or kwargs.get("profile"):
|
|
61
|
+
return True
|
|
62
|
+
if os.environ.get("ANTHROPIC_API_KEY") or os.environ.get("ANTHROPIC_AUTH_TOKEN"):
|
|
63
|
+
return True
|
|
64
|
+
from meltygui.completion.providers.anthropic_oauth import active_profile_present
|
|
65
|
+
try:
|
|
66
|
+
return active_profile_present()
|
|
67
|
+
except OSError:
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ClaudeSession(FimSession):
|
|
72
|
+
"""One Anthropic client. Credentials come from the Internet Accounts
|
|
73
|
+
entry `account` (kind "anthropic"): a pasted `api_key`, else the
|
|
74
|
+
browser sign-in's SDK `profile` (the client refreshes its token by
|
|
75
|
+
itself), plus `base_url`; with neither stored the SDK's normal
|
|
76
|
+
resolution applies (ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN env, the
|
|
77
|
+
active `ant auth login` profile).
|
|
78
|
+
|
|
79
|
+
Claude is NOT loaded (no `import anthropic`, no client) unless a
|
|
80
|
+
credential exists — construction raises early otherwise, so a studio
|
|
81
|
+
with no key never pays the anthropic import or a doomed request."""
|
|
82
|
+
KIND = "anthropic"
|
|
83
|
+
|
|
84
|
+
def __init__(self, account="default", base_url=None, timeout_s=30.0):
|
|
85
|
+
self.account = account
|
|
86
|
+
if not has_credentials(account):
|
|
87
|
+
raise RuntimeError("no Anthropic sign-in or API key — Internet Accounts → Sign in")
|
|
88
|
+
import anthropic
|
|
89
|
+
from meltygui.completion.providers.anthropic_requests import sdk_middleware
|
|
90
|
+
kw = {"timeout": timeout_s, "max_retries": 1,
|
|
91
|
+
"middleware": [sdk_middleware()]} # announces every request (except retry)
|
|
92
|
+
kw.update(account_client_kwargs(account))
|
|
93
|
+
if base_url:
|
|
94
|
+
kw["base_url"] = base_url
|
|
95
|
+
self.client = anthropic.Anthropic(**kw)
|
|
96
|
+
self._status = ("ready",)
|
|
97
|
+
|
|
98
|
+
def status(self):
|
|
99
|
+
return self._status
|
|
100
|
+
|
|
101
|
+
def close(self):
|
|
102
|
+
try:
|
|
103
|
+
self.client.close()
|
|
104
|
+
except Exception:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
def alive(self):
|
|
108
|
+
return getattr(self, "client", None) is not None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _window(req: FimRequest, prefix_chars: int, suffix_chars: int):
|
|
112
|
+
"""(prefix, suffix) cut to whole lines within the char budgets, the
|
|
113
|
+
prefix annotated with last-run values."""
|
|
114
|
+
prefix = req.annotated_prefix()
|
|
115
|
+
if len(prefix) > prefix_chars:
|
|
116
|
+
cut = prefix.rfind("\n", 0, len(prefix) - prefix_chars)
|
|
117
|
+
prefix = prefix[cut + 1:] if cut >= 0 else prefix[-prefix_chars:]
|
|
118
|
+
suffix = req.suffix
|
|
119
|
+
if len(suffix) > suffix_chars:
|
|
120
|
+
cut = suffix.find("\n", suffix_chars)
|
|
121
|
+
suffix = suffix[:cut] if cut >= 0 else suffix[:suffix_chars]
|
|
122
|
+
return prefix, suffix
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def clean_completion(text: str, suffix: str) -> str:
|
|
126
|
+
"""Strip a whole-message code fence and trim a tail that duplicates
|
|
127
|
+
the start of the suffix (models like to close what the file already
|
|
128
|
+
closes)."""
|
|
129
|
+
m = _FENCE_RE.match(text)
|
|
130
|
+
if m:
|
|
131
|
+
text = m.group(1)
|
|
132
|
+
s = suffix.lstrip()
|
|
133
|
+
if s and text:
|
|
134
|
+
probe = s.split("\n", 1)[0].rstrip()
|
|
135
|
+
if probe:
|
|
136
|
+
t = text.rstrip()
|
|
137
|
+
for n in range(min(len(probe), len(t)), 0, -1):
|
|
138
|
+
if t.endswith(probe[:n]) and (n >= 3 or probe[:n] in (")", "]", "}", '"', "'")):
|
|
139
|
+
text = t[:-n]
|
|
140
|
+
break
|
|
141
|
+
return text
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@fim_provider(name="claude", session=ClaudeSession)
|
|
145
|
+
def claude_fim(req: FimRequest, session: ClaudeSession, model="claude-opus-5",
|
|
146
|
+
effort="low", prefix_chars=8000, suffix_chars=2000,
|
|
147
|
+
fallbacks=True) -> FimResult:
|
|
148
|
+
"""Claude over the Messages API. `effort` is the Opus 5 thinking depth
|
|
149
|
+
(None omits it — for models without effort). `fallbacks` opts into the
|
|
150
|
+
server-side refusal fallback (`fallbacks: "default"`) so a classifier
|
|
151
|
+
decline is rerouted instead of leaving the ghost empty."""
|
|
152
|
+
prefix, suffix = _window(req, prefix_chars, suffix_chars)
|
|
153
|
+
ctx = req.context
|
|
154
|
+
blocks = []
|
|
155
|
+
stable = ctx.render(("stable",)) if ctx is not None else ""
|
|
156
|
+
if stable:
|
|
157
|
+
blocks.append({"type": "text", "text": "<context>\n" + stable + "\n</context>",
|
|
158
|
+
"cache_control": {"type": "ephemeral"}})
|
|
159
|
+
run = ctx.render(("run",)) if ctx is not None else ""
|
|
160
|
+
if run:
|
|
161
|
+
blocks.append({"type": "text", "text": "<last_run>\n" + run + "\n</last_run>",
|
|
162
|
+
"cache_control": {"type": "ephemeral"}})
|
|
163
|
+
volatile = ctx.render(("volatile",)) if ctx is not None else ""
|
|
164
|
+
body = ""
|
|
165
|
+
if volatile:
|
|
166
|
+
body += "<nearby_definitions>\n" + volatile + "\n</nearby_definitions>\n\n"
|
|
167
|
+
body += (f"<file path=\"{req.path or 'buffer'}\" language=\"{req.language}\">\n"
|
|
168
|
+
f"{prefix}<|cursor|>{suffix}\n</file>")
|
|
169
|
+
blocks.append({"type": "text", "text": body})
|
|
170
|
+
|
|
171
|
+
kwargs = dict(model=model, max_tokens=max(16, req.max_tokens),
|
|
172
|
+
system=[{"type": "text", "text": SYSTEM, "cache_control": {"type": "ephemeral"}}],
|
|
173
|
+
messages=[{"role": "user", "content": blocks}])
|
|
174
|
+
if effort:
|
|
175
|
+
kwargs["output_config"] = {"effort": effort}
|
|
176
|
+
use_beta = bool(fallbacks)
|
|
177
|
+
if use_beta:
|
|
178
|
+
kwargs["betas"] = ["server-side-fallback-2026-07-01"]
|
|
179
|
+
kwargs["fallbacks"] = "default"
|
|
180
|
+
api = session.client.beta.messages if use_beta else session.client.messages
|
|
181
|
+
|
|
182
|
+
acc = []
|
|
183
|
+
with api.stream(**kwargs) as stream:
|
|
184
|
+
for event in stream:
|
|
185
|
+
if req.cancelled.is_set():
|
|
186
|
+
stream.close()
|
|
187
|
+
break
|
|
188
|
+
if getattr(event, "type", None) == "text":
|
|
189
|
+
acc.append(event.text)
|
|
190
|
+
req.emit("".join(acc))
|
|
191
|
+
final = None
|
|
192
|
+
if not req.cancelled.is_set():
|
|
193
|
+
try:
|
|
194
|
+
final = stream.get_final_message()
|
|
195
|
+
except Exception:
|
|
196
|
+
final = None
|
|
197
|
+
if final is not None and getattr(final, "stop_reason", None) == "refusal":
|
|
198
|
+
return FimResult("", provider="claude")
|
|
199
|
+
text = clean_completion("".join(acc), suffix)
|
|
200
|
+
# Only "max_tokens" means the model was cut off (continue on Tab). "end_sequence"
|
|
201
|
+
# / "stop_sequence" is a natural finish - don't auto-emit another suggestion.
|
|
202
|
+
truncated = getattr(final, "stop_reason", None) == "max_tokens"
|
|
203
|
+
return FimResult(text, provider="claude", truncated=truncated)
|