- Created 02-02-SUMMARY.md with implementation details - Updated STATE.md: Plan 2 of 3 complete, 50% progress - Added decisions: onContextSwitched callback, SSH context ID format - Updated metrics: 3 plans completed, 5 min average - No deviations from plan
257 lines
7.7 KiB
Markdown
257 lines
7.7 KiB
Markdown
---
|
|
phase: 02-service-infrastructure
|
|
plan: 02
|
|
subsystem: main-process
|
|
tags: [registry-integration, ipc-refactoring, ssh-context-management]
|
|
dependency-graph:
|
|
requires: [02-01]
|
|
provides: [registry-based-service-routing]
|
|
affects: [all-ipc-handlers, ssh-connect-flow]
|
|
tech-stack:
|
|
added: []
|
|
patterns: [registry-routing, dynamic-service-resolution, context-switching]
|
|
key-files:
|
|
created: []
|
|
modified:
|
|
- src/main/index.ts
|
|
- src/main/ipc/handlers.ts
|
|
- src/main/ipc/projects.ts
|
|
- src/main/ipc/sessions.ts
|
|
- src/main/ipc/search.ts
|
|
- src/main/ipc/subagents.ts
|
|
- src/main/ipc/ssh.ts
|
|
decisions:
|
|
- "File watcher event rewiring handled by exported onContextSwitched callback from index.ts"
|
|
- "SSH handler imports onContextSwitched dynamically to avoid circular dependencies"
|
|
- "Context ID for SSH uses simple format: ssh-{host}"
|
|
- "Destroy existing SSH context on reconnection to same host"
|
|
metrics:
|
|
duration: 6
|
|
completed: 2026-02-12
|
|
---
|
|
|
|
# Phase 02 Plan 02: Registry Integration Summary
|
|
|
|
**Registry-based service routing with multi-context SSH support**
|
|
|
|
## Objective Achieved
|
|
|
|
Replaced global service variables in main/index.ts with ServiceContextRegistry, updated all IPC handlers to route through registry.getActive(), and implemented SSH context creation/destruction flow.
|
|
|
|
## Tasks Completed
|
|
|
|
### Task 1: Refactor main/index.ts to use ServiceContextRegistry
|
|
|
|
**Changed:**
|
|
- Removed global service variables (projectScanner, sessionParser, subagentResolver, chunkBuilder, dataCache, fileWatcher, cleanupInterval)
|
|
- Added `contextRegistry: ServiceContextRegistry`
|
|
- Removed `handleModeSwitch` callback entirely
|
|
- Created `wireFileWatcherEvents(context)` helper to manage event listener cleanup
|
|
- Created `onContextSwitched(context)` export for SSH handler to call
|
|
|
|
**Implementation:**
|
|
```typescript
|
|
// Create ServiceContextRegistry
|
|
contextRegistry = new ServiceContextRegistry();
|
|
|
|
// Create local context
|
|
const localContext = new ServiceContext({
|
|
id: 'local',
|
|
type: 'local',
|
|
fsProvider: new LocalFileSystemProvider(),
|
|
});
|
|
|
|
// Register and start
|
|
contextRegistry.registerContext(localContext);
|
|
localContext.start();
|
|
|
|
// Wire file watcher events
|
|
wireFileWatcherEvents(localContext);
|
|
|
|
// Initialize IPC handlers with registry
|
|
initializeIpcHandlers(contextRegistry, updaterService, sshConnectionManager);
|
|
```
|
|
|
|
**handlers.ts changes:**
|
|
- Changed `initializeIpcHandlers` to accept `ServiceContextRegistry` instead of individual services
|
|
- Removed `reinitializeServiceHandlers` entirely (no longer needed)
|
|
- Updated all domain handler initialize calls to pass registry
|
|
|
|
**Files modified:**
|
|
- src/main/index.ts (111 insertions, 161 deletions)
|
|
- src/main/ipc/handlers.ts
|
|
|
|
**Commit:** 5bf41c6
|
|
|
|
### Task 2: Update domain IPC handlers to route via registry
|
|
|
|
**Pattern applied to all handlers:**
|
|
```typescript
|
|
let registry: ServiceContextRegistry;
|
|
|
|
export function initialize{Domain}Handlers(contextRegistry: ServiceContextRegistry): void {
|
|
registry = contextRegistry;
|
|
}
|
|
|
|
async function handleXxx(...): Promise<...> {
|
|
const { projectScanner, sessionParser, ... } = registry.getActive();
|
|
// Use services
|
|
}
|
|
```
|
|
|
|
**projects.ts:**
|
|
- Changed signature to `initializeProjectHandlers(registry: ServiceContextRegistry)`
|
|
- Resolve `projectScanner` via `registry.getActive()` in each handler
|
|
- 3 handlers updated
|
|
|
|
**sessions.ts:**
|
|
- Changed signature to `initializeSessionHandlers(registry: ServiceContextRegistry)`
|
|
- Destructure all services from `registry.getActive()` at invocation time
|
|
- 6 handlers updated
|
|
|
|
**search.ts:**
|
|
- Changed signature to `initializeSearchHandlers(registry: ServiceContextRegistry)`
|
|
- Resolve `projectScanner` via `registry.getActive()`
|
|
- 1 handler updated
|
|
|
|
**subagents.ts:**
|
|
- Changed signature to `initializeSubagentHandlers(registry: ServiceContextRegistry)`
|
|
- Resolve all services from `registry.getActive()`
|
|
- Still passes fsProvider and projectsDir to buildSubagentDetail as before
|
|
- 1 handler updated
|
|
|
|
**ssh.ts:**
|
|
- Changed signature to `initializeSshHandlers(manager, registry)`
|
|
- Removed `onModeSwitch` callback parameter
|
|
- **SSH_CONNECT handler:**
|
|
- Creates new `ServiceContext` with SSH provider
|
|
- Registers in registry
|
|
- Starts context
|
|
- Switches registry to new context
|
|
- Dynamically imports `onContextSwitched` from index.ts and calls it
|
|
- **SSH_DISCONNECT handler:**
|
|
- Switches registry back to 'local'
|
|
- Destroys SSH context
|
|
- Calls `onContextSwitched` with local context
|
|
- All other SSH handlers unchanged (test, getConfigHosts, etc.)
|
|
|
|
**Files modified:**
|
|
- src/main/ipc/projects.ts
|
|
- src/main/ipc/sessions.ts
|
|
- src/main/ipc/search.ts
|
|
- src/main/ipc/subagents.ts
|
|
- src/main/ipc/ssh.ts (100 insertions, 70 deletions)
|
|
|
|
**Commit:** 24051ac
|
|
|
|
## Deviations from Plan
|
|
|
|
None - plan executed exactly as written.
|
|
|
|
## Verification Results
|
|
|
|
**Type checking:** ✅ Pass
|
|
```
|
|
pnpm typecheck — zero errors
|
|
```
|
|
|
|
**Tests:** ✅ Pass
|
|
```
|
|
Test Files: 31 passed
|
|
Tests: 494 passed
|
|
Duration: 4.88s
|
|
```
|
|
|
|
**Code inspection:** ✅ Pass
|
|
- main/index.ts has `contextRegistry` instead of individual service globals
|
|
- `reinitializeServiceHandlers` no longer exists in handlers.ts
|
|
- All IPC handlers use `registry.getActive()` pattern (12 occurrences)
|
|
- SSH connect creates ServiceContext and registers it
|
|
- SSH disconnect destroys SSH context and switches to local
|
|
- File watcher events rewired via onContextSwitched callback
|
|
|
|
## Architecture Impact
|
|
|
|
**Before (single-context):**
|
|
```
|
|
main/index.ts:
|
|
let projectScanner: ProjectScanner
|
|
let sessionParser: SessionParser
|
|
...
|
|
|
|
IPC handlers:
|
|
let projectScanner = /* set at init */
|
|
function handleXxx() {
|
|
projectScanner.scan() // always uses same instance
|
|
}
|
|
|
|
SSH connect:
|
|
recreate all services with new provider
|
|
call reinitializeServiceHandlers()
|
|
```
|
|
|
|
**After (multi-context):**
|
|
```
|
|
main/index.ts:
|
|
let contextRegistry: ServiceContextRegistry
|
|
contextRegistry.registerContext(localContext)
|
|
|
|
IPC handlers:
|
|
let registry: ServiceContextRegistry
|
|
function handleXxx() {
|
|
const { projectScanner } = registry.getActive()
|
|
projectScanner.scan() // dynamically resolved
|
|
}
|
|
|
|
SSH connect:
|
|
create new ServiceContext
|
|
registry.registerContext(sshContext)
|
|
registry.switch('ssh-host')
|
|
// local context stays alive in background
|
|
```
|
|
|
|
**Key improvements:**
|
|
1. **No service recreation** - contexts are isolated, switching is instant
|
|
2. **Local context persists** - can switch back without re-initialization
|
|
3. **No reinitializeServiceHandlers** - dynamic routing eliminates the need
|
|
4. **Clean separation** - SSH connection management vs. service context management
|
|
5. **File watcher stays alive** - only pause/resume on switch
|
|
|
|
## Next Steps
|
|
|
|
**Phase 02 Plan 03 (SSH notification manager integration):**
|
|
- Set NotificationManager on SSH context's FileWatcher
|
|
- Ensure error detection works for SSH sessions
|
|
- Wire up SSH context file watcher to NotificationManager
|
|
|
|
**Phase 03 (Renderer state management):**
|
|
- Snapshot/restore Zustand state on context switch
|
|
- Validate tab restoration against current context
|
|
- Update workspace indicators in sidebar
|
|
|
|
## Self-Check
|
|
|
|
**Created files exist:** N/A (no new files created)
|
|
|
|
**Modified files verified:**
|
|
```
|
|
✓ src/main/index.ts — uses contextRegistry
|
|
✓ src/main/ipc/handlers.ts — accepts registry, no reinitialize function
|
|
✓ src/main/ipc/projects.ts — routes via registry.getActive()
|
|
✓ src/main/ipc/sessions.ts — routes via registry.getActive()
|
|
✓ src/main/ipc/search.ts — routes via registry.getActive()
|
|
✓ src/main/ipc/subagents.ts — routes via registry.getActive()
|
|
✓ src/main/ipc/ssh.ts — creates/destroys ServiceContext
|
|
```
|
|
|
|
**Commits exist:**
|
|
```
|
|
✓ 5bf41c6 — refactor(02-02): main/index.ts to use ServiceContextRegistry
|
|
✓ 24051ac — refactor(02-02): IPC handlers route via ServiceContextRegistry
|
|
```
|
|
|
|
**Self-Check: PASSED**
|
|
|
|
---
|
|
*Completed: 2026-02-12*
|
|
*Duration: 6 minutes*
|