aurora-actr 0.3.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.
aurora/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """
2
+ AURORA Namespace Package
3
+
4
+ This namespace package provides unified access to all AURORA components
5
+ through a single import path: aurora.core, aurora.context_code, etc.
6
+
7
+ This is a PEP 420 implicit namespace package that aggregates the
8
+ individual aurora-* packages into a unified namespace.
9
+ """
10
+
11
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
aurora/cli/__init__.py ADDED
@@ -0,0 +1,42 @@
1
+ """
2
+ Aurora CLI Namespace Package
3
+
4
+ Provides transparent access to aurora_cli package through the aurora.cli namespace.
5
+ This enables imports like:
6
+ from aurora.cli.config import Config
7
+ from aurora.cli.commands.init import init_command
8
+ """
9
+
10
+ import importlib
11
+ import sys
12
+
13
+
14
+ # Pre-populate sys.modules with all known submodules to enable direct imports
15
+ _SUBMODULES = ["commands", "config", "errors", "escalation", "execution", "main", "memory_manager"]
16
+
17
+ for _submodule_name in _SUBMODULES:
18
+ _original = f"aurora_cli.{_submodule_name}"
19
+ _namespace = f"aurora.cli.{_submodule_name}"
20
+ try:
21
+ if _original not in sys.modules:
22
+ _module = importlib.import_module(_original)
23
+ else:
24
+ _module = sys.modules[_original]
25
+ sys.modules[_namespace] = _module
26
+ except ImportError:
27
+ pass # Submodule may not exist yet
28
+
29
+
30
+ def __getattr__(name):
31
+ """Dynamically import submodules from aurora_cli when accessed."""
32
+ original_module_name = f"aurora_cli.{name}"
33
+ try:
34
+ module = importlib.import_module(original_module_name)
35
+ sys.modules[f"aurora.cli.{name}"] = module
36
+ return module
37
+ except ImportError:
38
+ raise AttributeError(f"module 'aurora.cli' has no attribute '{name}'")
39
+
40
+
41
+ # Re-export all public members
42
+ from aurora_cli import * # noqa: E402, F401, F403, I001
aurora/cli/py.typed ADDED
File without changes
@@ -0,0 +1,42 @@
1
+ """
2
+ Aurora Context Code Namespace Package
3
+
4
+ Provides transparent access to aurora_context_code package through the aurora.context_code namespace.
5
+ This enables imports like:
6
+ from aurora.context_code.semantic.hybrid_retriever import HybridRetriever
7
+ from aurora.context_code.parser import PythonParser
8
+ """
9
+
10
+ import importlib
11
+ import sys
12
+
13
+
14
+ # Pre-populate sys.modules with all known submodules to enable direct imports
15
+ _SUBMODULES = ["languages", "parser", "registry", "semantic"]
16
+
17
+ for _submodule_name in _SUBMODULES:
18
+ _original = f"aurora_context_code.{_submodule_name}"
19
+ _namespace = f"aurora.context_code.{_submodule_name}"
20
+ try:
21
+ if _original not in sys.modules:
22
+ _module = importlib.import_module(_original)
23
+ else:
24
+ _module = sys.modules[_original]
25
+ sys.modules[_namespace] = _module
26
+ except ImportError:
27
+ pass # Submodule may not exist yet
28
+
29
+
30
+ def __getattr__(name):
31
+ """Dynamically import submodules from aurora_context_code when accessed."""
32
+ original_module_name = f"aurora_context_code.{name}"
33
+ try:
34
+ module = importlib.import_module(original_module_name)
35
+ sys.modules[f"aurora.context_code.{name}"] = module
36
+ return module
37
+ except ImportError:
38
+ raise AttributeError(f"module 'aurora.context_code' has no attribute '{name}'")
39
+
40
+
41
+ # Re-export all public members
42
+ from aurora_context_code import * # noqa: E402, F401, F403, I001
File without changes
@@ -0,0 +1,56 @@
1
+ """
2
+ Aurora Core Namespace Package
3
+
4
+ Provides transparent access to aurora_core package through the aurora.core namespace.
5
+ This enables imports like:
6
+ from aurora.core.store import SQLiteStore
7
+ from aurora.core.chunks.base import Chunk
8
+ """
9
+
10
+ import importlib
11
+ import sys
12
+
13
+
14
+ # Pre-populate sys.modules with all known submodules to enable direct imports
15
+ _SUBMODULES = [
16
+ "store",
17
+ "chunks",
18
+ "activation",
19
+ "budget",
20
+ "config",
21
+ "context",
22
+ "logging",
23
+ "optimization",
24
+ "resilience",
25
+ "types",
26
+ "exceptions",
27
+ ]
28
+
29
+ for _submodule_name in _SUBMODULES:
30
+ _original = f"aurora_core.{_submodule_name}"
31
+ _namespace = f"aurora.core.{_submodule_name}"
32
+ try:
33
+ if _original not in sys.modules:
34
+ _module = importlib.import_module(_original)
35
+ else:
36
+ _module = sys.modules[_original]
37
+ sys.modules[_namespace] = _module
38
+ except ImportError:
39
+ pass # Submodule may not exist yet
40
+
41
+
42
+ def __getattr__(name):
43
+ """Dynamically import submodules from aurora_core when accessed."""
44
+ # Map aurora.core.store -> aurora_core.store
45
+ original_module_name = f"aurora_core.{name}"
46
+ try:
47
+ module = importlib.import_module(original_module_name)
48
+ # Cache in sys.modules under both names
49
+ sys.modules[f"aurora.core.{name}"] = module
50
+ return module
51
+ except ImportError:
52
+ raise AttributeError(f"module 'aurora.core' has no attribute '{name}'")
53
+
54
+
55
+ # Re-export all public aurora_core members at the package level
56
+ from aurora_core import * # noqa: E402, F401, F403, I001
aurora/core/py.typed ADDED
File without changes
aurora/mcp/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ AURORA MCP Server - Model Context Protocol Integration.
3
+
4
+ This module provides FastMCP server implementation for integrating AURORA
5
+ with Claude Desktop and other MCP clients.
6
+ """
7
+
8
+ __version__ = "0.2.0"
9
+
10
+ __all__ = ["server", "tools", "config"]
aurora/mcp/config.py ADDED
@@ -0,0 +1,116 @@
1
+ """
2
+ AURORA MCP Configuration and Logging.
3
+
4
+ This module provides logging configuration for MCP tools with performance metrics.
5
+ """
6
+
7
+ import logging
8
+ import time
9
+ from collections.abc import Callable
10
+ from datetime import datetime
11
+ from functools import wraps
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+
16
+ def setup_mcp_logging(log_file: str = "~/.aurora/mcp.log") -> logging.Logger:
17
+ """
18
+ Setup MCP logging with performance metrics.
19
+
20
+ Args:
21
+ log_file: Path to log file (default: ~/.aurora/mcp.log)
22
+
23
+ Returns:
24
+ Configured logger instance
25
+ """
26
+ # Expand user path
27
+ log_path = Path(log_file).expanduser()
28
+
29
+ # Ensure directory exists
30
+ log_path.parent.mkdir(parents=True, exist_ok=True)
31
+
32
+ # Create logger
33
+ logger = logging.getLogger("aurora.mcp")
34
+ logger.setLevel(logging.INFO)
35
+
36
+ # Remove existing handlers
37
+ logger.handlers = []
38
+
39
+ # File handler with custom format
40
+ file_handler = logging.FileHandler(str(log_path))
41
+ file_handler.setLevel(logging.INFO)
42
+
43
+ # Custom format: [timestamp] level tool_name metric1=value1 metric2=value2
44
+ formatter = logging.Formatter(
45
+ "[%(asctime)s] %(levelname)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
46
+ )
47
+ file_handler.setFormatter(formatter)
48
+
49
+ logger.addHandler(file_handler)
50
+
51
+ return logger
52
+
53
+
54
+ def log_performance(tool_name: str) -> Callable:
55
+ """
56
+ Decorator to log performance metrics for MCP tools.
57
+
58
+ Args:
59
+ tool_name: Name of the MCP tool being logged
60
+
61
+ Returns:
62
+ Decorator function
63
+
64
+ Example:
65
+ @log_performance("aurora_search")
66
+ def aurora_search(query: str, limit: int = 10) -> str:
67
+ ...
68
+ """
69
+
70
+ def decorator(func: Callable) -> Callable:
71
+ @wraps(func)
72
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
73
+ # Get logger
74
+ logger = logging.getLogger("aurora.mcp")
75
+
76
+ # Record start time
77
+ start_time = time.time()
78
+
79
+ # Extract relevant parameters for logging
80
+ params = []
81
+ if args:
82
+ # First arg is usually 'self', skip it
83
+ if len(args) > 1:
84
+ params.append(f"arg={args[1]}")
85
+ for key, value in kwargs.items():
86
+ params.append(f"{key}={value}")
87
+
88
+ param_str = " ".join(params) if params else "no_params"
89
+
90
+ try:
91
+ # Execute function
92
+ result = func(*args, **kwargs)
93
+
94
+ # Calculate duration
95
+ duration_ms = (time.time() - start_time) * 1000
96
+
97
+ # Log success
98
+ logger.info(f"{tool_name} {param_str} latency={duration_ms:.1f}ms status=success")
99
+
100
+ return result
101
+
102
+ except Exception as e:
103
+ # Calculate duration
104
+ duration_ms = (time.time() - start_time) * 1000
105
+
106
+ # Log error
107
+ logger.error(
108
+ f"{tool_name} {param_str} latency={duration_ms:.1f}ms status=error error={str(e)}"
109
+ )
110
+
111
+ # Re-raise exception
112
+ raise
113
+
114
+ return wrapper
115
+
116
+ return decorator
aurora/mcp/server.py ADDED
@@ -0,0 +1,385 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AURORA MCP Server - FastMCP implementation.
4
+
5
+ Provides Model Context Protocol server for AURORA codebase indexing and search.
6
+ """
7
+
8
+ import argparse
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+
14
+ try:
15
+ from fastmcp import FastMCP
16
+ except ImportError:
17
+ print("Error: FastMCP not installed. Install with: pip install fastmcp", file=sys.stderr)
18
+ sys.exit(1)
19
+
20
+ from aurora.mcp.tools import AuroraMCPTools
21
+
22
+
23
+ class AuroraMCPServer:
24
+ """MCP Server for AURORA codebase tools."""
25
+
26
+ def __init__(
27
+ self, db_path: str | None = None, config_path: str | None = None, test_mode: bool = False
28
+ ):
29
+ """
30
+ Initialize AURORA MCP Server.
31
+
32
+ Args:
33
+ db_path: Path to SQLite database (default: ~/.aurora/memory.db)
34
+ config_path: Path to AURORA config file (default: ~/.aurora/config.json)
35
+ test_mode: If True, skip FastMCP initialization (for testing)
36
+ """
37
+ self.db_path = db_path or str(Path.home() / ".aurora" / "memory.db")
38
+ self.config_path = config_path or str(Path.home() / ".aurora" / "config.json")
39
+ self.test_mode = test_mode
40
+
41
+ # Initialize tools
42
+ self.tools = AuroraMCPTools(self.db_path, self.config_path)
43
+
44
+ # Initialize FastMCP server only if not in test mode
45
+ if not test_mode:
46
+ self.mcp = FastMCP("aurora")
47
+ # Register tools
48
+ self._register_tools()
49
+ else:
50
+ self.mcp = None
51
+
52
+ def _register_tools(self) -> None:
53
+ """Register MCP tools with the server."""
54
+
55
+ @self.mcp.tool()
56
+ def aurora_search(query: str, limit: int = 10) -> str:
57
+ """
58
+ Search AURORA indexed codebase.
59
+
60
+ Args:
61
+ query: Search query string
62
+ limit: Maximum number of results (default: 10)
63
+
64
+ Returns:
65
+ JSON string with search results
66
+ """
67
+ return self.tools.aurora_search(query, limit)
68
+
69
+ @self.mcp.tool()
70
+ def aurora_index(path: str, pattern: str = "*.py") -> str:
71
+ """
72
+ Index codebase directory.
73
+
74
+ Args:
75
+ path: Directory path to index
76
+ pattern: File pattern to match (default: *.py)
77
+
78
+ Returns:
79
+ JSON string with indexing stats
80
+ """
81
+ return self.tools.aurora_index(path, pattern)
82
+
83
+ @self.mcp.tool()
84
+ def aurora_context(file_path: str, function: str | None = None) -> str:
85
+ """
86
+ Get code context from file.
87
+
88
+ Args:
89
+ file_path: Path to source file
90
+ function: Optional function name to extract
91
+
92
+ Returns:
93
+ String with code content
94
+ """
95
+ return self.tools.aurora_context(file_path, function)
96
+
97
+ @self.mcp.tool()
98
+ def aurora_related(chunk_id: str, max_hops: int = 2) -> str:
99
+ """
100
+ Find related code chunks using ACT-R spreading activation.
101
+
102
+ Args:
103
+ chunk_id: Source chunk ID
104
+ max_hops: Maximum relationship hops (default: 2)
105
+
106
+ Returns:
107
+ JSON string with related chunks and activation scores
108
+ """
109
+ return self.tools.aurora_related(chunk_id, max_hops)
110
+
111
+ @self.mcp.tool()
112
+ def aurora_query(
113
+ query: str,
114
+ limit: int = 10,
115
+ type_filter: str | None = None,
116
+ verbose: bool = False,
117
+ ) -> str:
118
+ """
119
+ Retrieve relevant context from AURORA memory without LLM inference.
120
+
121
+ This tool provides intelligent context retrieval with complexity assessment
122
+ and confidence scoring. It returns structured context for the host LLM
123
+ (Claude Code CLI) to reason about, rather than calling external LLM APIs.
124
+
125
+ Args:
126
+ query: Natural language query string (required)
127
+ limit: Maximum number of chunks to retrieve (default: 10)
128
+ type_filter: Filter by memory type - "code", "reas", "know", or None (default: None)
129
+ verbose: Include detailed metadata in response (default: False)
130
+
131
+ Returns:
132
+ JSON string with:
133
+ - context: Retrieved memory chunks with content, metadata, and relevance scores
134
+ - assessment: Complexity assessment and retrieval confidence score
135
+ - metadata: Database stats and result counts
136
+
137
+ Examples:
138
+ Basic retrieval:
139
+ aurora_query("What is a Python decorator?")
140
+
141
+ Type-filtered retrieval:
142
+ aurora_query("async patterns", type_filter="code", limit=5)
143
+
144
+ Detailed metadata:
145
+ aurora_query("SOAR pipeline", verbose=True)
146
+
147
+ Note:
148
+ No API key required. This tool runs inside Claude Code CLI which
149
+ provides the LLM reasoning capabilities. For standalone usage with
150
+ LLM responses, use the CLI command: $ aur query "your question"
151
+ """
152
+ return self.tools.aurora_query(query, limit, type_filter, verbose)
153
+
154
+ @self.mcp.tool()
155
+ def aurora_get(index: int) -> str:
156
+ """
157
+ Retrieve a full chunk by index from the last search results.
158
+
159
+ This tool allows you to get the complete content of a specific result
160
+ from your last aurora_search or aurora_query call. Results are numbered
161
+ starting from 1 (1-indexed).
162
+
163
+ Workflow:
164
+ 1. Call aurora_search or aurora_query to get numbered results
165
+ 2. Review the list and choose which result you want
166
+ 3. Call aurora_get(N) to retrieve the full chunk for result N
167
+
168
+ Args:
169
+ index: 1-indexed position in last search results (must be >= 1)
170
+
171
+ Returns:
172
+ JSON string with:
173
+ - chunk: Complete chunk with all metadata (id, type, content, file_path, etc.)
174
+ - metadata: Index position and total count
175
+
176
+ Examples:
177
+ After aurora_search("async patterns"):
178
+ aurora_get(1) # Get first result
179
+ aurora_get(3) # Get third result
180
+
181
+ Note:
182
+ Session cache expires after 10 minutes. Results are stored per-session
183
+ and cleared when a new search is performed.
184
+ """
185
+ return self.tools.aurora_get(index)
186
+
187
+ @self.mcp.tool()
188
+ def aurora_list_agents() -> str:
189
+ """
190
+ List all discovered agents from configured sources.
191
+
192
+ Use this tool to browse, discover, and find available agents. Returns
193
+ a complete inventory of all agents accessible in the current environment.
194
+
195
+ Primary action keywords: list, show, get, fetch, retrieve, browse, discover
196
+ Domain keywords: agents, specialists, experts, roles, personas, subagents, assistants
197
+ Context keywords: available, registered, defined, configured, ready, accessible, discovered
198
+ Use case keywords: what, which, who, all, every, complete, inventory, catalog
199
+
200
+ No API key required. Local agent directory listing only.
201
+
202
+ Returns:
203
+ JSON array of agents containing:
204
+ - id: Agent identifier (kebab-case)
205
+ - title: Agent role/title
206
+ - source_path: Path to agent markdown file
207
+ - when_to_use: Guidance on when to invoke this agent
208
+
209
+ Examples:
210
+ # List all available agents
211
+ aurora_list_agents()
212
+
213
+ # After listing, you can:
214
+ # - Use aurora_search_agents() to filter by keyword
215
+ # - Use aurora_show_agent(id) to view full agent details
216
+ """
217
+ return self.tools.aurora_list_agents()
218
+
219
+ @self.mcp.tool()
220
+ def aurora_search_agents(query: str) -> str:
221
+ """
222
+ Search agents by keyword with relevance scoring.
223
+
224
+ Use this tool to find, search, discover, and filter agents by keywords.
225
+ Returns matching agents sorted by relevance score (0.0-1.0).
226
+
227
+ Primary action keywords: search, find, discover, filter, locate, identify, match
228
+ Domain keywords: agent, specialist, expert, role, persona, subagent, assistant
229
+ Context keywords: for, with, about, related, relevant, matching, suitable
230
+ Use case keywords: help, assist, guide, when, which, who, best, right
231
+
232
+ Uses substring matching to search agent id, title, and when_to_use fields.
233
+ No API key required. Local substring-based search only.
234
+
235
+ Args:
236
+ query: Search query string (required, non-empty)
237
+
238
+ Returns:
239
+ JSON array of matching agents containing:
240
+ - id: Agent identifier
241
+ - title: Agent role/title
242
+ - source_path: Path to agent markdown file
243
+ - when_to_use: When to use guidance
244
+ - relevance_score: Match score from 0.0 to 1.0
245
+
246
+ Examples:
247
+ # Search for testing-related agents
248
+ aurora_search_agents("test")
249
+
250
+ # Find agents for code review
251
+ aurora_search_agents("review")
252
+
253
+ # Discover quality assurance specialists
254
+ aurora_search_agents("quality")
255
+
256
+ Note:
257
+ Returns empty array if no matches found. Results sorted by relevance
258
+ score descending (best matches first).
259
+ """
260
+ return self.tools.aurora_search_agents(query)
261
+
262
+ @self.mcp.tool()
263
+ def aurora_show_agent(agent_id: str) -> str:
264
+ """
265
+ Show full agent details including complete markdown content.
266
+
267
+ Use this tool to retrieve, view, get, fetch, or display full details for
268
+ a specific agent by ID. Returns complete agent information including the
269
+ entire markdown file content with instructions and examples.
270
+
271
+ Primary action keywords: show, get, retrieve, fetch, view, display, read, load
272
+ Domain keywords: agent, specialist, expert, role, persona, details, info
273
+ Context keywords: full, complete, entire, whole, detailed, comprehensive
274
+ Use case keywords: about, details, information, content, instructions, guide
275
+
276
+ No API key required. Reads local agent markdown file only.
277
+
278
+ Args:
279
+ agent_id: Agent identifier (required, non-empty, kebab-case)
280
+
281
+ Returns:
282
+ JSON with full agent details:
283
+ - id: Agent identifier
284
+ - title: Agent role/title
285
+ - source_path: Path to agent markdown file
286
+ - when_to_use: When to use guidance
287
+ - content: Complete markdown file content
288
+
289
+ Or error JSON if agent not found:
290
+ - error: "Agent not found"
291
+ - agent_id: The requested agent ID
292
+
293
+ Examples:
294
+ # Show full details for QA test architect
295
+ aurora_show_agent("qa-test-architect")
296
+
297
+ # Get complete information for full stack developer
298
+ aurora_show_agent("full-stack-dev")
299
+
300
+ # View orchestrator agent details
301
+ aurora_show_agent("orchestrator")
302
+
303
+ Note:
304
+ Use aurora_list_agents() or aurora_search_agents() to discover
305
+ available agent IDs first.
306
+ """
307
+ return self.tools.aurora_show_agent(agent_id)
308
+
309
+ def run(self) -> None:
310
+ """Run the MCP server."""
311
+ self.mcp.run()
312
+
313
+ def list_tools(self) -> None:
314
+ """List all available tools (for testing)."""
315
+ print("AURORA MCP Server - Available Tools:")
316
+ print("=" * 50)
317
+
318
+ # Get registered tools from FastMCP
319
+ tools = [
320
+ ("aurora_search", "Search indexed codebase with semantic + keyword search"),
321
+ ("aurora_index", "Index a directory of code files"),
322
+ ("aurora_context", "Retrieve code context from a specific file/function"),
323
+ ("aurora_related", "Find related code using ACT-R spreading activation"),
324
+ ("aurora_query", "Retrieve relevant context without LLM inference"),
325
+ ("aurora_get", "Get full chunk by index from last search results"),
326
+ ("aurora_list_agents", "List all discovered agents from configured sources"),
327
+ ("aurora_search_agents", "Search agents by keyword with relevance scoring"),
328
+ ("aurora_show_agent", "Show full agent details including markdown content"),
329
+ ]
330
+
331
+ for name, description in tools:
332
+ print(f"\n{name}:")
333
+ print(f" {description}")
334
+
335
+ print("\n" + "=" * 50)
336
+ print(f"Database: {self.db_path}")
337
+ print(f"Config: {self.config_path}")
338
+
339
+
340
+ def main() -> None:
341
+ """Main entry point for MCP server CLI."""
342
+ parser = argparse.ArgumentParser(
343
+ description="AURORA MCP Server - Model Context Protocol integration",
344
+ formatter_class=argparse.RawDescriptionHelpFormatter,
345
+ )
346
+
347
+ parser.add_argument(
348
+ "--db-path",
349
+ type=str,
350
+ help="Path to SQLite database (default: ~/.aurora/memory.db)",
351
+ )
352
+
353
+ parser.add_argument(
354
+ "--config",
355
+ type=str,
356
+ help="Path to AURORA config file (default: ~/.aurora/config.json)",
357
+ )
358
+
359
+ parser.add_argument(
360
+ "--test",
361
+ action="store_true",
362
+ help="Test mode: start server and list available tools",
363
+ )
364
+
365
+ args = parser.parse_args()
366
+
367
+ # Create server instance
368
+ server = AuroraMCPServer(db_path=args.db_path, config_path=args.config, test_mode=args.test)
369
+
370
+ if args.test:
371
+ print("AURORA MCP Server - Test Mode")
372
+ print("=" * 50)
373
+ server.list_tools()
374
+ print("\nTest mode complete. Server initialized successfully!")
375
+ sys.exit(0)
376
+
377
+ # Run server
378
+ print("Starting AURORA MCP Server...")
379
+ print(f"Database: {server.db_path}")
380
+ print(f"Config: {server.config_path}")
381
+ server.run()
382
+
383
+
384
+ if __name__ == "__main__":
385
+ main()