know-cli 0.3.4__tar.gz → 0.3.6__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.
- {know_cli-0.3.4 → know_cli-0.3.6}/PKG-INFO +1 -1
- {know_cli-0.3.4 → know_cli-0.3.6}/pyproject.toml +1 -1
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/lexical_index.py +6 -2
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/semantic_search.py +27 -8
- {know_cli-0.3.4 → know_cli-0.3.6}/.github/actions/know-cli/action.yml +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/.github/workflows/example-advanced.yml +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/.github/workflows/example-basic.yml +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/.gitignore +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/AGENTS.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/KNOW_SKILL.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/README.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/IMPLEMENTATION_PLAN.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/IMPROVEMENTS.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/STRATEGIC_AUDIT.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/arc.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/architecture-diff.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/architecture.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/dependencies.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/digest-compact.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/digest-llm.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/onboarding-new-devs.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/docs/onboarding-new_devs.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/__init__.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/ai.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/cli.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/config.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/context_engine.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/cost.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/diff.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/exceptions.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/generator.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/git_hooks.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/history.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/import_graph.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/index.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/knowledge_base.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/logger.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/mcp_server.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/models.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/parsers.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/quality.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/scanner.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/state.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/stats.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/token_counter.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/tools.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/src/know/watcher.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/README.md +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/conftest.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/mcp_stub/mcp/__init__.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/mcp_stub/mcp/server/__init__.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/mcp_stub/mcp/server/fastmcp.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_efficiency.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_history_cost.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_know.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_search_hybrid.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_state.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_unit.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_week2.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_week3.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_week4.py +0 -0
- {know_cli-0.3.4 → know_cli-0.3.6}/tests/test_week6_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: know-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: Context Intelligence for AI Coding Agents — smart, token-budgeted code context
|
|
5
5
|
Project-URL: Homepage, https://github.com/vic/know-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/vic/know-cli
|
|
@@ -217,8 +217,12 @@ class ChunkFTSIndex:
|
|
|
217
217
|
cleaned = re.sub(r"[^A-Za-z0-9_]+", " ", q).strip()
|
|
218
218
|
if not cleaned:
|
|
219
219
|
return q
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
terms = cleaned.split()
|
|
221
|
+
if len(terms) == 1:
|
|
222
|
+
return terms[0]
|
|
223
|
+
# Use OR to avoid over-strict matching on multi-word queries.
|
|
224
|
+
# Ranking still handled by BM25.
|
|
225
|
+
return " OR ".join(terms)
|
|
222
226
|
|
|
223
227
|
query_sanitized = _sanitize(query)
|
|
224
228
|
|
|
@@ -684,7 +684,10 @@ class SemanticSearcher:
|
|
|
684
684
|
# Hard fallback: plain text grep when hybrid/vector/lexical all miss.
|
|
685
685
|
# This guarantees useful results for exact keyword queries in TS/React projects.
|
|
686
686
|
if not results and query.strip():
|
|
687
|
+
import re
|
|
688
|
+
|
|
687
689
|
q = query.strip().lower()
|
|
690
|
+
q_tokens = [t for t in re.findall(r"[a-z0-9_]+", q) if len(t) >= 3]
|
|
688
691
|
exts = {".py", ".ts", ".tsx", ".js", ".jsx", ".go", ".rs", ".java", ".cpp", ".c", ".h", ".md"}
|
|
689
692
|
fallback = []
|
|
690
693
|
for p in root.rglob("*"):
|
|
@@ -703,16 +706,32 @@ class SemanticSearcher:
|
|
|
703
706
|
text = p.read_text(encoding="utf-8", errors="ignore")
|
|
704
707
|
except Exception:
|
|
705
708
|
continue
|
|
706
|
-
|
|
709
|
+
|
|
710
|
+
text_l = text.lower()
|
|
711
|
+
# Prefer exact phrase, fallback to token hits.
|
|
712
|
+
idx = text_l.find(q)
|
|
713
|
+
if idx < 0 and q_tokens:
|
|
714
|
+
token_positions = [text_l.find(tok) for tok in q_tokens]
|
|
715
|
+
token_positions = [pos for pos in token_positions if pos >= 0]
|
|
716
|
+
if not token_positions:
|
|
717
|
+
continue
|
|
718
|
+
idx = min(token_positions)
|
|
719
|
+
|
|
707
720
|
if idx < 0:
|
|
708
721
|
continue
|
|
722
|
+
|
|
709
723
|
line_no = text[:idx].count("\n") + 1
|
|
710
724
|
snippet = _format_snippet(p, line_no, line_no, context=2, include_line_numbers=include_line_numbers)
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
725
|
+
# crude relevance: token coverage in file text
|
|
726
|
+
coverage = 0
|
|
727
|
+
if q_tokens:
|
|
728
|
+
coverage = sum(1 for tok in q_tokens if tok in text_l)
|
|
729
|
+
fallback.append((coverage, rel, line_no, snippet))
|
|
730
|
+
|
|
731
|
+
fallback.sort(key=lambda x: (-x[0], x[1]))
|
|
732
|
+
fallback = fallback[:top_k]
|
|
714
733
|
|
|
715
|
-
for i, (rel, line_no, snippet) in enumerate(fallback, start=1):
|
|
734
|
+
for i, (coverage, rel, line_no, snippet) in enumerate(fallback, start=1):
|
|
716
735
|
results.append({
|
|
717
736
|
"schema": "know.search.v1",
|
|
718
737
|
"engine": "text-fallback",
|
|
@@ -723,7 +742,7 @@ class SemanticSearcher:
|
|
|
723
742
|
"chunk_type": "line",
|
|
724
743
|
"start_line": line_no,
|
|
725
744
|
"end_line": line_no,
|
|
726
|
-
"scores": {"rrf": 0.01, "lexical_bm25": None, "vector": None},
|
|
745
|
+
"scores": {"rrf": 0.01 + min(0.01, 0.002 * coverage), "lexical_bm25": None, "vector": None},
|
|
727
746
|
"snippet": snippet,
|
|
728
747
|
"rationale": {"lexical_available": lexical_available, "vector_available": vector_available},
|
|
729
748
|
})
|
|
@@ -834,8 +853,8 @@ class SemanticSearcher:
|
|
|
834
853
|
|
|
835
854
|
results = []
|
|
836
855
|
for i in top_indices:
|
|
837
|
-
|
|
838
|
-
|
|
856
|
+
# Keep top-k even when cosine is <= 0. In sparse/short queries,
|
|
857
|
+
# all scores can be near/under 0 and filtering causes empty results.
|
|
839
858
|
chunk_key = file_paths[i]
|
|
840
859
|
# Parse chunk key: "file_path::name::line_start"
|
|
841
860
|
parts = chunk_key.split("::")
|
|
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
|
|
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
|
|
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
|