code-context-control 2.49.0__py3-none-any.whl → 2.49.1__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.
cli/c3.py CHANGED
@@ -85,7 +85,7 @@ console = Console() if HAS_RICH else None
85
85
  # Config
86
86
  CONFIG_DIR = ".c3"
87
87
  CONFIG_FILE = ".c3/config.json"
88
- __version__ = "2.49.0"
88
+ __version__ = "2.49.1"
89
89
 
90
90
 
91
91
  def _command_deps() -> CommandDeps:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-context-control
3
- Version: 2.49.0
3
+ Version: 2.49.1
4
4
  Summary: Local code-intelligence layer for AI coding tools (Claude Code, Codex, Gemini, Copilot). Retrieve less, read less, edit safer — and version the configs that shape your agent (CLAUDE.md, skills, hooks, MCP).
5
5
  Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  cli/__init__.py,sha256=ec66drCZGNMRU4V6ov0zVhYZph1us12Vn8OvG_LJyRY,22
2
2
  cli/_hook_utils.py,sha256=zlquaQm0dvwdaZewD6YnFyF_LBzhmfFUUhL_8UbBKGA,11749
3
- cli/c3.py,sha256=G0_1nQcdA4SgpVx5FjvIrpoVR10vm8CqwJMoPPCRSqI,304587
3
+ cli/c3.py,sha256=gQY5eY2DO1gk7xSa4734VLHLi_6aFwxd32HBUjGBbZQ,304587
4
4
  cli/docs.html,sha256=CC_-4PaQxfjNXbcqcVuU5rzdbP1NosYJxFRiXZV4joI,143645
5
5
  cli/edits.html,sha256=UjAhoCmBmQ89cklGvJqzC6eyNP2tc8H6T-e01DVkLvE,43418
6
6
  cli/hook_artifact.py,sha256=Se1CNBfoBFyvJQlRmYdNtdRXIkQp9zaF0O6ndRMo7ts,2198
@@ -93,18 +93,17 @@ cli/ui/components/sessions.js,sha256=FIKtil76B8tCkAmcFV7hlj6GQ_DCJK2jCzvEmdK7NBE
93
93
  cli/ui/components/settings.js,sha256=8LVTV2TQl9tcRXhXbtBEJOCBdiyk-x2QASoVYZUAuEA,71442
94
94
  cli/ui/components/sidebar.js,sha256=cAY_jwYB-o1X_wWn__VXlG4IegVObuE3NmVsuFWqxtg,7417
95
95
  cli/ui/components/tasks.js,sha256=OxLhspzzEQjxxtSEpOpugO2KptD4xNrimf_xM0wiVv8,12752
96
- code_context_control-2.49.0.dist-info/licenses/LICENSE,sha256=l8Kh5QCNWNvR6kIt8L0BUZvc2LAFiHv2c-FnsGnUZf4,11301
96
+ code_context_control-2.49.1.dist-info/licenses/LICENSE,sha256=l8Kh5QCNWNvR6kIt8L0BUZvc2LAFiHv2c-FnsGnUZf4,11301
97
97
  core/__init__.py,sha256=TSDCEcM4V7gcZVM3w2ykJaqEUch4Dkon-rivV17T73s,2501
98
98
  core/config.py,sha256=9R8bIcHhjSPdrfcCeMPnS4YgLCyRNWwlt_Z75PZcBDE,14780
99
99
  core/ide.py,sha256=9LzsDVK2LL8RVpL40l6oNGiasZ3D8OCU_9i9A0gJKBo,6876
100
100
  core/mcp_toml.py,sha256=wfc7c6X7lIW5YpdWFnRK0qQ0M46v2t8j6WzcqfTKhaE,5627
101
101
  core/web_security.py,sha256=HwgK5aBATfvRIeO_4gWgzK77gKwGuzVlmiuNGm4gGxI,7884
102
102
  oracle/__init__.py,sha256=-OTD7Jh4mUMA4QgPGthPLWXttgZLpkIPhGQ87ZfHBx0,63
103
- oracle/config.py,sha256=XEYMH0InBJxhls4b0vD7gvBqMUdxVVHrTHTLz-rZVZg,3838
103
+ oracle/config.py,sha256=4geiSXhwXbKvy2EaKibKxpg8DgUVJWkNeSMcpQFOo_s,3913
104
104
  oracle/mcp_oracle.py,sha256=B5B-qSxi37outsuRHn1Ns6Gj8e7W593rmL34LMzuE8M,8980
105
- oracle/oracle.html,sha256=g8HS_wXx4jPwi2ccSOdMe6FHiYP51DmkFuznWHZjBfQ,193362
106
- oracle/oracle_server.py,sha256=kWVIypqW1p7t6tpDKSQlWVrEcj2ez6zNjOWvGjLPaZo,41902
107
- oracle/oracle_ui.html,sha256=bkSmag8UF93nshnIzOEyiN3ilY9qBlYzERofxcrnStI,68165
105
+ oracle/oracle_server.py,sha256=zDywXKQC8Yxq8HrwpBEIJvanr-OKkO62eQZCVGGKcTI,41589
106
+ oracle/oracle_ui.html,sha256=qML_m7GY-iPEhQOiczDd8T6IEVtqcrjwEoudK9f9C5U,68441
108
107
  oracle/services/__init__.py,sha256=Nb4POd1_YIwLVYsGfr-DiK-iKTelkU0fh9m7wjeLQHA,23
109
108
  oracle/services/activity_reporter.py,sha256=ZAxNFyUy7QRP28anQLRbKEwm5SGG97KIQYFQDLjYqlM,11729
110
109
  oracle/services/api_auth.py,sha256=1PW3pG--1DJb_F6qMhP3gBTYHxxPE2bsHmVmIhC81Y8,3566
@@ -115,7 +114,7 @@ oracle/services/cross_memory.py,sha256=F8JeYkEFSwQL3iGS9KV1onaMSFj3opr6f3nCxwvzn
115
114
  oracle/services/federated_graph.py,sha256=I9FWedcht6-FU2hoIlMHlXyjpwrspKueIN-jEYek6vg,19947
116
115
  oracle/services/health_checker.py,sha256=SlsW4nxP5u8gHJY9FpeaZoC9_K-NhoiHr2Q7JvGMvdY,4359
117
116
  oracle/services/insight_engine.py,sha256=YBZX28P-ME-nJ02cebFIVH0WvIGebFnQQCt8paXri4Y,11417
118
- oracle/services/local_session.py,sha256=2DC7Lyr1g4_LkT4N7MHlQgaLSeulHPd-FvJK1hpN6ek,1877
117
+ oracle/services/local_session.py,sha256=f6qzHPZPtn1XIV5wNnlJ85BY3tApAh2NoYdtaIFpMDs,1887
119
118
  oracle/services/memory_reader.py,sha256=rSEmoIXQu2JkolHJIQWpn0piPJpyuf1KZvW_9liQwkU,3727
120
119
  oracle/services/memory_writer.py,sha256=hpvYsxjhl293jEjGcRKfjG5njUaAOXKqbmJaUu1WdUU,6997
121
120
  oracle/services/ollama_bridge.py,sha256=T3Xif3OXsjtsJvsNXhr_iRlB3fr9lbFipuA_1ngK7jQ,16705
@@ -125,16 +124,16 @@ oracle/services/tool_executor.py,sha256=xtAkBWkclh_FwOgzprjGkyRIV8-A7Lc3bz0UFPSh
125
124
  oracle/services/tool_registry.py,sha256=fHXgQ2Y7T8JdjrxYgAnOlYRANtve5SikkEuf4b86i94,25686
126
125
  oracle/ui/activity.js,sha256=zbJjqkY-tTQS4YKcdSEr2Z5zAbwbOIPyTNzldQSPU7I,4830
127
126
  oracle/ui/agents.js,sha256=RNnsGUVg5DlRYiv-Ovzb3W4yyP4z0qTX3o7Y1_BgZpo,4538
128
- oracle/ui/app.js,sha256=wj3GquJYuc21578HdMlvHwthpVilzP0N6HjZUvTjUzE,678
127
+ oracle/ui/app.js,sha256=fyfFL7YNbl_z1WSUOMXScp4qcavuFVg5cnA7D1i3zYU,795
129
128
  oracle/ui/busy.js,sha256=ePFGqEheHpn-E971pN_9DbQvvkxD-d2V7Efbw68bpo0,4122
130
129
  oracle/ui/core.js,sha256=M6gt_AjxKLoZ8sEYsHT1n4-qR4F7qMSe80Quls1hgL8,3214
131
130
  oracle/ui/crossgraph.js,sha256=7yBCciuEzZ0LYspWMO0xTe_GuPQ_NccnIeRrqEq5Qxs,9234
132
- oracle/ui/header.js,sha256=IrtNb6M77ZCtuqdcX-bxM6RQavLtTY7sbgCXKhOf8-o,3381
131
+ oracle/ui/header.js,sha256=KA-vZ-KIVEDZ1RejMSXX76t3Zno1r7q85xQWzMQizvw,3598
133
132
  oracle/ui/insights.js,sha256=zACyfGz9-4y2eFd6OM1IE-L_HyL1wnqo46nJDyRx7-M,2408
134
133
  oracle/ui/projects.js,sha256=ULE6Py1iULVmRGy0mCnEAxKNwHvn-baUYlNDF5xGYM8,13002
135
134
  oracle/ui/settings.js,sha256=4p4CB_5GFic1uHeiDHtN7yB5Ma0dLN5HAVDQ_04QbGo,7889
136
135
  oracle/ui/suggestions.js,sha256=ItQTlyd6LS_QxvbJmNMYeHY3cl0lSRgBdR53XKkBpP0,2332
137
- oracle/ui/theme_tabs.js,sha256=JN018kQjX-AEoh4QT1d59VrBb_XwNuGDsFG7blKwBUA,2728
136
+ oracle/ui/theme_tabs.js,sha256=sIFnBLgI_Hp7c-GRZrWN2v4pvRBJUnIhhwGG91qydKI,3347
138
137
  oracle/ui/chat/conversations.js,sha256=FOpXNrIeiJUR9VueBYEuLml-VfJfuHo05ZVkT-x7XRI,5907
139
138
  oracle/ui/chat/input.js,sha256=9m48OZzmhCygND24pjZikOBzEXhOK6YqwWt4d5bjKbs,9329
140
139
  oracle/ui/chat/markdown.js,sha256=14Le4i88756PQvsl2ZuKGMuRw1FDuEPXr_oi2U6kLFM,1508
@@ -220,8 +219,8 @@ tui/screens/search_view.py,sha256=MMHjVdlk3HZSuDBSvq8IGrqv_Mh5Us6YqXQ80bcWSMk,19
220
219
  tui/screens/session_view.py,sha256=eZ1eDwHTvPOck1wCCviixtOaCxIkBT_95ytNNNriGNA,5991
221
220
  tui/screens/stats.py,sha256=p81PjzdaIv7hllb8f45-rlVe4lJZwSdIMqu7e86_u5s,6223
222
221
  tui/screens/ui_view.py,sha256=1QJCgLh2YfgWIpvzRG1KOGXYEaOYX6ojN61Azjf2oX0,2125
223
- code_context_control-2.49.0.dist-info/METADATA,sha256=NMoj1GVXc44yI2rE0rCLnwFu4NLtuZwM6XONZTQnWTM,23785
224
- code_context_control-2.49.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
225
- code_context_control-2.49.0.dist-info/entry_points.txt,sha256=7kX_WUsDCF2hbXzvbNyscyaBb9AeA-DJY5v_5hN0DlU,93
226
- code_context_control-2.49.0.dist-info/top_level.txt,sha256=wRt41zBybVF3qAiNXHz9BURbkKvUvfhmWWtKMhaw6eE,29
227
- code_context_control-2.49.0.dist-info/RECORD,,
222
+ code_context_control-2.49.1.dist-info/METADATA,sha256=nYHYs-fLmzcaQ-VP7YRq7MKu6r9i4fnq3rEPCVlx5UU,23785
223
+ code_context_control-2.49.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
224
+ code_context_control-2.49.1.dist-info/entry_points.txt,sha256=7kX_WUsDCF2hbXzvbNyscyaBb9AeA-DJY5v_5hN0DlU,93
225
+ code_context_control-2.49.1.dist-info/top_level.txt,sha256=wRt41zBybVF3qAiNXHz9BURbkKvUvfhmWWtKMhaw6eE,29
226
+ code_context_control-2.49.1.dist-info/RECORD,,
oracle/config.py CHANGED
@@ -32,6 +32,7 @@ DEFAULTS = {
32
32
  "digest_retention_days": 14, # prune stored digests
33
33
  "auto_open_browser": True,
34
34
  "theme": "dark",
35
+ "ui_last_tab": "chat", # persisted UI preference (hub parity)
35
36
  "max_facts_per_analysis": 100,
36
37
  "insight_confidence_threshold": 0.5,
37
38
  "log_level": "INFO",
oracle/oracle_server.py CHANGED
@@ -3,7 +3,6 @@
3
3
  import atexit
4
4
  import json
5
5
  import logging
6
- import os
7
6
  import socket
8
7
  import sys
9
8
  import threading
@@ -16,7 +15,7 @@ _PROJECT_ROOT = Path(__file__).resolve().parent.parent
16
15
  if str(_PROJECT_ROOT) not in sys.path:
17
16
  sys.path.insert(0, str(_PROJECT_ROOT))
18
17
 
19
- from flask import Flask, Response, jsonify, request, send_from_directory # noqa: E402
18
+ from flask import Flask, Response, jsonify, request # noqa: E402
20
19
 
21
20
  from oracle.config import ORACLE_DIR, load_config, save_config # noqa: E402
22
21
  from oracle.mcp_oracle import mcp_url, start_mcp_thread # noqa: E402
@@ -248,15 +247,6 @@ def index():
248
247
  return resp
249
248
 
250
249
 
251
- @app.route("/legacy")
252
- def index_legacy():
253
- """Frozen pre-bundle Oracle UI — escape hatch for one release, then removed."""
254
- resp = send_from_directory(os.path.dirname(__file__), "oracle.html")
255
- if local_session.is_loopback(request.remote_addr):
256
- local_session.attach_cookie(resp)
257
- return resp
258
-
259
-
260
250
  # ── Health ────────────────────────────────────────────────
261
251
  @app.route("/api/health")
262
252
  def api_health():
@@ -272,6 +262,7 @@ def api_health():
272
262
  return jsonify({
273
263
  "status": "ok",
274
264
  "service": "c3-oracle",
265
+ "version": _c3_version(),
275
266
  "model": _cfg.get("model", "gemma4:31b-cloud"),
276
267
  "ollama_available": ollama_ok,
277
268
  "model_verified": _model_verified,
oracle/oracle_ui.html CHANGED
@@ -44,6 +44,7 @@
44
44
  }
45
45
  .logo { font-size: 17px; font-weight: 700; letter-spacing: .5px; display: flex; align-items: center; gap: 10px; }
46
46
  .logo span { color: var(--accent); }
47
+ .version-badge { font-size: 10px; font-weight: 500; font-family: monospace; color: var(--text2); background: var(--bg3); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; }
47
48
  .header-right { display: flex; align-items: center; gap: 8px; }
48
49
  .badge { background: var(--bg3); border: 1px solid var(--border); border-radius: 9999px; padding: 3px 12px; font-size: 11px; color: var(--text2); }
49
50
  .badge .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; }
@@ -797,6 +798,7 @@
797
798
  <header>
798
799
  <div class="logo">
799
800
  <span>Oracle</span> Memory Agent
801
+ <span class="version-badge" id="oracleVersion" style="display:none"></span>
800
802
  <div class="activity-spinner" id="activitySpinner"></div>
801
803
  <div class="activity-label" id="activityLabel"></div>
802
804
  </div>
@@ -1,6 +1,6 @@
1
1
  """Per-boot local dashboard session for the Oracle server.
2
2
 
3
- The Oracle dashboard (oracle.html) runs in a local browser and calls mutating
3
+ The Oracle dashboard (oracle_ui.html bundle) runs in a local browser and calls mutating
4
4
  ``/api/*`` endpoints without a Bearer token. Rather than injecting the durable
5
5
  Discovery token into page JS (readable by any XSS) or trusting every loopback
6
6
  process (exactly the attacker the write gate exists to stop), the server
oracle/ui/app.js CHANGED
@@ -4,6 +4,8 @@
4
4
  // ═══════════════════════════════════════════════════════════
5
5
  (async function init() {
6
6
  await Promise.all([refreshHeader(), loadProjects(), loadInsights(), loadSuggestions(), loadSettings(), loadDiscoveryKey(), chatLoadConversations(), chatLoadCommands()]);
7
+ // Restore persisted UI preferences (loadSettings cached the config).
8
+ restoreLastTab(window.oracleConfig || {});
7
9
  // Auto-refresh every 60s
8
10
  setInterval(() => { refreshHeader(); loadProjects(); }, 60000);
9
11
  })();
oracle/ui/header.js CHANGED
@@ -24,6 +24,12 @@ async function refreshHeader() {
24
24
  api('/api/review/status').catch(() => ({})),
25
25
  ]);
26
26
 
27
+ // Version badge (hub topbar parity)
28
+ if (health.version) {
29
+ const vEl = document.getElementById('oracleVersion');
30
+ if (vEl) { vEl.textContent = 'v' + health.version; vEl.style.display = ''; }
31
+ }
32
+
27
33
  // Ollama
28
34
  ollamaOk = !!health.ollama_available;
29
35
  model = health.model || '?';
oracle/ui/theme_tabs.js CHANGED
@@ -25,6 +25,18 @@ function toggleTheme() {
25
25
  // ═══════════════════════════════════════════════════════════
26
26
  // ── Tab switching ──
27
27
  // ═══════════════════════════════════════════════════════════
28
+ let _restoringTab = false;
29
+
30
+ function restoreLastTab(cfg) {
31
+ // Re-open the tab from the persisted UI preference (hub parity).
32
+ const last = (cfg && cfg.ui_last_tab) || 'chat';
33
+ if (last === 'chat') return; // chat is the default active tab
34
+ const tab = document.querySelector(`.tab[data-tab="${last}"]`);
35
+ if (!tab) return;
36
+ _restoringTab = true;
37
+ try { tab.click(); } finally { _restoringTab = false; }
38
+ }
39
+
28
40
  document.querySelectorAll('.tab').forEach(tab => {
29
41
  tab.addEventListener('click', () => {
30
42
  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
@@ -46,6 +58,10 @@ document.querySelectorAll('.tab').forEach(tab => {
46
58
  if (tab.dataset.tab === 'activity' && !window._actLoaded) {
47
59
  loadActivity(); window._actLoaded = true;
48
60
  }
61
+ // Persist the UI preference (hub parity) — skip during restore.
62
+ if (!_restoringTab) {
63
+ api('/api/config', { method: 'POST', body: { ui_last_tab: tab.dataset.tab } }).catch(() => {});
64
+ }
49
65
  });
50
66
  });
51
67