@ai-devkit/agent-manager 0.4.0 → 0.6.0

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.
Files changed (50) hide show
  1. package/dist/adapters/AgentAdapter.d.ts +21 -2
  2. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  3. package/dist/adapters/ClaudeCodeAdapter.d.ts +44 -35
  4. package/dist/adapters/ClaudeCodeAdapter.d.ts.map +1 -1
  5. package/dist/adapters/ClaudeCodeAdapter.js +230 -298
  6. package/dist/adapters/ClaudeCodeAdapter.js.map +1 -1
  7. package/dist/adapters/CodexAdapter.d.ts +41 -31
  8. package/dist/adapters/CodexAdapter.d.ts.map +1 -1
  9. package/dist/adapters/CodexAdapter.js +198 -278
  10. package/dist/adapters/CodexAdapter.js.map +1 -1
  11. package/dist/index.d.ts +2 -4
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -10
  14. package/dist/index.js.map +1 -1
  15. package/dist/utils/index.d.ts +6 -3
  16. package/dist/utils/index.d.ts.map +1 -1
  17. package/dist/utils/index.js +12 -11
  18. package/dist/utils/index.js.map +1 -1
  19. package/dist/utils/matching.d.ts +39 -0
  20. package/dist/utils/matching.d.ts.map +1 -0
  21. package/dist/utils/matching.js +107 -0
  22. package/dist/utils/matching.js.map +1 -0
  23. package/dist/utils/process.d.ts +25 -40
  24. package/dist/utils/process.d.ts.map +1 -1
  25. package/dist/utils/process.js +151 -105
  26. package/dist/utils/process.js.map +1 -1
  27. package/dist/utils/session.d.ts +30 -0
  28. package/dist/utils/session.d.ts.map +1 -0
  29. package/dist/utils/session.js +101 -0
  30. package/dist/utils/session.js.map +1 -0
  31. package/package.json +1 -1
  32. package/src/__tests__/AgentManager.test.ts +5 -27
  33. package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +754 -830
  34. package/src/__tests__/adapters/CodexAdapter.test.ts +581 -273
  35. package/src/__tests__/utils/matching.test.ts +199 -0
  36. package/src/__tests__/utils/process.test.ts +202 -0
  37. package/src/__tests__/utils/session.test.ts +117 -0
  38. package/src/adapters/AgentAdapter.ts +23 -4
  39. package/src/adapters/ClaudeCodeAdapter.ts +285 -437
  40. package/src/adapters/CodexAdapter.ts +202 -400
  41. package/src/index.ts +2 -4
  42. package/src/utils/index.ts +6 -3
  43. package/src/utils/matching.ts +96 -0
  44. package/src/utils/process.ts +133 -119
  45. package/src/utils/session.ts +92 -0
  46. package/dist/utils/file.d.ts +0 -52
  47. package/dist/utils/file.d.ts.map +0 -1
  48. package/dist/utils/file.js +0 -135
  49. package/dist/utils/file.js.map +0 -1
  50. package/src/utils/file.ts +0 -100
@@ -2,165 +2,211 @@
2
2
  /**
3
3
  * Process Detection Utilities
4
4
  *
5
- * Utilities for detecting and inspecting running processes on the system.
6
- * Primarily focused on macOS/Unix-like systems using the `ps` command.
5
+ * Shared shell command wrappers for detecting and inspecting running processes.
6
+ * All execSync calls for process data live here — adapters must not call execSync directly.
7
7
  */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
8
41
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.listProcesses = listProcesses;
10
- exports.getProcessCwd = getProcessCwd;
42
+ exports.listAgentProcesses = listAgentProcesses;
43
+ exports.batchGetProcessCwds = batchGetProcessCwds;
44
+ exports.batchGetProcessStartTimes = batchGetProcessStartTimes;
45
+ exports.enrichProcesses = enrichProcesses;
11
46
  exports.getProcessTty = getProcessTty;
12
- exports.isProcessRunning = isProcessRunning;
13
- exports.getProcessInfo = getProcessInfo;
47
+ const path = __importStar(require("path"));
14
48
  const child_process_1 = require("child_process");
15
49
  /**
16
- * List running processes on the system
17
- *
18
- * @param options Filtering options
19
- * @returns Array of process information
50
+ * List running processes matching an agent executable name.
20
51
  *
21
- * @example
22
- * ```typescript
23
- * // List all Claude Code processes
24
- * const processes = listProcesses({ namePattern: 'claude' });
52
+ * Uses `ps aux | grep <pattern>` at shell level for performance, then post-filters
53
+ * by checking that the executable basename matches exactly (avoids matching
54
+ * `claude-helper`, `vscode-claude-extension`, or the grep process itself).
25
55
  *
26
- * // Get specific process info
27
- * const process = listProcesses({ pids: [12345] });
28
- * ```
56
+ * Returned ProcessInfo has pid, command, tty populated.
57
+ * cwd and startTime are NOT populated — call enrichProcesses() to fill them.
29
58
  */
30
- function listProcesses(options = {}) {
59
+ function listAgentProcesses(namePattern) {
60
+ // Validate pattern contains only safe characters (alphanumeric, dash, underscore)
61
+ if (!namePattern || !/^[a-zA-Z0-9_-]+$/.test(namePattern)) {
62
+ return [];
63
+ }
31
64
  try {
32
- // Get all processes with full details
33
- // Format: user pid command
34
- const psOutput = (0, child_process_1.execSync)('ps aux', { encoding: 'utf-8' });
35
- const lines = psOutput.trim().split('\n');
36
- // Skip header line
37
- const processLines = lines.slice(1);
65
+ // Use [c]laude trick to avoid matching the grep process itself
66
+ const escapedPattern = `[${namePattern[0]}]${namePattern.slice(1)}`;
67
+ const output = (0, child_process_1.execSync)(`ps aux | grep -i '${escapedPattern}'`, { encoding: 'utf-8' });
38
68
  const processes = [];
39
- for (const line of processLines) {
40
- // Parse ps aux output
41
- // Format: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
69
+ for (const line of output.trim().split('\n')) {
70
+ if (!line.trim())
71
+ continue;
42
72
  const parts = line.trim().split(/\s+/);
43
73
  if (parts.length < 11)
44
74
  continue;
45
75
  const pid = parseInt(parts[1], 10);
46
- if (isNaN(pid))
76
+ if (Number.isNaN(pid))
47
77
  continue;
48
78
  const tty = parts[6];
49
79
  const command = parts.slice(10).join(' ');
50
- // Apply PID filter
51
- if (options.pids && !options.pids.includes(pid)) {
80
+ // Post-filter: check that the executable basename matches exactly
81
+ const executable = command.trim().split(/\s+/)[0] || '';
82
+ const base = path.basename(executable).toLowerCase();
83
+ if (base !== namePattern.toLowerCase() && base !== `${namePattern.toLowerCase()}.exe`) {
52
84
  continue;
53
85
  }
54
- // Apply name pattern filter (case-insensitive)
55
- if (options.namePattern) {
56
- const pattern = options.namePattern.toLowerCase();
57
- const commandLower = command.toLowerCase();
58
- if (!commandLower.includes(pattern)) {
59
- continue;
60
- }
61
- }
62
- // Get working directory for this process
63
- const cwd = getProcessCwd(pid);
64
- // Get TTY in short format (remove /dev/ prefix if present)
65
86
  const ttyShort = tty.startsWith('/dev/') ? tty.slice(5) : tty;
66
87
  processes.push({
67
88
  pid,
68
89
  command,
69
- cwd,
90
+ cwd: '',
70
91
  tty: ttyShort,
71
92
  });
72
93
  }
73
94
  return processes;
74
95
  }
75
- catch (error) {
76
- // If ps command fails, return empty array
77
- console.error('Failed to list processes:', error);
96
+ catch {
78
97
  return [];
79
98
  }
80
99
  }
81
100
  /**
82
- * Get the current working directory for a specific process
101
+ * Batch-get current working directories for multiple PIDs.
83
102
  *
84
- * @param pid Process ID
85
- * @returns Working directory path, or empty string if unavailable
103
+ * Single `lsof -a -d cwd -Fn -p PID1,PID2,...` call.
104
+ * Returns partial results if lsof fails for one PID, others still return.
86
105
  */
87
- function getProcessCwd(pid) {
106
+ function batchGetProcessCwds(pids) {
107
+ const result = new Map();
108
+ if (pids.length === 0)
109
+ return result;
88
110
  try {
89
- // Use lsof to get the current working directory
90
- // -a: AND the selections, -d cwd: get cwd only, -Fn: output format (file names only)
91
- const output = (0, child_process_1.execSync)(`lsof -a -p ${pid} -d cwd -Fn 2>/dev/null`, {
92
- encoding: 'utf-8',
93
- });
94
- // Parse lsof output
95
- // Format: p{PID}\nn{path}
96
- const lines = output.trim().split('\n');
97
- for (const line of lines) {
98
- if (line.startsWith('n')) {
99
- return line.slice(1); // Remove 'n' prefix
111
+ const output = (0, child_process_1.execSync)(`lsof -a -d cwd -Fn -p ${pids.join(',')} 2>/dev/null`, { encoding: 'utf-8' });
112
+ // lsof output format: p{PID}\nn{path}\np{PID}\nn{path}...
113
+ let currentPid = null;
114
+ for (const line of output.trim().split('\n')) {
115
+ if (line.startsWith('p')) {
116
+ currentPid = parseInt(line.slice(1), 10);
117
+ }
118
+ else if (line.startsWith('n') && currentPid !== null) {
119
+ result.set(currentPid, line.slice(1));
120
+ currentPid = null;
100
121
  }
101
122
  }
102
- return '';
103
123
  }
104
- catch (error) {
105
- // If lsof fails, try alternative method using pwdx (Linux)
106
- try {
107
- const output = (0, child_process_1.execSync)(`pwdx ${pid} 2>/dev/null`, {
108
- encoding: 'utf-8',
109
- });
110
- // Format: {PID}: {path}
111
- const match = output.match(/^\d+:\s*(.+)$/);
112
- return match ? match[1].trim() : '';
113
- }
114
- catch {
115
- // Both methods failed
116
- return '';
124
+ catch {
125
+ // Try per-PID fallback with pwdx (Linux)
126
+ for (const pid of pids) {
127
+ try {
128
+ const output = (0, child_process_1.execSync)(`pwdx ${pid} 2>/dev/null`, { encoding: 'utf-8' });
129
+ const match = output.match(/^\d+:\s*(.+)$/);
130
+ if (match) {
131
+ result.set(pid, match[1].trim());
132
+ }
133
+ }
134
+ catch {
135
+ // Skip this PID
136
+ }
117
137
  }
118
138
  }
139
+ return result;
119
140
  }
120
141
  /**
121
- * Get the TTY device for a specific process
142
+ * Batch-get process start times for multiple PIDs.
122
143
  *
123
- * @param pid Process ID
124
- * @returns TTY device name (e.g., "ttys030"), or "?" if unavailable
144
+ * Single `ps -o pid=,lstart= -p PID1,PID2,...` call.
145
+ * Uses lstart format which gives full timestamp (e.g., "Thu Feb 5 16:00:57 2026").
146
+ * Returns partial results.
125
147
  */
126
- function getProcessTty(pid) {
148
+ function batchGetProcessStartTimes(pids) {
149
+ const result = new Map();
150
+ if (pids.length === 0)
151
+ return result;
127
152
  try {
128
- const output = (0, child_process_1.execSync)(`ps -p ${pid} -o tty=`, {
129
- encoding: 'utf-8',
130
- });
131
- const tty = output.trim();
132
- // Remove /dev/ prefix if present
133
- return tty.startsWith('/dev/') ? tty.slice(5) : tty;
153
+ const output = (0, child_process_1.execSync)(`ps -o pid=,lstart= -p ${pids.join(',')}`, { encoding: 'utf-8' });
154
+ for (const rawLine of output.split('\n')) {
155
+ const line = rawLine.trim();
156
+ if (!line)
157
+ continue;
158
+ // Format: " PID DAY MON DD HH:MM:SS YYYY"
159
+ // e.g., " 78070 Wed Mar 18 23:18:01 2026"
160
+ const match = line.match(/^\s*(\d+)\s+(.+)$/);
161
+ if (!match)
162
+ continue;
163
+ const pid = parseInt(match[1], 10);
164
+ const dateStr = match[2].trim();
165
+ if (!Number.isFinite(pid))
166
+ continue;
167
+ const date = new Date(dateStr);
168
+ if (!Number.isNaN(date.getTime())) {
169
+ result.set(pid, date);
170
+ }
171
+ }
134
172
  }
135
- catch (error) {
136
- return '?';
173
+ catch {
174
+ // Return whatever we have
137
175
  }
176
+ return result;
138
177
  }
139
178
  /**
140
- * Check if a process with the given PID is running
179
+ * Enrich ProcessInfo array with cwd and startTime.
141
180
  *
142
- * @param pid Process ID
143
- * @returns True if process is running
181
+ * Calls batchGetProcessCwds and batchGetProcessStartTimes in batched shell calls,
182
+ * then populates each ProcessInfo in-place. Returns partial results —
183
+ * if a PID fails, that process keeps empty cwd / undefined startTime.
144
184
  */
145
- function isProcessRunning(pid) {
146
- try {
147
- // Send signal 0 to check if process exists
148
- // This doesn't actually send a signal, just checks if we can
149
- (0, child_process_1.execSync)(`kill -0 ${pid} 2>/dev/null`);
150
- return true;
151
- }
152
- catch {
153
- return false;
185
+ function enrichProcesses(processes) {
186
+ if (processes.length === 0)
187
+ return processes;
188
+ const pids = processes.map(p => p.pid);
189
+ const cwdMap = batchGetProcessCwds(pids);
190
+ const startTimeMap = batchGetProcessStartTimes(pids);
191
+ for (const proc of processes) {
192
+ proc.cwd = cwdMap.get(proc.pid) || '';
193
+ proc.startTime = startTimeMap.get(proc.pid);
154
194
  }
195
+ return processes;
155
196
  }
156
197
  /**
157
- * Get detailed information for a specific process
158
- *
159
- * @param pid Process ID
160
- * @returns Process information, or null if process not found
198
+ * Get the TTY device for a specific process
161
199
  */
162
- function getProcessInfo(pid) {
163
- const processes = listProcesses({ pids: [pid] });
164
- return processes.length > 0 ? processes[0] : null;
200
+ function getProcessTty(pid) {
201
+ try {
202
+ const output = (0, child_process_1.execSync)(`ps -p ${pid} -o tty=`, {
203
+ encoding: 'utf-8',
204
+ });
205
+ const tty = output.trim();
206
+ return tty.startsWith('/dev/') ? tty.slice(5) : tty;
207
+ }
208
+ catch {
209
+ return '?';
210
+ }
165
211
  }
166
212
  //# sourceMappingURL=process.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/utils/process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/utils/process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Session File Utilities
3
+ *
4
+ * Shell command wrappers for discovering session files and their birth times.
5
+ * Uses `stat` to get exact epoch-second birth timestamps without reading file contents.
6
+ */
7
+ /**
8
+ * Represents a session file with its birth time metadata.
9
+ */
10
+ export interface SessionFile {
11
+ /** Session identifier (filename without .jsonl extension) */
12
+ sessionId: string;
13
+ /** Full path to the session file */
14
+ filePath: string;
15
+ /** Parent directory of the session file */
16
+ projectDir: string;
17
+ /** File creation time in milliseconds since epoch */
18
+ birthtimeMs: number;
19
+ /** CWD this session maps to — set by the adapter after calling batchGetSessionFileBirthtimes() */
20
+ resolvedCwd: string;
21
+ }
22
+ /**
23
+ * Get birth times for .jsonl session files across multiple directories in a single shell call.
24
+ *
25
+ * Combines all directory globs into one `stat` command to avoid per-directory exec overhead.
26
+ * Returns empty array if no directories have .jsonl files or command fails.
27
+ * resolvedCwd is left empty — the adapter must set it.
28
+ */
29
+ export declare function batchGetSessionFileBirthtimes(dirs: string[]): SessionFile[];
30
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IAEjB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IAEnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IAEpB,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAiB3E"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ /**
3
+ * Session File Utilities
4
+ *
5
+ * Shell command wrappers for discovering session files and their birth times.
6
+ * Uses `stat` to get exact epoch-second birth timestamps without reading file contents.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.batchGetSessionFileBirthtimes = batchGetSessionFileBirthtimes;
43
+ const path = __importStar(require("path"));
44
+ const child_process_1 = require("child_process");
45
+ /**
46
+ * Get birth times for .jsonl session files across multiple directories in a single shell call.
47
+ *
48
+ * Combines all directory globs into one `stat` command to avoid per-directory exec overhead.
49
+ * Returns empty array if no directories have .jsonl files or command fails.
50
+ * resolvedCwd is left empty — the adapter must set it.
51
+ */
52
+ function batchGetSessionFileBirthtimes(dirs) {
53
+ if (dirs.length === 0)
54
+ return [];
55
+ try {
56
+ const isMacOS = process.platform === 'darwin';
57
+ const globs = dirs.map((d) => `"${d}"/*.jsonl`).join(' ');
58
+ // || true prevents non-zero exit when some globs have no .jsonl matches
59
+ const command = isMacOS
60
+ ? `stat -f '%B %N' ${globs} 2>/dev/null || true`
61
+ : `stat --format='%W %n' ${globs} 2>/dev/null || true`;
62
+ const output = (0, child_process_1.execSync)(command, { encoding: 'utf-8' });
63
+ return parseStatOutput(output);
64
+ }
65
+ catch {
66
+ return [];
67
+ }
68
+ }
69
+ /**
70
+ * Parse stat output lines into SessionFile entries.
71
+ */
72
+ function parseStatOutput(output) {
73
+ const results = [];
74
+ for (const rawLine of output.trim().split('\n')) {
75
+ const line = rawLine.trim();
76
+ if (!line)
77
+ continue;
78
+ // Format: "<epoch_seconds> <filepath>"
79
+ const spaceIdx = line.indexOf(' ');
80
+ if (spaceIdx === -1)
81
+ continue;
82
+ const epochStr = line.slice(0, spaceIdx);
83
+ const filePath = line.slice(spaceIdx + 1).trim();
84
+ const epochSeconds = parseInt(epochStr, 10);
85
+ if (!Number.isFinite(epochSeconds) || epochSeconds <= 0)
86
+ continue;
87
+ const fileName = path.basename(filePath);
88
+ if (!fileName.endsWith('.jsonl'))
89
+ continue;
90
+ const sessionId = fileName.replace(/\.jsonl$/, '');
91
+ results.push({
92
+ sessionId,
93
+ filePath,
94
+ projectDir: path.dirname(filePath),
95
+ birthtimeMs: epochSeconds * 1000,
96
+ resolvedCwd: '',
97
+ });
98
+ }
99
+ return results;
100
+ }
101
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCH,sEAiBC;AA/CD,2CAA6B;AAC7B,iDAAyC;AAsBzC;;;;;;GAMG;AACH,SAAgB,6BAA6B,CAAC,IAAc;IACxD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1D,wEAAwE;QACxE,MAAM,OAAO,GAAG,OAAO;YACnB,CAAC,CAAC,mBAAmB,KAAK,sBAAsB;YAChD,CAAC,CAAC,yBAAyB,KAAK,sBAAsB,CAAC;QAE3D,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QAExD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,MAAc;IACnC,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,uCAAuC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,CAAC,CAAC;YAAE,SAAS;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEjD,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC;YAAE,SAAS;QAElE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAS;QAE3C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAEnD,OAAO,CAAC,IAAI,CAAC;YACT,SAAS;YACT,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YAClC,WAAW,EAAE,YAAY,GAAG,IAAI;YAChC,WAAW,EAAE,EAAE;SAClB,CAAC,CAAC;IACP,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-devkit/agent-manager",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Standalone agent detection and management utilities for AI DevKit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { describe, it, expect, beforeEach } from '@jest/globals';
6
6
  import { AgentManager } from '../AgentManager';
7
- import type { AgentAdapter, AgentInfo, AgentType } from '../adapters/AgentAdapter';
7
+ import type { AgentAdapter, AgentInfo, AgentType, ConversationMessage } from '../adapters/AgentAdapter';
8
8
  import { AgentStatus } from '../adapters/AgentAdapter';
9
9
 
10
10
  // Mock adapter for testing
@@ -26,6 +26,10 @@ class MockAdapter implements AgentAdapter {
26
26
  return true;
27
27
  }
28
28
 
29
+ getConversation(): ConversationMessage[] {
30
+ return [];
31
+ }
32
+
29
33
  setAgents(agents: AgentInfo[]): void {
30
34
  this.mockAgents = agents;
31
35
  }
@@ -45,7 +49,6 @@ function createMockAgent(overrides: Partial<AgentInfo> = {}): AgentInfo {
45
49
  pid: 12345,
46
50
  projectPath: '/test/path',
47
51
  sessionId: 'test-session-id',
48
- slug: 'test-slug',
49
52
  lastActive: new Date(),
50
53
  ...overrides,
51
54
  };
@@ -130,17 +133,6 @@ describe('AgentManager', () => {
130
133
  });
131
134
  });
132
135
 
133
- describe('hasAdapter', () => {
134
- it('should return true for registered adapter', () => {
135
- manager.registerAdapter(new MockAdapter('claude'));
136
- expect(manager.hasAdapter('claude')).toBe(true);
137
- });
138
-
139
- it('should return false for non-registered adapter', () => {
140
- expect(manager.hasAdapter('claude')).toBe(false);
141
- });
142
- });
143
-
144
136
  describe('listAgents', () => {
145
137
  it('should return empty array when no adapters registered', async () => {
146
138
  const agents = await manager.listAgents();
@@ -222,20 +214,6 @@ describe('AgentManager', () => {
222
214
  });
223
215
  });
224
216
 
225
- describe('getAdapterCount', () => {
226
- it('should return 0 when no adapters registered', () => {
227
- expect(manager.getAdapterCount()).toBe(0);
228
- });
229
-
230
- it('should return correct count', () => {
231
- manager.registerAdapter(new MockAdapter('claude'));
232
- expect(manager.getAdapterCount()).toBe(1);
233
-
234
- manager.registerAdapter(new MockAdapter('gemini_cli'));
235
- expect(manager.getAdapterCount()).toBe(2);
236
- });
237
- });
238
-
239
217
  describe('clear', () => {
240
218
  it('should remove all adapters', () => {
241
219
  manager.registerAdapter(new MockAdapter('claude'));