dirsql-plugin-embeddings 0.1.13__tar.gz → 0.1.15__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.
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/PKG-INFO +1 -1
- dirsql_plugin_embeddings-0.1.15/changelog.d/2026-08-12-empty-search-reports-why.md +3 -0
- dirsql_plugin_embeddings-0.1.15/changelog.d/2026-08-12-no-per-call-progress-bar.md +3 -0
- dirsql_plugin_embeddings-0.1.15/e2e-attestations/claude-814-suppress-per-call-progress.json +7 -0
- dirsql_plugin_embeddings-0.1.15/e2e-attestations/claude-816-empty-corpus-error.json +7 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/cli/search.py +7 -2
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/worker.py +4 -2
- dirsql_plugin_embeddings-0.1.15/src/dirsql_plugin_embeddings/search/run.py +45 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/search/sql.py +4 -0
- dirsql_plugin_embeddings-0.1.13/src/dirsql_plugin_embeddings/search/run.py +0 -20
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/.gitignore +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/README.md +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/changelog.d/2026-08-10-delete-old-surface.md +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/changelog.d/2026-08-10-embed-worker.md +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/changelog.d/2026-08-11-one-liner-cli.md +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/e2e-attestations/claude-804-embed-worker.json +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/e2e-attestations/claude-805-one-liner.json +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/migrations.d/2026-08-10-delete-old-surface.md +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/pyproject.toml +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/__init__.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/cli/__init__.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/cli/main.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/cli/worker.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/dirsql.toml +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/__init__.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/cache.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/model.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/progress.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/embedding/values.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/search/__init__.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/src/dirsql_plugin_embeddings/search/output.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/testing-conventions.toml +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/tests/conftest.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/tests/e2e/__init__.py +0 -0
- {dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/tests/integration/__init__.py +0 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
**Fixed**
|
|
2
|
+
|
|
3
|
+
- **A search that ranks nothing now says why and exits nonzero, instead of printing nothing and exiting 0.** Silent empty output was indistinguishable from "searched and found nothing relevant" — the reported case was running `dirsql-plugin-embeddings 'docs/**/*.md' <query>` from inside `docs/`, where the glob matches nothing. The message names the glob and the directory it searched from (`no files matched 'docs/**/*.md' (searched from /current/dir)`), and distinguishes that from a corpus whose files all matched but had no embeddable text, so it never claims the wrong reason. (#816)
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
**Fixed**
|
|
2
|
+
|
|
3
|
+
- **`embed()` no longer renders a progress bar for every call.** The worker embeds exactly one value per protocol round trip, so the per-call tqdm bar could only ever say `1/1` — on a TTY a 20-file corpus query printed ~21 of them to stderr. The bar is gone; the Hugging Face model-*download* bar, which measures something worth watching, is unchanged and still TTY-gated. (#814)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
|
-
from ..search.run import run_search
|
|
3
|
+
from ..search.run import NothingToRank, run_search
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
@click.command(hidden=True)
|
|
@@ -22,5 +22,10 @@ from ..search.run import run_search
|
|
|
22
22
|
)
|
|
23
23
|
def search(glob, query, limit, model):
|
|
24
24
|
"""Rank files matching GLOB by semantic similarity to QUERY."""
|
|
25
|
-
|
|
25
|
+
try:
|
|
26
|
+
lines = run_search(glob, query, limit, model)
|
|
27
|
+
except NothingToRank as error:
|
|
28
|
+
click.echo(f"dirsql-plugin-embeddings: {error}", err=True)
|
|
29
|
+
raise SystemExit(1) from None
|
|
30
|
+
for line in lines:
|
|
26
31
|
click.echo(line)
|
|
@@ -3,7 +3,6 @@ from hashlib import sha256
|
|
|
3
3
|
|
|
4
4
|
from . import model
|
|
5
5
|
from .cache import make_cache
|
|
6
|
-
from .progress import stderr_is_tty
|
|
7
6
|
from .values import ProtocolError, decode_value
|
|
8
7
|
|
|
9
8
|
MALFORMED_SHAPE = (
|
|
@@ -27,7 +26,10 @@ class Worker:
|
|
|
27
26
|
|
|
28
27
|
def _compute(self, digest, identifier):
|
|
29
28
|
text, loaded = self._pending
|
|
30
|
-
|
|
29
|
+
# No progress bar: the protocol embeds one value per round trip, so a
|
|
30
|
+
# per-call bar can only ever say 1/1. The model *download* bar, which
|
|
31
|
+
# measures something, is TTY-gated in `progress.configure`.
|
|
32
|
+
(vector,) = loaded.encode([text], show_progress_bar=False)
|
|
31
33
|
return [float(component) for component in vector]
|
|
32
34
|
|
|
33
35
|
def embed(self, text, model_id):
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
from importlib import resources
|
|
4
|
+
|
|
5
|
+
import dirsql
|
|
6
|
+
|
|
7
|
+
from .output import format_rows
|
|
8
|
+
from .sql import build_search_sql, count_corpus_sql
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NothingToRank(Exception):
|
|
12
|
+
"""The search produced no rows, and why -- so the CLI can say which."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def config_fragment():
|
|
16
|
+
return str(resources.files("dirsql_plugin_embeddings").joinpath("dirsql.toml"))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def no_rows_message(glob, matched, root):
|
|
20
|
+
if not matched:
|
|
21
|
+
return f"no files matched {glob!r} (searched from {root})"
|
|
22
|
+
return (
|
|
23
|
+
f"{glob!r} matched {matched} file(s), but none had text content to"
|
|
24
|
+
f" embed -- unreadable or not valid UTF-8 (searched from {root})"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def _search(glob, query, limit, model):
|
|
29
|
+
db = dirsql.DirSQL(config=config_fragment())
|
|
30
|
+
rows = await db.query(build_search_sql(glob, query, limit, model))
|
|
31
|
+
if rows:
|
|
32
|
+
return rows, None
|
|
33
|
+
# Only now, on the error path, is the second scan worth its cost: it is
|
|
34
|
+
# what tells "no files matched" apart from "matched, none embeddable".
|
|
35
|
+
# One row, always: `SELECT COUNT(*)` cannot return anything else, and
|
|
36
|
+
# unpacking says so rather than trusting an index.
|
|
37
|
+
(counted,) = await db.query(count_corpus_sql(glob))
|
|
38
|
+
return rows, counted["n"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def run_search(glob, query, limit, model=None):
|
|
42
|
+
rows, matched = asyncio.run(_search(glob, query, limit, model))
|
|
43
|
+
if not rows:
|
|
44
|
+
raise NothingToRank(no_rows_message(glob, matched, os.getcwd()))
|
|
45
|
+
return format_rows(rows)
|
|
@@ -30,3 +30,7 @@ def build_search_sql(glob, query, limit, model=None):
|
|
|
30
30
|
f" FROM (SELECT path, {inner} AS emb FROM {quote(normalize_glob(glob))})"
|
|
31
31
|
f" ORDER BY distance LIMIT {int(limit):d}"
|
|
32
32
|
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def count_corpus_sql(glob):
|
|
36
|
+
return f"SELECT COUNT(*) AS n FROM {quote(normalize_glob(glob))}"
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
from importlib import resources
|
|
3
|
-
|
|
4
|
-
import dirsql
|
|
5
|
-
|
|
6
|
-
from .output import format_rows
|
|
7
|
-
from .sql import build_search_sql
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def config_fragment():
|
|
11
|
-
return str(resources.files("dirsql_plugin_embeddings").joinpath("dirsql.toml"))
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
async def _query(sql):
|
|
15
|
-
return await dirsql.DirSQL(config=config_fragment()).query(sql)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def run_search(glob, query, limit, model=None):
|
|
19
|
-
rows = asyncio.run(_query(build_search_sql(glob, query, limit, model)))
|
|
20
|
-
return format_rows(rows)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/testing-conventions.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql_plugin_embeddings-0.1.13 → dirsql_plugin_embeddings-0.1.15}/tests/integration/__init__.py
RENAMED
|
File without changes
|