claude-flow 1.0.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +612 -0
  3. package/bin/claude-flow +0 -0
  4. package/bin/claude-flow-simple +0 -0
  5. package/bin/claude-flow-typecheck +0 -0
  6. package/deno.json +84 -0
  7. package/package.json +45 -0
  8. package/scripts/check-links.ts +274 -0
  9. package/scripts/check-performance-regression.ts +168 -0
  10. package/scripts/claude-sparc.sh +562 -0
  11. package/scripts/coverage-report.ts +692 -0
  12. package/scripts/demo-task-system.ts +224 -0
  13. package/scripts/install.js +72 -0
  14. package/scripts/test-batch-tasks.ts +29 -0
  15. package/scripts/test-coordination-features.ts +238 -0
  16. package/scripts/test-mcp.ts +251 -0
  17. package/scripts/test-runner.ts +571 -0
  18. package/scripts/validate-examples.ts +288 -0
  19. package/src/cli/cli-core.ts +273 -0
  20. package/src/cli/commands/agent.ts +83 -0
  21. package/src/cli/commands/config.ts +442 -0
  22. package/src/cli/commands/help.ts +765 -0
  23. package/src/cli/commands/index.ts +963 -0
  24. package/src/cli/commands/mcp.ts +191 -0
  25. package/src/cli/commands/memory.ts +74 -0
  26. package/src/cli/commands/monitor.ts +403 -0
  27. package/src/cli/commands/session.ts +595 -0
  28. package/src/cli/commands/start.ts +156 -0
  29. package/src/cli/commands/status.ts +345 -0
  30. package/src/cli/commands/task.ts +79 -0
  31. package/src/cli/commands/workflow.ts +763 -0
  32. package/src/cli/completion.ts +553 -0
  33. package/src/cli/formatter.ts +310 -0
  34. package/src/cli/index.ts +211 -0
  35. package/src/cli/main.ts +23 -0
  36. package/src/cli/repl.ts +1050 -0
  37. package/src/cli/simple-cli.js +211 -0
  38. package/src/cli/simple-cli.ts +211 -0
  39. package/src/coordination/README.md +400 -0
  40. package/src/coordination/advanced-scheduler.ts +487 -0
  41. package/src/coordination/circuit-breaker.ts +366 -0
  42. package/src/coordination/conflict-resolution.ts +490 -0
  43. package/src/coordination/dependency-graph.ts +475 -0
  44. package/src/coordination/index.ts +63 -0
  45. package/src/coordination/manager.ts +460 -0
  46. package/src/coordination/messaging.ts +290 -0
  47. package/src/coordination/metrics.ts +585 -0
  48. package/src/coordination/resources.ts +322 -0
  49. package/src/coordination/scheduler.ts +390 -0
  50. package/src/coordination/work-stealing.ts +224 -0
  51. package/src/core/config.ts +627 -0
  52. package/src/core/event-bus.ts +186 -0
  53. package/src/core/json-persistence.ts +183 -0
  54. package/src/core/logger.ts +262 -0
  55. package/src/core/orchestrator-fixed.ts +312 -0
  56. package/src/core/orchestrator.ts +1234 -0
  57. package/src/core/persistence.ts +276 -0
  58. package/src/mcp/auth.ts +438 -0
  59. package/src/mcp/claude-flow-tools.ts +1280 -0
  60. package/src/mcp/load-balancer.ts +510 -0
  61. package/src/mcp/router.ts +240 -0
  62. package/src/mcp/server.ts +548 -0
  63. package/src/mcp/session-manager.ts +418 -0
  64. package/src/mcp/tools.ts +180 -0
  65. package/src/mcp/transports/base.ts +21 -0
  66. package/src/mcp/transports/http.ts +457 -0
  67. package/src/mcp/transports/stdio.ts +254 -0
  68. package/src/memory/backends/base.ts +22 -0
  69. package/src/memory/backends/markdown.ts +283 -0
  70. package/src/memory/backends/sqlite.ts +329 -0
  71. package/src/memory/cache.ts +238 -0
  72. package/src/memory/indexer.ts +238 -0
  73. package/src/memory/manager.ts +572 -0
  74. package/src/terminal/adapters/base.ts +29 -0
  75. package/src/terminal/adapters/native.ts +504 -0
  76. package/src/terminal/adapters/vscode.ts +340 -0
  77. package/src/terminal/manager.ts +308 -0
  78. package/src/terminal/pool.ts +271 -0
  79. package/src/terminal/session.ts +250 -0
  80. package/src/terminal/vscode-bridge.ts +242 -0
  81. package/src/utils/errors.ts +231 -0
  82. package/src/utils/helpers.ts +476 -0
  83. package/src/utils/types.ts +493 -0
@@ -0,0 +1,340 @@
1
+ /**
2
+ * VSCode terminal adapter implementation
3
+ */
4
+
5
+ import { ITerminalAdapter, Terminal } from './base.ts';
6
+ import { ILogger } from '../../core/logger.ts';
7
+ import { TerminalError } from '../../utils/errors.ts';
8
+ import { generateId, delay, timeout, createDeferred } from '../../utils/helpers.ts';
9
+
10
+ /**
11
+ * VSCode API interface (injected via extension)
12
+ */
13
+ interface VSCodeAPI {
14
+ window: {
15
+ createTerminal(options: {
16
+ name: string;
17
+ shellPath?: string;
18
+ shellArgs?: string[];
19
+ env?: Record<string, string>;
20
+ }): VSCodeTerminal;
21
+ onDidCloseTerminal(listener: (terminal: VSCodeTerminal) => void): { dispose(): void };
22
+ };
23
+ }
24
+
25
+ interface VSCodeTerminal {
26
+ name: string;
27
+ processId: Promise<number | undefined>;
28
+ sendText(text: string, addNewLine?: boolean): void;
29
+ show(preserveFocus?: boolean): void;
30
+ hide(): void;
31
+ dispose(): void;
32
+ }
33
+
34
+ /**
35
+ * VSCode terminal implementation
36
+ */
37
+ class VSCodeTerminalWrapper implements Terminal {
38
+ id: string;
39
+ pid?: number;
40
+ private vscodeTerminal?: VSCodeTerminal;
41
+ private outputBuffer = '';
42
+ private commandMarker: string;
43
+ private outputDeferred = createDeferred<string>();
44
+ private isDisposed = false;
45
+
46
+ constructor(
47
+ private vscodeApi: VSCodeAPI,
48
+ private shellType: string,
49
+ private logger: ILogger,
50
+ ) {
51
+ this.id = generateId('vscode-term');
52
+ this.commandMarker = `__CLAUDE_FLOW_${this.id}__`;
53
+ }
54
+
55
+ async initialize(): Promise<void> {
56
+ try {
57
+ // Create VSCode terminal
58
+ const shellPath = this.getShellPath();
59
+ const terminalOptions: any = {
60
+ name: `Claude-Flow Terminal ${this.id}`,
61
+ shellArgs: this.getShellArgs(),
62
+ env: {
63
+ CLAUDE_FLOW_TERMINAL: 'true',
64
+ CLAUDE_FLOW_TERMINAL_ID: this.id,
65
+ PS1: '$ ', // Simple prompt
66
+ },
67
+ };
68
+ if (shellPath !== undefined) {
69
+ terminalOptions.shellPath = shellPath;
70
+ }
71
+ this.vscodeTerminal = this.vscodeApi.window.createTerminal(terminalOptions);
72
+
73
+ // Get process ID
74
+ const processId = await this.vscodeTerminal.processId;
75
+ if (processId !== undefined) {
76
+ this.pid = processId;
77
+ }
78
+
79
+ // Show terminal (but don't steal focus)
80
+ this.vscodeTerminal.show(true);
81
+
82
+ // Wait for terminal to be ready
83
+ await this.waitForReady();
84
+
85
+ this.logger.debug('VSCode terminal initialized', { id: this.id, pid: this.pid });
86
+ } catch (error) {
87
+ throw new TerminalError('Failed to create VSCode terminal', { error });
88
+ }
89
+ }
90
+
91
+ async executeCommand(command: string): Promise<string> {
92
+ if (!this.vscodeTerminal || !this.isAlive()) {
93
+ throw new TerminalError('Terminal is not alive');
94
+ }
95
+
96
+ try {
97
+ // Clear output buffer
98
+ this.outputBuffer = '';
99
+ this.outputDeferred = createDeferred<string>();
100
+
101
+ // Send command with marker
102
+ const markedCommand = `${command} && echo "${this.commandMarker}"`;
103
+ this.vscodeTerminal.sendText(markedCommand, true);
104
+
105
+ // Wait for command to complete
106
+ const output = await timeout(
107
+ this.outputDeferred.promise,
108
+ 30000,
109
+ 'Command execution timeout',
110
+ );
111
+
112
+ return output;
113
+ } catch (error) {
114
+ throw new TerminalError('Failed to execute command', { command, error });
115
+ }
116
+ }
117
+
118
+ async write(data: string): Promise<void> {
119
+ if (!this.vscodeTerminal || !this.isAlive()) {
120
+ throw new TerminalError('Terminal is not alive');
121
+ }
122
+
123
+ this.vscodeTerminal.sendText(data, false);
124
+ }
125
+
126
+ async read(): Promise<string> {
127
+ if (!this.vscodeTerminal || !this.isAlive()) {
128
+ throw new TerminalError('Terminal is not alive');
129
+ }
130
+
131
+ // Return buffered output
132
+ const output = this.outputBuffer;
133
+ this.outputBuffer = '';
134
+ return output;
135
+ }
136
+
137
+ isAlive(): boolean {
138
+ return !this.isDisposed && this.vscodeTerminal !== undefined;
139
+ }
140
+
141
+ async kill(): Promise<void> {
142
+ if (this.vscodeTerminal && !this.isDisposed) {
143
+ try {
144
+ // Try graceful shutdown first
145
+ this.vscodeTerminal.sendText('exit', true);
146
+ await delay(500);
147
+
148
+ // Dispose terminal
149
+ this.vscodeTerminal.dispose();
150
+ this.isDisposed = true;
151
+ } catch (error) {
152
+ this.logger.warn('Error killing VSCode terminal', { id: this.id, error });
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Process terminal output (called by extension)
159
+ */
160
+ processOutput(data: string): void {
161
+ this.outputBuffer += data;
162
+
163
+ // Check for command completion marker
164
+ const markerIndex = this.outputBuffer.indexOf(this.commandMarker);
165
+ if (markerIndex !== -1) {
166
+ // Extract output before marker
167
+ const output = this.outputBuffer.substring(0, markerIndex).trim();
168
+
169
+ // Clear buffer up to after marker
170
+ this.outputBuffer = this.outputBuffer.substring(
171
+ markerIndex + this.commandMarker.length,
172
+ ).trim();
173
+
174
+ // Resolve pending command
175
+ this.outputDeferred.resolve(output);
176
+ }
177
+ }
178
+
179
+ private getShellPath(): string | undefined {
180
+ switch (this.shellType) {
181
+ case 'bash':
182
+ return '/bin/bash';
183
+ case 'zsh':
184
+ return '/bin/zsh';
185
+ case 'powershell':
186
+ return Deno.build.os === 'windows' ? 'powershell.exe' : 'pwsh';
187
+ case 'cmd':
188
+ return Deno.build.os === 'windows' ? 'cmd.exe' : undefined;
189
+ default:
190
+ return undefined;
191
+ }
192
+ }
193
+
194
+ private getShellArgs(): string[] {
195
+ switch (this.shellType) {
196
+ case 'bash':
197
+ return ['--norc', '--noprofile'];
198
+ case 'zsh':
199
+ return ['--no-rcs'];
200
+ case 'powershell':
201
+ return ['-NoProfile', '-NonInteractive'];
202
+ case 'cmd':
203
+ return ['/Q'];
204
+ default:
205
+ return [];
206
+ }
207
+ }
208
+
209
+ private async waitForReady(): Promise<void> {
210
+ // Send a test command to ensure terminal is ready
211
+ this.vscodeTerminal!.sendText('echo "READY"', true);
212
+
213
+ const startTime = Date.now();
214
+ while (Date.now() - startTime < 5000) {
215
+ if (this.outputBuffer.includes('READY')) {
216
+ this.outputBuffer = '';
217
+ return;
218
+ }
219
+ await delay(100);
220
+ }
221
+
222
+ throw new TerminalError('Terminal failed to become ready');
223
+ }
224
+ }
225
+
226
+ /**
227
+ * VSCode terminal adapter
228
+ */
229
+ export class VSCodeAdapter implements ITerminalAdapter {
230
+ private terminals = new Map<string, VSCodeTerminalWrapper>();
231
+ private vscodeApi?: VSCodeAPI;
232
+ private shellType: string;
233
+ private terminalCloseListener?: { dispose(): void };
234
+
235
+ constructor(private logger: ILogger) {
236
+ this.shellType = this.detectShell();
237
+ }
238
+
239
+ async initialize(): Promise<void> {
240
+ this.logger.info('Initializing VSCode terminal adapter');
241
+
242
+ // Check if running in VSCode extension context
243
+ if (!this.isVSCodeExtensionContext()) {
244
+ throw new TerminalError('Not running in VSCode extension context');
245
+ }
246
+
247
+ // Get VSCode API from global
248
+ this.vscodeApi = (globalThis as any).vscode;
249
+ if (!this.vscodeApi) {
250
+ throw new TerminalError('VSCode API not available');
251
+ }
252
+
253
+ // Register terminal close listener
254
+ this.terminalCloseListener = this.vscodeApi.window.onDidCloseTerminal((terminal) => {
255
+ // Find and clean up closed terminal
256
+ for (const [id, wrapper] of this.terminals.entries()) {
257
+ if ((wrapper as any).vscodeTerminal === terminal) {
258
+ this.logger.info('VSCode terminal closed', { id });
259
+ this.terminals.delete(id);
260
+ break;
261
+ }
262
+ }
263
+ });
264
+
265
+ this.logger.info('VSCode terminal adapter initialized');
266
+ }
267
+
268
+ async shutdown(): Promise<void> {
269
+ this.logger.info('Shutting down VSCode terminal adapter');
270
+
271
+ // Dispose listener
272
+ if (this.terminalCloseListener) {
273
+ this.terminalCloseListener.dispose();
274
+ }
275
+
276
+ // Kill all terminals
277
+ const terminals = Array.from(this.terminals.values());
278
+ await Promise.all(terminals.map(term => term.kill()));
279
+
280
+ this.terminals.clear();
281
+ }
282
+
283
+ async createTerminal(): Promise<Terminal> {
284
+ if (!this.vscodeApi) {
285
+ throw new TerminalError('VSCode API not initialized');
286
+ }
287
+
288
+ const terminal = new VSCodeTerminalWrapper(
289
+ this.vscodeApi,
290
+ this.shellType,
291
+ this.logger,
292
+ );
293
+
294
+ await terminal.initialize();
295
+ this.terminals.set(terminal.id, terminal);
296
+
297
+ // Register output processor if extension provides it
298
+ const outputProcessor = (globalThis as any).registerTerminalOutputProcessor;
299
+ if (outputProcessor) {
300
+ outputProcessor(terminal.id, (data: string) => terminal.processOutput(data));
301
+ }
302
+
303
+ return terminal;
304
+ }
305
+
306
+ async destroyTerminal(terminal: Terminal): Promise<void> {
307
+ await terminal.kill();
308
+ this.terminals.delete(terminal.id);
309
+ }
310
+
311
+ private isVSCodeExtensionContext(): boolean {
312
+ // Check for VSCode extension environment
313
+ return typeof (globalThis as any).vscode !== 'undefined' &&
314
+ typeof (globalThis as any).vscode.window !== 'undefined';
315
+ }
316
+
317
+ private detectShell(): string {
318
+ // Get default shell from VSCode settings or environment
319
+ const platform = Deno.build.os;
320
+
321
+ if (platform === 'windows') {
322
+ // Windows defaults
323
+ const comspec = Deno.env.get('COMSPEC');
324
+ if (comspec?.toLowerCase().includes('powershell')) {
325
+ return 'powershell';
326
+ }
327
+ return 'cmd';
328
+ } else {
329
+ // Unix-like defaults
330
+ const shell = Deno.env.get('SHELL');
331
+ if (shell) {
332
+ const shellName = shell.split('/').pop();
333
+ if (shellName && ['bash', 'zsh', 'fish', 'sh'].includes(shellName)) {
334
+ return shellName;
335
+ }
336
+ }
337
+ return 'bash';
338
+ }
339
+ }
340
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Terminal manager interface and implementation
3
+ */
4
+
5
+ import { AgentProfile, AgentSession, TerminalConfig } from '../utils/types.ts';
6
+ import { IEventBus } from '../core/event-bus.ts';
7
+ import { ILogger } from '../core/logger.ts';
8
+ import { TerminalError, TerminalSpawnError } from '../utils/errors.ts';
9
+ import { ITerminalAdapter } from './adapters/base.ts';
10
+ import { VSCodeAdapter } from './adapters/vscode.ts';
11
+ import { NativeAdapter } from './adapters/native.ts';
12
+ import { TerminalPool } from './pool.ts';
13
+ import { TerminalSession } from './session.ts';
14
+
15
+ export interface ITerminalManager {
16
+ initialize(): Promise<void>;
17
+ shutdown(): Promise<void>;
18
+ spawnTerminal(profile: AgentProfile): Promise<string>;
19
+ terminateTerminal(terminalId: string): Promise<void>;
20
+ executeCommand(terminalId: string, command: string): Promise<string>;
21
+ getHealthStatus(): Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>;
22
+ performMaintenance(): Promise<void>;
23
+ }
24
+
25
+ /**
26
+ * Terminal manager implementation
27
+ */
28
+ export class TerminalManager implements ITerminalManager {
29
+ private adapter: ITerminalAdapter;
30
+ private pool: TerminalPool;
31
+ private sessions = new Map<string, TerminalSession>();
32
+ private initialized = false;
33
+
34
+ constructor(
35
+ private config: TerminalConfig,
36
+ private eventBus: IEventBus,
37
+ private logger: ILogger,
38
+ ) {
39
+ // Select adapter based on configuration
40
+ this.adapter = this.createAdapter();
41
+
42
+ // Create terminal pool
43
+ this.pool = new TerminalPool(
44
+ this.config.poolSize,
45
+ this.config.recycleAfter,
46
+ this.adapter,
47
+ this.logger,
48
+ );
49
+ }
50
+
51
+ async initialize(): Promise<void> {
52
+ if (this.initialized) {
53
+ return;
54
+ }
55
+
56
+ this.logger.info('Initializing terminal manager...');
57
+
58
+ try {
59
+ // Initialize adapter
60
+ await this.adapter.initialize();
61
+
62
+ // Initialize pool
63
+ await this.pool.initialize();
64
+
65
+ this.initialized = true;
66
+ this.logger.info('Terminal manager initialized');
67
+ } catch (error) {
68
+ this.logger.error('Failed to initialize terminal manager', error);
69
+ throw new TerminalError('Terminal manager initialization failed', { error });
70
+ }
71
+ }
72
+
73
+ async shutdown(): Promise<void> {
74
+ if (!this.initialized) {
75
+ return;
76
+ }
77
+
78
+ this.logger.info('Shutting down terminal manager...');
79
+
80
+ try {
81
+ // Terminate all sessions
82
+ const sessionIds = Array.from(this.sessions.keys());
83
+ await Promise.all(
84
+ sessionIds.map((id) => this.terminateTerminal(id)),
85
+ );
86
+
87
+ // Shutdown pool
88
+ await this.pool.shutdown();
89
+
90
+ // Shutdown adapter
91
+ await this.adapter.shutdown();
92
+
93
+ this.initialized = false;
94
+ this.logger.info('Terminal manager shutdown complete');
95
+ } catch (error) {
96
+ this.logger.error('Error during terminal manager shutdown', error);
97
+ throw error;
98
+ }
99
+ }
100
+
101
+ async spawnTerminal(profile: AgentProfile): Promise<string> {
102
+ if (!this.initialized) {
103
+ throw new TerminalError('Terminal manager not initialized');
104
+ }
105
+
106
+ this.logger.debug('Spawning terminal', { agentId: profile.id });
107
+
108
+ try {
109
+ // Get terminal from pool
110
+ const terminal = await this.pool.acquire();
111
+
112
+ // Create session
113
+ const session = new TerminalSession(
114
+ terminal,
115
+ profile,
116
+ this.config.commandTimeout,
117
+ this.logger,
118
+ );
119
+
120
+ // Initialize session
121
+ await session.initialize();
122
+
123
+ // Store session
124
+ this.sessions.set(session.id, session);
125
+
126
+ this.logger.info('Terminal spawned', {
127
+ terminalId: session.id,
128
+ agentId: profile.id,
129
+ });
130
+
131
+ return session.id;
132
+ } catch (error) {
133
+ this.logger.error('Failed to spawn terminal', error);
134
+ throw new TerminalSpawnError('Failed to spawn terminal', { error });
135
+ }
136
+ }
137
+
138
+ async terminateTerminal(terminalId: string): Promise<void> {
139
+ const session = this.sessions.get(terminalId);
140
+ if (!session) {
141
+ throw new TerminalError(`Terminal not found: ${terminalId}`);
142
+ }
143
+
144
+ this.logger.debug('Terminating terminal', { terminalId });
145
+
146
+ try {
147
+ // Cleanup session
148
+ await session.cleanup();
149
+
150
+ // Return terminal to pool
151
+ await this.pool.release(session.terminal);
152
+
153
+ // Remove session
154
+ this.sessions.delete(terminalId);
155
+
156
+ this.logger.info('Terminal terminated', { terminalId });
157
+ } catch (error) {
158
+ this.logger.error('Failed to terminate terminal', error);
159
+ throw error;
160
+ }
161
+ }
162
+
163
+ async executeCommand(terminalId: string, command: string): Promise<string> {
164
+ const session = this.sessions.get(terminalId);
165
+ if (!session) {
166
+ throw new TerminalError(`Terminal not found: ${terminalId}`);
167
+ }
168
+
169
+ return await session.executeCommand(command);
170
+ }
171
+
172
+ async getHealthStatus(): Promise<{
173
+ healthy: boolean;
174
+ error?: string;
175
+ metrics?: Record<string, number>;
176
+ }> {
177
+ try {
178
+ const poolHealth = await this.pool.getHealthStatus();
179
+ const activeSessions = this.sessions.size;
180
+ const healthySessions = Array.from(this.sessions.values())
181
+ .filter((session) => session.isHealthy()).length;
182
+
183
+ const metrics = {
184
+ activeSessions,
185
+ healthySessions,
186
+ poolSize: poolHealth.size,
187
+ availableTerminals: poolHealth.available,
188
+ recycledTerminals: poolHealth.recycled,
189
+ };
190
+
191
+ const healthy = poolHealth.healthy && healthySessions === activeSessions;
192
+
193
+ if (healthy) {
194
+ return {
195
+ healthy,
196
+ metrics,
197
+ };
198
+ } else {
199
+ return {
200
+ healthy,
201
+ metrics,
202
+ error: 'Some terminals are unhealthy',
203
+ };
204
+ }
205
+ } catch (error) {
206
+ return {
207
+ healthy: false,
208
+ error: error instanceof Error ? error.message : 'Unknown error',
209
+ };
210
+ }
211
+ }
212
+
213
+ async performMaintenance(): Promise<void> {
214
+ if (!this.initialized) {
215
+ return;
216
+ }
217
+
218
+ this.logger.debug('Performing terminal manager maintenance');
219
+
220
+ try {
221
+ // Clean up dead sessions
222
+ const deadSessions = Array.from(this.sessions.entries())
223
+ .filter(([_, session]) => !session.isHealthy());
224
+
225
+ for (const [terminalId, _] of deadSessions) {
226
+ this.logger.warn('Cleaning up dead terminal session', { terminalId });
227
+ await this.terminateTerminal(terminalId).catch(error =>
228
+ this.logger.error('Failed to clean up terminal', { terminalId, error })
229
+ );
230
+ }
231
+
232
+ // Perform pool maintenance
233
+ await this.pool.performMaintenance();
234
+
235
+ // Emit maintenance event
236
+ this.eventBus.emit('terminal:maintenance', {
237
+ deadSessions: deadSessions.length,
238
+ activeSessions: this.sessions.size,
239
+ poolStatus: await this.pool.getHealthStatus(),
240
+ });
241
+
242
+ this.logger.debug('Terminal manager maintenance completed');
243
+ } catch (error) {
244
+ this.logger.error('Error during terminal manager maintenance', error);
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Get all active sessions
250
+ */
251
+ getActiveSessions(): AgentSession[] {
252
+ return Array.from(this.sessions.values()).map(session => ({
253
+ id: session.id,
254
+ agentId: session.profile.id,
255
+ terminalId: session.terminal.id,
256
+ startTime: session.startTime,
257
+ status: session.isHealthy() ? 'active' : 'error',
258
+ lastActivity: session.lastActivity,
259
+ memoryBankId: '', // TODO: Link to memory bank
260
+ }));
261
+ }
262
+
263
+ /**
264
+ * Get session by ID
265
+ */
266
+ getSession(sessionId: string): TerminalSession | undefined {
267
+ return this.sessions.get(sessionId);
268
+ }
269
+
270
+ /**
271
+ * Stream terminal output
272
+ */
273
+ async streamOutput(terminalId: string, callback: (output: string) => void): Promise<() => void> {
274
+ const session = this.sessions.get(terminalId);
275
+ if (!session) {
276
+ throw new TerminalError(`Terminal not found: ${terminalId}`);
277
+ }
278
+
279
+ return session.streamOutput(callback);
280
+ }
281
+
282
+ private createAdapter(): ITerminalAdapter {
283
+ switch (this.config.type) {
284
+ case 'vscode':
285
+ return new VSCodeAdapter(this.logger);
286
+ case 'native':
287
+ return new NativeAdapter(this.logger);
288
+ case 'auto':
289
+ // Detect environment and choose appropriate adapter
290
+ if (this.isVSCodeEnvironment()) {
291
+ this.logger.info('Detected VSCode environment, using VSCode adapter');
292
+ return new VSCodeAdapter(this.logger);
293
+ } else {
294
+ this.logger.info('Using native terminal adapter');
295
+ return new NativeAdapter(this.logger);
296
+ }
297
+ default:
298
+ throw new TerminalError(`Unknown terminal type: ${this.config.type}`);
299
+ }
300
+ }
301
+
302
+ private isVSCodeEnvironment(): boolean {
303
+ // Check for VSCode-specific environment variables
304
+ return Deno.env.get('TERM_PROGRAM') === 'vscode' ||
305
+ Deno.env.get('VSCODE_PID') !== undefined ||
306
+ Deno.env.get('VSCODE_IPC_HOOK') !== undefined;
307
+ }
308
+ }