closeli-mcp-gateway 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.
- package/.env.example +30 -0
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/config/environment.d.ts +29 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +48 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +201 -0
- package/dist/server.js.map +1 -0
- package/dist/session/ProcessExecutor.d.ts +20 -0
- package/dist/session/ProcessExecutor.d.ts.map +1 -0
- package/dist/session/ProcessExecutor.js +286 -0
- package/dist/session/ProcessExecutor.js.map +1 -0
- package/dist/session/Session.d.ts +60 -0
- package/dist/session/Session.d.ts.map +1 -0
- package/dist/session/Session.js +5 -0
- package/dist/session/Session.js.map +1 -0
- package/dist/session/SessionManager.d.ts +53 -0
- package/dist/session/SessionManager.d.ts.map +1 -0
- package/dist/session/SessionManager.js +228 -0
- package/dist/session/SessionManager.js.map +1 -0
- package/dist/tools/claude-code.d.ts +17 -0
- package/dist/tools/claude-code.d.ts.map +1 -0
- package/dist/tools/claude-code.js +79 -0
- package/dist/tools/claude-code.js.map +1 -0
- package/dist/tools/codex.d.ts +17 -0
- package/dist/tools/codex.d.ts.map +1 -0
- package/dist/tools/codex.js +79 -0
- package/dist/tools/codex.js.map +1 -0
- package/dist/tools/get-session-status.d.ts +16 -0
- package/dist/tools/get-session-status.d.ts.map +1 -0
- package/dist/tools/get-session-status.js +88 -0
- package/dist/tools/get-session-status.js.map +1 -0
- package/dist/tools/resume.d.ts +16 -0
- package/dist/tools/resume.d.ts.map +1 -0
- package/dist/tools/resume.js +68 -0
- package/dist/tools/resume.js.map +1 -0
- package/dist/tools/types.d.ts +28 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +74 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/utils/errors.d.ts +54 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +66 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +80 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +52 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Setup
|
|
3
|
+
* Register tools and start server
|
|
4
|
+
*/
|
|
5
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { logger } from './utils/logger.js';
|
|
10
|
+
import { sessionManager } from './session/SessionManager.js';
|
|
11
|
+
import { handleCodexTool } from './tools/codex.js';
|
|
12
|
+
import { handleClaudeCodeTool } from './tools/claude-code.js';
|
|
13
|
+
import { handleResumeTool } from './tools/resume.js';
|
|
14
|
+
import { handleGetSessionStatusTool } from './tools/get-session-status.js';
|
|
15
|
+
/**
|
|
16
|
+
* Tool parameter schema definitions
|
|
17
|
+
*/
|
|
18
|
+
const CodexParamsSchema = z.object({
|
|
19
|
+
workspace: z.string().describe('Working directory path'),
|
|
20
|
+
prompt: z.string().describe('Task prompt'),
|
|
21
|
+
});
|
|
22
|
+
const ClaudeCodeParamsSchema = z.object({
|
|
23
|
+
workspace: z.string().describe('Working directory path'),
|
|
24
|
+
prompt: z.string().describe('Task prompt'),
|
|
25
|
+
});
|
|
26
|
+
const ResumeParamsSchema = z.object({
|
|
27
|
+
sessionId: z.string().describe('Session ID (UUID)'),
|
|
28
|
+
});
|
|
29
|
+
const GetSessionStatusParamsSchema = z.object({
|
|
30
|
+
sessionId: z.string().describe('Session ID (UUID)'),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Create and configure MCP server
|
|
34
|
+
*/
|
|
35
|
+
export function createServer() {
|
|
36
|
+
const server = new Server({
|
|
37
|
+
name: 'closeli-mcp-gateway',
|
|
38
|
+
version: '1.0.0',
|
|
39
|
+
}, {
|
|
40
|
+
capabilities: {
|
|
41
|
+
tools: {},
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
// Register tools list handler
|
|
45
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
46
|
+
return {
|
|
47
|
+
tools: [
|
|
48
|
+
{
|
|
49
|
+
name: 'codex',
|
|
50
|
+
description: 'Start a new codex task. Executes codex exec command to handle long-running tasks. If task does not complete within timeout, returns sessionId for client to continue waiting using resume tool.',
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
workspace: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Absolute path of working directory',
|
|
57
|
+
},
|
|
58
|
+
prompt: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'Task prompt to execute',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
required: ['workspace', 'prompt'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'claude-code',
|
|
68
|
+
description: 'Start a new claude-code task. Executes claude command to handle long-running tasks. If task does not complete within timeout, returns sessionId for client to continue waiting using resume tool.',
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
workspace: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'Absolute path of working directory',
|
|
75
|
+
},
|
|
76
|
+
prompt: {
|
|
77
|
+
type: 'string',
|
|
78
|
+
description: 'Task prompt to execute',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
required: ['workspace', 'prompt'],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'resume',
|
|
86
|
+
description: 'Continue waiting for previously started task result. This is a universal tool that works with any task type (codex or claude-code). Use the sessionId returned from previous call to continue waiting.',
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties: {
|
|
90
|
+
sessionId: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description: 'Session ID (UUID format)',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
required: ['sessionId'],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'get-session-status',
|
|
100
|
+
description: 'Query current running status of a session. View whether task is still running, running duration, output line count, recent output, etc. Used to monitor progress of long-running tasks.',
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
properties: {
|
|
104
|
+
sessionId: {
|
|
105
|
+
type: 'string',
|
|
106
|
+
description: 'Session ID (UUID format)',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
required: ['sessionId'],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
// Register tool call handler
|
|
116
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
117
|
+
const { name, arguments: args } = request.params;
|
|
118
|
+
logger.info('Tool called', { name, args });
|
|
119
|
+
try {
|
|
120
|
+
switch (name) {
|
|
121
|
+
case 'codex': {
|
|
122
|
+
const params = CodexParamsSchema.parse(args);
|
|
123
|
+
return await handleCodexTool(params);
|
|
124
|
+
}
|
|
125
|
+
case 'claude-code': {
|
|
126
|
+
const params = ClaudeCodeParamsSchema.parse(args);
|
|
127
|
+
return await handleClaudeCodeTool(params);
|
|
128
|
+
}
|
|
129
|
+
case 'resume': {
|
|
130
|
+
const params = ResumeParamsSchema.parse(args);
|
|
131
|
+
return await handleResumeTool(params);
|
|
132
|
+
}
|
|
133
|
+
case 'get-session-status': {
|
|
134
|
+
const params = GetSessionStatusParamsSchema.parse(args);
|
|
135
|
+
return await handleGetSessionStatusTool(params);
|
|
136
|
+
}
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
logger.error('Error handling tool call', {
|
|
143
|
+
name,
|
|
144
|
+
error: error instanceof Error ? error.message : String(error),
|
|
145
|
+
});
|
|
146
|
+
return {
|
|
147
|
+
content: [
|
|
148
|
+
{
|
|
149
|
+
type: 'text',
|
|
150
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
isError: true,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return server;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Start server
|
|
161
|
+
*/
|
|
162
|
+
export async function startServer() {
|
|
163
|
+
logger.info('Starting MCP server...');
|
|
164
|
+
// Start orphan cleanup
|
|
165
|
+
sessionManager.startOrphanCleanup();
|
|
166
|
+
// Create server
|
|
167
|
+
const server = createServer();
|
|
168
|
+
// Use stdio transport
|
|
169
|
+
const transport = new StdioServerTransport();
|
|
170
|
+
await server.connect(transport);
|
|
171
|
+
logger.info('MCP server started successfully');
|
|
172
|
+
// Setup graceful shutdown
|
|
173
|
+
setupGracefulShutdown(server);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Setup graceful shutdown handling
|
|
177
|
+
*/
|
|
178
|
+
function setupGracefulShutdown(server) {
|
|
179
|
+
const shutdown = async (signal) => {
|
|
180
|
+
logger.info(`Received ${signal}, shutting down gracefully...`);
|
|
181
|
+
try {
|
|
182
|
+
// Stop orphan cleanup
|
|
183
|
+
sessionManager.stopOrphanCleanup();
|
|
184
|
+
// Cleanup all sessions
|
|
185
|
+
await sessionManager.cleanupAllSessions();
|
|
186
|
+
// Close server
|
|
187
|
+
await server.close();
|
|
188
|
+
logger.info('Server shutdown complete');
|
|
189
|
+
process.exit(0);
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
logger.error('Error during shutdown', {
|
|
193
|
+
error: error instanceof Error ? error.message : String(error),
|
|
194
|
+
});
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
199
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process Execution Module
|
|
3
|
+
* Responsible for starting, monitoring, and terminating child processes
|
|
4
|
+
*/
|
|
5
|
+
import { ChildProcess } from 'child_process';
|
|
6
|
+
import * as pty from 'node-pty';
|
|
7
|
+
import { Session, ToolType } from './Session.js';
|
|
8
|
+
/**
|
|
9
|
+
* Start a process and return the process instance
|
|
10
|
+
*/
|
|
11
|
+
export declare function spawnProcess(tool: ToolType, workspace: string, prompt: string): ChildProcess | pty.IPty;
|
|
12
|
+
/**
|
|
13
|
+
* Set up process output capture
|
|
14
|
+
*/
|
|
15
|
+
export declare function setupOutputCapture(childProcess: ChildProcess | pty.IPty, session: Session): void;
|
|
16
|
+
/**
|
|
17
|
+
* Gracefully terminate a process
|
|
18
|
+
*/
|
|
19
|
+
export declare function killProcessGracefully(childProcess: ChildProcess | pty.IPty): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=ProcessExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProcessExecutor.d.ts","sourceRoot":"","sources":["../../src/session/ProcessExecutor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAIhC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEjD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,YAAY,GAAG,GAAG,CAAC,IAAI,CAsCzB;AA+BD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAyLhG;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,YAAY,GAAG,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChG"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process Execution Module
|
|
3
|
+
* Responsible for starting, monitoring, and terminating child processes
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
import { config } from '../config/environment.js';
|
|
8
|
+
import { ProcessExecutionError } from '../utils/errors.js';
|
|
9
|
+
/**
|
|
10
|
+
* Start a process and return the process instance
|
|
11
|
+
*/
|
|
12
|
+
export function spawnProcess(tool, workspace, prompt) {
|
|
13
|
+
const { command, args } = buildCommand(tool, prompt);
|
|
14
|
+
logger.info('Spawning process', {
|
|
15
|
+
tool,
|
|
16
|
+
command,
|
|
17
|
+
workspace,
|
|
18
|
+
promptLength: prompt.length,
|
|
19
|
+
});
|
|
20
|
+
try {
|
|
21
|
+
// Currently using normal spawn for all, as node-pty has compatibility issues with Node v25
|
|
22
|
+
const childProcess = spawn(command, args, {
|
|
23
|
+
cwd: workspace,
|
|
24
|
+
env: {
|
|
25
|
+
...process.env,
|
|
26
|
+
// For claude, try to disable TTY detection
|
|
27
|
+
TERM: tool === 'claude-code' ? 'xterm-256color' : 'dumb',
|
|
28
|
+
CI: 'true',
|
|
29
|
+
},
|
|
30
|
+
shell: false,
|
|
31
|
+
});
|
|
32
|
+
if (!childProcess.pid) {
|
|
33
|
+
throw new ProcessExecutionError('Failed to spawn process: no PID assigned');
|
|
34
|
+
}
|
|
35
|
+
logger.info('Process spawned successfully', {
|
|
36
|
+
pid: childProcess.pid,
|
|
37
|
+
tool,
|
|
38
|
+
});
|
|
39
|
+
return childProcess;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
43
|
+
logger.error('Failed to spawn process', { tool, error: message });
|
|
44
|
+
throw new ProcessExecutionError(`Failed to spawn ${tool}: ${message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build command and arguments based on tool type
|
|
49
|
+
*/
|
|
50
|
+
function buildCommand(tool, prompt) {
|
|
51
|
+
switch (tool) {
|
|
52
|
+
case 'codex':
|
|
53
|
+
return {
|
|
54
|
+
command: 'codex',
|
|
55
|
+
args: ['exec', '--skip-git-repo-check', '--full-auto', prompt],
|
|
56
|
+
};
|
|
57
|
+
case 'claude-code':
|
|
58
|
+
const args = ['--print'];
|
|
59
|
+
// Add arguments based on VERBOSE environment variable
|
|
60
|
+
if (config.VERBOSE) {
|
|
61
|
+
args.push('--verbose', '--output-format', 'stream-json');
|
|
62
|
+
}
|
|
63
|
+
args.push('--dangerously-skip-permissions', prompt);
|
|
64
|
+
return {
|
|
65
|
+
command: 'claude',
|
|
66
|
+
args,
|
|
67
|
+
};
|
|
68
|
+
default:
|
|
69
|
+
throw new ProcessExecutionError(`Unknown tool type: ${tool}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Set up process output capture
|
|
74
|
+
*/
|
|
75
|
+
export function setupOutputCapture(childProcess, session) {
|
|
76
|
+
// Now using normal ChildProcess for all
|
|
77
|
+
const normalProcess = childProcess;
|
|
78
|
+
// Close stdin - this is important for claude in --print mode
|
|
79
|
+
// claude waits for stdin to close before starting output
|
|
80
|
+
if (normalProcess.stdin) {
|
|
81
|
+
try {
|
|
82
|
+
normalProcess.stdin.end();
|
|
83
|
+
logger.debug('Closed process stdin', {
|
|
84
|
+
sessionId: session.id,
|
|
85
|
+
tool: session.tool,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.warn('Failed to close stdin', {
|
|
90
|
+
sessionId: session.id,
|
|
91
|
+
error: error instanceof Error ? error.message : String(error),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Check if stdout exists
|
|
96
|
+
if (!normalProcess.stdout) {
|
|
97
|
+
logger.error('Process stdout is null', {
|
|
98
|
+
sessionId: session.id,
|
|
99
|
+
pid: session.pid,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
logger.debug('Setting up stdout capture', {
|
|
104
|
+
sessionId: session.id,
|
|
105
|
+
pid: session.pid,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Check if stderr exists
|
|
109
|
+
if (!normalProcess.stderr) {
|
|
110
|
+
logger.error('Process stderr is null', {
|
|
111
|
+
sessionId: session.id,
|
|
112
|
+
pid: session.pid,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
logger.debug('Setting up stderr capture', {
|
|
117
|
+
sessionId: session.id,
|
|
118
|
+
pid: session.pid,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Capture stdout
|
|
122
|
+
normalProcess.stdout?.on('data', (chunk) => {
|
|
123
|
+
const text = chunk.toString('utf-8');
|
|
124
|
+
logger.debug('Received stdout data', {
|
|
125
|
+
sessionId: session.id,
|
|
126
|
+
chunkSize: chunk.length,
|
|
127
|
+
textLength: text.length,
|
|
128
|
+
});
|
|
129
|
+
const lines = text.split('\n').filter((line) => line.length > 0);
|
|
130
|
+
// VERBOSE mode: output detailed logs
|
|
131
|
+
if (config.VERBOSE) {
|
|
132
|
+
// Log all output
|
|
133
|
+
lines.forEach((line) => {
|
|
134
|
+
logger.info('[PROCESS OUTPUT]', {
|
|
135
|
+
sessionId: session.id,
|
|
136
|
+
tool: session.tool,
|
|
137
|
+
stream: 'stdout',
|
|
138
|
+
line,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// claude-code VERBOSE mode uses stream-json, only save final result
|
|
142
|
+
if (session.tool === 'claude-code') {
|
|
143
|
+
lines.forEach((line) => {
|
|
144
|
+
try {
|
|
145
|
+
const json = JSON.parse(line);
|
|
146
|
+
if (json.type === 'result') {
|
|
147
|
+
// Save result text content (may be multi-line)
|
|
148
|
+
const resultText = json.result || '';
|
|
149
|
+
const resultLines = resultText.split('\n');
|
|
150
|
+
session.stdout = resultLines;
|
|
151
|
+
logger.info('Captured final result for claude-code', {
|
|
152
|
+
sessionId: session.id,
|
|
153
|
+
isError: json.is_error,
|
|
154
|
+
duration: json.duration_ms,
|
|
155
|
+
lines: resultLines.length,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
// Not valid JSON, ignore
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Other tools: save all output
|
|
166
|
+
session.stdout.push(...lines);
|
|
167
|
+
if (session.stdout.length > config.MAX_OUTPUT_LINES) {
|
|
168
|
+
const excess = session.stdout.length - config.MAX_OUTPUT_LINES;
|
|
169
|
+
session.stdout.splice(0, excess);
|
|
170
|
+
logger.warn('Output buffer limit reached, discarding oldest lines', {
|
|
171
|
+
sessionId: session.id,
|
|
172
|
+
discarded: excess,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Non-VERBOSE mode: don't output logs, save all output
|
|
179
|
+
session.stdout.push(...lines);
|
|
180
|
+
if (session.stdout.length > config.MAX_OUTPUT_LINES) {
|
|
181
|
+
const excess = session.stdout.length - config.MAX_OUTPUT_LINES;
|
|
182
|
+
session.stdout.splice(0, excess);
|
|
183
|
+
logger.warn('Output buffer limit reached, discarding oldest lines', {
|
|
184
|
+
sessionId: session.id,
|
|
185
|
+
discarded: excess,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// Capture stderr
|
|
191
|
+
normalProcess.stderr?.on('data', (chunk) => {
|
|
192
|
+
const text = chunk.toString('utf-8');
|
|
193
|
+
logger.debug('Received stderr data', {
|
|
194
|
+
sessionId: session.id,
|
|
195
|
+
chunkSize: chunk.length,
|
|
196
|
+
textLength: text.length,
|
|
197
|
+
});
|
|
198
|
+
const lines = text.split('\n').filter((line) => line.length > 0);
|
|
199
|
+
// VERBOSE mode: output stderr to logs (including tokens used, etc.)
|
|
200
|
+
if (config.VERBOSE) {
|
|
201
|
+
lines.forEach((line) => {
|
|
202
|
+
logger.info('[PROCESS ERROR]', {
|
|
203
|
+
sessionId: session.id,
|
|
204
|
+
tool: session.tool,
|
|
205
|
+
stream: 'stderr',
|
|
206
|
+
line,
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
// stderr not saved to session (not returned to client)
|
|
211
|
+
});
|
|
212
|
+
// Handle process exit
|
|
213
|
+
normalProcess.on('exit', (code, signal) => {
|
|
214
|
+
session.exitCode = code;
|
|
215
|
+
session.completedAt = new Date();
|
|
216
|
+
if (signal) {
|
|
217
|
+
session.status = 'killed';
|
|
218
|
+
logger.warn('Process killed by signal', {
|
|
219
|
+
sessionId: session.id,
|
|
220
|
+
signal,
|
|
221
|
+
pid: session.pid,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else if (code === 0) {
|
|
225
|
+
session.status = 'completed';
|
|
226
|
+
logger.info('Process completed successfully', {
|
|
227
|
+
sessionId: session.id,
|
|
228
|
+
pid: session.pid,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
session.status = 'failed';
|
|
233
|
+
logger.error('Process failed with exit code', {
|
|
234
|
+
sessionId: session.id,
|
|
235
|
+
exitCode: code,
|
|
236
|
+
pid: session.pid,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
// Handle process errors
|
|
241
|
+
normalProcess.on('error', (error) => {
|
|
242
|
+
session.status = 'failed';
|
|
243
|
+
session.completedAt = new Date();
|
|
244
|
+
logger.error('Process error', {
|
|
245
|
+
sessionId: session.id,
|
|
246
|
+
error: error.message,
|
|
247
|
+
pid: session.pid,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Gracefully terminate a process
|
|
253
|
+
*/
|
|
254
|
+
export async function killProcessGracefully(childProcess) {
|
|
255
|
+
// Now using normal ChildProcess for all
|
|
256
|
+
const normalProcess = childProcess;
|
|
257
|
+
if (!normalProcess.pid || normalProcess.killed) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const pid = normalProcess.pid;
|
|
261
|
+
logger.info('Attempting graceful process termination', { pid });
|
|
262
|
+
// Attempt graceful termination
|
|
263
|
+
normalProcess.kill('SIGTERM');
|
|
264
|
+
// Wait for grace period
|
|
265
|
+
await sleep(config.KILL_GRACE_PERIOD_MS);
|
|
266
|
+
// If still running, force kill
|
|
267
|
+
if (!normalProcess.killed) {
|
|
268
|
+
logger.warn('Process did not terminate gracefully, forcing kill', { pid });
|
|
269
|
+
normalProcess.kill('SIGKILL');
|
|
270
|
+
// Try to kill process group (Unix systems)
|
|
271
|
+
try {
|
|
272
|
+
process.kill(-pid, 'SIGKILL');
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
// Process may have already exited, ignore error
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
logger.info('Process terminated', { pid });
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Helper function: async sleep
|
|
282
|
+
*/
|
|
283
|
+
function sleep(ms) {
|
|
284
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=ProcessExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProcessExecutor.js","sourceRoot":"","sources":["../../src/session/ProcessExecutor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAG3D;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAc,EACd,SAAiB,EACjB,MAAc;IAEd,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE;QAC9B,IAAI;QACJ,OAAO;QACP,SAAS;QACT,YAAY,EAAE,MAAM,CAAC,MAAM;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,2FAA2F;QAC3F,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACxC,GAAG,EAAE,SAAS;YACd,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,2CAA2C;gBAC3C,IAAI,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM;gBACxD,EAAE,EAAE,MAAM;aACX;YACD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;YACtB,MAAM,IAAI,qBAAqB,CAAC,0CAA0C,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE;YAC1C,GAAG,EAAE,YAAY,CAAC,GAAG;YACrB,IAAI;SACL,CAAC,CAAC;QAEH,OAAO,YAAY,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,MAAM,IAAI,qBAAqB,CAAC,mBAAmB,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAc,EAAE,MAAc;IAClD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO;gBACL,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,CAAC;aAC/D,CAAC;QACJ,KAAK,aAAa;YAChB,MAAM,IAAI,GAAa,CAAC,SAAS,CAAC,CAAC;YAEnC,sDAAsD;YACtD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;YAEpD,OAAO;gBACL,OAAO,EAAE,QAAQ;gBACjB,IAAI;aACL,CAAC;QACJ;YACE,MAAM,IAAI,qBAAqB,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAqC,EAAE,OAAgB;IACxF,wCAAwC;IACxC,MAAM,aAAa,GAAG,YAA4B,CAAC;IAEnD,6DAA6D;IAC7D,yDAAyD;IACzD,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;gBACnC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,OAAO,CAAC,IAAI;aACnB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE;gBACnC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE;YACrC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;YACxC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE;YACrC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;YACxC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;IAED,iBAAiB;IACjB,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;YACnC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,UAAU,EAAE,IAAI,CAAC,MAAM;SACxB,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjE,qCAAqC;QACrC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,iBAAiB;YACjB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE;oBAC9B,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,QAAQ;oBAChB,IAAI;iBACL,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,oEAAoE;YACpE,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACnC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;oBACrB,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;4BAC3B,+CAA+C;4BAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;4BACrC,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;4BAC3C,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC;4BAC7B,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE;gCACnD,SAAS,EAAE,OAAO,CAAC,EAAE;gCACrB,OAAO,EAAE,IAAI,CAAC,QAAQ;gCACtB,QAAQ,EAAE,IAAI,CAAC,WAAW;gCAC1B,KAAK,EAAE,WAAW,CAAC,MAAM;6BAC1B,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,yBAAyB;oBAC3B,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,+BAA+B;gBAC/B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;gBAE9B,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;oBACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;oBAC/D,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;oBACjC,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;wBAClE,SAAS,EAAE,OAAO,CAAC,EAAE;wBACrB,SAAS,EAAE,MAAM;qBAClB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,uDAAuD;YACvD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YAE9B,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;oBAClE,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,SAAS,EAAE,MAAM;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,iBAAiB;IACjB,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;YACnC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,SAAS,EAAE,KAAK,CAAC,MAAM;YACvB,UAAU,EAAE,IAAI,CAAC,MAAM;SACxB,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjE,oEAAoE;QACpE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE;oBAC7B,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,MAAM,EAAE,QAAQ;oBAChB,IAAI;iBACL,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,uDAAuD;IACzD,CAAC,CAAC,CAAC;IAEH,sBAAsB;IACtB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;QACxC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QACxB,OAAO,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;QAEjC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;gBACtC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,MAAM;gBACN,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE;gBAC5C,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE;gBAC5C,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,QAAQ,EAAE,IAAI;gBACd,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAClC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC;QAC1B,OAAO,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE;YAC5B,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,YAAqC;IAC/E,wCAAwC;IACxC,MAAM,aAAa,GAAG,YAA4B,CAAC;IAEnD,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC;IAE9B,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAEhE,+BAA+B;IAC/B,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE9B,wBAAwB;IACxB,MAAM,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEzC,+BAA+B;IAC/B,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3E,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE9B,2CAA2C;QAC3C,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gDAAgD;QAClD,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-related type definitions
|
|
3
|
+
*/
|
|
4
|
+
import { ChildProcess } from 'child_process';
|
|
5
|
+
import * as pty from 'node-pty';
|
|
6
|
+
/**
|
|
7
|
+
* Tool type
|
|
8
|
+
*/
|
|
9
|
+
export type ToolType = 'codex' | 'claude-code';
|
|
10
|
+
/**
|
|
11
|
+
* Session status
|
|
12
|
+
*/
|
|
13
|
+
export type SessionStatus = 'running' | 'completed' | 'failed' | 'killed';
|
|
14
|
+
/**
|
|
15
|
+
* Session data structure
|
|
16
|
+
*/
|
|
17
|
+
export interface Session {
|
|
18
|
+
/** Unique session ID (UUID) */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Tool type used */
|
|
21
|
+
tool: ToolType;
|
|
22
|
+
/** Working directory */
|
|
23
|
+
workspace: string;
|
|
24
|
+
/** Task prompt */
|
|
25
|
+
prompt: string;
|
|
26
|
+
/** Node process reference (supports both normal process and PTY) */
|
|
27
|
+
process: ChildProcess | pty.IPty;
|
|
28
|
+
/** Process ID */
|
|
29
|
+
pid: number;
|
|
30
|
+
/** Standard output lines */
|
|
31
|
+
stdout: string[];
|
|
32
|
+
/** Standard error output lines */
|
|
33
|
+
stderr: string[];
|
|
34
|
+
/** Exit code (when completed) */
|
|
35
|
+
exitCode: number | null;
|
|
36
|
+
/** Session creation time */
|
|
37
|
+
createdAt: Date;
|
|
38
|
+
/** Last client check time */
|
|
39
|
+
lastClientCheckTime: Date;
|
|
40
|
+
/** Completion time (if completed) */
|
|
41
|
+
completedAt: Date | null;
|
|
42
|
+
/** Current status */
|
|
43
|
+
status: SessionStatus;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Wait result return type
|
|
47
|
+
*/
|
|
48
|
+
export interface WaitResult {
|
|
49
|
+
/** Whether completed */
|
|
50
|
+
complete: boolean;
|
|
51
|
+
/** Standard output */
|
|
52
|
+
stdout?: string[];
|
|
53
|
+
/** Standard error output */
|
|
54
|
+
stderr?: string[];
|
|
55
|
+
/** Exit code */
|
|
56
|
+
exitCode?: number | null;
|
|
57
|
+
/** Status */
|
|
58
|
+
status?: SessionStatus;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=Session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Session.d.ts","sourceRoot":"","sources":["../../src/session/Session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,OAAO,EAAE,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC;IACjC,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IAGZ,4BAA4B;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kCAAkC;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxB,4BAA4B;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,6BAA6B;IAC7B,mBAAmB,EAAE,IAAI,CAAC;IAC1B,qCAAqC;IACrC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IAGzB,qBAAqB;IACrB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wBAAwB;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa;IACb,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Session.js","sourceRoot":"","sources":["../../src/session/Session.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Manager
|
|
3
|
+
* Responsible for creating, managing, and cleaning up sessions
|
|
4
|
+
*/
|
|
5
|
+
import { Session, ToolType, WaitResult } from './Session.js';
|
|
6
|
+
/**
|
|
7
|
+
* SessionManager singleton class
|
|
8
|
+
*/
|
|
9
|
+
export declare class SessionManager {
|
|
10
|
+
private sessions;
|
|
11
|
+
private cleanupTimer;
|
|
12
|
+
/**
|
|
13
|
+
* Create new session and start process
|
|
14
|
+
*/
|
|
15
|
+
createSession(tool: ToolType, workspace: string, prompt: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Get session and update last check time
|
|
18
|
+
*/
|
|
19
|
+
getSession(sessionId: string): Session;
|
|
20
|
+
/**
|
|
21
|
+
* Wait for session result, throw error if timeout
|
|
22
|
+
*/
|
|
23
|
+
waitForResult(sessionId: string, maxWaitMs: number): Promise<WaitResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Clean up session (terminate process and remove from Map)
|
|
26
|
+
*/
|
|
27
|
+
cleanupSession(sessionId: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Start orphan session cleanup
|
|
30
|
+
*/
|
|
31
|
+
startOrphanCleanup(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Stop orphan session cleanup
|
|
34
|
+
*/
|
|
35
|
+
stopOrphanCleanup(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Check and clean up orphaned sessions
|
|
38
|
+
*/
|
|
39
|
+
private checkOrphanedSessions;
|
|
40
|
+
/**
|
|
41
|
+
* Clean up all sessions (used when shutting down server)
|
|
42
|
+
*/
|
|
43
|
+
cleanupAllSessions(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Get current active session count
|
|
46
|
+
*/
|
|
47
|
+
getActiveSessionCount(): number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Global singleton instance
|
|
51
|
+
*/
|
|
52
|
+
export declare const sessionManager: SessionManager;
|
|
53
|
+
//# sourceMappingURL=SessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/session/SessionManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG7D;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,YAAY,CAA+B;IAEnD;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyDvF;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IActC;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAiD9E;;OAEG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BtD;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAgB1B;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;YACW,qBAAqB;IAwBnC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAczC;;OAEG;IACH,qBAAqB,IAAI,MAAM;CAGhC;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|