Skip to content

Commit 3ceb7d3

Browse files
committed
refactor(agent-manager): replace hardcoded types with enums
1 parent 6367ba8 commit 3ceb7d3

6 files changed

Lines changed: 39 additions & 17 deletions

File tree

docs/ai/design/feature-agent-manager.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ Types are adapted for a data-first package contract:
7272
- **AgentInfo**: Full agent information (name, type, status, pid, projectPath, sessionId, slug, lastActive, etc.)
7373
- **ProcessInfo**: `{ pid, command, cwd, tty }`
7474
- **AgentAdapter**: Interface with `type`, `detectAgents()`, `canHandle()`
75-
- **TerminalLocation**: `{ type, identifier, tty }` (from TerminalFocusManager)
75+
- **TerminalType**: Enum (`TMUX`, `ITERM2`, `TERMINAL_APP`, `UNKNOWN`)
76+
- **TerminalLocation**: `{ type: TerminalType, identifier, tty }` (from TerminalFocusManager)
7677

7778
## API Design
7879

@@ -89,7 +90,7 @@ export { AgentStatus } from './adapters/AgentAdapter';
8990
export type { AgentType, AgentInfo, ProcessInfo } from './adapters/AgentAdapter';
9091

9192
// Terminal
92-
export { TerminalFocusManager } from './terminal/TerminalFocusManager';
93+
export { TerminalFocusManager, TerminalType } from './terminal/TerminalFocusManager';
9394
export type { TerminalLocation } from './terminal/TerminalFocusManager';
9495

9596
// Utilities

docs/ai/implementation/feature-agent-manager.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ Data-model refinements (February 25, 2026):
103103
- Removed `AgentInfo.statusDisplay`
104104
- Removed `AgentInfo.lastActiveDisplay`
105105
- 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
106109

107110
## Phase 6 Check Implementation (February 25, 2026)
108111

packages/agent-manager/src/adapters/ClaudeCodeAdapter.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,21 @@ interface SessionsIndex {
1919
originalPath: string;
2020
}
2121

22+
enum SessionEntryType {
23+
ASSISTANT = 'assistant',
24+
USER = 'user',
25+
PROGRESS = 'progress',
26+
THINKING = 'thinking',
27+
SYSTEM = 'system',
28+
MESSAGE = 'message',
29+
TEXT = 'text',
30+
}
31+
2232
/**
2333
* Entry in session JSONL file
2434
*/
2535
interface SessionEntry {
26-
type?: 'assistant' | 'user' | 'progress' | 'thinking' | 'system' | 'message' | 'text';
36+
type?: SessionEntryType;
2737
timestamp?: string;
2838
slug?: string;
2939
cwd?: string;
@@ -289,24 +299,24 @@ export class ClaudeCodeAdapter implements AgentAdapter {
289299
return AgentStatus.IDLE;
290300
}
291301

292-
if (entryType === 'user') {
302+
if (entryType === SessionEntryType.USER) {
293303
// Check if user interrupted manually - this puts agent back in waiting state
294304
const content = session.lastEntry.message?.content;
295305
if (Array.isArray(content)) {
296306
const isInterrupted = content.some(c =>
297-
(c.type === 'text' && c.text?.includes('[Request interrupted')) ||
307+
(c.type === SessionEntryType.TEXT && c.text?.includes('[Request interrupted')) ||
298308
(c.type === 'tool_result' && c.content?.includes('[Request interrupted'))
299309
);
300310
if (isInterrupted) return AgentStatus.WAITING;
301311
}
302312
return AgentStatus.RUNNING;
303313
}
304314

305-
if (entryType === 'progress' || entryType === 'thinking') {
315+
if (entryType === SessionEntryType.PROGRESS || entryType === SessionEntryType.THINKING) {
306316
return AgentStatus.RUNNING;
307-
} else if (entryType === 'assistant') {
317+
} else if (entryType === SessionEntryType.ASSISTANT) {
308318
return AgentStatus.WAITING;
309-
} else if (entryType === 'system') {
319+
} else if (entryType === SessionEntryType.SYSTEM) {
310320
return AgentStatus.IDLE;
311321
}
312322

packages/agent-manager/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export { ClaudeCodeAdapter } from './adapters/ClaudeCodeAdapter';
44
export { AgentStatus } from './adapters/AgentAdapter';
55
export type { AgentAdapter, AgentType, AgentInfo, ProcessInfo } from './adapters/AgentAdapter';
66

7-
export { TerminalFocusManager } from './terminal/TerminalFocusManager';
7+
export { TerminalFocusManager, TerminalType } from './terminal/TerminalFocusManager';
88
export type { TerminalLocation } from './terminal/TerminalFocusManager';
99

1010
export { listProcesses, getProcessCwd, getProcessTty, isProcessRunning, getProcessInfo } from './utils/process';

packages/agent-manager/src/terminal/TerminalFocusManager.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@ import { getProcessTty } from '../utils/process';
55
const execAsync = promisify(exec);
66
const execFileAsync = promisify(execFile);
77

8+
export enum TerminalType {
9+
TMUX = 'tmux',
10+
ITERM2 = 'iterm2',
11+
TERMINAL_APP = 'terminal-app',
12+
UNKNOWN = 'unknown',
13+
}
14+
815
export interface TerminalLocation {
9-
type: 'tmux' | 'iterm2' | 'terminal-app' | 'unknown';
16+
type: TerminalType;
1017
identifier: string; // e.g., "session:window.pane" for tmux, or TTY for others
1118
tty: string; // e.g., "/dev/ttys030"
1219
}
@@ -39,7 +46,7 @@ export class TerminalFocusManager {
3946

4047
// 4. Fallback: we know the TTY but not the emulator wrapper
4148
return {
42-
type: 'unknown',
49+
type: TerminalType.UNKNOWN,
4350
identifier: '',
4451
tty: fullTty
4552
};
@@ -51,11 +58,11 @@ export class TerminalFocusManager {
5158
async focusTerminal(location: TerminalLocation): Promise<boolean> {
5259
try {
5360
switch (location.type) {
54-
case 'tmux':
61+
case TerminalType.TMUX:
5562
return await this.focusTmuxPane(location.identifier);
56-
case 'iterm2':
63+
case TerminalType.ITERM2:
5764
return await this.focusITerm2Session(location.tty);
58-
case 'terminal-app':
65+
case TerminalType.TERMINAL_APP:
5966
return await this.focusTerminalAppWindow(location.tty);
6067
default:
6168
return false;
@@ -78,7 +85,7 @@ export class TerminalFocusManager {
7885
const [paneTty, identifier] = line.split('|');
7986
if (paneTty === tty && identifier) {
8087
return {
81-
type: 'tmux',
88+
type: TerminalType.TMUX,
8289
identifier,
8390
tty
8491
};
@@ -113,7 +120,7 @@ export class TerminalFocusManager {
113120
const { stdout } = await execAsync(`osascript -e '${script}'`);
114121
if (stdout.trim() === "found") {
115122
return {
116-
type: 'iterm2',
123+
type: TerminalType.ITERM2,
117124
identifier: tty,
118125
tty
119126
};
@@ -145,7 +152,7 @@ export class TerminalFocusManager {
145152
const { stdout } = await execAsync(`osascript -e '${script}'`);
146153
if (stdout.trim() === "found") {
147154
return {
148-
type: 'terminal-app',
155+
type: TerminalType.TERMINAL_APP,
149156
identifier: tty,
150157
tty
151158
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { TerminalFocusManager } from './TerminalFocusManager';
2+
export { TerminalType } from './TerminalFocusManager';
23
export type { TerminalLocation } from './TerminalFocusManager';

0 commit comments

Comments
 (0)