
Aidb Architecture
- 1 installs
- 19 repo stars
- Updated May 12, 2026
- ai-debugger-inc/aidb
aidb-architecture is a Claude Code skill providing an architectural reference for the AIDB debugging library and its MCP integration across six layers.
About
aidb-architecture is a Claude Code skill that documents the architecture of AIDB, a debugging library and MCP server. It maps a 6-layer design covering the MCP, service, session, adapter, DAP client and protocol layers, with component responsibilities, data flows and design decisions. A developer uses it to navigate the AIDB codebase and decide which layer to modify, and it defers deep topics to sibling skills.
- Architectural reference for AIDB core and its MCP integration
- Maps a 6-layer design (MCP, Service, Session, Adapter, DAP Client, Protocol)
- Quick-navigation table into per-layer resource docs and data-flow patterns
Aidb Architecture by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,366 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Jul 7, 2026 (Skillselion catalog sync)
aidb-architecture capabilities & compatibility
Free; it is a reference document with no runtime dependencies or API keys.
- Capabilities
- architecture reference · codebase navigation · debugger internals
- Use cases
- documentation · debugging
- Pricing
- Free
What aidb-architecture says it does
This skill provides a comprehensive architectural reference for understanding AIDB's multi-layered architecture, focusing on `aidb` core library and `aidb_mcp` MCP integration.
**Purpose:** Enable developers to navigate the codebase confidently, understand component responsibilities, trace data flows, and make correct architectural decisions.
npx skills add https://github.com/ai-debugger-inc/aidb --skill aidb-architectureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 19 |
| Last updated | May 12, 2026 |
| Repository | ai-debugger-inc/aidb ↗ |
What it does
Understand and navigate the AIDB debugger codebase's 6-layer architecture and decide which layer to change.
Who is it for?
Understanding AIDB's overall design, tracing cross-layer data flow and deciding which layer to modify.
Skip if: Adapter implementation, DAP protocol details or MCP tool development, which its docs route to other AIDB skills.
When should I use this skill?
The user needs to understand AIDB's system design, trace data flow across layers or make an architectural decision.
What you get
A clear layer-by-layer map of AIDB with component responsibilities and data flows.
- a 6-layer architecture map
- component responsibility and data-flow explanations
- navigation into per-layer resource docs
By the numbers
- 6-layer architecture
- 12 debugging tools in the MCP layer
Files
AIDB Architecture Skill
Overview
This skill provides a comprehensive architectural reference for understanding AIDB's multi-layered architecture, focusing on aidb core library and aidb_mcp MCP integration.
Purpose: Enable developers to navigate the codebase confidently, understand component responsibilities, trace data flows, and make correct architectural decisions.
Scope:
- PRIMARY:
aidb/(core debugging library),aidb_mcp/(MCP server integration) - SECONDARY:
aidb_common/,aidb_logging/(supporting utilities) - EXCLUDED:
aidb_cli/(covered bydev-cli-developmentskill)
______________________________________________________________________
When to Use This Skill
Use this skill when:
- Understanding overall system architecture
- Tracing data flow across layers (e.g., MCP tool call → DAP adapter)
- Identifying component responsibilities
- Making architectural decisions (which layer to modify)
- Understanding design patterns and rationale
- Debugging cross-layer issues
Do NOT use this skill for:
- Deep adapter implementation patterns → Use
adapter-developmentskill - DAP protocol details → Use
dap-protocol-guideskill - MCP tool development → Use
mcp-tools-developmentskill
______________________________________________________________________
6-Layer Architecture
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: MCP Layer (aidb_mcp/) │
│ ├── 12 debugging tools for AI agents │
│ ├── Handler dispatch, response optimization │
│ └── Session management integration │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: Service Layer (aidb/service/) │
│ ├── DebugService - Main entry point │
│ ├── SessionManager, SessionBuilder (in aidb/session/) │
│ └── .execution / .stepping / .breakpoints / .variables │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: Session Layer (aidb/session/) │
│ ├── Session - Infrastructure hub │
│ ├── SessionState, SessionConnector │
│ ├── SessionRegistry, ResourceManager │
│ └── Parent-child session support (JavaScript) │
├─────────────────────────────────────────────────────────────┤
│ Layer 4: Adapter Layer (aidb/adapters/) │
│ ├── DebugAdapter - Component delegation base │
│ ├── ProcessManager, PortManager, LaunchOrchestrator │
│ └── Language Adapters - Python, JavaScript, Java │
├─────────────────────────────────────────────────────────────┤
│ Layer 5: DAP Client Layer (aidb/dap/client/) │
│ ├── DAPClient - Single request path │
│ ├── Transport, RequestHandler, EventProcessor │
│ └── MessageRouter, ConnectionManager │
├─────────────────────────────────────────────────────────────┤
│ Layer 6: Protocol Layer (aidb/dap/protocol/) │
│ └── Fully-typed DAP specification (see dap-protocol-guide) │
└─────────────────────────────────────────────────────────────┘______________________________________________________________________
Quick Navigation
"I want to understand..."
| Topic | Resource | Contents |
|---|---|---|
| MCP & Service Layers | api-mcp-layer.md | 12 tools, handler pattern, response system, DebugService, execution/stepping |
| Session Layer | session-layer.md | Infrastructure hub, SessionState, SessionConnector, parent-child sessions |
| Adapter Layer | adapter-architecture.md | DebugAdapter base, ProcessManager, PortManager, lifecycle hooks, Python/JS/Java |
| DAP Client | dap-client.md | Single request path, Future-based async, event handling, design decisions |
| Patterns & Resources | patterns-and-resources.md | Architectural principles, three-tier cleanup, resource management, data flows |
______________________________________________________________________
Key Architectural Principles
1. Component Delegation - Focused components vs monolithic classes 1. Language-Agnostic Design - Pluggable adapter architecture 1. Human-Cadence Debugging - Breakpoints before execution, one step at a time 1. Resource Lifecycle Management - Multi-tier cleanup with defense-in-depth 1. Parent-Child Session Support - JavaScript subprocess debugging 1. Single Request Path - No circular dependencies in DAP client 1. Three-Tier Cleanup - DAP disconnect → process termination → port release
For detailed explanations, see patterns-and-resources.md.
______________________________________________________________________
Resource Management Summary
Three-Tier Cleanup Strategy:
1. Tier 1: DAP disconnect (graceful adapter shutdown) 1. Tier 2: Process termination (SIGTERM → SIGKILL escalation) 1. Tier 3: Port release (registry updates)
Why Order Matters: Prevents port conflicts and orphaned processes.
Key Components:
- Process Registry (
aidb/resources/pids.py) - Port Registry (
aidb/resources/ports.py) - Orphan Cleanup (
aidb/resources/orphan_cleanup.py) - ResourceManager (
aidb/session/resource.py)
______________________________________________________________________
Related Skills
| Skill | Use For |
|---|---|
adapter-development | Language-specific adapter implementation patterns |
dap-protocol-guide | DAP protocol specification and usage |
mcp-tools-development | MCP tool creation and agent optimization |
______________________________________________________________________
Resources
| Resource | Content |
|---|---|
| api-mcp-layer.md | MCP server, 12 tools, handler pattern, Service layer, execution/stepping |
| session-layer.md | Session architecture, infrastructure hub, state management, parent-child |
| adapter-architecture.md | Adapter base class, components, lifecycle hooks, language-specific patterns |
| dap-client.md | DAP client design, single request path, Future-based async, events |
| patterns-and-resources.md | Architectural principles, resource management, cleanup, data flows |
Documentation:
- Architecture overview →
docs/developer-guide/overview.md - Component source →
src/aidb/,src/aidb_mcp/,src/aidb_cli/,src/aidb_common/,src/aidb_logging/
______________________________________________________________________
Quick Reference
6 Layers: MCP → Service → Session → Adapter → DAP Client → Protocol
Key Patterns: Component delegation, language-agnostic, human-cadence debugging, resource lifecycle, parent-child sessions, single request path
5 Resource Files: api-mcp-layer, session-layer, adapter-architecture, dap-client, patterns-and-resources
Adapter Layer Architecture
Layer Purpose: Language-specific debug adapter implementations providing consistent debugging interfaces for Python, JavaScript, and Java through component delegation.
Location: src/aidb/adapters/
Note: This document focuses on architecture. For deep implementation patterns, see the adapter-development skill.
______________________________________________________________________
Quick Reference
Looking for:
- Adapter structure → Section 1: DebugAdapter Base Class
- Core components → Section 2: Component Architecture
- Extension system → Section 3: Lifecycle Hooks System
- Language patterns → Section 4: Language Adapters
- Configuration → Section 5: Configuration Management
- Design patterns → Section 6: Key Design Patterns
______________________________________________________________________
1. DebugAdapter Base Class
1.1 Component Delegation Architecture
Location: src/aidb/adapters/base/adapter.py
What: Abstract base class for all language-specific debug adapters (Python, JavaScript, Java).
Why Component Delegation?
Problem: Monolithic "God Object" adapters become unmaintainable (1000+ lines, tight coupling, difficult testing).
Solution: Delegate responsibilities to focused components with single responsibilities.
Architecture:
DebugAdapter (abstract base)
├── ProcessManager - Process lifecycle (launch, monitor, stop, cleanup)
├── PortManager - Port allocation (acquire, release, track)
├── LaunchOrchestrator - Launch sequence coordination (hooks, port, process, verify)
└── Auxiliary Components (lazy-initialized)
├── AdapterTraceLogManager - Trace log management
├── AdapterOutputCapture - Stdout/stderr capture
└── AdapterBinaryLocator - Binary discovery1.2 Core Component Access
Pattern: Adapter delegates operations to components via composition
| Component | Access Pattern | Key Operations |
|---|---|---|
| ProcessManager | adapter.pid, adapter.is_alive, adapter.captured_output | launch_subprocess(), stop(), wait_for_adapter_ready(), cleanup_orphaned_processes() |
| PortManager | adapter.port | acquire(port), release() |
| LaunchOrchestrator | adapter._launch_orchestrator | launch(target, port, args), launch_with_config(launch_config, port, workspace_root) |
1.3 Auxiliary Components (Lazy-Initialized)
Pattern: Create on first access via properties to avoid unnecessary initialization
- AdapterTraceLogManager:
adapter.trace_manager- Trace log management - AdapterOutputCapture:
adapter.output_capture- Stdout/stderr capture - AdapterBinaryLocator:
adapter.adapter_locator- Binary discovery
1.4 Abstract Methods (Must Override)
Language adapters MUST implement:
`_build_launch_command(target, adapter_host, adapter_port, args)`
- Build adapter-specific command array
- Example (Python):
["python", "-m", "debugpy", "--listen", "host:port", target] - Example (Java): Raises
NotImplementedError(uses JDT LS bridge instead)
`_add_adapter_specific_vars(env)`
- Add language-specific environment variables
- Example (Python):
env["DEBUGPY_LOG_DIR"] = self.log_dir - Example (JavaScript):
env["NODE_OPTIONS"] = "--enable-source-maps"
`_get_process_name_pattern()`
- Pattern for orphan process detection
- Example (Python):
"debugpy" - Example (Java):
"jdtls"
1.5 Template Methods (Can Override)
`_prepare_environment()` - Multi-step environment preparation
def _prepare_environment(self) -> dict[str, str]:
env = self._load_base_environment() # Step 1: Base env
env = self._add_trace_configuration(env) # Step 2: Trace config
return self._add_adapter_specific_vars(env) # Step 3: Language-specific`get_launch_configuration()` - DAP launch request configuration
- Returns dict for DAP
LaunchRequest - Language-specific fields (e.g.,
justMyCodefor Python)
`get_trace_config()` - Trace logging configuration
- Returns dict for adapter trace settings
- Controls verbosity, output location
______________________________________________________________________
2. Component Architecture
2.1 ProcessManager
Location: src/aidb/adapters/base/components/process_manager.py
Responsibilities:
- Launch: Spawns subprocess with tagged environment variables (
AIDB_OWNER,AIDB_SESSION_ID,AIDB_PROCESS_TYPE), registers withResourceManager, captures stdout/stderr - Monitor: Polls port with exponential backoff (30s Java, 10s Python/JS), checks liveness, uses config-specific timeouts
- Stop: Graceful SIGTERM → forceful SIGKILL, recursive child termination via
psutil, handles zombies - Orphan Cleanup: Time-budgeted scan (5s min age), matches by environment variables, cross-references active sessions
Key Features: Process tagging for safe orphan detection, adaptive timeouts per language, recursive child management, async output capture to circular buffers
2.2 PortManager
Location: src/aidb/adapters/base/components/port_manager.py
Responsibilities:
- Acquire: Tries requested port, falls back to language ranges (Python: 6000-7000, JS: 9230-9800, Java: 5006-5020), registers with global
PortRegistry - Release: Returns port to pool, deregisters from
PortRegistry - Track: Property access via
port_manager.port
Integration: Delegates to session's ResourceManager (see resource-management.md)
2.3 LaunchOrchestrator
Location: src/aidb/adapters/base/components/launch_orchestrator.py
Orchestrates launch sequence: PRE_LAUNCH hooks → acquire port → build command → prepare environment → launch subprocess → wait for ready → POST_LAUNCH hooks → return (process, port)
VS Code Integration: Resolves launch.json configurations, supports variable substitution (${workspaceFolder}, ${file}), merges with adapter defaults via launch_with_config()
Error Handling: Centralized failure logging, port release on failure, process cleanup on failure
______________________________________________________________________
3. Lifecycle Hooks System
3.1 Hook Types
Location: src/aidb/adapters/base/hooks.py
What: Enum defining lifecycle extension points for adapters.
Hook Types:
Initialization:
PRE_INITIALIZE/POST_INITIALIZE
Launch/Attach:
PRE_LAUNCH/POST_LAUNCHPRE_ATTACH/POST_ATTACH
Breakpoints:
PRE_SET_BREAKPOINTS/POST_SET_BREAKPOINTS
Configuration:
PRE_CONFIGURATION_DONE/POST_CONFIGURATION_DONE
Process Lifecycle:
PRE_STOP/POST_STOPPRE_CLEANUP/POST_CLEANUP
Custom:
CUSTOM- Adapter-specific hooks
3.2 Priority System
Execution Order: Lower priority values execute first (0-100 scale)
Common Priorities:
90-100- Critical validation (blocks on failure)70-80- High priority (setup, early validation)50- Default priority20-30- Post-operation delays/waits10- Low priority (cleanup, logging)
Example:
# Execute in order: validate (90) → setup (50) → log (10)
self.register_hook(LifecycleHook.PRE_LAUNCH, self._validate_target, priority=90)
self.register_hook(LifecycleHook.PRE_LAUNCH, self._setup_trace, priority=50)
self.register_hook(LifecycleHook.PRE_LAUNCH, self._log_launch, priority=10)3.3 HookContext Object
What: Context object passed to all hook callbacks.
Fields:
adapter- The adapter instancesession- The debug sessiondata- Hook-specific data (mutable dictionary)cancelled- Set toTrueto cancel operationresult- Override operation result (error message when cancelled)
Cancellation Pattern:
def _validate_target_hook(self, context: HookContext) -> None:
target = context.data.get("target")
if not Path(target).exists():
context.cancelled = True
context.result = f"Target not found: {target}"
return3.4 Hook Registration
Pattern: Register during adapter initialization
def __init__(self, session, ctx=None, config=None, **kwargs):
super().__init__(session, ctx, config, **kwargs)
self._register_my_hooks()
def _register_my_hooks(self):
self.register_hook(
LifecycleHook.PRE_LAUNCH,
self._validate_environment,
priority=90
)
self.register_hook(
LifecycleHook.POST_LAUNCH,
self._wait_for_ready,
priority=20
)______________________________________________________________________
4. Language Adapters
Pattern: All adapters use hooks and initialization sequences defined in config.
Language-Specific Characteristics
| Aspect | Python (debugpy) | JavaScript (vscode-js-debug) | Java (JDT LS + java-debug) |
|---|---|---|---|
| Architecture | Direct debugpy adapter | Parent-child sessions | LSP-DAP bridge |
| Unique Features | Module mode (-m pytest), framework flags (Django/Flask), transport-only disconnect | Source maps, child DAP connections, breakpoint transfer via __pendingTargetId | JDT LS pooling, auto-compile, Maven/Gradle detection, dummy process |
| Init Sequence | Attach BEFORE initialized event | Child sets own breakpoints after parent setup | Extended timeouts (30s init, 10s BP verification) |
| Timeouts | 10s ready, 0.5s process | 10s ready, 0.5s process | 30s ready, 2s process |
| Hit Conditions | All modes supported | All modes supported | EXACT only (no operators) |
| Default Port | 5678 | 9229 | 5005 |
Key Implementation Details
Python (`src/aidb/adapters/lang/python/python.py`):
- Launch:
["python", "-m", "debugpy", "--listen", "host:port", "--wait-for-client", target, *args] - Lifecycle hooks: trace setup (priority 90), orphan cleanup (priority 85), wait for debugpy (priority 20)
- Trace management:
PythonTraceManagerconsolidates per-PID debugpy logs with rotation (last 5 files, 10MB size control)
JavaScript (`src/aidb/adapters/lang/javascript/javascript.py`):
- Launch:
["node", "/path/to/dapDebugServer.js", "9229"](single server handles parent + all children) - Parent-child pattern: Parent spawns children via
startDebuggingreverse request, each child creates separate DAP connection to same adapter server - TypeScript support: Auto-detect
.tsfiles, check forts-node, comprehensive source map configuration
Java (`src/aidb/adapters/lang/java/java.py`):
- Launch: Compile → Start JDT LS (or get from
JDTLSProjectPool) → Open file → Resolve classpath → Start debug session → Create dummy process - Bridge management:
JavaLSPDAPBridgemanages JDT LS lifecycle, pooled instances skip DAP disconnect to avoid freeze - Compilation:
JavaCompilationManagerauto-compiles.javato.classifauto_compile=True
For detailed implementation patterns: See adapter-development skill.
______________________________________________________________________
5. Configuration Management
Location: src/aidb/adapters/base/config.py
AdapterConfig (Base): Dataclass defining language, ports, timeouts, file extensions, and capability declarations.
Key Method: get_initialization_sequence() returns ordered InitializationOp list (language-specific).
Language-Specific Configs:
- PythonAdapterConfig (`src/aidb/adapters/lang/python/config.py`): Framework flags (django, flask, pytest), debugging options (justMyCode, subProcess), all hit conditions supported
- JavaScriptAdapterConfig (`src/aidb/adapters/lang/javascript/config.py`): Adapter type (pwa-node/chrome/msedge), source maps, child session coordination, all hit conditions supported
- JavaAdapterConfig (`src/aidb/adapters/lang/java/config.py`): JDK/JDT LS paths, auto-compile, classpath/vmargs, EXACT hit condition only
For full field reference: See implementation files in src/aidb/adapters/lang/*/config.py
______________________________________________________________________
6. Key Design Patterns
6.1 Component Delegation
Problem: Monolithic adapter classes (1000+ lines, tight coupling) Solution: Delegate to focused components (ProcessManager, PortManager, LaunchOrchestrator) Benefit: Independent testing, modification, understanding
6.2 Lazy Initialization
Problem: Not all utilities needed for every operation Solution: Create auxiliary components on first access via properties Benefit: Avoids unnecessary initialization, reduces memory usage
6.3 Priority-Based Hooks
Problem: Multiple concerns at same lifecycle point Solution: Hook system with priority-based execution (90=validate, 50=setup, 10=log) Benefit: Independent concerns without method overrides
6.4 Template Method
Problem: Environment preparation has common + language-specific steps Solution: Base class defines algorithm (_prepare_environment()), subclasses override steps (_add_adapter_specific_vars()) Benefit: Reuses common logic, customizes specific steps
______________________________________________________________________
Quick Reference
Language Quirks:
- Python: Module mode, attach before initialized, transport-only disconnect
- JavaScript: Parent-child sessions, separate child DAP, breakpoint transfer
- Java: LSP-DAP bridge, JDT LS pool, compilation manager, dummy process
Hook Priorities: 90-100 (validate), 70-80 (setup), 50 (default), 20-30 (post-op), 10 (cleanup/log)
Key Files: Base adapter (adapter.py), components (process_manager.py, port_manager.py, launch_orchestrator.py), hooks (hooks.py), language adapters (python/python.py, javascript/javascript.py, java/java.py)
For Deep Dives: See adapter-development skill for implementation patterns and HOW-TO guides.
MCP & Service Layers
The top two layers of AIDB: MCP server for AI agents and Service layer for debugging operations.
MCP Layer (aidb_mcp/)
Purpose: Model Context Protocol server exposing 12 debugging tools to AI agents.
Architecture
Client (AI Agent) → stdio → AidbMCPServer
├── _handle_list_tools() → Return tool definitions
├── _handle_call_tool() → Execute tool, return response
└── _handle_list_resources() → Return debugging resources
↓
TOOL_HANDLERS registry → DebugServiceThe 12 Tools
| Tool | Purpose | Handler Location |
|---|---|---|
aidb.init | Initialize debugging context | handlers/session/initialization.py |
aidb.session_start | Create and start debug session | handlers/session/lifecycle.py |
aidb.execute | Run/continue actions | handlers/execution/control.py |
aidb.step | Step over/into/out | handlers/execution/stepping.py |
aidb.inspect | Inspect locals/globals/stack/threads | handlers/inspection/state_inspection.py |
aidb.breakpoint | Set/remove/list/clear breakpoints | handlers/inspection/breakpoints.py |
aidb.variable | Get/set/patch variables | handlers/inspection/variables.py |
aidb.session | Status/list/stop/restart/switch | handlers/session/management.py |
aidb.config | Config, env vars, launch.json | handlers/session/configuration.py |
aidb.context | Rich debugging context | handlers/context/handler.py |
aidb.run_until | Temporary breakpoints | handlers/execution/run_until.py |
aidb.adapter | Download/install adapters | handlers/adapter_download.py |
Handler Pattern
@mcp_tool()
async def handle_step(args: dict) -> dict:
# 1. Validate init completed (via decorator)
# 2. Get injected parameters from decorator:
service = args["_service"] # DebugService instance
context = args["_context"] # MCPSessionContext
session_id = args["_session_id"]
# 3. Validate params
# 4. Call DebugService: await service.stepping.step_over(thread_id)
# 5. Update context
# 6. Return Response().to_mcp_response()@mcp_tool Decorator Stack
The @mcp_tool() decorator provides a standardized wrapper for all handlers:
@timed # 1. Performance tracking
@audit_operation # 2. Audit logging (persistent trail)
@with_thread_safety # 3. Thread safety + session injection
@with_parameter_validation # 4. Parameter validation (optional)
@with_execution_context # 5. Context capture + history recordingResponse System
Base Response → auto-serializes dataclass fields + to_mcp_response() ErrorResponse → success=False, error_code, error_message ResponseDeduplicator → removes redundant fields (30-50% token savings)
Session Management
MCP Session (1) → DebugService (1) → aidb.Session (1+)
→ MCPSessionContext (1)MCPSessionContext tracks: current position, execution state, breakpoints, init status, stack/variable history.
______________________________________________________________________
Service Layer (aidb/service/)
Purpose: Stateless service layer providing debugging operations on a Session.
Core Components
DebugService (debug_service.py) - Main entry point
class DebugService:
"""Stateless debugging operations on a Session."""
def __init__(self, session: Session) -> None:
self._session = session
self.execution = ExecutionControl(session)
self.stepping = SteppingService(session)
self.breakpoints = BreakpointManager(session)
self.variables = VariableInspector(session)
self.stack = StackNavigator(session)SessionBuilder (session/builder.py) - Fluent construction
with_target(),with_attach(),with_language()with_launch_config()for VS Code launch.jsonwith_breakpoints(),with_timeout()
SessionManager (session/manager.py) - Lifecycle management
- Thread-safe session count (max 10 concurrent)
- Creates sessions via SessionBuilder
Operations by Namespace
Execution Control (service.execution):
continue_(),pause(),restart(),terminate()get_current_thread_id(),get_output()
Stepping (service.stepping):
step_into(),step_over(),step_out(),step_back()get_current_thread_id()
Breakpoints (service.breakpoints):
set(),remove(),list(),clear_all()watch(),unwatch()(watchpoints)
Variables (service.variables):
evaluate(),set_variable(),set_expression()locals_(),globals_(),scopes()
Stack (service.stack):
callstack(),threads(),exception()get_current_thread_id(),get_current_frame_id()
Child Session Resolution
JavaScript uses parent-child sessions. Service resolves to active session automatically:
@property
def session(self) -> Session:
return resolve_active_session(self._session, self.ctx)______________________________________________________________________
Key Files
MCP:
aidb_mcp/server/app.py- AidbMCPServeraidb_mcp/handlers/registry.py- TOOL_HANDLERSaidb_mcp/core/decorators.py- @mcp_tool decoratoraidb_mcp/responses/base.py- Response classesaidb_mcp/session/manager.py- Session management
Service:
aidb/service/debug_service.py- DebugServiceaidb/service/execution/control.py- ExecutionControlaidb/service/execution/stepping.py- SteppingServiceaidb/service/breakpoints/manager.py- BreakpointManageraidb/service/variables/inspector.py- VariableInspectoraidb/service/stack/navigator.py- StackNavigator
Session:
aidb/session/builder.py- SessionBuilderaidb/session/manager.py- SessionManager
DAP Client Layer
The DAP client layer (src/aidb/dap/client/) provides the foundation for all Debug Adapter Protocol communication in AIDB.
Position in Architecture:
Session Layer (src/aidb/session/)
↓
DAP Client Layer (src/aidb/dap/client/) ← YOU ARE HERE
↓
Protocol Layer (src/aidb/dap/protocol/)
↓
Debug Adapters (debugpy, vscode-js-debug, java-debug-server)Related Skills: dap-protocol-guide (DAP specification), adapter-development (adapter integration)
______________________________________________________________________
Core Design Decisions
1. Single Request Path
Problem: Multiple components sending requests directly → race conditions, duplicate sequence numbers, circular dependencies.
Solution: ALL requests MUST go through DAPClient.send_request():
# ✅ CORRECT: Use single entry point
response = await client.send_request(request)
# ❌ WRONG: Never bypass DAPClient
# await client.transport.send_message(request) # FORBIDDENEnforcement: Semaphore serializes requests, transport is private, components can't access sequence numbers.
2. No Requests in Event Handlers
Problem: Event handlers sending requests → deadlocks (receiver thread blocked waiting for response it can't receive).
Solution: Event handlers ONLY update state and signal futures. Listeners (user code) CAN send requests, internal handlers CANNOT.
# ❌ WRONG: Deadlock
def handle_terminated(event):
await client.send_request(DisconnectRequest(...)) # Blocked forever
# ✅ CORRECT: Update state only
def _handle_terminated(self, event: Event) -> None:
self._state.terminated = True
for future in self._terminated_listeners:
if not future.done():
future.set_result(event)3. Future-Based Async
Each request creates asyncio.Future[Response] for clean timeout, cancellation, and cross-task correlation.
4. Component Composition
Each concern is a separate component (Transport, RequestHandler, EventProcessor, etc.) wired together. DAPClient composes these and exposes a clean facade.
______________________________________________________________________
Components
DAPClient - Main Orchestrator
File: src/aidb/dap/client/client.py
Key Methods:
send_request(request, timeout, retry_config)- THE single entry pointsend_request_no_wait(request)- Fire-and-forget for deferred responsesconnect(),disconnect(),reconnect()- Connection lifecyclewait_for_stopped(),wait_for_event(event_type)- Event synchronizationeventsproperty - Exposes PublicEventAPI for subscriptions
Component Composition:
self._transport = DAPTransport(host, port, ctx)
self._state = SessionState()
self._event_processor = EventProcessor(self._state, ctx)
self._public_events = PublicEventAPI(self._event_processor, ctx)
self._request_handler = RequestHandler(transport=self._transport, ctx=ctx)
self._connection_manager = ConnectionManager(transport, state, ctx)
self._message_router = MessageRouter(ctx)
self._reverse_request_handler = ReverseRequestHandler(ctx)DAPTransport - TCP Communication
File: src/aidb/dap/client/transport.py
Raw TCP with Content-Length header framing. IPv4/IPv6 fallback, async-safe sending.
Content-Length: 119\r\n
\r\n
{"seq":1,"type":"request","command":"initialize","arguments":{...}}RequestHandler - Request/Response Lifecycle
File: src/aidb/dap/client/request_handler.py
Manages request/response correlation using Future-based async pattern.
Request Lifecycle:
1. Generate sequence number (thread-safe) 1. Create Future, store in _pending_requests[seq] 1. Send via transport 1. Wait for response (or timeout) 1. Future resolved when response arrives
Execution-Aware Pattern: For continue/step commands, register terminated/stopped listeners BEFORE sending to prevent race conditions.
EventProcessor - Event Dispatching
File: src/aidb/dap/client/events.py
Route events to subscribers and update session state. CRITICAL: Event handlers NEVER send requests.
Dispatch table: Maps event types to handlers (initialized, stopped, continued, terminated, output).
MessageRouter - Message Type Routing
File: src/aidb/dap/client/message_router.py
Routes incoming messages based on type: response → RequestHandler, event → EventProcessor, request → ReverseRequestHandler.
ConnectionManager - Connection Lifecycle
File: src/aidb/dap/client/connection_manager.py
Manage connection lifecycle, reconnection with backoff. CRITICAL: Send DisconnectRequest BEFORE closing transport (essential for pooled adapters like Java JDT LS).
PublicEventAPI - Type-Safe Subscriptions
File: src/aidb/dap/client/public_events.py
Clean public API wrapping EventProcessor. Supports subscriptions (persistent) and waits (one-time).
# Persistent subscription
subscription_id = client.events.subscribe_to_event(EventType.STOPPED.value, handler)
# One-time wait
event = await client.events.wait_for_event_async(EventType.STOPPED.value)______________________________________________________________________
Integration Flows
Request Flow
User Code → DAPClient.send_request() ← SINGLE ENTRY POINT
→ RequestHandler.send_request()
→ Acquire semaphore, generate seq, create Future
→ DAPTransport.send_message()
→ [TCP Socket] → Debug Adapter
[Response returns]
Debug Adapter → [TCP] → DAPTransport.receive_message()
→ MessageRouter → RequestHandler.handle_response()
→ future.set_result(response) ← Completes awaitEvent Flow
Debug Adapter → [TCP] → DAPTransport.receive_message()
→ MessageRouter (type="event")
→ EventProcessor.process_event()
→ Update state, signal futures, notify listeners
→ [NO REQUEST SENT - one-way only]______________________________________________________________________
Quick Reference
Common Tasks
Adding a New Request Type: Use existing protocol types, call client.send_request(YourRequest(...)). No changes to DAP client needed.
Subscribing to Events:
subscription_id = client.events.subscribe_to_event(EventType.STOPPED.value, handler)
event = await client.events.wait_for_event_async(EventType.STOPPED.value)
client.events.unsubscribe_from_event(subscription_id)Debugging Connection Issues: Check client.get_connection_status(), enable AIDB_LOG_LEVEL=DEBUG, verify adapter process running.
Common Mistakes
| Don't | Do |
|---|---|
| Access transport directly | Use DAPClient.send_request() |
| Send requests from event handlers | Update state, defer requests to caller |
| Assume synchronous event order | Use await client.wait_for_stopped() |
______________________________________________________________________
Key Takeaways
1. Single Request Path - All requests through DAPClient.send_request() prevents race conditions 1. Event Handlers Never Send Requests - Prevents receiver deadlocks 1. Future-Based Async - Provides timeout, cancellation, async integration 1. Component Composition - Each concern focused, testable, maintainable
Architectural Patterns & Resource Management
Core design patterns and resource lifecycle management for AIDB.
______________________________________________________________________
Architectural Principles
1. Component Delegation (Not God Objects)
Problem: Monolithic classes become unmaintainable.
Solution: Delegate responsibilities to focused components with single responsibilities.
Examples:
Session→SessionState,SessionConnector,ResourceManagerDebugService→ExecutionControl,SteppingService,BreakpointManager,VariableInspector,StackNavigatorDebugAdapter→ProcessManager,PortManager,LaunchOrchestratorDAPClient→Transport,RequestHandler,EventProcessor
2. Language-Agnostic Design
Pluggable adapter architecture: abstract DebugAdapter base class, language adapters override abstract methods, common DAP client for all languages.
# Same API for all languages
session = api.session_builder.python_module("script.py").build()
session = api.session_builder.javascript_file("app.js").build()
session = api.session_builder.java_class("Main").build()3. Human-Cadence Debugging
Operations happen at human speed, not API speed:
- Breakpoints before execution (for fast programs)
- Inspection on paused programs only
- Stepping is sequential (one line at a time)
4. Single Request Path (DAP Client)
ALL requests through DAPClient.send_request(). Event handlers NEVER send requests. See dap-client.md.
5. Three-Tier Cleanup
Resources cleaned in reverse dependency order: DAP → Process → Port. See below.
______________________________________________________________________
Resource Management
AIDB uses defense-in-depth: global registries + per-session managers + orphan cleanup.
Global Process Registry
File: src/aidb/resources/pids.py
Process Group Termination: Debug adapters spawn child processes. Killing just the adapter PID leaves children orphaned. Process groups ensure ALL processes terminated together.
# Two-phase termination
for pgid in self._process_groups.get(session_id, []):
os.killpg(pgid, signal.SIGTERM) # Graceful
for proc in processes:
proc.terminate() # SIGTERM
await asyncio.wait_for(proc.wait(), timeout=5.0)
# If timeout:
proc.kill() # SIGKILLGlobal Port Registry
File: src/aidb/resources/ports.py
Cross-Process Coordination: File-based locking (fcntl.flock) + socket reservation.
Socket Reservation eliminates TOCTOU race:
# Without reservation (RACE):
if port_free(): # Process A checks
# [Process B steals port here]
bind(port) # Process A fails!
# With reservation (SAFE):
sock = bind(port) # Process A holds socket
# Process B cannot bind
adapter.bind(port) # Process A releases, adapter bindsLanguage-Specific Port Ranges: Python (5678+), JavaScript (9229+), Java (5005+).
Three-Tier Cleanup Strategy
File: src/aidb/session/resource.py
Order is critical. Changing order causes port conflicts and orphaned processes.
Tier 1: DAP Disconnect
- Send DAP
disconnectrequest - Allows adapter to gracefully shutdown
- Adapter terminates its own children
Tier 2: Process Termination
- SIGTERM to process groups
- SIGTERM → SIGKILL escalation for individuals
- Ensures resources freed
Tier 3: Port Release
- Close reserved sockets
- Update registries (in-process and cross-process)
- Ports available for reallocation
Why This Order:
- DAP first → Adapter cleans children gracefully
- Process second → Ensures port released at OS level
- Port third → Registry updated, port reusable
Orphan Cleanup
File: src/aidb/resources/orphan_cleanup.py
Environment variable tagging for reliable detection:
env["AIDB_OWNER"] = "aidb"
env["AIDB_SESSION_ID"] = session_id
env["AIDB_PROCESS_TYPE"] = "adapter"Orphan Criteria (ALL must be true):
AIDB_OWNER == "aidb"- Session ID not in active sessions
- Age > 60s (race condition protection)
- Not pool resource
______________________________________________________________________
Data Flow Summary
Layer-by-Layer Transformations:
1. MCP → API - JSON → Python args 1. API → Session - User params → Domain models 1. Session → Adapter - Models → Adapter config 1. Adapter → DAP - Config → Protocol requests 1. DAP → Transport - Typed → JSON bytes
Key Flows:
| Flow | Layers | Notes |
|---|---|---|
| Session Start | All 6 | Most complex: port allocation, process launch, DAP init, breakpoints |
| Stopped Event | 5-1 | Adapter → Transport → Router → EventProcessor → State update |
| Variable Inspection | 1-5 | Multiple DAP requests: threads, stack, scopes, variables |
| Cleanup | 3-tier | DAP disconnect → Process termination → Port release |
Status Progression: NOT_STARTED → INITIALIZING → CONNECTED → RUNNING → PAUSED ↔ RUNNING → TERMINATED
______________________________________________________________________
Quick Reference
Key Design Decisions
| Decision | Why |
|---|---|
| Component Delegation | Testability, maintainability, readability |
| Language-Agnostic Interface | Same Python interface for Python/JS/Java |
| Human-Cadence Debugging | Matches real debugger usage |
| Single Request Path | Prevents race conditions, deadlocks |
| Three-Tier Cleanup | Defense-in-depth, prevents leaks |
| Socket Reservation | Eliminates TOCTOU races |
| Environment Tagging | Reliable orphan detection |
When to Apply
| Pattern | Apply When |
|---|---|
| Component Delegation | Class exceeds 300 lines |
| Language-Agnostic | Adding new language support |
| Human-Cadence | Documenting workflows, designing MCP tools |
| Resource Lifecycle | Creating new resource types, debugging leaks |
| Three-Tier Cleanup | Modifying Session.stop(), cleanup logic |
Debugging Tips
- Enable trace logging:
AIDB_LOG_LEVEL=DEBUG AIDB_ADAPTER_TRACE=1 - Check session status:
session.status - Verify DAP connection:
session.dap.is_connected - Inspect breakpoints:
session.breakpoints - Check for orphans:
ps aux | grep debugpy - Check for port leaks:
lsof -i :PORT
Session Layer Architecture
The session layer (src/aidb/session/) is the infrastructure hub of AIDB, managing debugging session lifecycle and coordinating language-specific adapters with DAP client connections.
Related Skills: adapter-development (adapter integration), dap-protocol-guide (DAP client interactions), testing-strategy (testing session lifecycle)
______________________________________________________________________
Core Principle: Infrastructure Only
Problem: Monolithic session classes become unwieldy (1000+ lines) when mixing infrastructure with business logic.
Solution: Session is a thin infrastructure layer that delegates:
- Infrastructure (connection, state, resources) → Session components
- Debugging operations (step, continue, breakpoints) → Service layer (
src/aidb/service/)
class Session:
def __init__(self, adapter, config):
self._state = SessionState()
self._connector = SessionConnector(self)
self._resources = ResourceManager(config)
# NOTE: No debug operations - those are in DebugService
@property
def state(self) -> SessionState:
return self._state
@property
def dap(self) -> DAPClient:
return self._connector.dap______________________________________________________________________
Components
Session - Infrastructure Hub
File: src/aidb/session/session_core.py
Coordinates infrastructure components and provides unified interface. Does NOT implement debugging logic.
Responsibilities: Initialize components in correct order, expose properties for component access, provide lifecycle methods (start(), cleanup()), register with SessionRegistry.
SessionState - Status Computation
File: src/aidb/session/state.py
Compute session status based on multiple state factors with precedence rules.
Precedence Logic:
1. If self._error is set → SessionStatus.ERROR 1. If not initialized → SessionStatus.INITIALIZED 1. If child session and stopped → SessionStatus.STOPPED 1. Evaluate DAP connection state 1. Evaluate adapter process state
Key Pattern: Status is COMPUTED, not stored. Every call to get_status() evaluates current conditions.
SessionConnector - DAP Connection Lifecycle
File: src/aidb/session/connector.py
Manage DAP client connection lifecycle independently from session creation.
Connection Flow:
1. session.connector.connect() called 1. DAPClient created, transport started 1. DAP handshake: initialize request 1. Launch/attach request based on config 1. configurationDone request 1. state.set_initialized() called 1. Deferred event handlers registered
Stub Events API: Before DAP connection exists, session.events.on() stores handlers in queue. After connection, handlers registered with real DAPClient.
InitializationMixin - DAP Sequence Handling
File: src/aidb/session/ops/initialization.py
Handles the complex DAP initialization sequence:
InitializationMixin- DAP sequence: initialize → launch/attach → breakpoints → configurationDone
Note: Orchestration and introspection operations have moved to the Service layer (src/aidb/service/).
SessionRegistry - Global Session Tracking
File: src/aidb/session/registry.py
Thread-safe global access to all active sessions using threading.RLock (reentrant for nested cleanup operations).
Why Global Registry: JavaScript/TypeScript creates child sessions for subprocesses that need to find their parent.
ResourceManager - Three-Tier Cleanup
File: src/aidb/session/resource.py
Orchestrates three-tier cleanup strategy (DAP → processes → ports). See patterns-and-resources.md for details.
Parent-Child Sessions (JavaScript)
Files: src/aidb/session/child_registry.py, src/aidb/adapters/lang/javascript/javascript.py
JavaScript subprocess debugging creates child sessions that share parent's DAP client.
Key Pattern: Child sets self._parent_session_id, SessionConnector skips DAP client creation. Events routed by thread ID.
______________________________________________________________________
Initialization Order (Critical)
Components initialize in specific order due to dependencies:
1. SessionState - No dependencies 1. ResourceManager - No dependencies 1. SessionConnector - Needs state for initialization status 1. Adapter assignment - Session holds adapter reference
______________________________________________________________________
Design Decisions
Infrastructure vs Operations
Session handles infrastructure (connection, state, resources). Debugging operations (step, continue, breakpoints, variables) live in the Service layer. This separation provides:
- Clear boundaries between infrastructure and business logic
- Stateless operations that are easier to test
- Clean MCP integration (handlers use DebugService)
Thread-Safe Registries with RLock
Cleanup flow acquires lock to unregister session. During unregister, child cleanup may trigger, which also needs lock. RLock allows same thread to acquire again.
Stub Events API for Deferred Connection
Adapters register event handlers during start_session(), but DAP connection doesn't exist yet. Stub API queues handlers until connection succeeds.
Parent-Child DAP Client Sharing
DAP spec allows one connection per debug adapter instance. Node.js debugger handles all subprocesses on one connection, distinguishing by thread IDs.
______________________________________________________________________
Quick Reference
Where to Look
| Task | Location |
|---|---|
| Adding a new session status | src/aidb/session/state.py + src/aidb/models/entities/session.py |
| Debugging connection issues | src/aidb/session/connector.py |
| Adding a new debugging operation | src/aidb/service/{execution,breakpoints,variables,stack}/ |
| Fixing resource leaks | src/aidb/session/resource.py |
| Working with parent-child sessions | src/aidb/session/child_registry.py |
| DAP initialization sequence | src/aidb/session/ops/initialization.py |
Common Mistakes
| Don't | Why |
|---|---|
| Set status directly | Status is computed via get_status(), not stored |
| Create multiple DAP clients | One per debug adapter instance; child sessions share parent's |
Access session.dap before connection | SessionConnector raises exception |
| Implement debug logic in Session | Session is infrastructure; use DebugService for operations |
| Skip adapter resource registration | Cleanup can't release unregistered resources |
Debugging Tips
- Enable logging:
AIDB_LOG_LEVEL=DEBUG - Check session state:
session.state.get_status()andsession.state._error - Verify cleanup: Check for orphaned processes (
ps aux | grep debugpy) and ports (lsof -i :PORT)
Related skills
FAQ
What layers does AIDB have?
Six: MCP, Service, Session, Adapter, DAP Client and Protocol.
When should I not use this skill?
For adapter implementation, DAP protocol details or MCP tool development, which have dedicated AIDB skills.