Skip to content

Commit 661ff87

Browse files
Add standalone package for agent manager (#25)
* feat(agent-manager): add standalone package and lifecycle docs * refactor(agent-manager): normalize agent types and remove display fields * Update package lock * refactor(agent-manager): replace hardcoded types with enums
1 parent 6c5717d commit 661ff87

23 files changed

+2515
-0
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---
2+
phase: design
3+
title: "Agent Manager Package - Design"
4+
feature: agent-manager
5+
description: Architecture and design for the @ai-devkit/agent-manager package
6+
---
7+
8+
# Design: @ai-devkit/agent-manager Package
9+
10+
## Architecture Overview
11+
12+
```mermaid
13+
graph TD
14+
subgraph "@ai-devkit/agent-manager"
15+
AM[AgentManager] -->|registers| AA[AgentAdapter Interface]
16+
AA -->|implemented by| CCA[ClaudeCodeAdapter]
17+
AA -->|implemented by| FutureAdapter["Future Adapters..."]
18+
19+
CCA -->|uses| PU[Process Utils]
20+
CCA -->|uses| FU[File Utils]
21+
22+
TFM[TerminalFocusManager] -->|uses| PU
23+
24+
Types[Types & Enums] -->|consumed by| AM
25+
Types -->|consumed by| CCA
26+
Types -->|consumed by| TFM
27+
end
28+
29+
subgraph "CLI Package (consumer)"
30+
CMD[agent command] -->|imports| AM
31+
CMD -->|imports| CCA
32+
CMD -->|imports| TFM
33+
CMD -->|imports| Types
34+
end
35+
```
36+
37+
### Package Directory Structure
38+
39+
```
40+
packages/agent-manager/
41+
├── src/
42+
│ ├── index.ts # Public API barrel export
43+
│ ├── AgentManager.ts # Core orchestrator
44+
│ ├── adapters/
45+
│ │ ├── AgentAdapter.ts # Interface, types, enums
46+
│ │ ├── ClaudeCodeAdapter.ts # Claude Code detection
47+
│ │ └── index.ts # Adapter barrel export
48+
│ ├── terminal/
49+
│ │ ├── TerminalFocusManager.ts # Terminal focus (macOS)
50+
│ │ └── index.ts # Terminal barrel export
51+
│ └── utils/
52+
│ ├── process.ts # Process detection utilities
53+
│ ├── file.ts # File reading utilities
54+
│ └── index.ts # Utils barrel export
55+
├── src/__tests__/
56+
│ ├── AgentManager.test.ts
57+
│ └── adapters/
58+
│ └── ClaudeCodeAdapter.test.ts
59+
├── package.json
60+
├── tsconfig.json
61+
├── jest.config.js
62+
├── project.json
63+
└── .eslintrc.json
64+
```
65+
66+
## Data Models
67+
68+
Types are adapted for a data-first package contract:
69+
70+
- **AgentType**: `'claude' | 'gemini_cli' | 'codex' | 'other'`
71+
- **AgentStatus**: Enum (`RUNNING`, `WAITING`, `IDLE`, `UNKNOWN`)
72+
- **AgentInfo**: Full agent information (name, type, status, pid, projectPath, sessionId, slug, lastActive, etc.)
73+
- **ProcessInfo**: `{ pid, command, cwd, tty }`
74+
- **AgentAdapter**: Interface with `type`, `detectAgents()`, `canHandle()`
75+
- **TerminalType**: Enum (`TMUX`, `ITERM2`, `TERMINAL_APP`, `UNKNOWN`)
76+
- **TerminalLocation**: `{ type: TerminalType, identifier, tty }` (from TerminalFocusManager)
77+
78+
## API Design
79+
80+
### Public Exports (`index.ts`)
81+
82+
```typescript
83+
// Core
84+
export { AgentManager } from './AgentManager';
85+
86+
// Adapters
87+
export { ClaudeCodeAdapter } from './adapters/ClaudeCodeAdapter';
88+
export type { AgentAdapter } from './adapters/AgentAdapter';
89+
export { AgentStatus } from './adapters/AgentAdapter';
90+
export type { AgentType, AgentInfo, ProcessInfo } from './adapters/AgentAdapter';
91+
92+
// Terminal
93+
export { TerminalFocusManager, TerminalType } from './terminal/TerminalFocusManager';
94+
export type { TerminalLocation } from './terminal/TerminalFocusManager';
95+
96+
// Utilities
97+
export { listProcesses, getProcessCwd, getProcessTty, isProcessRunning, getProcessInfo } from './utils/process';
98+
export type { ListProcessesOptions } from './utils/process';
99+
export { readLastLines, readJsonLines, fileExists, readJson } from './utils/file';
100+
```
101+
102+
### Usage Example
103+
104+
```typescript
105+
import { AgentManager, ClaudeCodeAdapter } from '@ai-devkit/agent-manager';
106+
107+
const manager = new AgentManager();
108+
manager.registerAdapter(new ClaudeCodeAdapter());
109+
110+
const agents = await manager.listAgents();
111+
agents.forEach(agent => {
112+
console.log(`${agent.name}: ${agent.status}`);
113+
});
114+
```
115+
116+
### Migration Notes
117+
118+
- `AgentType` values are now normalized codes (`claude`, `gemini_cli`, `codex`, `other`)
119+
- `AgentInfo` no longer includes UI/display fields (`statusDisplay`, `lastActiveDisplay`)
120+
- `STATUS_CONFIG` / `StatusConfig` were removed; consumers should map presentation in their own layer
121+
122+
## Component Breakdown
123+
124+
### 1. AgentManager (core orchestrator)
125+
- Adapter registration/unregistration
126+
- Agent listing with parallel adapter queries
127+
- Agent resolution (exact/partial name matching)
128+
- Status-based sorting
129+
- **Extracted from**: `packages/cli/src/lib/AgentManager.ts`
130+
- **Changes**: None — direct copy
131+
132+
### 2. AgentAdapter + Types (interface layer)
133+
- Interface contract for adapters
134+
- Type definitions and enums
135+
- Normalized agent type codes for machine-friendly integrations
136+
- **Extracted from**: `packages/cli/src/lib/adapters/AgentAdapter.ts`
137+
- **Changes**: Agent type literals normalized; display-oriented fields removed from core model
138+
139+
### 3. ClaudeCodeAdapter (concrete adapter)
140+
- Claude Code process detection via `ps aux`
141+
- Session file reading from `~/.claude/projects/`
142+
- Status determination from JSONL entries
143+
- History-based summary extraction
144+
- **Extracted from**: `packages/cli/src/lib/adapters/ClaudeCodeAdapter.ts`
145+
- **Changes**: Import paths updated to use local `utils/` instead of `../../util/`
146+
147+
### 4. TerminalFocusManager (terminal control)
148+
- Terminal emulator detection (tmux, iTerm2, Terminal.app)
149+
- Terminal window/pane focusing
150+
- macOS-specific AppleScript integration
151+
- **Extracted from**: `packages/cli/src/lib/TerminalFocusManager.ts`
152+
- **Changes**: Import paths updated to use local `utils/process`
153+
154+
### 5. Process Utilities
155+
- `listProcesses()` — system process listing with filtering
156+
- `getProcessCwd()` — process working directory lookup
157+
- `getProcessTty()` — process TTY device lookup
158+
- `isProcessRunning()` — process existence check
159+
- `getProcessInfo()` — detailed single-process info
160+
- **Extracted from**: `packages/cli/src/util/process.ts`
161+
- **Changes**: `ProcessInfo` type import updated (now from `../adapters/AgentAdapter`)
162+
163+
### 6. File Utilities
164+
- `readLastLines()` — efficient last-N-lines reading
165+
- `readJsonLines()` — JSONL file parsing
166+
- `fileExists()` — file existence check
167+
- `readJson()` — safe JSON file parsing
168+
- **Extracted from**: `packages/cli/src/util/file.ts`
169+
- **Changes**: None — direct copy
170+
171+
## Design Decisions
172+
173+
| Decision | Choice | Rationale |
174+
|----------|--------|-----------|
175+
| Package name | `@ai-devkit/agent-manager` | Consistent with `@ai-devkit/memory` naming |
176+
| Build system | `tsc` (not SWC) | Simpler setup; no special transforms needed; consistent with CLI package |
177+
| Runtime deps | Zero | Only Node.js built-ins used; keeps package lightweight |
178+
| Include TerminalFocusManager | Yes, as separate module | Useful for consumers; closely related to agent management |
179+
| Include utilities | Yes, within package | They're tightly coupled to adapter implementation; not general-purpose enough for a separate package |
180+
| Test framework | Jest with ts-jest | Matches existing monorepo conventions |
181+
182+
## Non-Functional Requirements
183+
184+
### Performance
185+
- Process listing uses `ps aux` (single exec, ~50ms typical)
186+
- Session file reading limited to last 100 lines for large JSONL files
187+
- Adapter queries run in parallel via `Promise.all`
188+
189+
### Platform Support
190+
- Process detection: macOS and Linux (uses `ps aux`, `lsof`, `pwdx`)
191+
- Terminal focus: macOS only (AppleScript for iTerm2/Terminal.app, tmux universal)
192+
193+
### Security
194+
- No external network calls
195+
- Reads only from `~/.claude/` directory (user-owned)
196+
- Process inspection uses standard OS tools
197+
- No secrets or credentials handled
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
---
2+
phase: implementation
3+
title: "Agent Manager Package - Implementation Guide"
4+
feature: agent-manager
5+
description: Technical implementation notes for the @ai-devkit/agent-manager package
6+
---
7+
8+
# Implementation Guide: @ai-devkit/agent-manager Package
9+
10+
## Development Setup
11+
12+
### Prerequisites
13+
- Node.js >= 16.0.0
14+
- npm (workspaces enabled in root)
15+
- TypeScript 5.3+
16+
17+
### Setup Steps
18+
1. Package directory created at `packages/agent-manager/`
19+
2. Run `npm install` from monorepo root to link workspace
20+
3. Build with `npm run build` from `packages/agent-manager/`
21+
22+
## Code Structure
23+
24+
### Directory Organization
25+
```
26+
src/
27+
├── index.ts # Main barrel export
28+
├── AgentManager.ts # Core orchestrator class
29+
├── adapters/
30+
│ ├── index.ts # Adapter barrel
31+
│ ├── AgentAdapter.ts # Interface + types + enums
32+
│ └── ClaudeCodeAdapter.ts # Claude Code detection
33+
├── terminal/
34+
│ ├── index.ts # Terminal barrel
35+
│ └── TerminalFocusManager.ts # macOS terminal focus
36+
└── utils/
37+
├── index.ts # Utils barrel
38+
├── process.ts # Process detection
39+
└── file.ts # File reading helpers
40+
```
41+
42+
### Import Path Mapping (CLI → agent-manager)
43+
| CLI Path | Agent Manager Path |
44+
|----------|-------------------|
45+
| `src/lib/AgentManager.ts` | `src/AgentManager.ts` |
46+
| `src/lib/adapters/AgentAdapter.ts` | `src/adapters/AgentAdapter.ts` |
47+
| `src/lib/adapters/ClaudeCodeAdapter.ts` | `src/adapters/ClaudeCodeAdapter.ts` |
48+
| `src/lib/TerminalFocusManager.ts` | `src/terminal/TerminalFocusManager.ts` |
49+
| `src/util/process.ts` | `src/utils/process.ts` |
50+
| `src/util/file.ts` | `src/utils/file.ts` |
51+
52+
### Import Changes Required
53+
- `ClaudeCodeAdapter.ts`: `../../util/process``../utils/process`, `../../util/file``../utils/file`
54+
- `process.ts`: `../lib/adapters/AgentAdapter``../adapters/AgentAdapter`
55+
- `TerminalFocusManager.ts`: `../util/process``../utils/process`
56+
57+
## Patterns & Best Practices
58+
59+
- **Adapter pattern**: All agent detection goes through `AgentAdapter` interface
60+
- **Barrel exports**: Each directory has an `index.ts` for clean imports
61+
- **Zero dependencies**: Only Node.js built-ins (fs, path, child_process, util)
62+
- **Graceful degradation**: Adapter failures don't crash the system — partial results returned
63+
64+
## Error Handling
65+
66+
- AgentManager catches adapter errors individually, logs warnings, returns partial results
67+
- File utilities return empty arrays/null on read failures
68+
- Process utilities return empty results when `ps`/`lsof` commands fail
69+
- TerminalFocusManager returns `false`/`null` when terminal can't be found or focused
70+
71+
## Implementation Status
72+
73+
Completed on February 25, 2026 in worktree `feature-agent-manager`.
74+
75+
- Scaffolded `packages/agent-manager/` with `package.json`, `tsconfig.json`, `project.json`, `jest.config.js`, `.eslintrc.json`
76+
- Extracted source files from CLI package into:
77+
- `src/AgentManager.ts`
78+
- `src/adapters/AgentAdapter.ts`
79+
- `src/adapters/ClaudeCodeAdapter.ts`
80+
- `src/terminal/TerminalFocusManager.ts`
81+
- `src/utils/process.ts`
82+
- `src/utils/file.ts`
83+
- Applied import-path updates defined in design/planning docs
84+
- Added barrel exports:
85+
- `src/index.ts`
86+
- `src/adapters/index.ts`
87+
- `src/terminal/index.ts`
88+
- `src/utils/index.ts`
89+
- Extracted and fixed test imports for:
90+
- `src/__tests__/AgentManager.test.ts`
91+
- `src/__tests__/adapters/ClaudeCodeAdapter.test.ts`
92+
93+
Validation:
94+
- `npm run lint` passes
95+
- `npm run typecheck` passes
96+
- `npm run build` passes
97+
- `npm run test` passes (38 tests)
98+
99+
Data-model refinements (February 25, 2026):
100+
- Normalized `AgentType` to code-style values: `claude`, `gemini_cli`, `codex`, `other`
101+
- Removed display-oriented contract elements from package API:
102+
- Removed `STATUS_CONFIG` and `StatusConfig`
103+
- Removed `AgentInfo.statusDisplay`
104+
- Removed `AgentInfo.lastActiveDisplay`
105+
- Updated `ClaudeCodeAdapter` to return data-only fields (`status`, `lastActive`, `summary`) without UI formatting
106+
- Replaced hardcoded string literals with enums where appropriate:
107+
- Added `TerminalType` enum for terminal location/focus flow
108+
- Added `SessionEntryType` enum in `ClaudeCodeAdapter` status logic
109+
110+
## Phase 6 Check Implementation (February 25, 2026)
111+
112+
### Alignment Summary
113+
114+
- Overall status: **Mostly aligned**
115+
- Requirements/design coverage: package scaffold, extracted components, API surface, and validations are implemented as specified
116+
- Backward-compatibility non-goal respected: CLI behavior/source was not modified in this feature branch
117+
118+
### File-by-File Verification
119+
120+
- `packages/agent-manager/package.json`
121+
- Matches package naming/version/scripts/engine constraints from requirements
122+
- Uses zero runtime dependencies (only devDependencies)
123+
- `packages/agent-manager/tsconfig.json`, `project.json`, `jest.config.js`, `.eslintrc.json`
124+
- Conform to monorepo conventions and planned targets (build/test/lint/typecheck)
125+
- `packages/agent-manager/src/AgentManager.ts`
126+
- Adapter orchestration and status-based sorting match design
127+
- `packages/agent-manager/src/adapters/AgentAdapter.ts`
128+
- Types and interface extracted as designed
129+
- `packages/agent-manager/src/adapters/ClaudeCodeAdapter.ts`
130+
- Core detection/session/status logic extracted with planned import-path updates
131+
- `packages/agent-manager/src/terminal/TerminalFocusManager.ts`
132+
- Terminal focus logic extracted with planned import-path updates
133+
- `packages/agent-manager/src/utils/process.ts`, `src/utils/file.ts`
134+
- Utility extraction and API signatures match design intent
135+
- `packages/agent-manager/src/index.ts` and barrel files
136+
- Public API exports include core classes/types plus terminal and utils as designed
137+
- `packages/agent-manager/src/__tests__/...`
138+
- Test files extracted and passing in package context
139+
140+
### Deviations / Risks
141+
142+
1. **Resolved (February 25, 2026)**: Claude adapter tests now mock process/session/history dependencies and no longer rely on local `~/.claude` state or `ps` availability.
143+
2. **Resolved (February 25, 2026)**: Explicit `any` warnings in extracted runtime code were removed by tightening adapter and utility generic typings.
144+
145+
### Phase Decision
146+
147+
- No major implementation/design mismatch detected.
148+
- Proceed to **Phase 8 (Code Review)**.
149+
150+
## Phase 8 Code Review (February 25, 2026)
151+
152+
### Findings
153+
154+
1. **Resolved**: tmux focus command previously used shell interpolation for the target identifier.
155+
- Updated `TerminalFocusManager.focusTmuxPane()` to use `execFile('tmux', ['switch-client', '-t', identifier])` to avoid shell command injection paths.
156+
157+
2. **Non-blocking follow-up**: coverage threshold enforcement currently depends on running Jest with coverage enabled.
158+
- Suggested project policy: require `npm run test:coverage` (or equivalent) in CI for this package.
159+
160+
### Review Verdict
161+
162+
- No remaining blocking correctness or security issues in `packages/agent-manager`.
163+
- Feature is ready for commit/PR from a code review perspective.
164+
165+
## Code Review Continuation (February 25, 2026)
166+
167+
### Findings
168+
169+
1. **No new blocking issues** after `AgentType` normalization and display-field removal.
170+
2. **Compatibility note**: this is an intentional contract change for package consumers (type literals and removed display fields/constants).
171+
172+
### Documentation Updates Applied
173+
174+
- Requirements/design docs updated to describe the data-first API boundary.
175+
- Added explicit migration notes for callers formatting status/time displays externally.

0 commit comments

Comments
 (0)