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,220 @@
1
+ // EditsPanel — Edit Ledger: AI-tracked versioning & edit history
2
+ // Globals: T, I, GlowDot, Badge, StatBox, Btn, api, timeAgo, useState, useEffect, useCallback
3
+
4
+ const EditsPanel = () => {
5
+ const [edits, setEdits] = useState([]);
6
+ const [stats, setStats] = useState(null);
7
+ const [fileFilter, setFileFilter] = useState("");
8
+ const [loading, setLoading] = useState(true);
9
+ const [subView, setSubView] = useState("history"); // "history" | "stats"
10
+ const [expandedId, setExpandedId] = useState(null);
11
+
12
+ const loadEdits = useCallback(async () => {
13
+ try {
14
+ const params = new URLSearchParams({ limit: "100" });
15
+ if (fileFilter) params.set("file", fileFilter);
16
+ const data = await api.get(`/api/edits?${params}`);
17
+ setEdits(Array.isArray(data) ? data : []);
18
+ } catch { setEdits([]); }
19
+ setLoading(false);
20
+ }, [fileFilter]);
21
+
22
+ const loadStats = useCallback(async () => {
23
+ try {
24
+ const s = await api.get("/api/edits/stats");
25
+ setStats(s);
26
+ } catch {}
27
+ }, []);
28
+
29
+ useEffect(() => {
30
+ loadEdits();
31
+ loadStats();
32
+ const iv = setInterval(() => { loadEdits(); loadStats(); }, 15000);
33
+ return () => clearInterval(iv);
34
+ }, [loadEdits, loadStats]);
35
+
36
+ const typeColors = {
37
+ created: "#22c55e",
38
+ modified: "#3b82f6",
39
+ deleted: "#ef4444",
40
+ renamed: "#f59e0b",
41
+ };
42
+
43
+ // ── Diff renderer ────────────────────────────────────────────────────────
44
+ const renderDiffBlock = (label, text, bg, color) =>
45
+ React.createElement("div", { style: { flex: 1, minWidth: 0 } },
46
+ React.createElement("div", {
47
+ style: { fontSize: 10, fontWeight: 700, color, marginBottom: 4, textTransform: "uppercase", letterSpacing: "0.05em" }
48
+ }, label),
49
+ React.createElement("pre", {
50
+ style: {
51
+ margin: 0, padding: "8px 10px", borderRadius: 4, fontSize: 11,
52
+ background: bg, color: T.text, whiteSpace: "pre-wrap", wordBreak: "break-all",
53
+ fontFamily: "'JetBrains Mono', monospace", border: `1px solid ${color}30`,
54
+ maxHeight: 260, overflowY: "auto",
55
+ }
56
+ }, text || "(empty)")
57
+ );
58
+
59
+ const renderDetail = (detail) => {
60
+ if (!detail) return null;
61
+
62
+ // Batch edits: detail.patches is an array
63
+ if (detail.patches && detail.patches.length) {
64
+ return React.createElement("div", {
65
+ style: { display: "flex", flexDirection: "column", gap: 12, marginTop: 4 }
66
+ },
67
+ detail.patches.map((p, i) =>
68
+ React.createElement("div", { key: i },
69
+ p.summary && React.createElement("div", {
70
+ style: { fontSize: 11, color: T.textMuted, marginBottom: 6, fontStyle: "italic" }
71
+ }, `Patch ${i + 1}: ${p.summary}`),
72
+ React.createElement("div", { style: { display: "flex", gap: 8 } },
73
+ renderDiffBlock("removed", p.old_string, "#ef444418", "#ef4444"),
74
+ renderDiffBlock("added", p.new_string, "#22c55e18", "#22c55e"),
75
+ )
76
+ )
77
+ )
78
+ );
79
+ }
80
+
81
+ // Single edit: detail.old_string / detail.new_string
82
+ if (detail.old_string !== undefined || detail.new_string !== undefined) {
83
+ return React.createElement("div", { style: { display: "flex", gap: 8, marginTop: 4 } },
84
+ renderDiffBlock("removed", detail.old_string, "#ef444418", "#ef4444"),
85
+ renderDiffBlock("added", detail.new_string, "#22c55e18", "#22c55e"),
86
+ );
87
+ }
88
+
89
+ return null;
90
+ };
91
+
92
+ // ── Stats view ───────────────────────────────────────────────────────────
93
+ const renderStats = () => {
94
+ if (!stats) return null;
95
+ return React.createElement("div", { style: { display: "flex", gap: 12, flexWrap: "wrap", marginBottom: 16 } },
96
+ React.createElement(StatBox, { label: "Total Edits", value: stats.total || 0 }),
97
+ React.createElement(StatBox, { label: "Files Edited", value: stats.files || 0 }),
98
+ ...(stats.by_type ? Object.entries(stats.by_type).map(([k, v]) =>
99
+ React.createElement(StatBox, { key: k, label: k, value: v })
100
+ ) : [])
101
+ );
102
+ };
103
+
104
+ const renderMostEdited = () => {
105
+ if (!stats || !stats.most_edited || !stats.most_edited.length) return null;
106
+ return React.createElement("div", { style: { marginTop: 16 } },
107
+ React.createElement("div", { style: { fontSize: 13, fontWeight: 600, color: T.text, marginBottom: 8 } }, "Most Edited Files"),
108
+ ...stats.most_edited.slice(0, 8).map((m, i) =>
109
+ React.createElement("div", {
110
+ key: i,
111
+ style: {
112
+ display: "flex", justifyContent: "space-between", padding: "6px 10px",
113
+ background: i % 2 === 0 ? T.surface : "transparent", borderRadius: 4, fontSize: 12
114
+ }
115
+ },
116
+ React.createElement("span", { className: "mono", style: { color: T.accent } }, m.file),
117
+ React.createElement(Badge, { color: T.textMuted }, `${m.count} edits`)
118
+ )
119
+ )
120
+ );
121
+ };
122
+
123
+ // ── History view ─────────────────────────────────────────────────────────
124
+ const renderHistory = () => {
125
+ if (loading) return React.createElement("div", { style: { color: T.textMuted, fontSize: 13 } }, "Loading...");
126
+ if (!edits.length) return React.createElement("div", { style: { color: T.textMuted, fontSize: 13 } }, "No edits recorded yet.");
127
+
128
+ return React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } },
129
+ edits.slice().reverse().map((e, i) => {
130
+ const hasDiff = e.detail && (e.detail.patches || e.detail.old_string !== undefined || e.detail.new_string !== undefined);
131
+ const isExpanded = expandedId === (e.id || i);
132
+
133
+ return React.createElement("div", { key: e.id || i },
134
+ // ── Row ──────────────────────────────────────────────────────────
135
+ React.createElement("div", {
136
+ onClick: hasDiff ? () => setExpandedId(isExpanded ? null : (e.id || i)) : undefined,
137
+ style: {
138
+ display: "grid", gridTemplateColumns: "140px 1fr 70px 70px auto",
139
+ gap: 8, padding: "7px 10px", fontSize: 12, alignItems: "center",
140
+ background: isExpanded ? `${T.accent}10` : i % 2 === 0 ? T.surface : "transparent",
141
+ borderRadius: isExpanded ? "4px 4px 0 0" : 4,
142
+ cursor: hasDiff ? "pointer" : "default",
143
+ borderLeft: isExpanded ? `2px solid ${T.accent}` : "2px solid transparent",
144
+ }
145
+ },
146
+ // Timestamp
147
+ React.createElement("span", { className: "mono", style: { color: T.textMuted, fontSize: 11 } },
148
+ e.timestamp ? e.timestamp.slice(0, 19).replace("T", " ") : ""
149
+ ),
150
+ // File + summary
151
+ React.createElement("div", { style: { minWidth: 0 } },
152
+ React.createElement("span", { className: "mono", style: { color: T.accent, fontSize: 12 } }, e.file),
153
+ e.summary ? React.createElement("span", { style: { color: T.textMuted, marginLeft: 8, fontSize: 11 } }, e.summary) : null
154
+ ),
155
+ // Version badge
156
+ React.createElement(Badge, { color: "#8b5cf6" }, e.version || ""),
157
+ // Change type
158
+ React.createElement("span", {
159
+ style: { color: typeColors[e.change_type] || T.textMuted, fontSize: 11, fontWeight: 600 }
160
+ }, e.change_type || ""),
161
+ // Git info + diff + tags + expand chevron
162
+ React.createElement("div", { style: { display: "flex", gap: 6, alignItems: "center" } },
163
+ e.diff_summary ? React.createElement("span", { className: "mono", style: { fontSize: 10, color: T.textMuted } }, e.diff_summary) : null,
164
+ e.git && e.git.commit ? React.createElement("span", { className: "mono", style: { fontSize: 10, color: T.textDim } }, e.git.commit.slice(0, 7)) : null,
165
+ e.tags && e.tags.length ? e.tags.map((tag, ti) =>
166
+ React.createElement(Badge, { key: ti, color: T.warn }, tag)
167
+ ) : null,
168
+ hasDiff ? React.createElement("span", {
169
+ style: { fontSize: 14, color: T.textMuted, lineHeight: 1, userSelect: "none" }
170
+ }, isExpanded ? "▲" : "▼") : null,
171
+ )
172
+ ),
173
+ // ── Diff panel ───────────────────────────────────────────────────
174
+ isExpanded && hasDiff ? React.createElement("div", {
175
+ style: {
176
+ padding: "10px 12px 12px",
177
+ background: `${T.accent}08`,
178
+ borderRadius: "0 0 4px 4px",
179
+ borderLeft: `2px solid ${T.accent}`,
180
+ borderRight: `1px solid ${T.border}`,
181
+ borderBottom: `1px solid ${T.border}`,
182
+ }
183
+ }, renderDetail(e.detail)) : null
184
+ );
185
+ })
186
+ );
187
+ };
188
+
189
+ // ── Layout ────────────────────────────────────────────────────────────────
190
+ const toggleStyle = (active) => ({
191
+ padding: "4px 12px", borderRadius: 4, fontSize: 12, fontWeight: 600, cursor: "pointer",
192
+ border: `1px solid ${active ? T.accent : T.border}`,
193
+ background: active ? `${T.accent}20` : "transparent",
194
+ color: active ? T.accent : T.textMuted,
195
+ });
196
+
197
+ return React.createElement("div", null,
198
+ // Header row: toggle + filter
199
+ React.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 } },
200
+ React.createElement("div", { style: { display: "flex", gap: 6 } },
201
+ React.createElement("button", { style: toggleStyle(subView === "history"), onClick: () => setSubView("history") }, "History"),
202
+ React.createElement("button", { style: toggleStyle(subView === "stats"), onClick: () => setSubView("stats") }, "Stats")
203
+ ),
204
+ React.createElement("input", {
205
+ type: "text", placeholder: "Filter by file path...", value: fileFilter,
206
+ onChange: (e) => setFileFilter(e.target.value),
207
+ style: {
208
+ width: 260, padding: "5px 10px", borderRadius: 6, fontSize: 12,
209
+ border: `1px solid ${T.border}`, background: T.surface, color: T.text,
210
+ fontFamily: "'JetBrains Mono', monospace"
211
+ }
212
+ })
213
+ ),
214
+
215
+ // Content
216
+ subView === "stats"
217
+ ? React.createElement("div", null, renderStats(), renderMostEdited())
218
+ : renderHistory()
219
+ );
220
+ };