@dexto/core 1.5.4 → 1.5.6
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/dist/agent/DextoAgent.cjs +61 -155
- package/dist/agent/DextoAgent.d.ts +11 -54
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +61 -155
- package/dist/context/compaction/strategies/reactive-overflow.cjs +5 -3
- package/dist/context/compaction/strategies/reactive-overflow.d.ts +1 -0
- package/dist/context/compaction/strategies/reactive-overflow.d.ts.map +1 -1
- package/dist/context/compaction/strategies/reactive-overflow.js +5 -3
- package/dist/context/compaction/types.d.ts +13 -1
- package/dist/context/compaction/types.d.ts.map +1 -1
- package/dist/errors/types.cjs +0 -2
- package/dist/errors/types.d.ts +1 -5
- package/dist/errors/types.d.ts.map +1 -1
- package/dist/errors/types.js +0 -2
- package/dist/events/index.cjs +0 -2
- package/dist/events/index.d.ts +6 -25
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +0 -2
- package/dist/llm/executor/stream-processor.cjs +85 -27
- package/dist/llm/executor/stream-processor.d.ts +4 -0
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +85 -27
- package/dist/llm/executor/turn-executor.cjs +58 -130
- package/dist/llm/executor/turn-executor.d.ts +9 -43
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +58 -130
- package/dist/llm/executor/types.d.ts +0 -28
- package/dist/llm/executor/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +2 -5
- package/dist/llm/services/vercel.d.ts +1 -6
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +2 -5
- package/dist/logger/logger.cjs +6 -7
- package/dist/logger/logger.d.ts +1 -0
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +6 -7
- package/dist/session/chat-session.cjs +19 -12
- package/dist/session/chat-session.d.ts +3 -6
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +19 -12
- package/dist/session/session-manager.cjs +0 -135
- package/dist/session/session-manager.d.ts +0 -43
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +0 -135
- package/dist/telemetry/telemetry.cjs +12 -5
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +12 -5
- package/dist/tools/schemas.cjs +2 -2
- package/dist/tools/schemas.js +2 -2
- package/package.json +15 -5
- package/dist/filesystem/error-codes.cjs +0 -53
- package/dist/filesystem/error-codes.d.ts +0 -31
- package/dist/filesystem/error-codes.d.ts.map +0 -1
- package/dist/filesystem/error-codes.js +0 -30
- package/dist/filesystem/errors.cjs +0 -303
- package/dist/filesystem/errors.d.ts +0 -109
- package/dist/filesystem/errors.d.ts.map +0 -1
- package/dist/filesystem/errors.js +0 -280
- package/dist/filesystem/filesystem-service.cjs +0 -534
- package/dist/filesystem/filesystem-service.d.ts +0 -97
- package/dist/filesystem/filesystem-service.d.ts.map +0 -1
- package/dist/filesystem/filesystem-service.js +0 -501
- package/dist/filesystem/index.cjs +0 -37
- package/dist/filesystem/index.d.ts +0 -11
- package/dist/filesystem/index.d.ts.map +0 -1
- package/dist/filesystem/index.js +0 -11
- package/dist/filesystem/path-validator.cjs +0 -250
- package/dist/filesystem/path-validator.d.ts +0 -103
- package/dist/filesystem/path-validator.d.ts.map +0 -1
- package/dist/filesystem/path-validator.js +0 -217
- package/dist/filesystem/types.cjs +0 -16
- package/dist/filesystem/types.d.ts +0 -175
- package/dist/filesystem/types.d.ts.map +0 -1
- package/dist/filesystem/types.js +0 -0
- package/dist/process/command-validator.cjs +0 -554
- package/dist/process/command-validator.d.ts +0 -49
- package/dist/process/command-validator.d.ts.map +0 -1
- package/dist/process/command-validator.js +0 -531
- package/dist/process/error-codes.cjs +0 -47
- package/dist/process/error-codes.d.ts +0 -25
- package/dist/process/error-codes.d.ts.map +0 -1
- package/dist/process/error-codes.js +0 -24
- package/dist/process/errors.cjs +0 -244
- package/dist/process/errors.d.ts +0 -87
- package/dist/process/errors.d.ts.map +0 -1
- package/dist/process/errors.js +0 -221
- package/dist/process/index.cjs +0 -37
- package/dist/process/index.d.ts +0 -11
- package/dist/process/index.d.ts.map +0 -1
- package/dist/process/index.js +0 -11
- package/dist/process/process-service.cjs +0 -497
- package/dist/process/process-service.d.ts +0 -69
- package/dist/process/process-service.d.ts.map +0 -1
- package/dist/process/process-service.js +0 -464
- package/dist/process/types.cjs +0 -16
- package/dist/process/types.d.ts +0 -107
- package/dist/process/types.d.ts.map +0 -1
- package/dist/process/types.js +0 -0
- package/dist/session/compaction-service.cjs +0 -139
- package/dist/session/compaction-service.d.ts +0 -81
- package/dist/session/compaction-service.d.ts.map +0 -1
- package/dist/session/compaction-service.js +0 -106
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import "../chunk-PTJYTZNU.js";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import * as crypto from "node:crypto";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { CommandValidator } from "./command-validator.js";
|
|
6
|
-
import { ProcessError } from "./errors.js";
|
|
7
|
-
import { DextoLogComponent } from "../logger/v2/types.js";
|
|
8
|
-
const DEFAULT_TIMEOUT = 12e4;
|
|
9
|
-
const DEFAULT_MAX_TIMEOUT = 6e5;
|
|
10
|
-
const DEFAULT_MAX_CONCURRENT_PROCESSES = 5;
|
|
11
|
-
const DEFAULT_MAX_OUTPUT_BUFFER = 1024 * 1024;
|
|
12
|
-
class ProcessService {
|
|
13
|
-
config;
|
|
14
|
-
commandValidator;
|
|
15
|
-
initialized = false;
|
|
16
|
-
backgroundProcesses = /* @__PURE__ */ new Map();
|
|
17
|
-
logger;
|
|
18
|
-
constructor(config = {}, logger) {
|
|
19
|
-
this.config = {
|
|
20
|
-
securityLevel: config.securityLevel || "moderate",
|
|
21
|
-
maxTimeout: config.maxTimeout || DEFAULT_MAX_TIMEOUT,
|
|
22
|
-
maxConcurrentProcesses: config.maxConcurrentProcesses || DEFAULT_MAX_CONCURRENT_PROCESSES,
|
|
23
|
-
maxOutputBuffer: config.maxOutputBuffer || DEFAULT_MAX_OUTPUT_BUFFER,
|
|
24
|
-
allowedCommands: config.allowedCommands || [],
|
|
25
|
-
blockedCommands: config.blockedCommands || [],
|
|
26
|
-
environment: config.environment || {},
|
|
27
|
-
workingDirectory: config.workingDirectory
|
|
28
|
-
};
|
|
29
|
-
this.logger = logger.createChild(DextoLogComponent.PROCESS);
|
|
30
|
-
this.commandValidator = new CommandValidator(this.config, this.logger);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Initialize the service
|
|
34
|
-
*/
|
|
35
|
-
async initialize() {
|
|
36
|
-
if (this.initialized) {
|
|
37
|
-
this.logger.debug("ProcessService already initialized");
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
this.backgroundProcesses.clear();
|
|
41
|
-
this.initialized = true;
|
|
42
|
-
this.logger.info("ProcessService initialized successfully");
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Execute a command
|
|
46
|
-
*/
|
|
47
|
-
async executeCommand(command, options = {}) {
|
|
48
|
-
if (!this.initialized) {
|
|
49
|
-
throw ProcessError.notInitialized();
|
|
50
|
-
}
|
|
51
|
-
const validation = this.commandValidator.validateCommand(command);
|
|
52
|
-
if (!validation.isValid || !validation.normalizedCommand) {
|
|
53
|
-
throw ProcessError.invalidCommand(command, validation.error || "Unknown error");
|
|
54
|
-
}
|
|
55
|
-
const normalizedCommand = validation.normalizedCommand;
|
|
56
|
-
const rawTimeout = options.timeout !== void 0 && Number.isFinite(options.timeout) ? options.timeout : DEFAULT_TIMEOUT;
|
|
57
|
-
const timeout = Math.max(1, Math.min(rawTimeout, this.config.maxTimeout));
|
|
58
|
-
const cwd = this.resolveSafeCwd(options.cwd);
|
|
59
|
-
const env = {};
|
|
60
|
-
for (const [key, value] of Object.entries({
|
|
61
|
-
...process.env,
|
|
62
|
-
...this.config.environment,
|
|
63
|
-
...options.env
|
|
64
|
-
})) {
|
|
65
|
-
if (value !== void 0) {
|
|
66
|
-
env[key] = value;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (options.runInBackground) {
|
|
70
|
-
return await this.executeInBackground(normalizedCommand, options);
|
|
71
|
-
}
|
|
72
|
-
return await this.executeForeground(normalizedCommand, {
|
|
73
|
-
cwd,
|
|
74
|
-
timeout,
|
|
75
|
-
env,
|
|
76
|
-
...options.description !== void 0 && { description: options.description },
|
|
77
|
-
...options.abortSignal !== void 0 && { abortSignal: options.abortSignal }
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
static SIGKILL_TIMEOUT_MS = 200;
|
|
81
|
-
/**
|
|
82
|
-
* Kill a process tree (process group on Unix, taskkill on Windows)
|
|
83
|
-
*/
|
|
84
|
-
async killProcessTree(pid, child) {
|
|
85
|
-
if (process.platform === "win32") {
|
|
86
|
-
await new Promise((resolve) => {
|
|
87
|
-
const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], {
|
|
88
|
-
stdio: "ignore"
|
|
89
|
-
});
|
|
90
|
-
killer.once("exit", () => resolve());
|
|
91
|
-
killer.once("error", () => resolve());
|
|
92
|
-
});
|
|
93
|
-
} else {
|
|
94
|
-
try {
|
|
95
|
-
process.kill(-pid, "SIGTERM");
|
|
96
|
-
await new Promise((res) => setTimeout(res, ProcessService.SIGKILL_TIMEOUT_MS));
|
|
97
|
-
if (child.exitCode === null) {
|
|
98
|
-
process.kill(-pid, "SIGKILL");
|
|
99
|
-
}
|
|
100
|
-
} catch {
|
|
101
|
-
child.kill("SIGTERM");
|
|
102
|
-
await new Promise((res) => setTimeout(res, ProcessService.SIGKILL_TIMEOUT_MS));
|
|
103
|
-
if (child.exitCode === null) {
|
|
104
|
-
child.kill("SIGKILL");
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Execute command in foreground with timeout and abort support
|
|
111
|
-
*/
|
|
112
|
-
executeForeground(command, options) {
|
|
113
|
-
return new Promise((resolve, reject) => {
|
|
114
|
-
const startTime = Date.now();
|
|
115
|
-
let stdout = "";
|
|
116
|
-
let stderr = "";
|
|
117
|
-
let killed = false;
|
|
118
|
-
let aborted = false;
|
|
119
|
-
let closed = false;
|
|
120
|
-
if (options.abortSignal?.aborted) {
|
|
121
|
-
this.logger.debug(`Command cancelled before execution: ${command}`);
|
|
122
|
-
resolve({
|
|
123
|
-
stdout: "",
|
|
124
|
-
stderr: "(Command was cancelled)",
|
|
125
|
-
exitCode: 130,
|
|
126
|
-
// Standard exit code for SIGINT
|
|
127
|
-
duration: 0
|
|
128
|
-
});
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
this.logger.debug(`Executing command: ${command}`);
|
|
132
|
-
const child = spawn(command, {
|
|
133
|
-
cwd: options.cwd,
|
|
134
|
-
env: options.env,
|
|
135
|
-
shell: true,
|
|
136
|
-
detached: process.platform !== "win32"
|
|
137
|
-
// Create process group on Unix
|
|
138
|
-
});
|
|
139
|
-
const timeoutHandle = setTimeout(() => {
|
|
140
|
-
killed = true;
|
|
141
|
-
if (child.pid) {
|
|
142
|
-
void this.killProcessTree(child.pid, child);
|
|
143
|
-
} else {
|
|
144
|
-
child.kill("SIGTERM");
|
|
145
|
-
}
|
|
146
|
-
}, options.timeout);
|
|
147
|
-
const abortHandler = () => {
|
|
148
|
-
if (closed) return;
|
|
149
|
-
aborted = true;
|
|
150
|
-
this.logger.debug(`Command cancelled by user: ${command}`);
|
|
151
|
-
clearTimeout(timeoutHandle);
|
|
152
|
-
if (child.pid) {
|
|
153
|
-
void this.killProcessTree(child.pid, child);
|
|
154
|
-
} else {
|
|
155
|
-
child.kill("SIGTERM");
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
options.abortSignal?.addEventListener("abort", abortHandler, { once: true });
|
|
159
|
-
child.stdout?.on("data", (data) => {
|
|
160
|
-
stdout += data.toString();
|
|
161
|
-
});
|
|
162
|
-
child.stderr?.on("data", (data) => {
|
|
163
|
-
stderr += data.toString();
|
|
164
|
-
});
|
|
165
|
-
child.on("close", (code, signal) => {
|
|
166
|
-
closed = true;
|
|
167
|
-
clearTimeout(timeoutHandle);
|
|
168
|
-
options.abortSignal?.removeEventListener("abort", abortHandler);
|
|
169
|
-
const duration = Date.now() - startTime;
|
|
170
|
-
if (aborted) {
|
|
171
|
-
stdout += "\n\n(Command was cancelled)";
|
|
172
|
-
this.logger.debug(`Command cancelled after ${duration}ms: ${command}`);
|
|
173
|
-
resolve({
|
|
174
|
-
stdout,
|
|
175
|
-
stderr,
|
|
176
|
-
exitCode: 130,
|
|
177
|
-
// Standard exit code for SIGINT
|
|
178
|
-
duration
|
|
179
|
-
});
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (killed) {
|
|
183
|
-
reject(ProcessError.timeout(command, options.timeout));
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
let exitCode = typeof code === "number" ? code : 1;
|
|
187
|
-
if (code === null) {
|
|
188
|
-
stderr += `
|
|
189
|
-
Process terminated by signal ${signal ?? "UNKNOWN"}`;
|
|
190
|
-
}
|
|
191
|
-
this.logger.debug(
|
|
192
|
-
`Command completed with exit code ${exitCode} in ${duration}ms: ${command}`
|
|
193
|
-
);
|
|
194
|
-
resolve({
|
|
195
|
-
stdout,
|
|
196
|
-
stderr,
|
|
197
|
-
exitCode,
|
|
198
|
-
duration
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
child.on("error", (error) => {
|
|
202
|
-
clearTimeout(timeoutHandle);
|
|
203
|
-
options.abortSignal?.removeEventListener("abort", abortHandler);
|
|
204
|
-
if (error.code === "ENOENT") {
|
|
205
|
-
reject(ProcessError.commandNotFound(command));
|
|
206
|
-
} else if (error.code === "EACCES") {
|
|
207
|
-
reject(ProcessError.permissionDenied(command));
|
|
208
|
-
} else {
|
|
209
|
-
reject(ProcessError.executionFailed(command, error.message));
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Execute command in background
|
|
216
|
-
*/
|
|
217
|
-
async executeInBackground(command, options) {
|
|
218
|
-
const runningCount = Array.from(this.backgroundProcesses.values()).filter(
|
|
219
|
-
(p) => p.status === "running"
|
|
220
|
-
).length;
|
|
221
|
-
if (runningCount >= this.config.maxConcurrentProcesses) {
|
|
222
|
-
throw ProcessError.tooManyProcesses(runningCount, this.config.maxConcurrentProcesses);
|
|
223
|
-
}
|
|
224
|
-
const processId = crypto.randomBytes(4).toString("hex");
|
|
225
|
-
const cwd = this.resolveSafeCwd(options.cwd);
|
|
226
|
-
const env = {};
|
|
227
|
-
for (const [key, value] of Object.entries({
|
|
228
|
-
...process.env,
|
|
229
|
-
...this.config.environment,
|
|
230
|
-
...options.env
|
|
231
|
-
})) {
|
|
232
|
-
if (value !== void 0) {
|
|
233
|
-
env[key] = value;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
this.logger.debug(`Starting background process ${processId}: ${command}`);
|
|
237
|
-
const child = spawn(command, {
|
|
238
|
-
cwd,
|
|
239
|
-
env,
|
|
240
|
-
shell: true,
|
|
241
|
-
detached: false
|
|
242
|
-
});
|
|
243
|
-
const outputBuffer = {
|
|
244
|
-
stdout: [],
|
|
245
|
-
stderr: [],
|
|
246
|
-
complete: false,
|
|
247
|
-
lastRead: Date.now(),
|
|
248
|
-
bytesUsed: 0,
|
|
249
|
-
truncated: false
|
|
250
|
-
};
|
|
251
|
-
const bgProcess = {
|
|
252
|
-
processId,
|
|
253
|
-
command,
|
|
254
|
-
child,
|
|
255
|
-
startedAt: /* @__PURE__ */ new Date(),
|
|
256
|
-
status: "running",
|
|
257
|
-
outputBuffer,
|
|
258
|
-
description: options.description
|
|
259
|
-
};
|
|
260
|
-
this.backgroundProcesses.set(processId, bgProcess);
|
|
261
|
-
const bgTimeout = Math.max(
|
|
262
|
-
1,
|
|
263
|
-
Math.min(options.timeout || DEFAULT_TIMEOUT, this.config.maxTimeout)
|
|
264
|
-
);
|
|
265
|
-
const killTimer = setTimeout(() => {
|
|
266
|
-
if (bgProcess.status === "running") {
|
|
267
|
-
this.logger.warn(
|
|
268
|
-
`Background process ${processId} timed out after ${bgTimeout}ms, sending SIGTERM`
|
|
269
|
-
);
|
|
270
|
-
child.kill("SIGTERM");
|
|
271
|
-
setTimeout(() => {
|
|
272
|
-
if (bgProcess.status === "running") {
|
|
273
|
-
this.logger.warn(
|
|
274
|
-
`Background process ${processId} did not respond to SIGTERM, sending SIGKILL`
|
|
275
|
-
);
|
|
276
|
-
child.kill("SIGKILL");
|
|
277
|
-
}
|
|
278
|
-
}, 5e3);
|
|
279
|
-
}
|
|
280
|
-
}, bgTimeout);
|
|
281
|
-
child.stdout?.on("data", (data) => {
|
|
282
|
-
const chunk = data.toString();
|
|
283
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
284
|
-
if (outputBuffer.bytesUsed + chunkBytes <= this.config.maxOutputBuffer) {
|
|
285
|
-
outputBuffer.stdout.push(chunk);
|
|
286
|
-
outputBuffer.bytesUsed += chunkBytes;
|
|
287
|
-
} else {
|
|
288
|
-
if (!outputBuffer.truncated) {
|
|
289
|
-
outputBuffer.truncated = true;
|
|
290
|
-
this.logger.warn(`Output buffer full for process ${processId}`);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
child.stderr?.on("data", (data) => {
|
|
295
|
-
const chunk = data.toString();
|
|
296
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
297
|
-
if (outputBuffer.bytesUsed + chunkBytes <= this.config.maxOutputBuffer) {
|
|
298
|
-
outputBuffer.stderr.push(chunk);
|
|
299
|
-
outputBuffer.bytesUsed += chunkBytes;
|
|
300
|
-
} else {
|
|
301
|
-
if (!outputBuffer.truncated) {
|
|
302
|
-
outputBuffer.truncated = true;
|
|
303
|
-
this.logger.warn(`Error buffer full for process ${processId}`);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
child.on("close", (code) => {
|
|
308
|
-
clearTimeout(killTimer);
|
|
309
|
-
bgProcess.status = code === 0 ? "completed" : "failed";
|
|
310
|
-
bgProcess.exitCode = code ?? void 0;
|
|
311
|
-
bgProcess.completedAt = /* @__PURE__ */ new Date();
|
|
312
|
-
bgProcess.outputBuffer.complete = true;
|
|
313
|
-
this.logger.debug(`Background process ${processId} completed with exit code ${code}`);
|
|
314
|
-
});
|
|
315
|
-
child.on("error", (error) => {
|
|
316
|
-
clearTimeout(killTimer);
|
|
317
|
-
bgProcess.status = "failed";
|
|
318
|
-
bgProcess.completedAt = /* @__PURE__ */ new Date();
|
|
319
|
-
bgProcess.outputBuffer.complete = true;
|
|
320
|
-
const chunk = `Error: ${error.message}`;
|
|
321
|
-
const chunkBytes = Buffer.byteLength(chunk, "utf8");
|
|
322
|
-
if (bgProcess.outputBuffer.bytesUsed + chunkBytes <= this.config.maxOutputBuffer) {
|
|
323
|
-
bgProcess.outputBuffer.stderr.push(chunk);
|
|
324
|
-
bgProcess.outputBuffer.bytesUsed += chunkBytes;
|
|
325
|
-
} else {
|
|
326
|
-
if (!bgProcess.outputBuffer.truncated) {
|
|
327
|
-
bgProcess.outputBuffer.truncated = true;
|
|
328
|
-
this.logger.warn(`Error buffer full for process ${processId}`);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
this.logger.error(`Background process ${processId} failed: ${error.message}`);
|
|
332
|
-
});
|
|
333
|
-
return {
|
|
334
|
-
processId,
|
|
335
|
-
command,
|
|
336
|
-
pid: child.pid,
|
|
337
|
-
startedAt: bgProcess.startedAt,
|
|
338
|
-
description: options.description
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Get output from a background process
|
|
343
|
-
*/
|
|
344
|
-
async getProcessOutput(processId) {
|
|
345
|
-
if (!this.initialized) {
|
|
346
|
-
throw ProcessError.notInitialized();
|
|
347
|
-
}
|
|
348
|
-
const bgProcess = this.backgroundProcesses.get(processId);
|
|
349
|
-
if (!bgProcess) {
|
|
350
|
-
throw ProcessError.processNotFound(processId);
|
|
351
|
-
}
|
|
352
|
-
const stdout = bgProcess.outputBuffer.stdout.join("");
|
|
353
|
-
const stderr = bgProcess.outputBuffer.stderr.join("");
|
|
354
|
-
bgProcess.outputBuffer.stdout = [];
|
|
355
|
-
bgProcess.outputBuffer.stderr = [];
|
|
356
|
-
bgProcess.outputBuffer.lastRead = Date.now();
|
|
357
|
-
bgProcess.outputBuffer.bytesUsed = 0;
|
|
358
|
-
return {
|
|
359
|
-
stdout,
|
|
360
|
-
stderr,
|
|
361
|
-
status: bgProcess.status,
|
|
362
|
-
exitCode: bgProcess.exitCode,
|
|
363
|
-
duration: bgProcess.completedAt ? bgProcess.completedAt.getTime() - bgProcess.startedAt.getTime() : void 0
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Kill a background process
|
|
368
|
-
*/
|
|
369
|
-
async killProcess(processId) {
|
|
370
|
-
if (!this.initialized) {
|
|
371
|
-
throw ProcessError.notInitialized();
|
|
372
|
-
}
|
|
373
|
-
const bgProcess = this.backgroundProcesses.get(processId);
|
|
374
|
-
if (!bgProcess) {
|
|
375
|
-
throw ProcessError.processNotFound(processId);
|
|
376
|
-
}
|
|
377
|
-
if (bgProcess.status !== "running") {
|
|
378
|
-
this.logger.debug(`Process ${processId} is not running (status: ${bgProcess.status})`);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
try {
|
|
382
|
-
bgProcess.child.kill("SIGTERM");
|
|
383
|
-
setTimeout(() => {
|
|
384
|
-
if (bgProcess.child.exitCode === null) {
|
|
385
|
-
bgProcess.child.kill("SIGKILL");
|
|
386
|
-
}
|
|
387
|
-
}, 5e3);
|
|
388
|
-
this.logger.debug(`Process ${processId} sent SIGTERM`);
|
|
389
|
-
} catch (error) {
|
|
390
|
-
throw ProcessError.killFailed(
|
|
391
|
-
processId,
|
|
392
|
-
error instanceof Error ? error.message : String(error)
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* List all background processes
|
|
398
|
-
*/
|
|
399
|
-
async listProcesses() {
|
|
400
|
-
if (!this.initialized) {
|
|
401
|
-
throw ProcessError.notInitialized();
|
|
402
|
-
}
|
|
403
|
-
return Array.from(this.backgroundProcesses.values()).map((bgProcess) => ({
|
|
404
|
-
processId: bgProcess.processId,
|
|
405
|
-
command: bgProcess.command,
|
|
406
|
-
pid: bgProcess.child.pid,
|
|
407
|
-
status: bgProcess.status,
|
|
408
|
-
startedAt: bgProcess.startedAt,
|
|
409
|
-
completedAt: bgProcess.completedAt,
|
|
410
|
-
exitCode: bgProcess.exitCode,
|
|
411
|
-
description: bgProcess.description
|
|
412
|
-
}));
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Get buffer size in bytes
|
|
416
|
-
*/
|
|
417
|
-
getBufferSize(buffer) {
|
|
418
|
-
const stdoutSize = buffer.stdout.reduce((sum, line) => sum + line.length, 0);
|
|
419
|
-
const stderrSize = buffer.stderr.reduce((sum, line) => sum + line.length, 0);
|
|
420
|
-
return stdoutSize + stderrSize;
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Get service configuration
|
|
424
|
-
*/
|
|
425
|
-
getConfig() {
|
|
426
|
-
return { ...this.config };
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Resolve and confine cwd to the configured working directory
|
|
430
|
-
*/
|
|
431
|
-
resolveSafeCwd(cwd) {
|
|
432
|
-
const baseDir = this.config.workingDirectory || process.cwd();
|
|
433
|
-
if (!cwd) return baseDir;
|
|
434
|
-
const candidate = path.isAbsolute(cwd) ? path.resolve(cwd) : path.resolve(baseDir, cwd);
|
|
435
|
-
const rel = path.relative(baseDir, candidate);
|
|
436
|
-
const outside = rel.startsWith("..") || path.isAbsolute(rel);
|
|
437
|
-
if (outside) {
|
|
438
|
-
throw ProcessError.invalidWorkingDirectory(
|
|
439
|
-
cwd,
|
|
440
|
-
`Working directory must be within ${baseDir}`
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
return candidate;
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Cleanup completed processes
|
|
447
|
-
*/
|
|
448
|
-
async cleanup() {
|
|
449
|
-
const now = Date.now();
|
|
450
|
-
const CLEANUP_AGE = 36e5;
|
|
451
|
-
for (const [processId, bgProcess] of this.backgroundProcesses.entries()) {
|
|
452
|
-
if (bgProcess.status !== "running" && bgProcess.completedAt) {
|
|
453
|
-
const age = now - bgProcess.completedAt.getTime();
|
|
454
|
-
if (age > CLEANUP_AGE) {
|
|
455
|
-
this.backgroundProcesses.delete(processId);
|
|
456
|
-
this.logger.debug(`Cleaned up old process ${processId}`);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
export {
|
|
463
|
-
ProcessService
|
|
464
|
-
};
|
package/dist/process/types.cjs
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __copyProps = (to, from, except, desc) => {
|
|
7
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
-
for (let key of __getOwnPropNames(from))
|
|
9
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
-
}
|
|
12
|
-
return to;
|
|
13
|
-
};
|
|
14
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
-
var types_exports = {};
|
|
16
|
-
module.exports = __toCommonJS(types_exports);
|
package/dist/process/types.d.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Process Service Types
|
|
3
|
-
*
|
|
4
|
-
* Types and interfaces for command execution and process management
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Process execution options
|
|
8
|
-
*/
|
|
9
|
-
export interface ExecuteOptions {
|
|
10
|
-
/** Working directory */
|
|
11
|
-
cwd?: string | undefined;
|
|
12
|
-
/** Timeout in milliseconds (max: 600000) */
|
|
13
|
-
timeout?: number | undefined;
|
|
14
|
-
/** Run command in background */
|
|
15
|
-
runInBackground?: boolean | undefined;
|
|
16
|
-
/** Environment variables */
|
|
17
|
-
env?: Record<string, string> | undefined;
|
|
18
|
-
/** Description of what the command does (5-10 words) */
|
|
19
|
-
description?: string | undefined;
|
|
20
|
-
/** Abort signal for cancellation support */
|
|
21
|
-
abortSignal?: AbortSignal | undefined;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Process execution result (foreground execution only)
|
|
25
|
-
* For background execution, see ProcessHandle
|
|
26
|
-
*/
|
|
27
|
-
export interface ProcessResult {
|
|
28
|
-
stdout: string;
|
|
29
|
-
stderr: string;
|
|
30
|
-
exitCode: number;
|
|
31
|
-
duration: number;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Background process handle
|
|
35
|
-
*/
|
|
36
|
-
export interface ProcessHandle {
|
|
37
|
-
processId: string;
|
|
38
|
-
command: string;
|
|
39
|
-
pid?: number | undefined;
|
|
40
|
-
startedAt: Date;
|
|
41
|
-
description?: string | undefined;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Process output (for retrieving from background processes)
|
|
45
|
-
*/
|
|
46
|
-
export interface ProcessOutput {
|
|
47
|
-
stdout: string;
|
|
48
|
-
stderr: string;
|
|
49
|
-
status: 'running' | 'completed' | 'failed';
|
|
50
|
-
exitCode?: number | undefined;
|
|
51
|
-
duration?: number | undefined;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Process information
|
|
55
|
-
*/
|
|
56
|
-
export interface ProcessInfo {
|
|
57
|
-
processId: string;
|
|
58
|
-
command: string;
|
|
59
|
-
pid?: number | undefined;
|
|
60
|
-
status: 'running' | 'completed' | 'failed';
|
|
61
|
-
startedAt: Date;
|
|
62
|
-
completedAt?: Date | undefined;
|
|
63
|
-
exitCode?: number | undefined;
|
|
64
|
-
description?: string | undefined;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Command validation result
|
|
68
|
-
*/
|
|
69
|
-
export interface CommandValidation {
|
|
70
|
-
isValid: boolean;
|
|
71
|
-
error?: string;
|
|
72
|
-
normalizedCommand?: string;
|
|
73
|
-
requiresApproval?: boolean;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Process service configuration
|
|
77
|
-
*/
|
|
78
|
-
export interface ProcessConfig {
|
|
79
|
-
/** Security level for command execution */
|
|
80
|
-
securityLevel: 'strict' | 'moderate' | 'permissive';
|
|
81
|
-
/** Maximum timeout for commands in milliseconds */
|
|
82
|
-
maxTimeout: number;
|
|
83
|
-
/** Maximum concurrent background processes */
|
|
84
|
-
maxConcurrentProcesses: number;
|
|
85
|
-
/** Maximum output buffer size in bytes */
|
|
86
|
-
maxOutputBuffer: number;
|
|
87
|
-
/** Explicitly allowed commands (empty = all allowed with approval) */
|
|
88
|
-
allowedCommands: string[];
|
|
89
|
-
/** Blocked command patterns */
|
|
90
|
-
blockedCommands: string[];
|
|
91
|
-
/** Custom environment variables */
|
|
92
|
-
environment: Record<string, string>;
|
|
93
|
-
/** Working directory (defaults to process.cwd()) */
|
|
94
|
-
workingDirectory?: string | undefined;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Output buffer management
|
|
98
|
-
*/
|
|
99
|
-
export interface OutputBuffer {
|
|
100
|
-
stdout: string[];
|
|
101
|
-
stderr: string[];
|
|
102
|
-
complete: boolean;
|
|
103
|
-
lastRead: number;
|
|
104
|
-
bytesUsed: number;
|
|
105
|
-
truncated?: boolean;
|
|
106
|
-
}
|
|
107
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/process/types.ts"],"names":[],"mappings":"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"}
|
package/dist/process/types.js
DELETED
|
File without changes
|