code-context-control 2.28.0__py3-none-any.whl

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 (150) hide show
  1. cli/__init__.py +1 -0
  2. cli/_hook_utils.py +99 -0
  3. cli/c3.py +6152 -0
  4. cli/commands/__init__.py +1 -0
  5. cli/commands/common.py +312 -0
  6. cli/commands/parser.py +286 -0
  7. cli/docs.html +3178 -0
  8. cli/edits.html +878 -0
  9. cli/hook_auto_snapshot.py +142 -0
  10. cli/hook_c3_signal.py +61 -0
  11. cli/hook_c3read.py +116 -0
  12. cli/hook_edit_ledger.py +213 -0
  13. cli/hook_edit_unlock.py +170 -0
  14. cli/hook_filter.py +130 -0
  15. cli/hook_ghost_files.py +238 -0
  16. cli/hook_pretool_enforce.py +334 -0
  17. cli/hook_read.py +200 -0
  18. cli/hook_session_stats.py +62 -0
  19. cli/hook_terse_advisor.py +190 -0
  20. cli/hub.html +3764 -0
  21. cli/hub_server.py +1619 -0
  22. cli/mcp_proxy.py +428 -0
  23. cli/mcp_server.py +660 -0
  24. cli/server.py +2985 -0
  25. cli/tools/__init__.py +4 -0
  26. cli/tools/_helpers.py +65 -0
  27. cli/tools/agent.py +1165 -0
  28. cli/tools/compress.py +215 -0
  29. cli/tools/delegate.py +1184 -0
  30. cli/tools/edit.py +313 -0
  31. cli/tools/edits.py +118 -0
  32. cli/tools/filter.py +285 -0
  33. cli/tools/impact.py +163 -0
  34. cli/tools/memory.py +469 -0
  35. cli/tools/read.py +224 -0
  36. cli/tools/search.py +337 -0
  37. cli/tools/session.py +95 -0
  38. cli/tools/shell.py +193 -0
  39. cli/tools/status.py +306 -0
  40. cli/tools/validate.py +310 -0
  41. cli/ui/api.js +36 -0
  42. cli/ui/app.js +207 -0
  43. cli/ui/components/chat.js +758 -0
  44. cli/ui/components/dashboard.js +689 -0
  45. cli/ui/components/edits.js +220 -0
  46. cli/ui/components/instructions.js +481 -0
  47. cli/ui/components/memory.js +626 -0
  48. cli/ui/components/sessions.js +606 -0
  49. cli/ui/components/settings.js +1404 -0
  50. cli/ui/components/sidebar.js +156 -0
  51. cli/ui/icons.js +51 -0
  52. cli/ui/shared.js +119 -0
  53. cli/ui/theme.js +22 -0
  54. cli/ui.html +168 -0
  55. cli/ui_legacy.html +6797 -0
  56. cli/ui_nano.html +503 -0
  57. code_context_control-2.28.0.dist-info/METADATA +248 -0
  58. code_context_control-2.28.0.dist-info/RECORD +150 -0
  59. code_context_control-2.28.0.dist-info/WHEEL +5 -0
  60. code_context_control-2.28.0.dist-info/entry_points.txt +4 -0
  61. code_context_control-2.28.0.dist-info/licenses/LICENSE +201 -0
  62. code_context_control-2.28.0.dist-info/top_level.txt +5 -0
  63. core/__init__.py +75 -0
  64. core/config.py +269 -0
  65. core/ide.py +188 -0
  66. oracle/__init__.py +1 -0
  67. oracle/config.py +75 -0
  68. oracle/oracle.html +3900 -0
  69. oracle/oracle_server.py +663 -0
  70. oracle/services/__init__.py +1 -0
  71. oracle/services/c3_bridge.py +210 -0
  72. oracle/services/chat_engine.py +1103 -0
  73. oracle/services/chat_store.py +155 -0
  74. oracle/services/cross_memory.py +154 -0
  75. oracle/services/federated_graph.py +463 -0
  76. oracle/services/health_checker.py +117 -0
  77. oracle/services/insight_engine.py +307 -0
  78. oracle/services/memory_reader.py +106 -0
  79. oracle/services/memory_writer.py +182 -0
  80. oracle/services/ollama_bridge.py +332 -0
  81. oracle/services/project_scanner.py +87 -0
  82. oracle/services/review_agent.py +206 -0
  83. services/__init__.py +1 -0
  84. services/activity_log.py +93 -0
  85. services/agent_base.py +124 -0
  86. services/agents.py +1529 -0
  87. services/auto_memory.py +407 -0
  88. services/bench/__init__.py +6 -0
  89. services/bench/external/__init__.py +29 -0
  90. services/bench/external/aider_polyglot.py +405 -0
  91. services/bench/external/swe_bench.py +485 -0
  92. services/benchmark_dashboard.py +596 -0
  93. services/claude_md.py +785 -0
  94. services/compressor.py +592 -0
  95. services/context_snapshot.py +356 -0
  96. services/conversation_store.py +870 -0
  97. services/doc_index.py +537 -0
  98. services/e2e_benchmark.py +2884 -0
  99. services/e2e_evaluator.py +396 -0
  100. services/e2e_tasks.py +743 -0
  101. services/edit_ledger.py +459 -0
  102. services/embedding_index.py +341 -0
  103. services/error_reporting.py +123 -0
  104. services/file_memory.py +734 -0
  105. services/hub_service.py +585 -0
  106. services/indexer.py +712 -0
  107. services/memory.py +318 -0
  108. services/memory_consolidator.py +538 -0
  109. services/memory_graph.py +382 -0
  110. services/memory_grounder.py +304 -0
  111. services/memory_scorer.py +246 -0
  112. services/metrics.py +86 -0
  113. services/notifications.py +209 -0
  114. services/ollama_client.py +201 -0
  115. services/output_filter.py +488 -0
  116. services/parser.py +1238 -0
  117. services/project_manager.py +579 -0
  118. services/protocol.py +306 -0
  119. services/proxy_state.py +152 -0
  120. services/retrieval_broker.py +129 -0
  121. services/router.py +414 -0
  122. services/runtime.py +326 -0
  123. services/session_benchmark.py +1945 -0
  124. services/session_manager.py +1026 -0
  125. services/session_preloader.py +251 -0
  126. services/text_index.py +90 -0
  127. services/tool_classifier.py +176 -0
  128. services/transcript_index.py +340 -0
  129. services/validation_cache.py +155 -0
  130. services/vector_store.py +299 -0
  131. services/version_tracker.py +271 -0
  132. services/watcher.py +192 -0
  133. tui/__init__.py +0 -0
  134. tui/backend.py +59 -0
  135. tui/main.py +145 -0
  136. tui/screens/__init__.py +1 -0
  137. tui/screens/benchmark_view.py +109 -0
  138. tui/screens/claudemd_view.py +46 -0
  139. tui/screens/compress_view.py +52 -0
  140. tui/screens/index_view.py +74 -0
  141. tui/screens/init_view.py +82 -0
  142. tui/screens/mcp_view.py +73 -0
  143. tui/screens/optimize_view.py +41 -0
  144. tui/screens/pipe_view.py +46 -0
  145. tui/screens/projects_view.py +355 -0
  146. tui/screens/search_view.py +55 -0
  147. tui/screens/session_view.py +143 -0
  148. tui/screens/stats.py +158 -0
  149. tui/screens/ui_view.py +54 -0
  150. tui/theme.tcss +335 -0
@@ -0,0 +1,210 @@
1
+ """C3Bridge — gives Oracle full read-only access to C3 tool handlers.
2
+
3
+ Manages an LRU cache of C3Runtime instances (one per project) and wraps
4
+ each handler with project_path dispatch + read-only enforcement.
5
+ """
6
+
7
+ import asyncio
8
+ import logging
9
+ import threading
10
+ from pathlib import Path
11
+
12
+ from services.runtime import C3Runtime, build_runtime, stop_runtime
13
+
14
+ log = logging.getLogger("oracle.c3_bridge")
15
+
16
+ # Actions that are blocked in Oracle context (read-only).
17
+ _BLOCKED_EDITS_ACTIONS = {"log"}
18
+ _BLOCKED_MEMORY_ACTIONS = {"add", "update", "delete", "consolidate", "consolidate_deep", "ground"}
19
+ _BLOCKED_STATUS_VIEWS = {"ghost_files"}
20
+
21
+
22
+ def _noop_finalize(_name: str, _args: dict, resp: str, _summ: str = "", **_kw) -> str:
23
+ """No-op finalize — Oracle doesn't track MCP budgets."""
24
+ return resp
25
+
26
+
27
+ def _noop_facts(*_a, **_kw) -> str:
28
+ """Stub for maybe_facts callback (currently disabled in C3 too)."""
29
+ return ""
30
+
31
+
32
+ class C3Bridge:
33
+ """Bridge between Oracle and C3 tool handlers with per-project runtime cache."""
34
+
35
+ MAX_CACHED = 3
36
+
37
+ def __init__(self, scanner):
38
+ self.scanner = scanner
39
+ self._runtimes: dict[str, C3Runtime] = {}
40
+ self._access_order: list[str] = []
41
+ self._lock = threading.Lock()
42
+
43
+ # ── Runtime cache ──────────────────────────────────────────────
44
+
45
+ def get_runtime(self, project_path: str) -> C3Runtime:
46
+ """Return cached runtime or build a new one. LRU eviction at MAX_CACHED."""
47
+ project_path = str(Path(project_path).resolve())
48
+ with self._lock:
49
+ if project_path in self._runtimes:
50
+ self._access_order.remove(project_path)
51
+ self._access_order.append(project_path)
52
+ return self._runtimes[project_path]
53
+
54
+ # Validate before building (outside lock to avoid holding it long).
55
+ p = Path(project_path)
56
+ if not p.exists():
57
+ raise ValueError(f"Project path does not exist: {project_path}")
58
+ if not (p / ".c3").is_dir():
59
+ raise ValueError(f"No .c3 directory in {project_path}. Run 'c3 install' first.")
60
+
61
+ runtime = build_runtime(project_path, ide_name="claude-code")
62
+ log.info("Built C3Runtime for %s", project_path)
63
+
64
+ with self._lock:
65
+ # Double-check after build (another thread may have built it).
66
+ if project_path in self._runtimes:
67
+ stop_runtime(runtime)
68
+ self._access_order.remove(project_path)
69
+ self._access_order.append(project_path)
70
+ return self._runtimes[project_path]
71
+
72
+ self._runtimes[project_path] = runtime
73
+ self._access_order.append(project_path)
74
+
75
+ # Evict oldest if over limit.
76
+ while len(self._access_order) > self.MAX_CACHED:
77
+ evict = self._access_order.pop(0)
78
+ evicted = self._runtimes.pop(evict, None)
79
+ if evicted:
80
+ stop_runtime(evicted)
81
+ log.info("Evicted C3Runtime for %s", evict)
82
+
83
+ return runtime
84
+
85
+ def shutdown(self):
86
+ """Stop all cached runtimes."""
87
+ with self._lock:
88
+ for path, rt in self._runtimes.items():
89
+ stop_runtime(rt)
90
+ log.info("Shutdown C3Runtime for %s", path)
91
+ self._runtimes.clear()
92
+ self._access_order.clear()
93
+
94
+ # ── Helpers ────────────────────────────────────────────────────
95
+
96
+ def _discover_c3_projects(self) -> list[dict]:
97
+ """Return projects that have a .c3 directory."""
98
+ projects = self.scanner.discover()
99
+ return [p for p in projects if p.get("has_c3")]
100
+
101
+ # ── Per-project tool wrappers ─────────────────────────────────
102
+
103
+ def c3_search(self, project_path: str, query: str, action: str = "code",
104
+ top_k: int = 3, max_tokens: int = 1200) -> dict:
105
+ from cli.tools.search import handle_search
106
+ svc = self.get_runtime(project_path)
107
+ result = handle_search(query, action, top_k, max_tokens,
108
+ svc, _noop_finalize, _noop_facts)
109
+ return {"project": project_path, "result": result}
110
+
111
+ def c3_read(self, project_path: str, file_path: str,
112
+ symbols=None, lines=None) -> dict:
113
+ from cli.tools.read import handle_read
114
+ svc = self.get_runtime(project_path)
115
+ result = handle_read(file_path, symbols=symbols, lines=lines, svc=svc,
116
+ finalize=_noop_finalize)
117
+ return {"project": project_path, "result": result}
118
+
119
+ def c3_edits(self, project_path: str, action: str = "history",
120
+ file: str = "", change_type: str = "", summary: str = "",
121
+ lines_changed: str = "", tags: str = "", limit: int = 50,
122
+ since: str = "", edit_id: str = "", tag: str = "") -> dict:
123
+ if action in _BLOCKED_EDITS_ACTIONS:
124
+ return {"error": f"Action '{action}' is write-only and blocked in Oracle. "
125
+ "Use suggest_action for write operations."}
126
+ from cli.tools.edits import handle_edits
127
+ svc = self.get_runtime(project_path)
128
+ result = handle_edits(action, file, change_type, summary,
129
+ lines_changed, tags, limit, since,
130
+ edit_id, tag, svc, _noop_finalize)
131
+ return {"project": project_path, "result": result}
132
+
133
+ def c3_memory(self, project_path: str, action: str = "query",
134
+ query: str = "", fact: str = "", category: str = "",
135
+ top_k: int = 10, fact_id: str = "") -> dict:
136
+ if action in _BLOCKED_MEMORY_ACTIONS:
137
+ return {"error": f"Action '{action}' is blocked in Oracle (read-only). "
138
+ "Use suggest_action to propose memory changes."}
139
+ from cli.tools.memory import handle_memory
140
+ svc = self.get_runtime(project_path)
141
+ result = handle_memory(action, query, fact, category, top_k,
142
+ svc, _noop_finalize, fact_id=fact_id)
143
+ return {"project": project_path, "result": result}
144
+
145
+ def c3_compress(self, project_path: str, file_path: str,
146
+ mode: str = "map") -> dict:
147
+ from cli.tools.compress import handle_compress
148
+ svc = self.get_runtime(project_path)
149
+ result = handle_compress(file_path, mode, svc, _noop_finalize, _noop_facts)
150
+ return {"project": project_path, "result": result}
151
+
152
+ def c3_validate(self, project_path: str, file_path: str) -> dict:
153
+ from cli.tools.validate import handle_validate
154
+ svc = self.get_runtime(project_path)
155
+ result = asyncio.run(handle_validate(file_path, svc, _noop_finalize))
156
+ return {"project": project_path, "result": result}
157
+
158
+ def c3_status(self, project_path: str, view: str = "health",
159
+ detailed: bool = False) -> dict:
160
+ if view in _BLOCKED_STATUS_VIEWS:
161
+ return {"error": f"View '{view}' has side effects and is blocked in Oracle."}
162
+ from cli.tools.status import handle_status
163
+ svc = self.get_runtime(project_path)
164
+ result = handle_status(view, detailed, svc, _noop_finalize)
165
+ return {"project": project_path, "result": result}
166
+
167
+ def c3_filter(self, project_path: str, file_path: str = "", text: str = "",
168
+ pattern: str = "", max_lines: int = 100,
169
+ depth: str = "smart") -> dict:
170
+ from cli.tools.filter import handle_filter
171
+ svc = self.get_runtime(project_path)
172
+ result = handle_filter(file_path, text, pattern, max_lines,
173
+ depth, False, svc, _noop_finalize)
174
+ return {"project": project_path, "result": result}
175
+
176
+ # ── Cross-project aggregation ─────────────────────────────────
177
+
178
+ def c3_search_cross(self, query: str, action: str = "code",
179
+ top_k: int = 3) -> dict:
180
+ """Search code across ALL registered projects."""
181
+ projects = self._discover_c3_projects()
182
+ results = []
183
+ for proj in projects:
184
+ path = proj.get("path", "")
185
+ if not path:
186
+ continue
187
+ try:
188
+ r = self.c3_search(path, query, action, top_k)
189
+ results.append({"project": path, "result": r.get("result", "")})
190
+ except Exception as e:
191
+ results.append({"project": path, "error": str(e)})
192
+ return {"projects_queried": len(results), "results": results}
193
+
194
+ def c3_edits_cross(self, action: str = "history", tag: str = "",
195
+ limit: int = 20) -> dict:
196
+ """Query edit ledgers across ALL registered projects."""
197
+ if action in _BLOCKED_EDITS_ACTIONS:
198
+ return {"error": f"Action '{action}' is write-only and blocked in Oracle."}
199
+ projects = self._discover_c3_projects()
200
+ results = []
201
+ for proj in projects:
202
+ path = proj.get("path", "")
203
+ if not path:
204
+ continue
205
+ try:
206
+ r = self.c3_edits(path, action=action, tag=tag, limit=limit)
207
+ results.append({"project": path, "result": r.get("result", "")})
208
+ except Exception as e:
209
+ results.append({"project": path, "error": str(e)})
210
+ return {"projects_queried": len(results), "results": results}