cct-cli 0.7.9.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.
- calc_terminal/__init__.py +14 -0
- calc_terminal/__main__.py +14 -0
- calc_terminal/activity.py +1334 -0
- calc_terminal/agent.py +3387 -0
- calc_terminal/agent_runtime.py +519 -0
- calc_terminal/ai_context.py +447 -0
- calc_terminal/ai_modes.py +752 -0
- calc_terminal/ai_personalization.py +286 -0
- calc_terminal/ai_preview_feedback.py +213 -0
- calc_terminal/aicore.py +2572 -0
- calc_terminal/anim.py +367 -0
- calc_terminal/app.py +3685 -0
- calc_terminal/art.py +639 -0
- calc_terminal/atomsim.py +368 -0
- calc_terminal/attachments.py +743 -0
- calc_terminal/benchmark_system.py +414 -0
- calc_terminal/browser/__init__.py +36 -0
- calc_terminal/browser/browser_state.py +346 -0
- calc_terminal/browser/devserver.py +176 -0
- calc_terminal/browser/engine.py +494 -0
- calc_terminal/browser/navigation.py +84 -0
- calc_terminal/browser/preview.py +429 -0
- calc_terminal/browser/preview_entry.py +95 -0
- calc_terminal/browser/project_detector.py +144 -0
- calc_terminal/browser/server.py +449 -0
- calc_terminal/browser/state.py +75 -0
- calc_terminal/browser/watcher.py +99 -0
- calc_terminal/browser_gui/__init__.py +1 -0
- calc_terminal/browser_gui/__main__.py +3 -0
- calc_terminal/browser_gui/launcher.py +173 -0
- calc_terminal/browser_gui/playwright_browser.py +117 -0
- calc_terminal/browser_gui/qt_browser.py +1501 -0
- calc_terminal/browser_gui/webview_browser.py +57 -0
- calc_terminal/capabilities/__init__.py +35 -0
- calc_terminal/capabilities/adapters/__init__.py +33 -0
- calc_terminal/capabilities/adapters/bioinformatics.py +204 -0
- calc_terminal/capabilities/adapters/browser_adapter.py +205 -0
- calc_terminal/capabilities/adapters/filesystem.py +206 -0
- calc_terminal/capabilities/adapters/git_adapter.py +202 -0
- calc_terminal/capabilities/adapters/jupyter_adapter.py +138 -0
- calc_terminal/capabilities/adapters/ml_frameworks.py +158 -0
- calc_terminal/capabilities/adapters/platforms.py +200 -0
- calc_terminal/capabilities/adapters/python_exec.py +93 -0
- calc_terminal/capabilities/adapters/quantum_adapter.py +150 -0
- calc_terminal/capabilities/adapters/scientific_comp.py +123 -0
- calc_terminal/capabilities/adapters/structural_bio.py +161 -0
- calc_terminal/capabilities/adapters/terminal.py +99 -0
- calc_terminal/capabilities/bus.py +178 -0
- calc_terminal/capabilities/discovery.py +207 -0
- calc_terminal/capabilities/schema.py +221 -0
- calc_terminal/cat.ico +0 -0
- calc_terminal/cat_browser.py +2018 -0
- calc_terminal/chat_store.py +703 -0
- calc_terminal/cli.py +1178 -0
- calc_terminal/code_editor.py +640 -0
- calc_terminal/collaboration.py +723 -0
- calc_terminal/commands_data.py +139 -0
- calc_terminal/compatibility_engine.py +352 -0
- calc_terminal/compute/__init__.py +31 -0
- calc_terminal/compute/fabric.py +350 -0
- calc_terminal/config.py +227 -0
- calc_terminal/core/__init__.py +41 -0
- calc_terminal/core/checkpoint.py +156 -0
- calc_terminal/core/input/__init__.py +45 -0
- calc_terminal/core/mode_registry.py +300 -0
- calc_terminal/core/project_graph.py +172 -0
- calc_terminal/core/recovery.py +129 -0
- calc_terminal/core/security_layer.py +112 -0
- calc_terminal/core/task_graph.py +202 -0
- calc_terminal/core/unified_runtime.py +184 -0
- calc_terminal/core/verification.py +257 -0
- calc_terminal/customization.py +1566 -0
- calc_terminal/derivations.py +153 -0
- calc_terminal/device_control.py +263 -0
- calc_terminal/diagnostics/__init__.py +27 -0
- calc_terminal/diagnostics/doctor_engine.py +382 -0
- calc_terminal/diagnostics/self_test.py +247 -0
- calc_terminal/doctor.py +519 -0
- calc_terminal/easter_eggs.py +274 -0
- calc_terminal/editor/__init__.py +1 -0
- calc_terminal/editor/actions.py +263 -0
- calc_terminal/editor/commands.py +160 -0
- calc_terminal/editor/shortcuts.py +226 -0
- calc_terminal/engine.py +259 -0
- calc_terminal/errors.py +120 -0
- calc_terminal/event_stream.py +146 -0
- calc_terminal/eventbus.py +133 -0
- calc_terminal/extensions.py +733 -0
- calc_terminal/fallback_cli.py +1321 -0
- calc_terminal/first_run.py +265 -0
- calc_terminal/fomoji_auth.py +1043 -0
- calc_terminal/formulas.py +82 -0
- calc_terminal/fs_cache.py +121 -0
- calc_terminal/fs_watcher.py +277 -0
- calc_terminal/game.py +193 -0
- calc_terminal/gen1.py +5 -0
- calc_terminal/generators.py +245 -0
- calc_terminal/gestures/__init__.py +42 -0
- calc_terminal/gestures/bindings.py +175 -0
- calc_terminal/gestures/manager.py +477 -0
- calc_terminal/goodbye.py +363 -0
- calc_terminal/gpu3d.py +290 -0
- calc_terminal/graphs.py +358 -0
- calc_terminal/hardware_analyzer.py +440 -0
- calc_terminal/host/__init__.py +30 -0
- calc_terminal/host/browser_manager.py +187 -0
- calc_terminal/host/desktop.py +1386 -0
- calc_terminal/host/launcher.py +395 -0
- calc_terminal/host/terminal.py +279 -0
- calc_terminal/identity.py +216 -0
- calc_terminal/input/__init__.py +54 -0
- calc_terminal/input/capabilities.py +258 -0
- calc_terminal/input/focus.py +87 -0
- calc_terminal/input/gestures.py +64 -0
- calc_terminal/input/pointer.py +114 -0
- calc_terminal/input/touch.py +345 -0
- calc_terminal/keys.py +84 -0
- calc_terminal/live_automation.py +165 -0
- calc_terminal/mathtext.py +433 -0
- calc_terminal/mcp.py +386 -0
- calc_terminal/memory.py +337 -0
- calc_terminal/memory_v2.py +479 -0
- calc_terminal/metrics.py +333 -0
- calc_terminal/mode_detection.py +146 -0
- calc_terminal/model.py +2431 -0
- calc_terminal/model_router.py +665 -0
- calc_terminal/models/__init__.py +0 -0
- calc_terminal/models/active_state.py +187 -0
- calc_terminal/models/dynamic_registry.py +584 -0
- calc_terminal/models/manager.py +781 -0
- calc_terminal/models/model_metadata.json +3526 -0
- calc_terminal/models/profiles.py +194 -0
- calc_terminal/models/registry.py +265 -0
- calc_terminal/models/schema.py +197 -0
- calc_terminal/models/validator.py +287 -0
- calc_terminal/models/verification_engine.py +368 -0
- calc_terminal/native_picker.py +215 -0
- calc_terminal/ollama_catalog.py +279 -0
- calc_terminal/ollama_download.py +233 -0
- calc_terminal/orchestrator.py +304 -0
- calc_terminal/package_research.py +322 -0
- calc_terminal/packages.py +1024 -0
- calc_terminal/pc_specs.py +116 -0
- calc_terminal/permissions.py +334 -0
- calc_terminal/pet.py +106 -0
- calc_terminal/pipeline.py +505 -0
- calc_terminal/platform/__init__.py +491 -0
- calc_terminal/platform/desktop.py +491 -0
- calc_terminal/platform/web.py +781 -0
- calc_terminal/preview/__init__.py +1 -0
- calc_terminal/preview/dev_server.py +303 -0
- calc_terminal/preview/diagnostics.py +131 -0
- calc_terminal/preview/live_reload.py +66 -0
- calc_terminal/preview/manager.py +129 -0
- calc_terminal/project_stats.py +209 -0
- calc_terminal/projects.py +328 -0
- calc_terminal/providers/__init__.py +0 -0
- calc_terminal/providers/adapters/__init__.py +80 -0
- calc_terminal/providers/adapters/anthropic_adapter.py +127 -0
- calc_terminal/providers/adapters/base.py +106 -0
- calc_terminal/providers/adapters/chinese_adapters.py +420 -0
- calc_terminal/providers/adapters/gemini_adapter.py +101 -0
- calc_terminal/providers/adapters/ollama_adapter.py +83 -0
- calc_terminal/providers/adapters/openai_adapter.py +159 -0
- calc_terminal/providers/adapters/other_adapters.py +246 -0
- calc_terminal/providers/anthropic_provider.py +172 -0
- calc_terminal/providers/auto_update.py +416 -0
- calc_terminal/providers/base_provider.py +105 -0
- calc_terminal/providers/discovery_manager.py +207 -0
- calc_terminal/providers/gemini_provider.py +178 -0
- calc_terminal/providers/lifecycle.py +767 -0
- calc_terminal/providers/ollama_adapter.py +707 -0
- calc_terminal/providers/openai_provider.py +254 -0
- calc_terminal/providers/provider_manager.py +1827 -0
- calc_terminal/providers/providers.json +4075 -0
- calc_terminal/reactionsim.py +279 -0
- calc_terminal/registry.py +337 -0
- calc_terminal/report.py +162 -0
- calc_terminal/research/__init__.py +45 -0
- calc_terminal/research/artifact_intel.py +126 -0
- calc_terminal/research/data_lineage.py +123 -0
- calc_terminal/research/experiment_ledger.py +303 -0
- calc_terminal/research/reproducibility.py +131 -0
- calc_terminal/resilience/__init__.py +47 -0
- calc_terminal/resilience/agent_state.py +121 -0
- calc_terminal/resilience/capability_matcher.py +174 -0
- calc_terminal/resilience/circuit_breaker.py +158 -0
- calc_terminal/resilience/failover_engine.py +230 -0
- calc_terminal/resilience/health_monitor.py +192 -0
- calc_terminal/resilience/ollama_adapter.py +125 -0
- calc_terminal/resilience/orchestrator.py +312 -0
- calc_terminal/resilience/types.py +134 -0
- calc_terminal/sandbox.py +98 -0
- calc_terminal/scires.py +558 -0
- calc_terminal/security_scanner.py +126 -0
- calc_terminal/session.py +294 -0
- calc_terminal/sim3d.py +206 -0
- calc_terminal/solver.py +276 -0
- calc_terminal/sound.py +127 -0
- calc_terminal/task_reports.py +287 -0
- calc_terminal/terminal_host.py +201 -0
- calc_terminal/terminal_identity.py +411 -0
- calc_terminal/test_ai_mode_reliability.py +344 -0
- calc_terminal/test_browser.py +368 -0
- calc_terminal/test_code_editor_upgrade.py +485 -0
- calc_terminal/test_customization.py +1148 -0
- calc_terminal/test_customization_ui.py +612 -0
- calc_terminal/test_dynamic_registry.py +304 -0
- calc_terminal/test_extensions.py +436 -0
- calc_terminal/test_overhaul.py +557 -0
- calc_terminal/test_project_detect.py +255 -0
- calc_terminal/test_root_cause_fix.py +527 -0
- calc_terminal/test_stability.py +532 -0
- calc_terminal/test_terminal_identity.py +132 -0
- calc_terminal/test_v079_speed.py +460 -0
- calc_terminal/theme.py +1107 -0
- calc_terminal/timeline.py +139 -0
- calc_terminal/todos.py +246 -0
- calc_terminal/tool_call_normalizer.py +419 -0
- calc_terminal/tui.py +104 -0
- calc_terminal/ui/__init__.py +8 -0
- calc_terminal/ui/activity_panel.py +231 -0
- calc_terminal/ui/activity_stream_panel.py +238 -0
- calc_terminal/ui/animations.py +122 -0
- calc_terminal/ui/app.py +7271 -0
- calc_terminal/ui/attach_panel.py +597 -0
- calc_terminal/ui/attachments.py +424 -0
- calc_terminal/ui/backup_panel.py +810 -0
- calc_terminal/ui/browser_shell.py +887 -0
- calc_terminal/ui/cat_agent.py +357 -0
- calc_terminal/ui/chats_panel.py +899 -0
- calc_terminal/ui/command_palette.py +125 -0
- calc_terminal/ui/command_palette_modal.py +166 -0
- calc_terminal/ui/composer.py +1141 -0
- calc_terminal/ui/context_menu.py +197 -0
- calc_terminal/ui/conversation.py +1435 -0
- calc_terminal/ui/customization_panel.py +1229 -0
- calc_terminal/ui/dashboard.py +404 -0
- calc_terminal/ui/design_system.py +557 -0
- calc_terminal/ui/diff_panel.py +213 -0
- calc_terminal/ui/editor.py +2102 -0
- calc_terminal/ui/empty_state.py +302 -0
- calc_terminal/ui/events.py +487 -0
- calc_terminal/ui/extensions_panel.py +815 -0
- calc_terminal/ui/footer.py +166 -0
- calc_terminal/ui/gestures_panel.py +383 -0
- calc_terminal/ui/goodbye_screen.py +100 -0
- calc_terminal/ui/header.py +1034 -0
- calc_terminal/ui/help_panel.py +254 -0
- calc_terminal/ui/live_activities.py +914 -0
- calc_terminal/ui/mcp_panel.py +570 -0
- calc_terminal/ui/memory_center.py +524 -0
- calc_terminal/ui/mode_colors_panel.py +525 -0
- calc_terminal/ui/nav_screens.py +747 -0
- calc_terminal/ui/ollama_panel.py +536 -0
- calc_terminal/ui/palette.py +221 -0
- calc_terminal/ui/permission_panel.py +269 -0
- calc_terminal/ui/personalization_panel.py +517 -0
- calc_terminal/ui/personalize_center.py +1568 -0
- calc_terminal/ui/preview_panel.py +441 -0
- calc_terminal/ui/resizers.py +402 -0
- calc_terminal/ui/sidebar.py +1285 -0
- calc_terminal/ui/statusbar.py +168 -0
- calc_terminal/ui/theme_css.py +1396 -0
- calc_terminal/ui/thinking.py +226 -0
- calc_terminal/ui/timeline_panel.py +102 -0
- calc_terminal/ui/todo_panel.py +193 -0
- calc_terminal/ui/viewport.py +136 -0
- calc_terminal/ui/vision_panel.py +489 -0
- calc_terminal/ui/welcome_modal.py +343 -0
- calc_terminal/ui/widgets.py +160 -0
- calc_terminal/ui/workspace.py +831 -0
- calc_terminal/viewers/__init__.py +1 -0
- calc_terminal/viewers/document_viewer.py +252 -0
- calc_terminal/viewers/image_viewer.py +241 -0
- calc_terminal/viewers/pdf_viewer.py +203 -0
- calc_terminal/viewers/presentation_viewer.py +164 -0
- calc_terminal/viewers/registry.py +120 -0
- calc_terminal/viewers/spreadsheet_viewer.py +204 -0
- calc_terminal/vision/__init__.py +89 -0
- calc_terminal/vision/analysis.py +194 -0
- calc_terminal/vision/annotations.py +297 -0
- calc_terminal/vision/capture.py +171 -0
- calc_terminal/vision/context.py +231 -0
- calc_terminal/vision/correlation.py +169 -0
- calc_terminal/vision/cursor.py +258 -0
- calc_terminal/vision/events.py +66 -0
- calc_terminal/vision/frame_pipeline.py +259 -0
- calc_terminal/vision/priority.py +218 -0
- calc_terminal/vision/provider.py +180 -0
- calc_terminal/vision/safety.py +149 -0
- calc_terminal/vision/session.py +281 -0
- calc_terminal/vision/verify.py +162 -0
- calc_terminal/vision.py +514 -0
- calc_terminal/vscode_integration.py +113 -0
- calc_terminal/web/__init__.py +8 -0
- calc_terminal/web/cat_runtime.py +710 -0
- calc_terminal/web/server.py +2891 -0
- calc_terminal/web/static/css/app.css +3152 -0
- calc_terminal/web/static/icons/badge-72.png +0 -0
- calc_terminal/web/static/icons/cat.ico +0 -0
- calc_terminal/web/static/icons/icon-128.png +0 -0
- calc_terminal/web/static/icons/icon-144.png +0 -0
- calc_terminal/web/static/icons/icon-152.png +0 -0
- calc_terminal/web/static/icons/icon-192.png +0 -0
- calc_terminal/web/static/icons/icon-384.png +0 -0
- calc_terminal/web/static/icons/icon-512.png +0 -0
- calc_terminal/web/static/icons/icon-72.png +0 -0
- calc_terminal/web/static/icons/icon-96.png +0 -0
- calc_terminal/web/static/icons/icon.svg +34 -0
- calc_terminal/web/static/icons/new-project.png +0 -0
- calc_terminal/web/static/icons/open-project.png +0 -0
- calc_terminal/web/static/index.html +734 -0
- calc_terminal/web/static/js/app.js +2403 -0
- calc_terminal/web/static/manifest.json +88 -0
- calc_terminal/web/static/sw.js +230 -0
- calc_terminal/workflow_engine.py +769 -0
- calc_terminal/workspace.py +593 -0
- calc_terminal/workspace_index.py +385 -0
- cct_cli-0.7.9.0.dist-info/METADATA +210 -0
- cct_cli-0.7.9.0.dist-info/RECORD +325 -0
- cct_cli-0.7.9.0.dist-info/WHEEL +5 -0
- cct_cli-0.7.9.0.dist-info/entry_points.txt +4 -0
- cct_cli-0.7.9.0.dist-info/licenses/LICENSE +21 -0
- cct_cli-0.7.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CCT - native Windows file picker for Browse in Attach to Message.
|
|
3
|
+
|
|
4
|
+
Reliability order (v0.8.1 root-cause fix for "Browse does nothing"):
|
|
5
|
+
|
|
6
|
+
1. tkinter askopenfilenames with root.attributes("-topmost", True).
|
|
7
|
+
The -topmost attribute GUARANTEES the dialog appears above the
|
|
8
|
+
fullscreen terminal even when the terminal owns the foreground
|
|
9
|
+
(Windows Terminal / conhost). This is the primary method because
|
|
10
|
+
the old ctypes-first path could open GetOpenFileNameW BEHIND the
|
|
11
|
+
terminal window (hwndOwner=0 in Windows Terminal returns no usable
|
|
12
|
+
owner), where it silently waited for input the user could not see —
|
|
13
|
+
exactly the reported "button bounces, nothing happens" symptom.
|
|
14
|
+
|
|
15
|
+
2. ctypes GetOpenFileNameW (comdlg32) as a fallback when tkinter is
|
|
16
|
+
unavailable. hwndOwner=0 works reliably from worker threads;
|
|
17
|
+
lpstrInitialDir sets the start directory (never lpstrFile, which
|
|
18
|
+
causes CDERR_DIALOGFAILURE).
|
|
19
|
+
|
|
20
|
+
Both methods: files only (no folder selection), multi-select enabled,
|
|
21
|
+
"All Files (*.*)" plus common category filters — deliberately broad.
|
|
22
|
+
"""
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
print("This is a library file.")
|
|
25
|
+
import sys; sys.exit(1)
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
import ctypes
|
|
32
|
+
from ctypes import wintypes
|
|
33
|
+
_CTYPES_OK = True
|
|
34
|
+
except Exception:
|
|
35
|
+
_CTYPES_OK = False
|
|
36
|
+
|
|
37
|
+
_OFN_FILEMUSTEXIST = 0x00001000
|
|
38
|
+
_OFN_PATHMUSTEXIST = 0x00000800
|
|
39
|
+
_OFN_HIDEREADONLY = 0x00000004
|
|
40
|
+
_OFN_EXPLORER = 0x00080000
|
|
41
|
+
_OFN_ALLOWMULTISELECT = 0x00000200
|
|
42
|
+
_FLAGS = (_OFN_FILEMUSTEXIST | _OFN_PATHMUSTEXIST
|
|
43
|
+
| _OFN_HIDEREADONLY | _OFN_EXPLORER | _OFN_ALLOWMULTISELECT)
|
|
44
|
+
_BUFSIZE = 32768
|
|
45
|
+
|
|
46
|
+
FILTER = (
|
|
47
|
+
"All Files (*.*)\0*.*\0"
|
|
48
|
+
"Code Files (*.py;*.js;*.ts;*.tsx;*.jsx;*.java;*.c;*.h;*.cpp;*.rs;*.go)\0"
|
|
49
|
+
"*.py;*.js;*.ts;*.tsx;*.jsx;*.java;*.c;*.h;*.cpp;*.rs;*.go\0"
|
|
50
|
+
"Data Files (*.json;*.yaml;*.yml;*.toml;*.xml;*.csv)\0"
|
|
51
|
+
"*.json;*.yaml;*.yml;*.toml;*.xml;*.csv\0"
|
|
52
|
+
"Documents (*.txt;*.md;*.log;*.html;*.css;*.scss;*.pdf;*.doc;*.docx)\0"
|
|
53
|
+
"*.txt;*.md;*.log;*.html;*.css;*.scss;*.pdf;*.doc;*.docx\0"
|
|
54
|
+
"Images (*.png;*.jpg;*.jpeg;*.webp;*.gif;*.svg;*.bmp;*.ico)\0"
|
|
55
|
+
"*.png;*.jpg;*.jpeg;*.webp;*.gif;*.svg;*.bmp;*.ico\0"
|
|
56
|
+
"Archives (*.zip;*.tar;*.gz;*.bz2;*.rar;*.7z)\0"
|
|
57
|
+
"*.zip;*.tar;*.gz;*.bz2;*.rar;*.7z\0"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
TK_FILETYPES = [
|
|
61
|
+
("All Files", "*.*"),
|
|
62
|
+
("Code Files", "*.py *.js *.ts *.tsx *.jsx *.java *.c *.h *.cpp *.rs *.go"),
|
|
63
|
+
("Data Files", "*.json *.yaml *.yml *.toml *.xml *.csv"),
|
|
64
|
+
("Documents", "*.txt *.md *.log *.html *.css *.scss *.pdf *.doc *.docx"),
|
|
65
|
+
("Images", "*.png *.jpg *.jpeg *.webp *.gif *.svg *.bmp *.ico"),
|
|
66
|
+
("Archives", "*.zip *.tar *.gz *.bz2 *.rar *.7z"),
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def is_native_supported():
|
|
71
|
+
return sys.platform == "win32"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def parse_multi_buffer(raw):
|
|
75
|
+
if isinstance(raw, bytes):
|
|
76
|
+
raw = raw.decode("utf-16-le", errors="ignore")
|
|
77
|
+
parts = [p for p in raw.split("\x00") if p]
|
|
78
|
+
if not parts:
|
|
79
|
+
return []
|
|
80
|
+
if len(parts) == 1:
|
|
81
|
+
return parts if os.path.isabs(parts[0]) else []
|
|
82
|
+
directory = parts[0]
|
|
83
|
+
out = []
|
|
84
|
+
for name in parts[1:]:
|
|
85
|
+
candidate = os.path.join(directory, name)
|
|
86
|
+
if os.path.isabs(candidate):
|
|
87
|
+
out.append(candidate)
|
|
88
|
+
return out
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _pick_files_tkinter(initial_dir, title):
|
|
92
|
+
"""PRIMARY: tkinter dialog forced top-most, so it is always visible.
|
|
93
|
+
Returns list of paths ([] = user cancelled), None = tkinter unusable."""
|
|
94
|
+
try:
|
|
95
|
+
import tkinter as tk
|
|
96
|
+
from tkinter import filedialog
|
|
97
|
+
root = tk.Tk()
|
|
98
|
+
root.withdraw()
|
|
99
|
+
root.attributes("-topmost", True)
|
|
100
|
+
try:
|
|
101
|
+
filepaths = filedialog.askopenfilenames(
|
|
102
|
+
title=title,
|
|
103
|
+
initialdir=initial_dir,
|
|
104
|
+
filetypes=TK_FILETYPES,
|
|
105
|
+
)
|
|
106
|
+
if filepaths:
|
|
107
|
+
return list(filepaths)
|
|
108
|
+
return [] # user cancelled
|
|
109
|
+
finally:
|
|
110
|
+
try:
|
|
111
|
+
root.destroy()
|
|
112
|
+
except Exception:
|
|
113
|
+
pass
|
|
114
|
+
except Exception as e:
|
|
115
|
+
print("[NativePicker] tkinter picker failed: %s" % e, file=sys.stderr)
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class _OPENFILENAMEW(ctypes.Structure):
|
|
120
|
+
_fields_ = [
|
|
121
|
+
("lStructSize", wintypes.DWORD),
|
|
122
|
+
("hwndOwner", wintypes.HWND),
|
|
123
|
+
("hInstance", wintypes.HINSTANCE),
|
|
124
|
+
("lpstrFilter", wintypes.LPCWSTR),
|
|
125
|
+
("lpstrCustomFilter", wintypes.LPWSTR),
|
|
126
|
+
("nMaxCustFilter", wintypes.DWORD),
|
|
127
|
+
("nFilterIndex", wintypes.DWORD),
|
|
128
|
+
("lpstrFile", wintypes.LPWSTR),
|
|
129
|
+
("nMaxFile", wintypes.DWORD),
|
|
130
|
+
("lpstrFileTitle", wintypes.LPWSTR),
|
|
131
|
+
("nMaxFileTitle", wintypes.DWORD),
|
|
132
|
+
("lpstrInitialDir", wintypes.LPCWSTR),
|
|
133
|
+
("lpstrTitle", wintypes.LPCWSTR),
|
|
134
|
+
("Flags", wintypes.DWORD),
|
|
135
|
+
("nFileOffset", wintypes.WORD),
|
|
136
|
+
("nFileExtension", wintypes.WORD),
|
|
137
|
+
("lpstrDefExt", wintypes.LPCWSTR),
|
|
138
|
+
("lCustData", ctypes.c_void_p),
|
|
139
|
+
("lpfnHook", ctypes.c_void_p),
|
|
140
|
+
("lpTemplateName", wintypes.LPCWSTR),
|
|
141
|
+
]
|
|
142
|
+
if ctypes.sizeof(ctypes.c_void_p) == 8:
|
|
143
|
+
_fields_ += [("pvReserved", ctypes.c_void_p),
|
|
144
|
+
("dwReserved", wintypes.DWORD)]
|
|
145
|
+
_fields_ += [("FlagsEx", wintypes.DWORD)]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _pick_files_ctypes(initial_dir, title):
|
|
149
|
+
"""FALLBACK: ctypes GetOpenFileNameW. Returns list of paths or None."""
|
|
150
|
+
# CRITICAL: lpstrFile buffer must start EMPTY.
|
|
151
|
+
# Setting buf.value to a directory path causes CDERR_DIALOGFAILURE (12290).
|
|
152
|
+
# Initial directory is set via lpstrInitialDir instead.
|
|
153
|
+
buf = ctypes.create_unicode_buffer(_BUFSIZE)
|
|
154
|
+
|
|
155
|
+
filter_str = FILTER + "\x00"
|
|
156
|
+
ofn = _OPENFILENAMEW()
|
|
157
|
+
ofn.lStructSize = ctypes.sizeof(_OPENFILENAMEW)
|
|
158
|
+
# hwndOwner=0: works reliably from worker threads.
|
|
159
|
+
# GetConsoleWindow() returns 0 in Windows Terminal/Textual.
|
|
160
|
+
# GetForegroundWindow() causes error 12290 (CDERR_DIALOGFAILURE).
|
|
161
|
+
ofn.hwndOwner = 0
|
|
162
|
+
ofn.lpstrFilter = filter_str
|
|
163
|
+
ofn.nFilterIndex = 1
|
|
164
|
+
ofn.lpstrFile = ctypes.cast(buf, wintypes.LPWSTR)
|
|
165
|
+
ofn.nMaxFile = _BUFSIZE
|
|
166
|
+
ofn.lpstrTitle = title
|
|
167
|
+
ofn.Flags = _FLAGS
|
|
168
|
+
|
|
169
|
+
# Set initial directory via lpstrInitialDir, NOT via buf.value
|
|
170
|
+
if initial_dir:
|
|
171
|
+
if not os.path.isdir(initial_dir):
|
|
172
|
+
initial_dir = os.path.dirname(initial_dir) or None
|
|
173
|
+
if initial_dir:
|
|
174
|
+
ofn.lpstrInitialDir = initial_dir
|
|
175
|
+
|
|
176
|
+
comdlg32 = ctypes.windll.comdlg32
|
|
177
|
+
fn = comdlg32.GetOpenFileNameW
|
|
178
|
+
fn.argtypes = [ctypes.POINTER(_OPENFILENAMEW)]
|
|
179
|
+
fn.restype = wintypes.BOOL
|
|
180
|
+
|
|
181
|
+
result = fn(ctypes.byref(ofn))
|
|
182
|
+
if result:
|
|
183
|
+
return parse_multi_buffer(buf.raw)
|
|
184
|
+
err = comdlg32.CommDlgExtendedError()
|
|
185
|
+
if err:
|
|
186
|
+
print("[NativePicker] CommDlgExtendedError=%d" % err, file=sys.stderr)
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def pick_files(initial_dir=None, title="Select file(s) to attach"):
|
|
191
|
+
"""Show a file picker. Tries the always-visible tkinter dialog first,
|
|
192
|
+
falls back to ctypes GetOpenFileNameW.
|
|
193
|
+
Returns list of paths (empty = cancelled), None = all methods failed."""
|
|
194
|
+
if not is_native_supported():
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
# Method 1: tkinter (topmost — cannot open behind the terminal)
|
|
198
|
+
result = _pick_files_tkinter(initial_dir, title)
|
|
199
|
+
if result is not None:
|
|
200
|
+
return result
|
|
201
|
+
|
|
202
|
+
# Method 2: ctypes GetOpenFileNameW
|
|
203
|
+
if not _CTYPES_OK:
|
|
204
|
+
return None
|
|
205
|
+
print("[NativePicker] Trying ctypes fallback...", file=sys.stderr)
|
|
206
|
+
try:
|
|
207
|
+
result = _pick_files_ctypes(initial_dir, title)
|
|
208
|
+
if result is not None:
|
|
209
|
+
return result
|
|
210
|
+
except Exception as e:
|
|
211
|
+
print("[NativePicker] ctypes exception: %s" % e, file=sys.stderr)
|
|
212
|
+
import traceback
|
|
213
|
+
traceback.print_exc(file=sys.stderr)
|
|
214
|
+
|
|
215
|
+
return None
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Ollama model catalog — Authentic, curated models with dynamic local discovery.
|
|
2
|
+
Creator: Kazi Zillani (CAT Platform).
|
|
3
|
+
|
|
4
|
+
Provides authentic model metadata (params, size, context, capabilities, family)
|
|
5
|
+
without artificial dummy variants. Supports dynamic registration of locally installed
|
|
6
|
+
models and custom user models.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import List, Dict, Any, Optional
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
# Base curated catalog of authentic, modern local models
|
|
13
|
+
CURATED_CATALOG: List[Dict[str, Any]] = []
|
|
14
|
+
|
|
15
|
+
def _add(name: str, params: str, size_gb: float, family: str, desc: str,
|
|
16
|
+
ctx: int = 8192, caps: Optional[List[str]] = None, categories: Optional[List[str]] = None):
|
|
17
|
+
CURATED_CATALOG.append({
|
|
18
|
+
"name": name,
|
|
19
|
+
"params": params,
|
|
20
|
+
"size_gb": float(size_gb),
|
|
21
|
+
"family": family,
|
|
22
|
+
"desc": desc,
|
|
23
|
+
"context": ctx,
|
|
24
|
+
"caps": caps or ["chat"],
|
|
25
|
+
"categories": categories or ["popular"],
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
# =====================================================================
|
|
29
|
+
# 1. CORE LLAMA (Meta)
|
|
30
|
+
# =====================================================================
|
|
31
|
+
_add("llama3.3:70b", "70B", 42.0, "llama", "Meta Llama 3.3 70B — State of the art open weights model", 131072, ["chat", "code", "reasoning"], ["popular", "large"])
|
|
32
|
+
_add("llama3.3:8b", "8B", 4.7, "llama", "Meta Llama 3.3 8B — Fast, capable general assistant", 131072, ["chat", "code"], ["popular", "coding"])
|
|
33
|
+
_add("llama3.2:3b", "3B", 2.0, "llama", "Meta Llama 3.2 3B — Lightweight on-device assistant", 131072, ["chat", "code"], ["popular", "small"])
|
|
34
|
+
_add("llama3.2:1b", "1B", 1.3, "llama", "Meta Llama 3.2 1B — Ultra-lightweight edge model", 131072, ["chat"], ["small"])
|
|
35
|
+
_add("llama3.1:8b", "8B", 4.7, "llama", "Meta Llama 3.1 8B — High context general purpose model", 131072, ["chat", "code"], ["popular", "coding"])
|
|
36
|
+
_add("llama3.1:70b", "70B", 42.0, "llama", "Meta Llama 3.1 70B — Heavyweight reasoning and coding", 131072, ["chat", "code", "reasoning"], ["large"])
|
|
37
|
+
_add("llama3.1:405b", "405B", 243.0, "llama", "Meta Llama 3.1 405B — Frontier flagship open weights", 131072, ["chat", "code", "reasoning"], ["large"])
|
|
38
|
+
_add("llama3:8b", "8B", 4.7, "llama", "Meta Llama 3 8B — Original Llama 3 release", 8192, ["chat", "code"], ["popular"])
|
|
39
|
+
_add("llama2:7b", "7B", 3.8, "llama", "Meta Llama 2 7B — Classic foundation model", 4096, ["chat"], ["small"])
|
|
40
|
+
_add("llama2:13b", "13B", 7.4, "llama", "Meta Llama 2 13B — Classic balanced model", 4096, ["chat"], ["popular"])
|
|
41
|
+
|
|
42
|
+
# =====================================================================
|
|
43
|
+
# 2. QWEN & QWEN CODER (Alibaba)
|
|
44
|
+
# =====================================================================
|
|
45
|
+
_add("qwen2.5-coder:7b", "7B", 4.7, "qwen", "Qwen 2.5 Coder 7B — Premier open-source code generation model", 32768, ["code", "chat"], ["popular", "coding"])
|
|
46
|
+
_add("qwen2.5-coder:14b", "14B", 9.0, "qwen", "Qwen 2.5 Coder 14B — Deep architectural coding & refactoring", 32768, ["code", "chat"], ["coding", "popular"])
|
|
47
|
+
_add("qwen2.5-coder:32b", "32B", 19.0, "qwen", "Qwen 2.5 Coder 32B — Enterprise-grade code intelligence", 32768, ["code", "chat", "reasoning"], ["coding", "large"])
|
|
48
|
+
_add("qwen2.5-coder:3b", "3B", 1.9, "qwen", "Qwen 2.5 Coder 3B — Fast on-device copilot & terminal assistant", 32768, ["code", "chat"], ["coding", "small"])
|
|
49
|
+
_add("qwen2.5-coder:1.5b", "1.5B", 1.0, "qwen", "Qwen 2.5 Coder 1.5B — Ultra-low latency autocomplete", 32768, ["code"], ["coding", "small"])
|
|
50
|
+
_add("qwen2.5:7b", "7B", 4.4, "qwen", "Qwen 2.5 7B — Multilingual general intelligence & math", 32768, ["chat", "code"], ["popular"])
|
|
51
|
+
_add("qwen2.5:14b", "14B", 9.0, "qwen", "Qwen 2.5 14B — Strong balanced reasoning and knowledge", 32768, ["chat", "code", "reasoning"], ["popular"])
|
|
52
|
+
_add("qwen2.5:32b", "32B", 19.0, "qwen", "Qwen 2.5 32B — High-fidelity analytical reasoning", 32768, ["chat", "code", "reasoning"], ["large"])
|
|
53
|
+
_add("qwen2.5:72b", "72B", 41.0, "qwen", "Qwen 2.5 72B — Flagship open weights generalist", 32768, ["chat", "code", "reasoning"], ["large"])
|
|
54
|
+
_add("qwen2.5:3b", "3B", 1.9, "qwen", "Qwen 2.5 3B — Agile compact multilingual model", 32768, ["chat"], ["small"])
|
|
55
|
+
_add("qwen2.5:1.5b", "1.5B", 0.9, "qwen", "Qwen 2.5 1.5B — Lightweight embedded model", 32768, ["chat"], ["small"])
|
|
56
|
+
_add("qwen2.5:0.5b", "0.5B", 0.4, "qwen", "Qwen 2.5 0.5B — Micro model for IoT and quick parsing", 32768, ["chat"], ["small"])
|
|
57
|
+
_add("qwq:32b", "32B", 20.0, "qwen", "QwQ 32B — Thinking & complex mathematical reasoning model", 32768, ["reasoning", "math", "code"], ["reasoning", "popular"])
|
|
58
|
+
|
|
59
|
+
# =====================================================================
|
|
60
|
+
# 3. DEEPSEEK (DeepSeek AI)
|
|
61
|
+
# =====================================================================
|
|
62
|
+
_add("deepseek-r1:1.5b", "1.5B", 1.1, "deepseek", "DeepSeek R1 Distill 1.5B — Micro step-by-step reasoning", 32768, ["reasoning"], ["reasoning", "small"])
|
|
63
|
+
_add("deepseek-r1:7b", "7B", 4.7, "deepseek", "DeepSeek R1 Distill 7B (Qwen) — Fast chain-of-thought", 32768, ["reasoning", "code"], ["reasoning", "popular"])
|
|
64
|
+
_add("deepseek-r1:8b", "8B", 4.9, "deepseek", "DeepSeek R1 Distill 8B (Llama) — Strong CoT reasoning", 32768, ["reasoning", "code"], ["reasoning", "popular"])
|
|
65
|
+
_add("deepseek-r1:14b", "14B", 9.0, "deepseek", "DeepSeek R1 Distill 14B — In-depth logical deduction & math", 32768, ["reasoning", "code", "math"], ["reasoning"])
|
|
66
|
+
_add("deepseek-r1:32b", "32B", 19.0, "deepseek", "DeepSeek R1 Distill 32B — High-end reasoning & complex problems", 32768, ["reasoning", "code", "math"], ["reasoning", "large"])
|
|
67
|
+
_add("deepseek-r1:70b", "70B", 42.0, "deepseek", "DeepSeek R1 Distill 70B — Top-tier open reasoning model", 32768, ["reasoning", "code", "math"], ["reasoning", "large"])
|
|
68
|
+
_add("deepseek-coder:6.7b", "6.7B", 3.8, "deepseek", "DeepSeek Coder 6.7B — Efficient coding specialist", 16384, ["code"], ["coding"])
|
|
69
|
+
_add("deepseek-coder-v2:16b", "16B", 8.9, "deepseek", "DeepSeek Coder V2 16B (MoE) — Multi-language coding engine", 32768, ["code", "chat"], ["coding"])
|
|
70
|
+
_add("deepseek-v3:671b", "671B", 400.0, "deepseek", "DeepSeek V3 671B (MoE) — Frontier flagship architecture", 65536, ["chat", "code", "reasoning"], ["large"])
|
|
71
|
+
|
|
72
|
+
# =====================================================================
|
|
73
|
+
# 4. GOOGLE GEMMA
|
|
74
|
+
# =====================================================================
|
|
75
|
+
_add("gemma3:1b", "1B", 0.8, "gemma", "Google Gemma 3 1B — Next-gen multimodal compact model", 32768, ["chat", "vision"], ["small", "vision"])
|
|
76
|
+
_add("gemma3:4b", "4B", 3.3, "gemma", "Google Gemma 3 4B — State-of-the-art multimodal lightweight model", 32768, ["chat", "vision", "code"], ["popular", "vision", "small"])
|
|
77
|
+
_add("gemma3:12b", "12B", 8.1, "gemma", "Google Gemma 3 12B — Advanced multimodal reasoning", 32768, ["chat", "vision", "code"], ["popular", "vision"])
|
|
78
|
+
_add("gemma3:27b", "27B", 17.0, "gemma", "Google Gemma 3 27B — High-capacity multimodal reasoning", 32768, ["chat", "vision", "reasoning"], ["large", "vision"])
|
|
79
|
+
_add("gemma2:2b", "2B", 1.6, "gemma", "Google Gemma 2 2B — High-efficiency on-device text generator", 8192, ["chat"], ["small"])
|
|
80
|
+
_add("gemma2:9b", "9B", 5.4, "gemma", "Google Gemma 2 9B — Outstanding performance-per-parameter", 8192, ["chat", "code"], ["popular"])
|
|
81
|
+
_add("gemma2:27b", "27B", 16.0, "gemma", "Google Gemma 2 27B — Powerful analytical text model", 8192, ["chat", "reasoning"], ["large"])
|
|
82
|
+
_add("codegemma:7b", "7B", 5.0, "gemma", "Google CodeGemma 7B — Code completion and synthesis", 8192, ["code"], ["coding"])
|
|
83
|
+
|
|
84
|
+
# =====================================================================
|
|
85
|
+
# 5. MISTRAL AI
|
|
86
|
+
# =====================================================================
|
|
87
|
+
_add("mistral:7b", "7B", 4.1, "mistral", "Mistral 7B — The classic high-performance 7B standard", 32768, ["chat", "code"], ["popular"])
|
|
88
|
+
_add("mistral-nemo:12b", "12B", 7.1, "mistral", "Mistral NeMo 12B — 128k context multilingual model with NVIDIA", 128000, ["chat", "code"], ["popular"])
|
|
89
|
+
_add("codestral:22b", "22B", 12.0, "mistral", "Mistral Codestral 22B — Fast 80+ language coding model", 32768, ["code"], ["coding", "popular"])
|
|
90
|
+
_add("mixtral:8x7b", "47B", 26.0, "mistral", "Mixtral 8x7B (MoE) — Fast sparse Mixture-of-Experts", 32768, ["chat", "code"], ["popular", "large"])
|
|
91
|
+
_add("mixtral:8x22b", "141B", 80.0, "mistral", "Mixtral 8x22B (MoE) — High-end reasoning Mixture-of-Experts", 65536, ["chat", "code", "reasoning"], ["large"])
|
|
92
|
+
_add("mathstral:7b", "7B", 4.1, "mistral", "Mistral Mathstral 7B — Mathematical reasoning and science", 32768, ["math", "reasoning"], ["reasoning"])
|
|
93
|
+
|
|
94
|
+
# =====================================================================
|
|
95
|
+
# 6. MICROSOFT PHI
|
|
96
|
+
# =====================================================================
|
|
97
|
+
_add("phi4:14b", "14B", 9.1, "phi", "Microsoft Phi-4 14B — Premier synthetic reasoning & STEM benchmark leader", 16384, ["reasoning", "math", "code"], ["popular", "reasoning"])
|
|
98
|
+
_add("phi3.5:3.8b", "3.8B", 2.2, "phi", "Microsoft Phi-3.5 Mini 3.8B — 128k context high-efficiency model", 128000, ["chat", "code"], ["small", "popular"])
|
|
99
|
+
_add("phi3:14b", "14B", 7.9, "phi", "Microsoft Phi-3 Medium 14B — Analytical reasoning", 16384, ["chat", "reasoning"], ["popular"])
|
|
100
|
+
_add("phi3:3.8b", "3.8B", 2.2, "phi", "Microsoft Phi-3 Mini 3.8B — Compact logic model", 8192, ["chat"], ["small"])
|
|
101
|
+
|
|
102
|
+
# =====================================================================
|
|
103
|
+
# 7. VISION & MULTIMODAL
|
|
104
|
+
# =====================================================================
|
|
105
|
+
_add("llava:7b", "7B", 4.7, "vision", "LLaVA 1.5 7B — Visual question answering and image inspection", 4096, ["vision", "chat"], ["vision", "popular"])
|
|
106
|
+
_add("llava:13b", "13B", 8.0, "vision", "LLaVA 1.5 13B — High-detail image understanding", 4096, ["vision", "chat"], ["vision"])
|
|
107
|
+
_add("llava-llama3:8b", "8B", 5.0, "vision", "LLaVA Llama-3 8B — Multimodal assistant on Llama 3", 8192, ["vision", "chat"], ["vision", "popular"])
|
|
108
|
+
_add("minicpm-v:8b", "8B", 5.5, "vision", "MiniCPM-V 2.6 8B — Outstanding OCR & high-res image analysis", 8192, ["vision", "chat"], ["vision"])
|
|
109
|
+
_add("moondream:1.8b", "1.8B", 1.0, "vision", "Moondream 2 1.8B — Fast edge-ready visual model", 4096, ["vision"], ["vision", "small"])
|
|
110
|
+
_add("bakllava:7b", "7B", 4.7, "vision", "BakLLaVA 7B — Mistral-backed visual assistant", 4096, ["vision"], ["vision"])
|
|
111
|
+
|
|
112
|
+
# =====================================================================
|
|
113
|
+
# 8. SMALL, FAST & ON-DEVICE
|
|
114
|
+
# =====================================================================
|
|
115
|
+
_add("smollm2:1.7b", "1.7B", 1.0, "smollm", "SmolLM2 1.7B — HuggingFace curated small model for edge devices", 8192, ["chat", "code"], ["small"])
|
|
116
|
+
_add("smollm2:360m", "360M", 0.3, "smollm", "SmolLM2 360M — Ultra-compact local language model", 8192, ["chat"], ["small"])
|
|
117
|
+
_add("smollm2:135m", "135M", 0.15, "smollm", "SmolLM2 135M — Micro test model with near-zero memory footprint", 2048, ["chat"], ["small"])
|
|
118
|
+
_add("tinyllama:1.1b", "1.1B", 0.6, "other", "TinyLlama 1.1B — 3T token trained compact architecture", 2048, ["chat"], ["small"])
|
|
119
|
+
_add("orca-mini:3b", "3B", 1.9, "other", "Orca Mini 3B — Microsoft Orca dataset instruction tuned", 4096, ["chat"], ["small"])
|
|
120
|
+
_add("granite3.1:2b", "2B", 1.3, "granite", "IBM Granite 3.1 2B — Enterprise small language model", 8192, ["chat", "code"], ["small"])
|
|
121
|
+
_add("granite3.1:8b", "8B", 4.9, "granite", "IBM Granite 3.1 8B — Enterprise general and tool-use model", 8192, ["chat", "code"], ["popular"])
|
|
122
|
+
|
|
123
|
+
# =====================================================================
|
|
124
|
+
# 9. SPECIALIZED CODING & ENTERPRISE
|
|
125
|
+
# =====================================================================
|
|
126
|
+
_add("codellama:7b", "7B", 3.8, "codellama", "CodeLlama 7B — Meta coding specialist", 16384, ["code"], ["coding"])
|
|
127
|
+
_add("codellama:13b", "13B", 7.4, "codellama", "CodeLlama 13B — Medium-footprint coding model", 16384, ["code"], ["coding"])
|
|
128
|
+
_add("codellama:34b", "34B", 19.0, "codellama", "CodeLlama 34B — High accuracy code completion", 16384, ["code"], ["coding", "large"])
|
|
129
|
+
_add("starcoder2:7b", "7B", 4.0, "starcoder", "StarCoder2 7B — BigCode consortium model for 600+ languages", 16384, ["code"], ["coding"])
|
|
130
|
+
_add("starcoder2:15b", "15B", 9.0, "starcoder", "StarCoder2 15B — High precision code assistant", 16384, ["code"], ["coding"])
|
|
131
|
+
_add("sqlcoder:15b", "15B", 8.5, "other", "Defog SQLCoder 15B — Natural language to SQL query engine", 4096, ["code", "sql"], ["coding"])
|
|
132
|
+
_add("command-r:35b", "35B", 19.0, "cohere", "Cohere Command R 35B — Optimized for RAG and tool execution", 128000, ["chat", "rag"], ["popular", "large"])
|
|
133
|
+
_add("command-r-plus:104b", "104B", 60.0, "cohere", "Cohere Command R+ 104B — Frontier enterprise RAG model", 128000, ["chat", "rag", "reasoning"], ["large"])
|
|
134
|
+
|
|
135
|
+
# =====================================================================
|
|
136
|
+
# 10. EMBEDDINGS & RETRIEVAL (RAG)
|
|
137
|
+
# =====================================================================
|
|
138
|
+
_add("nomic-embed-text:latest", "137M", 0.3, "nomic", "Nomic Embed Text — 8192 context high-quality text embedding", 8192, ["embedding"], ["embedding", "small"])
|
|
139
|
+
_add("bge-m3:latest", "567M", 1.2, "bge", "BAAI BGE-M3 — Multilingual, multi-granularity dense/sparse embedding", 8192, ["embedding"], ["embedding", "small"])
|
|
140
|
+
_add("all-minilm:latest", "33M", 0.1, "minilm", "All-MiniLM L6 v2 — Ultra-fast embedding model for semantic search", 512, ["embedding"], ["embedding", "small"])
|
|
141
|
+
_add("mxbai-embed-large:latest", "335M", 0.7, "mxbai", "MixedBread Embed Large — Top MTEB benchmark embedding model", 512, ["embedding"], ["embedding", "small"])
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Dynamic local model registry (persisted or populated from Ollama API)
|
|
145
|
+
DYNAMIC_REGISTRY: Dict[str, Dict[str, Any]] = {}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def register_custom_model(model_dict: Dict[str, Any]):
|
|
149
|
+
"""Register a custom or dynamically discovered model."""
|
|
150
|
+
name = model_dict.get("name")
|
|
151
|
+
if not name:
|
|
152
|
+
return
|
|
153
|
+
DYNAMIC_REGISTRY[name] = {
|
|
154
|
+
"name": name,
|
|
155
|
+
"params": model_dict.get("params", "Unknown"),
|
|
156
|
+
"size_gb": float(model_dict.get("size_gb", 4.0)),
|
|
157
|
+
"family": model_dict.get("family", "custom"),
|
|
158
|
+
"desc": model_dict.get("desc", f"Local model {name}"),
|
|
159
|
+
"context": int(model_dict.get("context", 8192)),
|
|
160
|
+
"caps": model_dict.get("caps", ["chat"]),
|
|
161
|
+
"categories": model_dict.get("categories", ["custom"]),
|
|
162
|
+
"installed": bool(model_dict.get("installed", False)),
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def register_installed_models(installed_names: List[str]):
|
|
167
|
+
"""Ensure any locally installed model in Ollama is present in the catalog."""
|
|
168
|
+
for raw_name in installed_names:
|
|
169
|
+
name = raw_name.strip()
|
|
170
|
+
if not name:
|
|
171
|
+
continue
|
|
172
|
+
# If already in curated catalog, mark as installed in memory
|
|
173
|
+
existing = get_model(name)
|
|
174
|
+
if not existing:
|
|
175
|
+
# Estimate size / params from tag if possible
|
|
176
|
+
params = "Unknown"
|
|
177
|
+
size_gb = 4.0
|
|
178
|
+
if ":" in name:
|
|
179
|
+
tag = name.split(":")[-1].lower()
|
|
180
|
+
if tag.endswith("b") and tag[:-1].replace(".", "").isdigit():
|
|
181
|
+
params = tag.upper()
|
|
182
|
+
try:
|
|
183
|
+
num = float(tag[:-1])
|
|
184
|
+
size_gb = round(num * 0.65, 1)
|
|
185
|
+
except Exception:
|
|
186
|
+
size_gb = 4.0
|
|
187
|
+
|
|
188
|
+
register_custom_model({
|
|
189
|
+
"name": name,
|
|
190
|
+
"params": params,
|
|
191
|
+
"size_gb": size_gb,
|
|
192
|
+
"family": name.split(":")[0],
|
|
193
|
+
"desc": f"Installed Ollama model: {name}",
|
|
194
|
+
"context": 8192,
|
|
195
|
+
"caps": ["chat"],
|
|
196
|
+
"categories": ["installed"],
|
|
197
|
+
"installed": True,
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def all_models(include_dynamic: bool = True) -> List[Dict[str, Any]]:
|
|
202
|
+
"""Return all catalog models, combining curated entries and dynamic/installed models."""
|
|
203
|
+
combined: Dict[str, Dict[str, Any]] = {}
|
|
204
|
+
for m in CURATED_CATALOG:
|
|
205
|
+
combined[m["name"]] = dict(m)
|
|
206
|
+
|
|
207
|
+
if include_dynamic:
|
|
208
|
+
for name, m in DYNAMIC_REGISTRY.items():
|
|
209
|
+
if name in combined:
|
|
210
|
+
combined[name].update(m)
|
|
211
|
+
else:
|
|
212
|
+
combined[name] = dict(m)
|
|
213
|
+
|
|
214
|
+
return list(combined.values())
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# Compatibility alias for legacy callers
|
|
218
|
+
CATALOG = all_models()
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def categories() -> List[str]:
|
|
222
|
+
"""Return list of standard navigation categories."""
|
|
223
|
+
return ["all", "popular", "coding", "reasoning", "vision", "small", "large", "embedding"]
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def search_models(
|
|
227
|
+
query: str = "",
|
|
228
|
+
category: Optional[str] = None,
|
|
229
|
+
family: Optional[str] = None,
|
|
230
|
+
cap: Optional[str] = None,
|
|
231
|
+
) -> List[Dict[str, Any]]:
|
|
232
|
+
"""Search models with optional category, family, and capability filters."""
|
|
233
|
+
q = (query or "").lower().strip()
|
|
234
|
+
cat = (category or "").lower().strip()
|
|
235
|
+
out = []
|
|
236
|
+
|
|
237
|
+
for m in all_models(include_dynamic=True):
|
|
238
|
+
if family and m.get("family") != family:
|
|
239
|
+
continue
|
|
240
|
+
if cap and cap not in m.get("caps", []):
|
|
241
|
+
continue
|
|
242
|
+
if cat and cat != "all":
|
|
243
|
+
cats = [c.lower() for c in m.get("categories", [])]
|
|
244
|
+
# Match either direct category list or family/caps
|
|
245
|
+
if cat not in cats and cat not in m.get("caps", []) and cat != m.get("family"):
|
|
246
|
+
continue
|
|
247
|
+
if q:
|
|
248
|
+
name_match = q in m.get("name", "").lower()
|
|
249
|
+
fam_match = q in m.get("family", "").lower()
|
|
250
|
+
desc_match = q in m.get("desc", "").lower()
|
|
251
|
+
params_match = q in m.get("params", "").lower()
|
|
252
|
+
if not (name_match or fam_match or desc_match or params_match):
|
|
253
|
+
continue
|
|
254
|
+
out.append(m)
|
|
255
|
+
|
|
256
|
+
return out
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def get_model(name: str) -> Optional[Dict[str, Any]]:
|
|
260
|
+
"""Look up a model by exact name or base prefix."""
|
|
261
|
+
if not name:
|
|
262
|
+
return None
|
|
263
|
+
name_clean = name.strip()
|
|
264
|
+
|
|
265
|
+
# Check dynamic first
|
|
266
|
+
if name_clean in DYNAMIC_REGISTRY:
|
|
267
|
+
return dict(DYNAMIC_REGISTRY[name_clean])
|
|
268
|
+
|
|
269
|
+
# Check curated exact match
|
|
270
|
+
for m in CURATED_CATALOG:
|
|
271
|
+
if m["name"] == name_clean:
|
|
272
|
+
return dict(m)
|
|
273
|
+
|
|
274
|
+
# Check if tag omitted (e.g. "qwen2.5-coder" matches "qwen2.5-coder:7b" or latest)
|
|
275
|
+
for m in CURATED_CATALOG:
|
|
276
|
+
if m["name"].startswith(name_clean + ":") or m["name"] == f"{name_clean}:latest":
|
|
277
|
+
return dict(m)
|
|
278
|
+
|
|
279
|
+
return None
|