vector-inspector 0.3.7__tar.gz → 0.3.9__tar.gz

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.
Files changed (82) hide show
  1. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/PKG-INFO +38 -9
  2. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/README.md +37 -8
  3. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/pyproject.toml +1 -1
  4. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/pgvector_connection.py +26 -1
  5. vector_inspector-0.3.9/src/vector_inspector/core/provider_factory.py +97 -0
  6. vector_inspector-0.3.9/src/vector_inspector/extensions/__init__.py +105 -0
  7. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/settings_service.py +76 -0
  8. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/splash_window.py +14 -2
  9. vector_inspector-0.3.9/src/vector_inspector/ui/controllers/__init__.py +1 -0
  10. vector_inspector-0.3.9/src/vector_inspector/ui/controllers/connection_controller.py +177 -0
  11. vector_inspector-0.3.9/src/vector_inspector/ui/dialogs/settings_dialog.py +124 -0
  12. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/main_window.py +222 -332
  13. vector_inspector-0.3.9/src/vector_inspector/ui/main_window_shell.py +106 -0
  14. vector_inspector-0.3.9/src/vector_inspector/ui/services/__init__.py +1 -0
  15. vector_inspector-0.3.9/src/vector_inspector/ui/services/dialog_service.py +113 -0
  16. vector_inspector-0.3.9/src/vector_inspector/ui/tabs.py +64 -0
  17. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/metadata_view.py +45 -0
  18. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/search_view.py +146 -13
  19. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/__init__.py +0 -0
  20. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/__main__.py +0 -0
  21. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/config/__init__.py +0 -0
  22. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/config/known_embedding_models.json +0 -0
  23. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/__init__.py +0 -0
  24. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/cache_manager.py +0 -0
  25. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connection_manager.py +0 -0
  26. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/__init__.py +0 -0
  27. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/base_connection.py +0 -0
  28. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/chroma_connection.py +0 -0
  29. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/pinecone_connection.py +0 -0
  30. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/qdrant_connection.py +0 -0
  31. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/qdrant_helpers/__init__.py +0 -0
  32. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/qdrant_helpers/qdrant_embedding_resolver.py +0 -0
  33. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/qdrant_helpers/qdrant_filter_builder.py +0 -0
  34. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/connections/template_connection.py +0 -0
  35. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_providers/__init__.py +0 -0
  36. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_providers/base_provider.py +0 -0
  37. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_providers/clip_provider.py +0 -0
  38. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_providers/provider_factory.py +0 -0
  39. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_providers/sentence_transformer_provider.py +0 -0
  40. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/embedding_utils.py +0 -0
  41. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/logging.py +0 -0
  42. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/core/model_registry.py +0 -0
  43. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/main.py +0 -0
  44. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/__init__.py +0 -0
  45. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/backup_helpers.py +0 -0
  46. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/backup_restore_service.py +0 -0
  47. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/credential_service.py +0 -0
  48. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/filter_service.py +0 -0
  49. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/import_export_service.py +0 -0
  50. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/profile_service.py +0 -0
  51. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/update_service.py +0 -0
  52. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/services/visualization_service.py +0 -0
  53. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/__init__.py +0 -0
  54. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/__init__.py +0 -0
  55. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/backup_restore_dialog.py +0 -0
  56. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/connection_manager_panel.py +0 -0
  57. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/filter_builder.py +0 -0
  58. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/item_dialog.py +0 -0
  59. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/loading_dialog.py +0 -0
  60. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/profile_manager_panel.py +0 -0
  61. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/components/update_details_dialog.py +0 -0
  62. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/dialogs/__init__.py +0 -0
  63. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/dialogs/cross_db_migration.py +0 -0
  64. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/dialogs/embedding_config_dialog.py +0 -0
  65. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/dialogs/provider_type_dialog.py +0 -0
  66. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/__init__.py +0 -0
  67. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/collection_browser.py +0 -0
  68. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/connection_view.py +0 -0
  69. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/info_panel.py +0 -0
  70. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/ui/views/visualization_view.py +0 -0
  71. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/utils/__init__.py +0 -0
  72. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/utils/lazy_imports.py +0 -0
  73. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/src/vector_inspector/utils/version.py +0 -0
  74. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_backup_helpers.py +0 -0
  75. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_backup_restore_service.py +0 -0
  76. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_chroma_connection.py +0 -0
  77. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_filter_service.py +0 -0
  78. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_pgvector_connection.py +0 -0
  79. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_pinecone_connection.py +0 -0
  80. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_qdrant_connection.py +0 -0
  81. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_runner.py +0 -0
  82. {vector_inspector-0.3.7 → vector_inspector-0.3.9}/tests/test_settings_service.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vector-inspector
3
- Version: 0.3.7
3
+ Version: 0.3.9
4
4
  Summary: A comprehensive desktop application for visualizing, querying, and managing vector database data
5
5
  Author-Email: Anthony Dawson <anthonypdawson+github@gmail.com>
6
6
  License: MIT
@@ -31,13 +31,40 @@ Requires-Dist: pgvector>=0.4.2
31
31
  Description-Content-Type: text/markdown
32
32
 
33
33
  # Latest updates
34
- * Added automatic update notification system:
35
- - Checks for new releases on GitHub once per launch/day
36
- - Shows update indicator in the status bar and Help menu
37
- - Clickable indicator opens a modal with release notes and update instructions
38
- - Manual Check for Update in Help menu
39
- - Version detection now uses installed package metadata for accuracy
40
- * Fixed bug where data browser row disappeared post-edit
34
+
35
+ - Major refactor and studio-ready architecture
36
+ - Refactored main window into modular components (InspectorShell, ProviderFactory, DialogService, ConnectionController, InspectorTabs)
37
+ - MainWindow is reusable as a widget; tab system is pluggable so Studio can extend or override tabs
38
+
39
+ - Data browser improvements
40
+ - Added Generate embeddings on edit (persisted per user)
41
+
42
+ - Settings / Preferences
43
+ - SettingsService persists preferences and exposes typed accessors (breadcrumb, search defaults, auto-embed, window geometry)
44
+ - SettingsService emits a setting_changed Qt signal so UI reacts immediately
45
+ - SettingsDialog (modal) added with add_section API and hook integration for extension panels
46
+ - Breadcrumb controls moved out of core so Pro (Vector Studio) injects them via the settings_panel_hook
47
+
48
+ - Extension hook for settings panels
49
+ - *settings_panel_hook* added to *vector_inspector.extensions*; Vector Studio registers breadcrumb controls at startup
50
+
51
+ - Breadcrumb and UI improvements
52
+ - Breadcrumb label now elides long trails (left/middle) and shows full trail on hover
53
+ - SearchView supports runtime elide-mode changes and responds to settings signals
54
+
55
+ - Window geometry persistence
56
+ - Main window saves/restores geometry when window.restore_geometry is enabled
57
+
58
+ - Pro (Vector Studio) features
59
+ - *Search Similar* (Pro): right-click any row in Data Browser or Search Results to run a vector-to-vector similarity search
60
+ - *table_context_menu* handler hardened for many embedding/id formats and includes fallbacks
61
+ - Vector Studio injects breadcrumb controls into Settings dialog via *settings_panel_hook*
62
+
63
+ - Tests and CI
64
+ - Added *tests/test_settings_injection.py* to assert settings panel hook registration
65
+ - Updated context-menu tests to use *log_info* and *assert* for pytest
66
+ - Local test run: 5 tests passed; GUI-heavy suite ~9s due to PySide6 startup
67
+
41
68
  ---
42
69
 
43
70
  # Vector Inspector
@@ -45,7 +72,7 @@ Description-Content-Type: text/markdown
45
72
  > **Disclaimer:** This tool is currently under active development and is **not production ready**. Not all features have been thoroughly tested and code is released frequently. Use with caution in critical or production environments.
46
73
 
47
74
  [![CI](https://github.com/anthonypdawson/vector-inspector/actions/workflows/ci-tests.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/ci-tests.yml)
48
- [![Publish](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish.yml)
75
+ [![Publish](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish%20copy.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish%20copy.yml)
49
76
 
50
77
  [![PyPI Version](https://img.shields.io/pypi/v/vector-inspector.svg?cacheSeconds=300)](https://pypi.org/project/vector-inspector/)
51
78
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/vector-inspector?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/vector-inspector)
@@ -74,6 +101,8 @@ Vector Inspector bridges the gap between vector databases and user-friendly data
74
101
 
75
102
  ## Key Features
76
103
 
104
+ > **Note:** Some features listed below may be not started or currently in progress.
105
+
77
106
  ### 1. **Multi-Provider Support**
78
107
  - Connect to vector databases:
79
108
  - ChromaDB (persistent local storage)
@@ -1,11 +1,38 @@
1
1
  # Latest updates
2
- * Added automatic update notification system:
3
- - Checks for new releases on GitHub once per launch/day
4
- - Shows update indicator in the status bar and Help menu
5
- - Clickable indicator opens a modal with release notes and update instructions
6
- - Manual Check for Update in Help menu
7
- - Version detection now uses installed package metadata for accuracy
8
- * Fixed bug where data browser row disappeared post-edit
2
+
3
+ - Major refactor and studio-ready architecture
4
+ - Refactored main window into modular components (InspectorShell, ProviderFactory, DialogService, ConnectionController, InspectorTabs)
5
+ - MainWindow is reusable as a widget; tab system is pluggable so Studio can extend or override tabs
6
+
7
+ - Data browser improvements
8
+ - Added Generate embeddings on edit (persisted per user)
9
+
10
+ - Settings / Preferences
11
+ - SettingsService persists preferences and exposes typed accessors (breadcrumb, search defaults, auto-embed, window geometry)
12
+ - SettingsService emits a setting_changed Qt signal so UI reacts immediately
13
+ - SettingsDialog (modal) added with add_section API and hook integration for extension panels
14
+ - Breadcrumb controls moved out of core so Pro (Vector Studio) injects them via the settings_panel_hook
15
+
16
+ - Extension hook for settings panels
17
+ - *settings_panel_hook* added to *vector_inspector.extensions*; Vector Studio registers breadcrumb controls at startup
18
+
19
+ - Breadcrumb and UI improvements
20
+ - Breadcrumb label now elides long trails (left/middle) and shows full trail on hover
21
+ - SearchView supports runtime elide-mode changes and responds to settings signals
22
+
23
+ - Window geometry persistence
24
+ - Main window saves/restores geometry when window.restore_geometry is enabled
25
+
26
+ - Pro (Vector Studio) features
27
+ - *Search Similar* (Pro): right-click any row in Data Browser or Search Results to run a vector-to-vector similarity search
28
+ - *table_context_menu* handler hardened for many embedding/id formats and includes fallbacks
29
+ - Vector Studio injects breadcrumb controls into Settings dialog via *settings_panel_hook*
30
+
31
+ - Tests and CI
32
+ - Added *tests/test_settings_injection.py* to assert settings panel hook registration
33
+ - Updated context-menu tests to use *log_info* and *assert* for pytest
34
+ - Local test run: 5 tests passed; GUI-heavy suite ~9s due to PySide6 startup
35
+
9
36
  ---
10
37
 
11
38
  # Vector Inspector
@@ -13,7 +40,7 @@
13
40
  > **Disclaimer:** This tool is currently under active development and is **not production ready**. Not all features have been thoroughly tested and code is released frequently. Use with caution in critical or production environments.
14
41
 
15
42
  [![CI](https://github.com/anthonypdawson/vector-inspector/actions/workflows/ci-tests.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/ci-tests.yml)
16
- [![Publish](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish.yml)
43
+ [![Publish](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish%20copy.yml/badge.svg?branch=master)](https://github.com/anthonypdawson/vector-inspector/actions/workflows/publish%20copy.yml)
17
44
 
18
45
  [![PyPI Version](https://img.shields.io/pypi/v/vector-inspector.svg?cacheSeconds=300)](https://pypi.org/project/vector-inspector/)
19
46
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/vector-inspector?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/vector-inspector)
@@ -42,6 +69,8 @@ Vector Inspector bridges the gap between vector databases and user-friendly data
42
69
 
43
70
  ## Key Features
44
71
 
72
+ > **Note:** Some features listed below may be not started or currently in progress.
73
+
45
74
  ### 1. **Multi-Provider Support**
46
75
  - Connect to vector databases:
47
76
  - ChromaDB (persistent local storage)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vector-inspector"
3
- version = "0.3.7"
3
+ version = "0.3.9"
4
4
  description = "A comprehensive desktop application for visualizing, querying, and managing vector database data"
5
5
  authors = [
6
6
  { name = "Anthony Dawson", email = "anthonypdawson+github@gmail.com" },
@@ -5,6 +5,8 @@ import json
5
5
  import psycopg2
6
6
  from psycopg2 import sql
7
7
 
8
+ from vector_inspector.core.logging import log_info
9
+
8
10
  ## No need to import register_vector; pgvector extension is enabled at table creation
9
11
  from vector_inspector.core.connections.base_connection import VectorDBConnection
10
12
  from vector_inspector.core.logging import log_error, log_info
@@ -1043,12 +1045,35 @@ class PgVectorConnection(VectorDBConnection):
1043
1045
  Returns:
1044
1046
  List of floats
1045
1047
  """
1048
+ log_info("[pgvector] _parse_vector raw value: %r (type: %s)", vector_str, type(vector_str))
1046
1049
  if isinstance(vector_str, list):
1050
+ log_info("[pgvector] _parse_vector: already list, len=%d", len(vector_str))
1047
1051
  return vector_str
1052
+ # Handle numpy arrays
1053
+ try:
1054
+ import numpy as np
1055
+
1056
+ if isinstance(vector_str, np.ndarray):
1057
+ log_info("[pgvector] _parse_vector: numpy array, shape=%s", vector_str.shape)
1058
+ return vector_str.tolist()
1059
+ except ImportError:
1060
+ pass
1048
1061
  if isinstance(vector_str, str):
1049
1062
  # Remove brackets and split by comma
1050
1063
  vector_str = vector_str.strip("[]")
1051
- return [float(x) for x in vector_str.split(",")]
1064
+ if not vector_str:
1065
+ log_info("[pgvector] _parse_vector: empty string after strip")
1066
+ return []
1067
+ try:
1068
+ parsed = [float(x) for x in vector_str.split(",")]
1069
+ log_info("[pgvector] _parse_vector: parsed list of len %d", len(parsed))
1070
+ return parsed
1071
+ except Exception as e:
1072
+ log_info(
1073
+ "[pgvector] _parse_vector: failed to parse '%s' with error: %s", vector_str, e
1074
+ )
1075
+ return []
1076
+ log_info("[pgvector] _parse_vector: unhandled type %s, returning []", type(vector_str))
1052
1077
  return []
1053
1078
 
1054
1079
  def compute_embeddings_for_documents(
@@ -0,0 +1,97 @@
1
+ """Factory for creating vector database connections from provider configs."""
2
+
3
+ from typing import Dict, Any
4
+ from vector_inspector.core.connections.base_connection import VectorDBConnection
5
+ from vector_inspector.core.connections.chroma_connection import ChromaDBConnection
6
+ from vector_inspector.core.connections.qdrant_connection import QdrantConnection
7
+ from vector_inspector.core.connections.pinecone_connection import PineconeConnection
8
+ from vector_inspector.core.connections.pgvector_connection import PgVectorConnection
9
+
10
+
11
+ class ProviderFactory:
12
+ """Factory for creating database connections from configuration."""
13
+
14
+ @staticmethod
15
+ def create(
16
+ provider: str, config: Dict[str, Any], credentials: Dict[str, Any] = None
17
+ ) -> VectorDBConnection:
18
+ """Create a connection object for the specified provider.
19
+
20
+ Args:
21
+ provider: Provider type (chromadb, qdrant, pinecone, pgvector)
22
+ config: Provider-specific configuration
23
+ credentials: Optional credentials (API keys, passwords, etc.)
24
+
25
+ Returns:
26
+ VectorDBConnection instance
27
+
28
+ Raises:
29
+ ValueError: If provider is unsupported or configuration is invalid
30
+ """
31
+ credentials = credentials or {}
32
+
33
+ if provider == "chromadb":
34
+ return ProviderFactory._create_chroma(config, credentials)
35
+ elif provider == "qdrant":
36
+ return ProviderFactory._create_qdrant(config, credentials)
37
+ elif provider == "pinecone":
38
+ return ProviderFactory._create_pinecone(config, credentials)
39
+ elif provider == "pgvector":
40
+ return ProviderFactory._create_pgvector(config, credentials)
41
+ else:
42
+ raise ValueError(f"Unsupported provider: {provider}")
43
+
44
+ @staticmethod
45
+ def _create_chroma(config: Dict[str, Any], credentials: Dict[str, Any]) -> ChromaDBConnection:
46
+ """Create a ChromaDB connection."""
47
+ conn_type = config.get("type")
48
+
49
+ if conn_type == "persistent":
50
+ return ChromaDBConnection(path=config.get("path"))
51
+ elif conn_type == "http":
52
+ return ChromaDBConnection(host=config.get("host"), port=config.get("port"))
53
+ else: # ephemeral
54
+ return ChromaDBConnection()
55
+
56
+ @staticmethod
57
+ def _create_qdrant(config: Dict[str, Any], credentials: Dict[str, Any]) -> QdrantConnection:
58
+ """Create a Qdrant connection."""
59
+ conn_type = config.get("type")
60
+ api_key = credentials.get("api_key")
61
+
62
+ if conn_type == "persistent":
63
+ return QdrantConnection(path=config.get("path"))
64
+ elif conn_type == "http":
65
+ return QdrantConnection(
66
+ host=config.get("host"), port=config.get("port"), api_key=api_key
67
+ )
68
+ else: # ephemeral
69
+ return QdrantConnection()
70
+
71
+ @staticmethod
72
+ def _create_pinecone(config: Dict[str, Any], credentials: Dict[str, Any]) -> PineconeConnection:
73
+ """Create a Pinecone connection."""
74
+ api_key = credentials.get("api_key")
75
+ if not api_key:
76
+ raise ValueError("Pinecone requires an API key")
77
+
78
+ return PineconeConnection(api_key=api_key)
79
+
80
+ @staticmethod
81
+ def _create_pgvector(config: Dict[str, Any], credentials: Dict[str, Any]) -> PgVectorConnection:
82
+ """Create a PgVector/Postgres connection."""
83
+ conn_type = config.get("type")
84
+
85
+ if conn_type == "http":
86
+ host = config.get("host", "localhost")
87
+ port = int(config.get("port", 5432))
88
+ database = config.get("database")
89
+ user = config.get("user")
90
+ # Prefer password from credentials
91
+ password = credentials.get("password")
92
+
93
+ return PgVectorConnection(
94
+ host=host, port=port, database=database, user=user, password=password
95
+ )
96
+
97
+ raise ValueError("Unsupported connection type for PgVector profile")
@@ -0,0 +1,105 @@
1
+ """Extension points for Vector Inspector.
2
+
3
+ This module provides hooks and callbacks that allow pro versions
4
+ or plugins to extend core functionality without modifying the base code.
5
+ """
6
+
7
+ from typing import Any, ClassVar
8
+ from collections.abc import Callable
9
+ from PySide6.QtWidgets import QMenu, QTableWidget
10
+
11
+
12
+ class TableContextMenuHook:
13
+ """Hook for adding custom context menu items to table widgets."""
14
+
15
+ _handlers: ClassVar[list[Callable]] = []
16
+
17
+ @classmethod
18
+ def register(cls, handler: Callable):
19
+ """Register a context menu handler.
20
+
21
+ Args:
22
+ handler: Callable that takes (menu: QMenu, table: QTableWidget, row: int, data: Dict)
23
+ and adds menu items to the menu.
24
+ """
25
+ if handler not in cls._handlers:
26
+ cls._handlers.append(handler)
27
+
28
+ @classmethod
29
+ def unregister(cls, handler: Callable):
30
+ """Unregister a context menu handler."""
31
+ if handler in cls._handlers:
32
+ cls._handlers.remove(handler)
33
+
34
+ @classmethod
35
+ def trigger(
36
+ cls,
37
+ menu: QMenu,
38
+ table: QTableWidget,
39
+ row: int,
40
+ data: dict[str, Any] | None = None,
41
+ ):
42
+ """Trigger all registered handlers.
43
+
44
+ Args:
45
+ menu: The QMenu to add items to
46
+ table: The QTableWidget that was right-clicked
47
+ row: The row number that was clicked
48
+ data: Optional data dictionary with context (ids, documents, metadatas, etc.)
49
+ """
50
+ for handler in cls._handlers:
51
+ try:
52
+ handler(menu, table, row, data)
53
+ except Exception as e:
54
+ # Log but don't break if a handler fails
55
+ from vector_inspector.core.logging import log_error
56
+
57
+ log_error("Context menu handler error: %s", e)
58
+
59
+ @classmethod
60
+ def clear(cls):
61
+ """Clear all registered handlers."""
62
+ cls._handlers.clear()
63
+
64
+
65
+ # Global singleton instance
66
+ table_context_menu_hook = TableContextMenuHook()
67
+
68
+
69
+ class SettingsPanelHook:
70
+ """Hook for adding custom sections to the Settings/Preferences dialog."""
71
+
72
+ _handlers: ClassVar[list[Callable]] = []
73
+
74
+ @classmethod
75
+ def register(cls, handler: Callable):
76
+ """Register a settings panel provider.
77
+
78
+ Handler signature: (parent_layout, settings_service, dialog)
79
+ where `parent_layout` is a QLayout the handler can add widgets to.
80
+ """
81
+ if handler not in cls._handlers:
82
+ cls._handlers.append(handler)
83
+
84
+ @classmethod
85
+ def unregister(cls, handler: Callable):
86
+ if handler in cls._handlers:
87
+ cls._handlers.remove(handler)
88
+
89
+ @classmethod
90
+ def trigger(cls, parent_layout, settings_service, dialog=None):
91
+ for handler in cls._handlers:
92
+ try:
93
+ handler(parent_layout, settings_service, dialog)
94
+ except Exception as e:
95
+ from vector_inspector.core.logging import log_error
96
+
97
+ log_error("Settings panel handler error: %s", e)
98
+
99
+ @classmethod
100
+ def clear(cls):
101
+ cls._handlers.clear()
102
+
103
+
104
+ # Global singleton instance
105
+ settings_panel_hook = SettingsPanelHook()
@@ -1,6 +1,8 @@
1
1
  """Service for persisting application settings."""
2
2
 
3
3
  import json
4
+ import base64
5
+ from PySide6.QtCore import QObject, Signal
4
6
  from pathlib import Path
5
7
  from typing import Dict, Any, Optional, List
6
8
  from vector_inspector.core.cache_manager import invalidate_cache_on_settings_change
@@ -12,6 +14,18 @@ class SettingsService:
12
14
 
13
15
  def __init__(self):
14
16
  """Initialize settings service."""
17
+
18
+ # Expose a shared QObject-based signal emitter so UI can react to
19
+ # settings changes without polling.
20
+ class _Signals(QObject):
21
+ setting_changed = Signal(str, object)
22
+
23
+ # singleton-like per-process signals instance
24
+ try:
25
+ self.signals
26
+ except Exception:
27
+ self.signals = _Signals()
28
+
15
29
  self.settings_dir = Path.home() / ".vector-inspector"
16
30
  self.settings_file = self.settings_dir / "settings.json"
17
31
  self.settings: Dict[str, Any] = {}
@@ -51,6 +65,62 @@ class SettingsService:
51
65
  """Get a setting value."""
52
66
  return self.settings.get(key, default)
53
67
 
68
+ # Convenience accessors for common settings
69
+ def get_breadcrumb_enabled(self) -> bool:
70
+ return bool(self.settings.get("breadcrumb.enabled", True))
71
+
72
+ def set_breadcrumb_enabled(self, enabled: bool):
73
+ self.set("breadcrumb.enabled", bool(enabled))
74
+
75
+ def get_breadcrumb_elide_mode(self) -> str:
76
+ return str(self.settings.get("breadcrumb.elide_mode", "left"))
77
+
78
+ def set_breadcrumb_elide_mode(self, mode: str):
79
+ if mode not in ("left", "middle"):
80
+ mode = "left"
81
+ self.set("breadcrumb.elide_mode", mode)
82
+
83
+ def get_default_n_results(self) -> int:
84
+ return int(self.settings.get("search.default_n_results", 10))
85
+
86
+ def set_default_n_results(self, n: int):
87
+ self.set("search.default_n_results", int(n))
88
+
89
+ def get_auto_generate_embeddings(self) -> bool:
90
+ return bool(self.settings.get("embeddings.auto_generate", True))
91
+
92
+ def set_auto_generate_embeddings(self, enabled: bool):
93
+ self.set("embeddings.auto_generate", bool(enabled))
94
+
95
+ def get_window_restore_geometry(self) -> bool:
96
+ return bool(self.settings.get("window.restore_geometry", True))
97
+
98
+ def set_window_restore_geometry(self, enabled: bool):
99
+ self.set("window.restore_geometry", bool(enabled))
100
+
101
+ def set_window_geometry(self, geometry_bytes: bytes):
102
+ """Save window geometry as base64 string."""
103
+ try:
104
+ if isinstance(geometry_bytes, str):
105
+ # assume base64 already
106
+ b64 = geometry_bytes
107
+ else:
108
+ b64 = base64.b64encode(bytes(geometry_bytes)).decode("ascii")
109
+ self.set("window.geometry", b64)
110
+ except Exception as e:
111
+ log_error("Failed to set window geometry: %s", e)
112
+
113
+ def get_window_geometry(self) -> Optional[bytes]:
114
+ """Return geometry bytes or None."""
115
+ try:
116
+ b64 = self.settings.get("window.geometry")
117
+ if not b64:
118
+ return None
119
+ return base64.b64decode(b64)
120
+ except Exception as e:
121
+ log_error("Failed to get window geometry: %s", e)
122
+ return None
123
+
54
124
  def get_cache_enabled(self) -> bool:
55
125
  """Get whether caching is enabled (default: True)."""
56
126
  return self.settings.get("cache_enabled", True)
@@ -74,6 +144,12 @@ class SettingsService:
74
144
  # Invalidate cache when settings change (only if cache is enabled)
75
145
  if key != "cache_enabled": # Don't invalidate when toggling cache itself
76
146
  invalidate_cache_on_settings_change()
147
+ # Emit change signal for UI/reactive components
148
+ try:
149
+ # Emit the raw python object (value) for convenience
150
+ self.signals.setting_changed.emit(key, value)
151
+ except Exception:
152
+ pass
77
153
 
78
154
  def clear(self):
79
155
  """Clear all settings."""
@@ -34,10 +34,22 @@ class SplashWindow(QDialog):
34
34
  layout.addWidget(github)
35
35
 
36
36
  # About info (reuse About dialog text)
37
- from vector_inspector.ui.main_window import get_about_html
37
+ from vector_inspector.utils.version import get_app_version
38
38
 
39
39
  about = QTextBrowser()
40
- about.setHtml(get_about_html())
40
+ version = get_app_version()
41
+ version_html = (
42
+ f"<h2>Vector Inspector {version}</h2>" if version else "<h2>Vector Inspector</h2>"
43
+ )
44
+ about_text = (
45
+ version_html + "<p>A comprehensive desktop application for visualizing, "
46
+ "querying, and managing multiple vector databases simultaneously.</p>"
47
+ '<p><a href="https://github.com/anthonypdawson/vector-inspector" style="color:#2980b9;">GitHub Project Page</a></p>'
48
+ "<hr />"
49
+ "<p>Built with PySide6</p>"
50
+ "<p><b>New:</b> Pinecone support!</p>"
51
+ )
52
+ about.setHtml(about_text)
41
53
  about.setOpenExternalLinks(True)
42
54
  about.setMaximumHeight(160)
43
55
  layout.addWidget(about)
@@ -0,0 +1 @@
1
+ """UI controllers for managing application logic."""