echo-vector 0.1.2__tar.gz → 1.0.4__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 (63) hide show
  1. echo_vector-1.0.4/.claude/commands/release.md +15 -0
  2. {echo_vector-0.1.2 → echo_vector-1.0.4}/PKG-INFO +1 -1
  3. echo_vector-1.0.4/echovector/__init__.py +18 -0
  4. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/cli/main.py +11 -1
  5. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/core.py +9 -2
  6. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/clap.py +8 -20
  7. {echo_vector-0.1.2 → echo_vector-1.0.4}/uv.lock +31 -36
  8. echo_vector-0.1.2/echovector/__init__.py +0 -7
  9. {echo_vector-0.1.2 → echo_vector-1.0.4}/.claude/settings.json +0 -0
  10. {echo_vector-0.1.2 → echo_vector-1.0.4}/.github/workflows/workflow.yml +0 -0
  11. {echo_vector-0.1.2 → echo_vector-1.0.4}/.gitignore +0 -0
  12. {echo_vector-0.1.2 → echo_vector-1.0.4}/.pre-commit-config.yaml +0 -0
  13. {echo_vector-0.1.2 → echo_vector-1.0.4}/.python-version +0 -0
  14. {echo_vector-0.1.2 → echo_vector-1.0.4}/CLAUDE.md +0 -0
  15. {echo_vector-0.1.2 → echo_vector-1.0.4}/Makefile +0 -0
  16. {echo_vector-0.1.2 → echo_vector-1.0.4}/README.md +0 -0
  17. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/api/__init__.py +0 -0
  18. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/api/server.py +0 -0
  19. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/audio/__init__.py +0 -0
  20. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/audio/chunker.py +0 -0
  21. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/audio/metadata.py +0 -0
  22. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/audio/processor.py +0 -0
  23. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/audio/streaming.py +0 -0
  24. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/cli/__init__.py +0 -0
  25. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/__init__.py +0 -0
  26. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/ast_model.py +0 -0
  27. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/base.py +0 -0
  28. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/cache.py +0 -0
  29. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/factory.py +0 -0
  30. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/hubert.py +0 -0
  31. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/local.py +0 -0
  32. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/wav2vec2.py +0 -0
  33. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/embeddings/whisper_enc.py +0 -0
  34. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/evaluation/__init__.py +0 -0
  35. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/evaluation/metrics.py +0 -0
  36. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/indexing/__init__.py +0 -0
  37. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/indexing/base.py +0 -0
  38. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/indexing/faiss_index.py +0 -0
  39. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/indexing/store.py +0 -0
  40. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/search/__init__.py +0 -0
  41. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/search/engine.py +0 -0
  42. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/search/filters.py +0 -0
  43. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/search/results.py +0 -0
  44. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/utils/__init__.py +0 -0
  45. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/utils/config.py +0 -0
  46. {echo_vector-0.1.2 → echo_vector-1.0.4}/echovector/utils/logging.py +0 -0
  47. {echo_vector-0.1.2 → echo_vector-1.0.4}/pyproject.toml +0 -0
  48. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/__init__.py +0 -0
  49. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/conftest.py +0 -0
  50. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/e2e/test_cli.py +0 -0
  51. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/fixtures/__init__.py +0 -0
  52. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/fixtures/audio_generators.py +0 -0
  53. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/integration/__init__.py +0 -0
  54. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/integration/test_integration.py +0 -0
  55. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/test_audio.mp3 +0 -0
  56. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_api.py +0 -0
  57. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_audio_processor.py +0 -0
  58. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_chunker.py +0 -0
  59. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_core.py +0 -0
  60. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_embeddings.py +0 -0
  61. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_faiss_index.py +0 -0
  62. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_results.py +0 -0
  63. {echo_vector-0.1.2 → echo_vector-1.0.4}/tests/unit/test_search_engine.py +0 -0
@@ -0,0 +1,15 @@
1
+ Run the full release pipeline: lint, typecheck, test, commit, tag, and push to trigger CI/CD publish to PyPI.
2
+
3
+ Usage: /release <version> (e.g. /release v0.1.3)
4
+
5
+ Steps:
6
+ 1. Verify a version argument was provided (format: vX.Y.Z)
7
+ 2. Run `uv run ruff format --check echovector/ tests/` and `uv run ruff check echovector/ tests/`
8
+ 3. Run `uv run mypy echovector/`
9
+ 4. Run `uv run pytest tests/ -m "not slow and not gpu" -q`
10
+ 5. If there are uncommitted changes, stage and commit them with message "release: $ARGUMENTS"
11
+ 6. Create git tag `$ARGUMENTS`
12
+ 7. Push the branch and the tag: `git push origin master` and `git push origin $ARGUMENTS`
13
+ 8. Report the tag that was pushed and remind the user to monitor CI at https://github.com/ahron-maslin/echo_vector/actions
14
+
15
+ If any step fails, stop and report the failure before proceeding.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echo_vector
3
- Version: 0.1.2
3
+ Version: 1.0.4
4
4
  Summary: Semantic text search over audio files without full transcription
5
5
  Project-URL: Homepage, https://github.com/ahron-maslin/echo_vector
6
6
  Project-URL: Documentation, https://github.com/ahron-maslin/echo_vector#readme
@@ -0,0 +1,18 @@
1
+ """EchoVector: Audio vector embedding and processing library."""
2
+
3
+ import warnings
4
+
5
+ from echovector.core import EchoVector
6
+
7
+ # librosa falls back to its deprecated audioread loader for formats libsndfile
8
+ # can't decode natively (e.g. m4a/aac), emitting a noisy FutureWarning we can't
9
+ # act on from here.
10
+ warnings.filterwarnings(
11
+ "ignore",
12
+ message="librosa.core.audio.__audioread_load",
13
+ category=FutureWarning,
14
+ )
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ __all__ = ["EchoVector"]
@@ -5,6 +5,7 @@ from typing import Annotated
5
5
 
6
6
  import typer
7
7
  from rich.console import Console
8
+ from rich.progress import Progress
8
9
  from rich.table import Table
9
10
 
10
11
  from echovector import EchoVector
@@ -74,7 +75,16 @@ def index(
74
75
  )
75
76
  if reset:
76
77
  engine.reset()
77
- count = engine.index(files, recursive=recursive)
78
+
79
+ with Progress(console=console) as progress:
80
+ task = progress.add_task("Indexing files...", total=None)
81
+
82
+ def _on_file_indexed(done: int, total: int, file_path: Path) -> None:
83
+ progress.update(
84
+ task, total=total, completed=done, description=f"Indexed {file_path.name}"
85
+ )
86
+
87
+ count = engine.index(files, recursive=recursive, on_file_indexed=_on_file_indexed)
78
88
  except Exception as exc:
79
89
  console.print(f"[bold red]Indexing failed:[/bold red] {exc}")
80
90
  raise typer.Exit(code=1) from exc
@@ -1,6 +1,6 @@
1
1
  """Core public API for EchoVector."""
2
2
 
3
- from collections.abc import Sequence
3
+ from collections.abc import Callable, Sequence
4
4
  from pathlib import Path
5
5
  from tempfile import TemporaryDirectory
6
6
  from typing import Any, cast
@@ -67,6 +67,7 @@ class EchoVector:
67
67
  recursive: bool | None = None,
68
68
  batch_size: int = 16,
69
69
  force: bool = False,
70
+ on_file_indexed: Callable[[int, int, Path], None] | None = None,
70
71
  ) -> int:
71
72
  """Index audio chunks from paths or directories.
72
73
 
@@ -76,6 +77,9 @@ class EchoVector:
76
77
  batch_size: Number of chunks to embed per batch.
77
78
  force: If True, remove and re-index files that are already stored.
78
79
  If False (default), already-indexed files are skipped.
80
+ on_file_indexed: Optional callback invoked after each file is
81
+ processed, with (files_done, total_files, file_path). Useful
82
+ for reporting progress.
79
83
 
80
84
  Returns:
81
85
  Number of new chunks added to the index.
@@ -103,7 +107,7 @@ class EchoVector:
103
107
  chunk_ids: list[str] = []
104
108
  chunk_metadata: list[dict[str, Any]] = []
105
109
 
106
- for file_path in files:
110
+ for file_number, file_path in enumerate(files, start=1):
107
111
  audio = self.audio_processor.load_audio(str(file_path))
108
112
  for (
109
113
  chunk_number,
@@ -131,6 +135,9 @@ class EchoVector:
131
135
  chunk_ids = []
132
136
  chunk_metadata = []
133
137
 
138
+ if on_file_indexed is not None:
139
+ on_file_indexed(file_number, len(files), file_path)
140
+
134
141
  if chunk_paths:
135
142
  self._add_chunk_batch(chunk_paths, chunk_ids, chunk_metadata)
136
143
 
@@ -1,20 +1,16 @@
1
1
  """CLAP (Contrastive Language-Audio Pretraining) embedding backend."""
2
2
 
3
- from typing import cast
3
+ from typing import Any, cast
4
4
 
5
5
  import librosa
6
6
  import numpy as np
7
7
  import numpy.typing as npt
8
+ import torch
9
+ from transformers import ClapModel, ClapProcessor
8
10
 
9
11
  from echovector.embeddings.base import EmbeddingBackend
10
12
 
11
- try:
12
- import torch
13
- from transformers import ClapModel, ClapProcessor
14
-
15
- _CLAP_AVAILABLE = True
16
- except ImportError: # pragma: no cover
17
- _CLAP_AVAILABLE = False
13
+ _CLAP_AVAILABLE = True
18
14
 
19
15
 
20
16
  class ClapBackend(EmbeddingBackend):
@@ -33,22 +29,14 @@ class ClapBackend(EmbeddingBackend):
33
29
  Args:
34
30
  model_name: The Hugging Face model identifier.
35
31
  device: Device to run the model on (e.g., 'cpu', 'cuda').
36
-
37
- Raises:
38
- ImportError: If torch or transformers are not installed.
39
32
  """
40
- if not _CLAP_AVAILABLE:
41
- raise ImportError(
42
- "CLAP backend requires torch and transformers. "
43
- "Install them with: pip install echo_vector"
44
- )
45
33
  if device is None:
46
34
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
47
35
  else:
48
36
  self.device = device
49
37
 
50
- self.processor = ClapProcessor.from_pretrained(model_name)
51
- self.model = ClapModel.from_pretrained(model_name)
38
+ self.processor: Any = ClapProcessor.from_pretrained(model_name) # pyright: ignore[reportArgumentType]
39
+ self.model: Any = ClapModel.from_pretrained(model_name) # pyright: ignore[reportArgumentType]
52
40
  self.model.to(self.device)
53
41
  self.model.eval()
54
42
 
@@ -81,7 +69,7 @@ class ClapBackend(EmbeddingBackend):
81
69
 
82
70
  audios = [self._load_and_resample(path, target_sr) for path in audio_paths]
83
71
 
84
- inputs = self.processor(
72
+ inputs = cast("Any", self.processor)(
85
73
  audios=audios,
86
74
  return_tensors="pt",
87
75
  sampling_rate=target_sr,
@@ -107,7 +95,7 @@ class ClapBackend(EmbeddingBackend):
107
95
  Returns:
108
96
  A numpy array of shape (batch_size, embedding_dim).
109
97
  """
110
- inputs = self.processor(
98
+ inputs = cast("Any", self.processor)(
111
99
  text=texts,
112
100
  return_tensors="pt",
113
101
  padding=True,
@@ -477,14 +477,16 @@ dependencies = [
477
477
  { name = "pydub" },
478
478
  { name = "rich" },
479
479
  { name = "soundfile" },
480
+ { name = "torch" },
480
481
  { name = "tqdm" },
482
+ { name = "transformers" },
481
483
  { name = "typer" },
482
484
  ]
483
485
 
484
486
  [package.optional-dependencies]
485
487
  all = [
486
488
  { name = "fastapi" },
487
- { name = "httpx" },
489
+ { name = "httpx2" },
488
490
  { name = "hypothesis" },
489
491
  { name = "mkdocs-gen-files" },
490
492
  { name = "mkdocs-literate-nav" },
@@ -498,20 +500,14 @@ all = [
498
500
  { name = "pytest-cov" },
499
501
  { name = "pytest-xdist" },
500
502
  { name = "ruff" },
501
- { name = "torch" },
502
- { name = "transformers" },
503
503
  { name = "uvicorn", extra = ["standard"] },
504
504
  ]
505
505
  api = [
506
506
  { name = "fastapi" },
507
507
  { name = "uvicorn", extra = ["standard"] },
508
508
  ]
509
- clap = [
510
- { name = "torch" },
511
- { name = "transformers" },
512
- ]
513
509
  dev = [
514
- { name = "httpx" },
510
+ { name = "httpx2" },
515
511
  { name = "hypothesis" },
516
512
  { name = "mutmut" },
517
513
  { name = "mypy" },
@@ -529,18 +525,13 @@ docs = [
529
525
  { name = "mkdocstrings", extra = ["python"] },
530
526
  ]
531
527
 
532
- [package.dev-dependencies]
533
- dev = [
534
- { name = "httpx" },
535
- ]
536
-
537
528
  [package.metadata]
538
529
  requires-dist = [
539
530
  { name = "faiss-cpu", specifier = ">=1.7,<2" },
540
531
  { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.109,<1" },
541
532
  { name = "fastapi", marker = "extra == 'api'", specifier = ">=0.109,<1" },
542
- { name = "httpx", marker = "extra == 'all'", specifier = ">=0.27,<1" },
543
- { name = "httpx", marker = "extra == 'dev'", specifier = ">=0.27,<1" },
533
+ { name = "httpx2", marker = "extra == 'all'", specifier = ">=2.0,<3" },
534
+ { name = "httpx2", marker = "extra == 'dev'", specifier = ">=2.0,<3" },
544
535
  { name = "hypothesis", marker = "extra == 'all'", specifier = ">=6.92,<7" },
545
536
  { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.92,<7" },
546
537
  { name = "librosa", specifier = ">=0.10,<1" },
@@ -570,22 +561,17 @@ requires-dist = [
570
561
  { name = "pytest-xdist", marker = "extra == 'all'", specifier = ">=3.5,<4" },
571
562
  { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.5,<4" },
572
563
  { name = "rich", specifier = ">=13.7,<14" },
573
- { name = "ruff", marker = "extra == 'all'", specifier = ">=0.3,<1" },
574
- { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3,<1" },
564
+ { name = "ruff", marker = "extra == 'all'", specifier = ">=0.15,<1" },
565
+ { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15,<1" },
575
566
  { name = "soundfile", specifier = ">=0.12,<1" },
576
- { name = "torch", marker = "extra == 'all'", specifier = ">=2.1,<3" },
577
- { name = "torch", marker = "extra == 'clap'", specifier = ">=2.1,<3" },
567
+ { name = "torch", specifier = ">=2.1,<3" },
578
568
  { name = "tqdm", specifier = ">=4.66,<5" },
579
- { name = "transformers", marker = "extra == 'all'", specifier = ">=4.36,<5" },
580
- { name = "transformers", marker = "extra == 'clap'", specifier = ">=4.36,<5" },
569
+ { name = "transformers", specifier = ">=4.36,<5" },
581
570
  { name = "typer", extras = ["all"], specifier = ">=0.12,<1" },
582
571
  { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.27,<1" },
583
572
  { name = "uvicorn", extras = ["standard"], marker = "extra == 'api'", specifier = ">=0.27,<1" },
584
573
  ]
585
- provides-extras = ["all", "api", "clap", "dev", "docs"]
586
-
587
- [package.metadata.requires-dev]
588
- dev = [{ name = "httpx", specifier = ">=0.28.1" }]
574
+ provides-extras = ["all", "api", "dev", "docs"]
589
575
 
590
576
  [[package]]
591
577
  name = "execnet"
@@ -717,16 +703,16 @@ wheels = [
717
703
  ]
718
704
 
719
705
  [[package]]
720
- name = "httpcore"
721
- version = "1.0.9"
706
+ name = "httpcore2"
707
+ version = "2.3.0"
722
708
  source = { registry = "https://pypi.org/simple" }
723
709
  dependencies = [
724
- { name = "certifi" },
725
710
  { name = "h11" },
711
+ { name = "truststore" },
726
712
  ]
727
- sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
713
+ sdist = { url = "https://files.pythonhosted.org/packages/e6/34/18f1c596e677962f040284246f393b10a1f8ce440b3a7e69c637d0f1c7ad/httpcore2-2.3.0.tar.gz", hash = "sha256:07327e251560960eea8e969d92d4c6a325feb13cca39e25340731336c3baf924", size = 64300, upload-time = "2026-06-01T13:15:02.998Z" }
728
714
  wheels = [
729
- { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
715
+ { url = "https://files.pythonhosted.org/packages/c2/dd/3357218c69360d1cecc196c230c9a1d5c9afd5dba362056e23e60a5e64e5/httpcore2-2.3.0-py3-none-any.whl", hash = "sha256:477e9e334f74e5240dcac002e890580f36a57d40ff0fb14cc9655731d23b8415", size = 80024, upload-time = "2026-06-01T13:15:00.001Z" },
730
716
  ]
731
717
 
732
718
  [[package]]
@@ -759,18 +745,18 @@ wheels = [
759
745
  ]
760
746
 
761
747
  [[package]]
762
- name = "httpx"
763
- version = "0.28.1"
748
+ name = "httpx2"
749
+ version = "2.3.0"
764
750
  source = { registry = "https://pypi.org/simple" }
765
751
  dependencies = [
766
752
  { name = "anyio" },
767
- { name = "certifi" },
768
- { name = "httpcore" },
753
+ { name = "httpcore2" },
769
754
  { name = "idna" },
755
+ { name = "truststore" },
770
756
  ]
771
- sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
757
+ sdist = { url = "https://files.pythonhosted.org/packages/9f/9a/cca0b9145f13d8ae34b885ae28d403a1469a433abc78e0f94f4ce94e650b/httpx2-2.3.0.tar.gz", hash = "sha256:227e7c41d95a76d4077a52640564132777215fc3394e07b66a3116c33d668fa9", size = 81115, upload-time = "2026-06-01T13:15:04.324Z" }
772
758
  wheels = [
773
- { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
759
+ { url = "https://files.pythonhosted.org/packages/87/ce/ae2911859847f9ba1d6b23027e53481cbeb50b93234f355a968d300ca2cb/httpx2-2.3.0-py3-none-any.whl", hash = "sha256:6f393663bdf6dbe7fe90118e3eb5b2bd024a675cae0390ac08cec9198812d8b7", size = 74538, upload-time = "2026-06-01T13:15:01.566Z" },
774
760
  ]
775
761
 
776
762
  [[package]]
@@ -2544,6 +2530,15 @@ wheels = [
2544
2530
  { url = "https://files.pythonhosted.org/packages/c1/68/fa86e5a39608000f645535b2c124920126327ab731f8c4fafd5b07ff8d4b/triton-3.7.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce061073102714b725f3660ec6939d94a1da7984b3aa99c921417cae273672f5", size = 201546766, upload-time = "2026-05-07T18:46:42.088Z" },
2545
2531
  ]
2546
2532
 
2533
+ [[package]]
2534
+ name = "truststore"
2535
+ version = "0.10.4"
2536
+ source = { registry = "https://pypi.org/simple" }
2537
+ sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" }
2538
+ wheels = [
2539
+ { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" },
2540
+ ]
2541
+
2547
2542
  [[package]]
2548
2543
  name = "typer"
2549
2544
  version = "0.25.1"
@@ -1,7 +0,0 @@
1
- """EchoVector: Audio vector embedding and processing library."""
2
-
3
- from echovector.core import EchoVector
4
-
5
- __version__ = "0.1.0"
6
-
7
- __all__ = ["EchoVector"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes