code-context-engine 0.4.14__tar.gz → 0.4.16__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 (88) hide show
  1. {code_context_engine-0.4.14/src/code_context_engine.egg-info → code_context_engine-0.4.16}/PKG-INFO +1 -1
  2. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/pyproject.toml +1 -1
  3. {code_context_engine-0.4.14 → code_context_engine-0.4.16/src/code_context_engine.egg-info}/PKG-INFO +1 -1
  4. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/cli.py +17 -12
  5. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/integration/mcp_server.py +37 -9
  6. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/LICENSE +0 -0
  7. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/README.md +0 -0
  8. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/setup.cfg +0 -0
  9. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/code_context_engine.egg-info/SOURCES.txt +0 -0
  10. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/code_context_engine.egg-info/dependency_links.txt +0 -0
  11. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/code_context_engine.egg-info/entry_points.txt +0 -0
  12. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/code_context_engine.egg-info/requires.txt +0 -0
  13. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/code_context_engine.egg-info/top_level.txt +0 -0
  14. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/__init__.py +0 -0
  15. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/cli_style.py +0 -0
  16. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/__init__.py +0 -0
  17. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/compressor.py +0 -0
  18. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/ollama_client.py +0 -0
  19. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/output_rules.py +0 -0
  20. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/prompts.py +0 -0
  21. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/compression/quality.py +0 -0
  22. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/config.py +0 -0
  23. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/dashboard/__init__.py +0 -0
  24. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/dashboard/_page.py +0 -0
  25. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/dashboard/server.py +0 -0
  26. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/editors.py +0 -0
  27. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/event_bus.py +0 -0
  28. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/__init__.py +0 -0
  29. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/chunker.py +0 -0
  30. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/embedder.py +0 -0
  31. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/embedding_cache.py +0 -0
  32. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/git_hooks.py +0 -0
  33. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/git_indexer.py +0 -0
  34. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/ignorefile.py +0 -0
  35. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/manifest.py +0 -0
  36. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/pipeline.py +0 -0
  37. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/secrets.py +0 -0
  38. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/indexer/watcher.py +0 -0
  39. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/integration/__init__.py +0 -0
  40. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/integration/bootstrap.py +0 -0
  41. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/integration/git_context.py +0 -0
  42. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/integration/session_capture.py +0 -0
  43. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/__init__.py +0 -0
  44. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/compressor.py +0 -0
  45. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/db.py +0 -0
  46. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/extractive.py +0 -0
  47. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/grammar.py +0 -0
  48. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/hook_installer.py +0 -0
  49. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/hook_server.py +0 -0
  50. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/hooks.py +0 -0
  51. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/memory/migrate.py +0 -0
  52. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/models.py +0 -0
  53. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/pricing.py +0 -0
  54. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/project_commands.py +0 -0
  55. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/retrieval/__init__.py +0 -0
  56. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/retrieval/confidence.py +0 -0
  57. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/retrieval/query_parser.py +0 -0
  58. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/retrieval/retriever.py +0 -0
  59. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/serve_http.py +0 -0
  60. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/services.py +0 -0
  61. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/__init__.py +0 -0
  62. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/backend.py +0 -0
  63. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/fts_store.py +0 -0
  64. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/graph_store.py +0 -0
  65. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/local_backend.py +0 -0
  66. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/remote_backend.py +0 -0
  67. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/storage/vector_store.py +0 -0
  68. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/src/context_engine/utils.py +0 -0
  69. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_init_probe.py +0 -0
  70. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_mcp_config.py +0 -0
  71. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_savings.py +0 -0
  72. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_savings_buckets.py +0 -0
  73. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_savings_e2e.py +0 -0
  74. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_serve.py +0 -0
  75. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_sessions_export.py +0 -0
  76. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_sessions_status.py +0 -0
  77. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_smoke.py +0 -0
  78. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_cli_uninstall.py +0 -0
  79. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_config.py +0 -0
  80. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_e2e.py +0 -0
  81. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_editors_opencode.py +0 -0
  82. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_event_bus.py +0 -0
  83. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_models.py +0 -0
  84. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_project_commands.py +0 -0
  85. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_real_life.py +0 -0
  86. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_services.py +0 -0
  87. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_token_efficiency.py +0 -0
  88. {code_context_engine-0.4.14 → code_context_engine-0.4.16}/tests/test_token_packing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-engine
3
- Version: 0.4.14
3
+ Version: 0.4.16
4
4
  Summary: Index your codebase. AI searches instead of re-reading files. 94% token savings, benchmarked on FastAPI. Works with Claude Code, Cursor, VS Code, Gemini CLI, Codex, and OpenCode.
5
5
  Author-email: Fazle Elahee <felahee@gmail.com>, Raj <rajkumar.sakti@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "code-context-engine"
3
- version = "0.4.14"
3
+ version = "0.4.16"
4
4
  description = "Index your codebase. AI searches instead of re-reading files. 94% token savings, benchmarked on FastAPI. Works with Claude Code, Cursor, VS Code, Gemini CLI, Codex, and OpenCode."
5
5
  readme = {file = "README.md", content-type = "text/markdown"}
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-engine
3
- Version: 0.4.14
3
+ Version: 0.4.16
4
4
  Summary: Index your codebase. AI searches instead of re-reading files. 94% token savings, benchmarked on FastAPI. Works with Claude Code, Cursor, VS Code, Gemini CLI, Codex, and OpenCode.
5
5
  Author-email: Fazle Elahee <felahee@gmail.com>, Raj <rajkumar.sakti@gmail.com>
6
6
  License-Expression: MIT
@@ -1676,6 +1676,10 @@ def search(ctx: click.Context, query: str, top_k: int) -> None:
1676
1676
  retriever = HybridRetriever(backend=backend, embedder=embedder)
1677
1677
  results = await retriever.retrieve(query, top_k=top_k)
1678
1678
 
1679
+ # Filter out CCE config/editor files (same filter as MCP server)
1680
+ from context_engine.integration.mcp_server import _is_cce_config
1681
+ results = [r for r in results if not _is_cce_config(r.file_path)]
1682
+
1679
1683
  lines: list[str] = []
1680
1684
  lines.append("")
1681
1685
  lines.append(section(f"Search · {query}"))
@@ -1684,23 +1688,24 @@ def search(ctx: click.Context, query: str, top_k: int) -> None:
1684
1688
  if not results:
1685
1689
  lines.append(f" {DOT} {dim('No results found')}")
1686
1690
  else:
1687
- # Compute tokens
1688
- served_tokens = 0
1689
- seen_files: set[str] = set()
1691
+ # Compute tokens per file, capping served at full-file size to
1692
+ # handle overlapping chunks (e.g. class + method from same file).
1693
+ per_file_served: dict[str, int] = {}
1690
1694
  for r in results:
1691
1695
  chunk_tokens = max(1, len(r.content) // 4)
1692
- served_tokens += chunk_tokens
1693
- seen_files.add(r.file_path)
1696
+ per_file_served[r.file_path] = per_file_served.get(r.file_path, 0) + chunk_tokens
1694
1697
 
1695
- # Estimate full file tokens
1698
+ # Estimate full file tokens and cap served per file
1696
1699
  full_file_tokens = 0
1697
- for fp in seen_files:
1700
+ served_tokens = 0
1701
+ for fp, raw_served in per_file_served.items():
1698
1702
  full_path = Path(project_dir) / fp
1699
- if full_path.exists():
1700
- try:
1701
- full_file_tokens += max(1, len(full_path.read_text(errors="ignore")) // 4)
1702
- except OSError:
1703
- pass
1703
+ try:
1704
+ file_tokens = max(1, len(full_path.read_text(errors="ignore")) // 4)
1705
+ except OSError:
1706
+ file_tokens = raw_served
1707
+ full_file_tokens += file_tokens
1708
+ served_tokens += min(raw_served, file_tokens)
1704
1709
 
1705
1710
  for i, r in enumerate(results, 1):
1706
1711
  conf = r.metadata.get("confidence", "")
@@ -940,22 +940,36 @@ class ContextEngineMCP:
940
940
 
941
941
  inline_chunks, overflow_chunks = _split_inline_overflow(all_chunks, max_tokens)
942
942
 
943
- # Accounting
944
- raw_tokens = 0
945
- served_tokens = 0
943
+ # Accounting — track per-file to cap overlapping chunks
944
+ per_file_raw: dict[str, int] = {}
945
+ per_file_served: dict[str, int] = {}
946
946
  seen_files: set[str] = set()
947
947
  for chunk in inline_chunks:
948
948
  served_text = chunk.compressed_content or chunk.content
949
- raw_tokens += _count_tokens(chunk.content)
950
- served_tokens += _count_tokens(served_text)
951
- seen_files.add(chunk.file_path)
949
+ fp = chunk.file_path
950
+ per_file_raw[fp] = per_file_raw.get(fp, 0) + _count_tokens(chunk.content)
951
+ per_file_served[fp] = per_file_served.get(fp, 0) + _count_tokens(served_text)
952
+ seen_files.add(fp)
952
953
  for chunk in overflow_chunks:
953
- raw_tokens += _count_tokens(chunk.content)
954
- served_tokens += 30 # compact reference ~30 tokens
955
- seen_files.add(chunk.file_path)
954
+ fp = chunk.file_path
955
+ per_file_raw[fp] = per_file_raw.get(fp, 0) + _count_tokens(chunk.content)
956
+ per_file_served[fp] = per_file_served.get(fp, 0) + 30
957
+ seen_files.add(fp)
956
958
 
957
959
  full_file_tokens = self._estimate_full_file_tokens(seen_files)
958
960
 
961
+ # Cap per-file served/raw at full-file size to prevent overlapping
962
+ # chunks (class + method) from inflating tokens beyond the file size.
963
+ file_token_caps = self._per_file_token_caps(seen_files)
964
+ raw_tokens = sum(
965
+ min(per_file_raw.get(fp, 0), file_token_caps.get(fp, per_file_raw.get(fp, 0)))
966
+ for fp in seen_files
967
+ )
968
+ served_tokens = sum(
969
+ min(per_file_served.get(fp, 0), file_token_caps.get(fp, per_file_served.get(fp, 0)))
970
+ for fp in seen_files
971
+ )
972
+
959
973
  # Auto-capture: every file that surfaced as a relevant result counts as
960
974
  # "touched" — we can't tell from here whether Claude will act on it,
961
975
  # but a file appearing in a search result is a stronger signal than
@@ -1013,6 +1027,20 @@ class ContextEngineMCP:
1013
1027
  total += max(1, size // _CHARS_PER_TOKEN)
1014
1028
  return total
1015
1029
 
1030
+ def _per_file_token_caps(self, file_paths: set[str]) -> dict[str, int]:
1031
+ """Return {file_path: estimated_tokens} for capping overlapping chunks."""
1032
+ from pathlib import Path as _Path
1033
+ caps = {}
1034
+ project_dir = _Path.cwd()
1035
+ for fp in file_paths:
1036
+ full_path = project_dir / fp
1037
+ try:
1038
+ size = full_path.stat().st_size
1039
+ except OSError:
1040
+ continue
1041
+ caps[fp] = max(1, size // _CHARS_PER_TOKEN)
1042
+ return caps
1043
+
1016
1044
  async def _handle_expand_chunk(self, args):
1017
1045
  chunk_id = (args.get("chunk_id") or "").strip()
1018
1046
  if not chunk_id: