emdash-core 0.1.7__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 (187) hide show
  1. emdash_core/__init__.py +3 -0
  2. emdash_core/agent/__init__.py +37 -0
  3. emdash_core/agent/agents.py +225 -0
  4. emdash_core/agent/code_reviewer.py +476 -0
  5. emdash_core/agent/compaction.py +143 -0
  6. emdash_core/agent/context_manager.py +140 -0
  7. emdash_core/agent/events.py +338 -0
  8. emdash_core/agent/handlers.py +224 -0
  9. emdash_core/agent/inprocess_subagent.py +377 -0
  10. emdash_core/agent/mcp/__init__.py +50 -0
  11. emdash_core/agent/mcp/client.py +346 -0
  12. emdash_core/agent/mcp/config.py +302 -0
  13. emdash_core/agent/mcp/manager.py +496 -0
  14. emdash_core/agent/mcp/tool_factory.py +213 -0
  15. emdash_core/agent/prompts/__init__.py +38 -0
  16. emdash_core/agent/prompts/main_agent.py +104 -0
  17. emdash_core/agent/prompts/subagents.py +131 -0
  18. emdash_core/agent/prompts/workflow.py +136 -0
  19. emdash_core/agent/providers/__init__.py +34 -0
  20. emdash_core/agent/providers/base.py +143 -0
  21. emdash_core/agent/providers/factory.py +80 -0
  22. emdash_core/agent/providers/models.py +220 -0
  23. emdash_core/agent/providers/openai_provider.py +463 -0
  24. emdash_core/agent/providers/transformers_provider.py +217 -0
  25. emdash_core/agent/research/__init__.py +81 -0
  26. emdash_core/agent/research/agent.py +143 -0
  27. emdash_core/agent/research/controller.py +254 -0
  28. emdash_core/agent/research/critic.py +428 -0
  29. emdash_core/agent/research/macros.py +469 -0
  30. emdash_core/agent/research/planner.py +449 -0
  31. emdash_core/agent/research/researcher.py +436 -0
  32. emdash_core/agent/research/state.py +523 -0
  33. emdash_core/agent/research/synthesizer.py +594 -0
  34. emdash_core/agent/reviewer_profile.py +475 -0
  35. emdash_core/agent/rules.py +123 -0
  36. emdash_core/agent/runner.py +601 -0
  37. emdash_core/agent/session.py +262 -0
  38. emdash_core/agent/spec_schema.py +66 -0
  39. emdash_core/agent/specification.py +479 -0
  40. emdash_core/agent/subagent.py +397 -0
  41. emdash_core/agent/subagent_prompts.py +13 -0
  42. emdash_core/agent/toolkit.py +482 -0
  43. emdash_core/agent/toolkits/__init__.py +64 -0
  44. emdash_core/agent/toolkits/base.py +96 -0
  45. emdash_core/agent/toolkits/explore.py +47 -0
  46. emdash_core/agent/toolkits/plan.py +55 -0
  47. emdash_core/agent/tools/__init__.py +141 -0
  48. emdash_core/agent/tools/analytics.py +436 -0
  49. emdash_core/agent/tools/base.py +131 -0
  50. emdash_core/agent/tools/coding.py +484 -0
  51. emdash_core/agent/tools/github_mcp.py +592 -0
  52. emdash_core/agent/tools/history.py +13 -0
  53. emdash_core/agent/tools/modes.py +153 -0
  54. emdash_core/agent/tools/plan.py +206 -0
  55. emdash_core/agent/tools/plan_write.py +135 -0
  56. emdash_core/agent/tools/search.py +412 -0
  57. emdash_core/agent/tools/spec.py +341 -0
  58. emdash_core/agent/tools/task.py +262 -0
  59. emdash_core/agent/tools/task_output.py +204 -0
  60. emdash_core/agent/tools/tasks.py +454 -0
  61. emdash_core/agent/tools/traversal.py +588 -0
  62. emdash_core/agent/tools/web.py +179 -0
  63. emdash_core/analytics/__init__.py +5 -0
  64. emdash_core/analytics/engine.py +1286 -0
  65. emdash_core/api/__init__.py +5 -0
  66. emdash_core/api/agent.py +308 -0
  67. emdash_core/api/agents.py +154 -0
  68. emdash_core/api/analyze.py +264 -0
  69. emdash_core/api/auth.py +173 -0
  70. emdash_core/api/context.py +77 -0
  71. emdash_core/api/db.py +121 -0
  72. emdash_core/api/embed.py +131 -0
  73. emdash_core/api/feature.py +143 -0
  74. emdash_core/api/health.py +93 -0
  75. emdash_core/api/index.py +162 -0
  76. emdash_core/api/plan.py +110 -0
  77. emdash_core/api/projectmd.py +210 -0
  78. emdash_core/api/query.py +320 -0
  79. emdash_core/api/research.py +122 -0
  80. emdash_core/api/review.py +161 -0
  81. emdash_core/api/router.py +76 -0
  82. emdash_core/api/rules.py +116 -0
  83. emdash_core/api/search.py +119 -0
  84. emdash_core/api/spec.py +99 -0
  85. emdash_core/api/swarm.py +223 -0
  86. emdash_core/api/tasks.py +109 -0
  87. emdash_core/api/team.py +120 -0
  88. emdash_core/auth/__init__.py +17 -0
  89. emdash_core/auth/github.py +389 -0
  90. emdash_core/config.py +74 -0
  91. emdash_core/context/__init__.py +52 -0
  92. emdash_core/context/models.py +50 -0
  93. emdash_core/context/providers/__init__.py +11 -0
  94. emdash_core/context/providers/base.py +74 -0
  95. emdash_core/context/providers/explored_areas.py +183 -0
  96. emdash_core/context/providers/touched_areas.py +360 -0
  97. emdash_core/context/registry.py +73 -0
  98. emdash_core/context/reranker.py +199 -0
  99. emdash_core/context/service.py +260 -0
  100. emdash_core/context/session.py +352 -0
  101. emdash_core/core/__init__.py +104 -0
  102. emdash_core/core/config.py +454 -0
  103. emdash_core/core/exceptions.py +55 -0
  104. emdash_core/core/models.py +265 -0
  105. emdash_core/core/review_config.py +57 -0
  106. emdash_core/db/__init__.py +67 -0
  107. emdash_core/db/auth.py +134 -0
  108. emdash_core/db/models.py +91 -0
  109. emdash_core/db/provider.py +222 -0
  110. emdash_core/db/providers/__init__.py +5 -0
  111. emdash_core/db/providers/supabase.py +452 -0
  112. emdash_core/embeddings/__init__.py +24 -0
  113. emdash_core/embeddings/indexer.py +534 -0
  114. emdash_core/embeddings/models.py +192 -0
  115. emdash_core/embeddings/providers/__init__.py +7 -0
  116. emdash_core/embeddings/providers/base.py +112 -0
  117. emdash_core/embeddings/providers/fireworks.py +141 -0
  118. emdash_core/embeddings/providers/openai.py +104 -0
  119. emdash_core/embeddings/registry.py +146 -0
  120. emdash_core/embeddings/service.py +215 -0
  121. emdash_core/graph/__init__.py +26 -0
  122. emdash_core/graph/builder.py +134 -0
  123. emdash_core/graph/connection.py +692 -0
  124. emdash_core/graph/schema.py +416 -0
  125. emdash_core/graph/writer.py +667 -0
  126. emdash_core/ingestion/__init__.py +7 -0
  127. emdash_core/ingestion/change_detector.py +150 -0
  128. emdash_core/ingestion/git/__init__.py +5 -0
  129. emdash_core/ingestion/git/commit_analyzer.py +196 -0
  130. emdash_core/ingestion/github/__init__.py +6 -0
  131. emdash_core/ingestion/github/pr_fetcher.py +296 -0
  132. emdash_core/ingestion/github/task_extractor.py +100 -0
  133. emdash_core/ingestion/orchestrator.py +540 -0
  134. emdash_core/ingestion/parsers/__init__.py +10 -0
  135. emdash_core/ingestion/parsers/base_parser.py +66 -0
  136. emdash_core/ingestion/parsers/call_graph_builder.py +121 -0
  137. emdash_core/ingestion/parsers/class_extractor.py +154 -0
  138. emdash_core/ingestion/parsers/function_extractor.py +202 -0
  139. emdash_core/ingestion/parsers/import_analyzer.py +119 -0
  140. emdash_core/ingestion/parsers/python_parser.py +123 -0
  141. emdash_core/ingestion/parsers/registry.py +72 -0
  142. emdash_core/ingestion/parsers/ts_ast_parser.js +313 -0
  143. emdash_core/ingestion/parsers/typescript_parser.py +278 -0
  144. emdash_core/ingestion/repository.py +346 -0
  145. emdash_core/models/__init__.py +38 -0
  146. emdash_core/models/agent.py +68 -0
  147. emdash_core/models/index.py +77 -0
  148. emdash_core/models/query.py +113 -0
  149. emdash_core/planning/__init__.py +7 -0
  150. emdash_core/planning/agent_api.py +413 -0
  151. emdash_core/planning/context_builder.py +265 -0
  152. emdash_core/planning/feature_context.py +232 -0
  153. emdash_core/planning/feature_expander.py +646 -0
  154. emdash_core/planning/llm_explainer.py +198 -0
  155. emdash_core/planning/similarity.py +509 -0
  156. emdash_core/planning/team_focus.py +821 -0
  157. emdash_core/server.py +153 -0
  158. emdash_core/sse/__init__.py +5 -0
  159. emdash_core/sse/stream.py +196 -0
  160. emdash_core/swarm/__init__.py +17 -0
  161. emdash_core/swarm/merge_agent.py +383 -0
  162. emdash_core/swarm/session_manager.py +274 -0
  163. emdash_core/swarm/swarm_runner.py +226 -0
  164. emdash_core/swarm/task_definition.py +137 -0
  165. emdash_core/swarm/worker_spawner.py +319 -0
  166. emdash_core/swarm/worktree_manager.py +278 -0
  167. emdash_core/templates/__init__.py +10 -0
  168. emdash_core/templates/defaults/agent-builder.md.template +82 -0
  169. emdash_core/templates/defaults/focus.md.template +115 -0
  170. emdash_core/templates/defaults/pr-review-enhanced.md.template +309 -0
  171. emdash_core/templates/defaults/pr-review.md.template +80 -0
  172. emdash_core/templates/defaults/project.md.template +85 -0
  173. emdash_core/templates/defaults/research_critic.md.template +112 -0
  174. emdash_core/templates/defaults/research_planner.md.template +85 -0
  175. emdash_core/templates/defaults/research_synthesizer.md.template +128 -0
  176. emdash_core/templates/defaults/reviewer.md.template +81 -0
  177. emdash_core/templates/defaults/spec.md.template +41 -0
  178. emdash_core/templates/defaults/tasks.md.template +78 -0
  179. emdash_core/templates/loader.py +296 -0
  180. emdash_core/utils/__init__.py +45 -0
  181. emdash_core/utils/git.py +84 -0
  182. emdash_core/utils/image.py +502 -0
  183. emdash_core/utils/logger.py +51 -0
  184. emdash_core-0.1.7.dist-info/METADATA +35 -0
  185. emdash_core-0.1.7.dist-info/RECORD +187 -0
  186. emdash_core-0.1.7.dist-info/WHEEL +4 -0
  187. emdash_core-0.1.7.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,352 @@
1
+ """Session context manager for Kuzu persistence."""
2
+
3
+ import os
4
+ import uuid
5
+ from datetime import datetime
6
+ from typing import Optional
7
+
8
+ from .models import ContextItem, SessionContext
9
+ from ..graph.connection import KuzuConnection
10
+ from ..utils.logger import log
11
+
12
+
13
+ class SessionContextManager:
14
+ """Manages session context persistence in Kuzu.
15
+
16
+ Handles:
17
+ - Creating and retrieving sessions by terminal ID
18
+ - Storing and updating context items
19
+ - Applying score decay to existing items
20
+ - Filtering items by minimum score
21
+ """
22
+
23
+ def __init__(self, connection: KuzuConnection):
24
+ """Initialize session context manager.
25
+
26
+ Args:
27
+ connection: Kuzu database connection
28
+ """
29
+ self.connection = connection
30
+ self._decay_factor = float(os.getenv("CONTEXT_DECAY_FACTOR", "0.8"))
31
+ self._ensure_schema()
32
+
33
+ def _ensure_schema(self):
34
+ """Ensure Session and ContextItem tables exist."""
35
+ try:
36
+ # Try to create tables (IF NOT EXISTS handles idempotency)
37
+ log.debug("Ensuring Session table exists...")
38
+ self.connection.execute_write(
39
+ """
40
+ CREATE NODE TABLE IF NOT EXISTS Session (
41
+ session_id STRING,
42
+ terminal_id STRING,
43
+ created_at TIMESTAMP,
44
+ last_active TIMESTAMP,
45
+ PRIMARY KEY (session_id)
46
+ )
47
+ """
48
+ )
49
+
50
+ log.debug("Ensuring ContextItem table exists...")
51
+ self.connection.execute_write(
52
+ """
53
+ CREATE NODE TABLE IF NOT EXISTS ContextItem (
54
+ id STRING,
55
+ session_id STRING,
56
+ qualified_name STRING,
57
+ entity_type STRING,
58
+ description STRING,
59
+ file_path STRING,
60
+ score DOUBLE,
61
+ touch_count INT64,
62
+ last_touched TIMESTAMP,
63
+ neighbors STRING[],
64
+ PRIMARY KEY (id)
65
+ )
66
+ """
67
+ )
68
+
69
+ log.debug("Ensuring SESSION_HAS_CONTEXT relationship exists...")
70
+ self.connection.execute_write(
71
+ """
72
+ CREATE REL TABLE IF NOT EXISTS SESSION_HAS_CONTEXT (
73
+ FROM Session TO ContextItem
74
+ )
75
+ """
76
+ )
77
+
78
+ except Exception as e:
79
+ log.warning(f"Failed to ensure schema (may already exist): {e}")
80
+
81
+ def get_or_create_session(self, terminal_id: str) -> SessionContext:
82
+ """Get existing session for terminal or create a new one.
83
+
84
+ Args:
85
+ terminal_id: Unique identifier for the terminal
86
+
87
+ Returns:
88
+ SessionContext for the terminal
89
+ """
90
+ # Try to find existing session
91
+ results = self.connection.execute(
92
+ """
93
+ MATCH (s:Session {terminal_id: $terminal_id})
94
+ RETURN s.session_id as session_id,
95
+ s.terminal_id as terminal_id,
96
+ s.created_at as created_at,
97
+ s.last_active as last_active
98
+ ORDER BY s.last_active DESC
99
+ LIMIT 1
100
+ """,
101
+ {"terminal_id": terminal_id},
102
+ )
103
+
104
+ if results:
105
+ row = results[0]
106
+ # Update last_active
107
+ self.connection.execute_write(
108
+ """
109
+ MATCH (s:Session {session_id: $session_id})
110
+ SET s.last_active = timestamp($now)
111
+ """,
112
+ {"session_id": row["session_id"], "now": datetime.now().isoformat()},
113
+ )
114
+
115
+ return SessionContext(
116
+ session_id=row["session_id"],
117
+ terminal_id=row["terminal_id"],
118
+ created_at=row.get("created_at"),
119
+ last_active=datetime.now(),
120
+ )
121
+
122
+ # Create new session
123
+ session_id = str(uuid.uuid4())
124
+ now = datetime.now()
125
+
126
+ self.connection.execute_write(
127
+ """
128
+ CREATE (s:Session {
129
+ session_id: $session_id,
130
+ terminal_id: $terminal_id,
131
+ created_at: timestamp($created_at),
132
+ last_active: timestamp($last_active)
133
+ })
134
+ """,
135
+ {
136
+ "session_id": session_id,
137
+ "terminal_id": terminal_id,
138
+ "created_at": now.isoformat(),
139
+ "last_active": now.isoformat(),
140
+ },
141
+ )
142
+
143
+ log.info(f"Created new session {session_id} for terminal {terminal_id}")
144
+
145
+ return SessionContext(
146
+ session_id=session_id,
147
+ terminal_id=terminal_id,
148
+ created_at=now,
149
+ last_active=now,
150
+ )
151
+
152
+ def add_context_items(self, session_id: str, items: list[ContextItem]):
153
+ """Add new context items, applying decay to existing ones.
154
+
155
+ Args:
156
+ session_id: Session to add items to
157
+ items: Context items to add
158
+ """
159
+ if not items:
160
+ return
161
+
162
+ # First, decay existing items
163
+ self._decay_existing(session_id)
164
+
165
+ # Then upsert new items
166
+ for item in items:
167
+ self._upsert_item(session_id, item)
168
+
169
+ log.info(f"Added {len(items)} context items to session {session_id}")
170
+
171
+ def _decay_existing(self, session_id: str):
172
+ """Apply decay factor to existing context items.
173
+
174
+ Args:
175
+ session_id: Session to decay items for
176
+ """
177
+ try:
178
+ self.connection.execute_write(
179
+ """
180
+ MATCH (s:Session {session_id: $session_id})-[:SESSION_HAS_CONTEXT]->(c:ContextItem)
181
+ SET c.score = c.score * $factor
182
+ """,
183
+ {"session_id": session_id, "factor": self._decay_factor},
184
+ )
185
+ except Exception as e:
186
+ log.warning(f"Failed to decay existing items: {e}")
187
+
188
+ def _upsert_item(self, session_id: str, item: ContextItem):
189
+ """Insert or update a context item.
190
+
191
+ Args:
192
+ session_id: Session ID
193
+ item: Context item to upsert
194
+ """
195
+ item_id = f"{session_id}:{item.qualified_name}"
196
+ now = datetime.now()
197
+
198
+ try:
199
+ # Check if item exists
200
+ existing = self.connection.execute(
201
+ """
202
+ MATCH (c:ContextItem {id: $id})
203
+ RETURN c.touch_count as touch_count
204
+ """,
205
+ {"id": item_id},
206
+ )
207
+
208
+ if existing:
209
+ # Update existing - increment touch count and reset score
210
+ touch_count = (existing[0].get("touch_count") or 0) + 1
211
+ self.connection.execute_write(
212
+ """
213
+ MATCH (c:ContextItem {id: $id})
214
+ SET c.score = 1.0,
215
+ c.touch_count = $touch_count,
216
+ c.last_touched = timestamp($now),
217
+ c.description = $description,
218
+ c.neighbors = $neighbors
219
+ """,
220
+ {
221
+ "id": item_id,
222
+ "touch_count": touch_count,
223
+ "now": now.isoformat(),
224
+ "description": item.description,
225
+ "neighbors": item.neighbors or [],
226
+ },
227
+ )
228
+ else:
229
+ # Create new item
230
+ self.connection.execute_write(
231
+ """
232
+ CREATE (c:ContextItem {
233
+ id: $id,
234
+ session_id: $session_id,
235
+ qualified_name: $qualified_name,
236
+ entity_type: $entity_type,
237
+ description: $description,
238
+ file_path: $file_path,
239
+ score: $score,
240
+ touch_count: $touch_count,
241
+ last_touched: timestamp($last_touched),
242
+ neighbors: $neighbors
243
+ })
244
+ """,
245
+ {
246
+ "id": item_id,
247
+ "session_id": session_id,
248
+ "qualified_name": item.qualified_name,
249
+ "entity_type": item.entity_type,
250
+ "description": item.description,
251
+ "file_path": item.file_path,
252
+ "score": item.score,
253
+ "touch_count": item.touch_count,
254
+ "last_touched": now.isoformat(),
255
+ "neighbors": item.neighbors or [],
256
+ },
257
+ )
258
+
259
+ # Create relationship
260
+ self.connection.execute_write(
261
+ """
262
+ MATCH (s:Session {session_id: $session_id})
263
+ MATCH (c:ContextItem {id: $item_id})
264
+ CREATE (s)-[:SESSION_HAS_CONTEXT]->(c)
265
+ """,
266
+ {"session_id": session_id, "item_id": item_id},
267
+ )
268
+
269
+ except Exception as e:
270
+ log.warning(f"Failed to upsert context item {item.qualified_name}: {e}")
271
+
272
+ def get_context(self, session_id: str, min_score: float = 0.3) -> list[ContextItem]:
273
+ """Get context items above minimum score.
274
+
275
+ Args:
276
+ session_id: Session to get items for
277
+ min_score: Minimum score threshold
278
+
279
+ Returns:
280
+ List of context items
281
+ """
282
+ try:
283
+ results = self.connection.execute(
284
+ """
285
+ MATCH (s:Session {session_id: $session_id})-[:SESSION_HAS_CONTEXT]->(c:ContextItem)
286
+ WHERE c.score >= $min_score
287
+ RETURN c.qualified_name as qualified_name,
288
+ c.entity_type as entity_type,
289
+ c.description as description,
290
+ c.file_path as file_path,
291
+ c.score as score,
292
+ c.touch_count as touch_count,
293
+ c.last_touched as last_touched,
294
+ c.neighbors as neighbors
295
+ ORDER BY c.score DESC
296
+ """,
297
+ {"session_id": session_id, "min_score": min_score},
298
+ )
299
+
300
+ items = []
301
+ for row in results:
302
+ items.append(
303
+ ContextItem(
304
+ qualified_name=row["qualified_name"],
305
+ entity_type=row["entity_type"],
306
+ description=row.get("description"),
307
+ file_path=row.get("file_path"),
308
+ score=row.get("score", 0.0),
309
+ touch_count=row.get("touch_count", 1),
310
+ last_touched=row.get("last_touched"),
311
+ neighbors=row.get("neighbors") or [],
312
+ )
313
+ )
314
+
315
+ return items
316
+
317
+ except Exception as e:
318
+ log.warning(f"Failed to get context for session {session_id}: {e}")
319
+ return []
320
+
321
+ def clear_session(self, session_id: str):
322
+ """Clear all context items for a session.
323
+
324
+ Args:
325
+ session_id: Session to clear
326
+ """
327
+ try:
328
+ # Delete context items
329
+ self.connection.execute_write(
330
+ """
331
+ MATCH (s:Session {session_id: $session_id})-[:SESSION_HAS_CONTEXT]->(c:ContextItem)
332
+ DETACH DELETE c
333
+ """,
334
+ {"session_id": session_id},
335
+ )
336
+ log.info(f"Cleared context for session {session_id}")
337
+ except Exception as e:
338
+ log.warning(f"Failed to clear session {session_id}: {e}")
339
+
340
+ def cleanup_old_sessions(self, max_age_days: int = 7):
341
+ """Remove sessions older than max_age_days.
342
+
343
+ Args:
344
+ max_age_days: Maximum age in days for sessions
345
+ """
346
+ try:
347
+ # This is a simplified cleanup - proper implementation would use
348
+ # timestamp comparison, but Kuzu's timestamp handling varies
349
+ log.info(f"Cleaning up sessions older than {max_age_days} days")
350
+ # TODO: Implement proper date-based cleanup
351
+ except Exception as e:
352
+ log.warning(f"Failed to cleanup old sessions: {e}")
@@ -0,0 +1,104 @@
1
+ """Core module for EmDash - models, configuration, and exceptions."""
2
+
3
+ from .config import (
4
+ EmDashConfig,
5
+ KuzuConfig,
6
+ IngestionConfig,
7
+ AnalyticsConfig,
8
+ GitHubConfig,
9
+ OpenAIConfig,
10
+ AnthropicConfig,
11
+ FireworksConfig,
12
+ ContextConfig,
13
+ AgentConfig,
14
+ MCPConfig,
15
+ get_config,
16
+ set_config,
17
+ get_config_dir,
18
+ get_user_config_path,
19
+ get_local_env_path,
20
+ load_env_files,
21
+ )
22
+
23
+ from .exceptions import (
24
+ EmDashException,
25
+ ConfigurationError,
26
+ DatabaseConnectionError,
27
+ RepositoryError,
28
+ ParsingError,
29
+ GraphBuildError,
30
+ QueryError,
31
+ AnalyticsError,
32
+ )
33
+
34
+ from .models import (
35
+ FileEntity,
36
+ ClassEntity,
37
+ FunctionEntity,
38
+ ModuleEntity,
39
+ ImportStatement,
40
+ CommitEntity,
41
+ FileModification,
42
+ AuthorEntity,
43
+ PullRequestEntity,
44
+ TaskEntity,
45
+ RepositoryEntity,
46
+ ClusterEntity,
47
+ CodebaseEntities,
48
+ FileEntities,
49
+ GitData,
50
+ )
51
+
52
+ from .review_config import (
53
+ ReviewConfig,
54
+ load_review_config,
55
+ )
56
+
57
+ __all__ = [
58
+ # Config
59
+ "EmDashConfig",
60
+ "KuzuConfig",
61
+ "IngestionConfig",
62
+ "AnalyticsConfig",
63
+ "GitHubConfig",
64
+ "OpenAIConfig",
65
+ "AnthropicConfig",
66
+ "FireworksConfig",
67
+ "ContextConfig",
68
+ "AgentConfig",
69
+ "MCPConfig",
70
+ "get_config",
71
+ "set_config",
72
+ "get_config_dir",
73
+ "get_user_config_path",
74
+ "get_local_env_path",
75
+ "load_env_files",
76
+ # Exceptions
77
+ "EmDashException",
78
+ "ConfigurationError",
79
+ "DatabaseConnectionError",
80
+ "RepositoryError",
81
+ "ParsingError",
82
+ "GraphBuildError",
83
+ "QueryError",
84
+ "AnalyticsError",
85
+ # Models
86
+ "FileEntity",
87
+ "ClassEntity",
88
+ "FunctionEntity",
89
+ "ModuleEntity",
90
+ "ImportStatement",
91
+ "CommitEntity",
92
+ "FileModification",
93
+ "AuthorEntity",
94
+ "PullRequestEntity",
95
+ "TaskEntity",
96
+ "RepositoryEntity",
97
+ "ClusterEntity",
98
+ "CodebaseEntities",
99
+ "FileEntities",
100
+ "GitData",
101
+ # Review config
102
+ "ReviewConfig",
103
+ "load_review_config",
104
+ ]