psadk 1.1.37 → 1.1.38
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.
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { PSAgentLogger } from '../PSAgentLogger';
|
|
2
2
|
import { PSAgentTool } from '../PSAgentTool';
|
|
3
|
+
export interface CommandSecurityOptions {
|
|
4
|
+
/** Validate/sanitize a command before execution. Return sanitized command string or throw/return null to reject. */
|
|
5
|
+
commandValidator?: (command: string) => string | null;
|
|
6
|
+
/** Restricted environment variables to pass to the child process. If set, replaces process.env entirely. */
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
/** Execution timeout in milliseconds (default: no timeout) */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** Max output buffer size in bytes (default: 10MB) */
|
|
11
|
+
maxBuffer?: number;
|
|
12
|
+
}
|
|
3
13
|
export declare class PSCommandLineTool extends PSAgentTool {
|
|
4
14
|
static readonly toolName = "run_commandline";
|
|
5
15
|
private cwd;
|
|
16
|
+
private security?;
|
|
6
17
|
constructor(options: {
|
|
7
18
|
cwd: string;
|
|
19
|
+
security?: CommandSecurityOptions;
|
|
8
20
|
});
|
|
9
21
|
run(input: Record<string, any>, log?: PSAgentLogger): Promise<Record<string, any>>;
|
|
10
22
|
}
|
|
@@ -31,6 +31,7 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
31
31
|
},
|
|
32
32
|
});
|
|
33
33
|
this.cwd = options.cwd || process.cwd();
|
|
34
|
+
this.security = options.security;
|
|
34
35
|
}
|
|
35
36
|
run(input, log) {
|
|
36
37
|
if (!input.command || typeof input.command !== 'string') {
|
|
@@ -38,10 +39,25 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
38
39
|
}
|
|
39
40
|
const logger = log || console;
|
|
40
41
|
return new Promise((resolve, reject) => {
|
|
41
|
-
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
43
|
+
let command = (0, helpers_1.unEscapeHTML)(input.command);
|
|
44
|
+
// Apply command validation if configured
|
|
45
|
+
if ((_a = this.security) === null || _a === void 0 ? void 0 : _a.commandValidator) {
|
|
46
|
+
const validated = this.security.commandValidator(command);
|
|
47
|
+
if (validated === null) {
|
|
48
|
+
return reject(new Error(`Command rejected by security policy: ${command}`));
|
|
49
|
+
}
|
|
50
|
+
command = validated;
|
|
51
|
+
}
|
|
42
52
|
try {
|
|
43
53
|
logger.info(`🛠️ Running command: \`${command}\``);
|
|
44
|
-
const output = (0, child_process_1.execSync)(command, {
|
|
54
|
+
const output = (0, child_process_1.execSync)(command, {
|
|
55
|
+
cwd: this.cwd,
|
|
56
|
+
encoding: 'utf-8',
|
|
57
|
+
env: (_c = (_b = this.security) === null || _b === void 0 ? void 0 : _b.env) !== null && _c !== void 0 ? _c : undefined,
|
|
58
|
+
timeout: (_e = (_d = this.security) === null || _d === void 0 ? void 0 : _d.timeoutMs) !== null && _e !== void 0 ? _e : undefined,
|
|
59
|
+
maxBuffer: (_g = (_f = this.security) === null || _f === void 0 ? void 0 : _f.maxBuffer) !== null && _g !== void 0 ? _g : 10 * 1024 * 1024,
|
|
60
|
+
});
|
|
45
61
|
logger.info('```bash\n' + `> ${command}\n` + `${output}\n` + '```\n\n');
|
|
46
62
|
return resolve({
|
|
47
63
|
status: 'success',
|
|
@@ -72,4 +88,4 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
72
88
|
}
|
|
73
89
|
exports.PSCommandLineTool = PSCommandLineTool;
|
|
74
90
|
PSCommandLineTool.toolName = 'run_commandline';
|
|
75
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUFNDb21tYW5kTGluZVRvb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xzL1BTQ29tbWFuZExpbmVUb29sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHVEQUF1RDtBQUN2RCxpREFBMkQ7QUFFM0QsK0JBQTJCO0FBRzNCLGdEQUE2QztBQUM3Qyw4Q0FBZ0Q7QUFhaEQsTUFBYSxpQkFBa0IsU0FBUSx5QkFBVztJQUloRCxZQUFZLE9BQTJEO1FBQ3JFLEtBQUssQ0FBQztZQUNKLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxRQUFRO1lBQ2hDLFdBQVcsRUFBRSwwREFBMEQ7WUFDdkUsSUFBSSxFQUFFLEtBQUs7WUFDWCxlQUFlLEVBQUUsSUFBSTtZQUNyQixJQUFJLEVBQUUsSUFBSTtZQUNWLFdBQVcsRUFBRTtnQkFDWCxHQUFHLEVBQUUsa0NBQWtDO2dCQUN2QyxNQUFNLEVBQUUsTUFBTTtnQkFDZCxXQUFXLEVBQUUsTUFBQyxDQUFDLFlBQVksQ0FDekIsTUFBQztxQkFDRSxNQUFNLENBQUM7b0JBQ04sT0FBTyxFQUFFLE1BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUM7d0JBQ3ZCLEtBQUssRUFBRSxTQUFTO3dCQUNoQixXQUFXLEVBQUUsK0NBQStDO3FCQUM3RCxDQUFDO2lCQUNILENBQUM7cUJBQ0QsSUFBSSxDQUFDO29CQUNKLEtBQUssRUFBRSw4QkFBOEI7b0JBQ3JDLFdBQVcsRUFDVCwyREFBMkQ7aUJBQzlELENBQUMsRUFDSixFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FDaEI7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO0lBQ25DLENBQUM7SUFDTSxHQUFHLENBQ1Is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
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { PSAgentLogger } from '../PSAgentLogger';
|
|
2
2
|
import { PSAgentTool } from '../PSAgentTool';
|
|
3
|
+
export interface CommandSecurityOptions {
|
|
4
|
+
/** Validate/sanitize a command before execution. Return sanitized command string or throw/return null to reject. */
|
|
5
|
+
commandValidator?: (command: string) => string | null;
|
|
6
|
+
/** Restricted environment variables to pass to the child process. If set, replaces process.env entirely. */
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
/** Execution timeout in milliseconds (default: no timeout) */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** Max output buffer size in bytes (default: 10MB) */
|
|
11
|
+
maxBuffer?: number;
|
|
12
|
+
}
|
|
3
13
|
export declare class PSCommandLineTool extends PSAgentTool {
|
|
4
14
|
static readonly toolName = "run_commandline";
|
|
5
15
|
private cwd;
|
|
16
|
+
private security?;
|
|
6
17
|
constructor(options: {
|
|
7
18
|
cwd: string;
|
|
19
|
+
security?: CommandSecurityOptions;
|
|
8
20
|
});
|
|
9
21
|
run(input: Record<string, any>, log?: PSAgentLogger): Promise<Record<string, any>>;
|
|
10
22
|
}
|
|
@@ -9,6 +9,7 @@ const helpers_1 = require("../utils/helpers");
|
|
|
9
9
|
class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
10
10
|
static toolName = 'run_commandline';
|
|
11
11
|
cwd;
|
|
12
|
+
security;
|
|
12
13
|
constructor(options) {
|
|
13
14
|
super({
|
|
14
15
|
name: PSCommandLineTool.toolName,
|
|
@@ -33,6 +34,7 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
33
34
|
},
|
|
34
35
|
});
|
|
35
36
|
this.cwd = options.cwd || process.cwd();
|
|
37
|
+
this.security = options.security;
|
|
36
38
|
}
|
|
37
39
|
run(input, log) {
|
|
38
40
|
if (!input.command || typeof input.command !== 'string') {
|
|
@@ -40,10 +42,24 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
40
42
|
}
|
|
41
43
|
const logger = log || console;
|
|
42
44
|
return new Promise((resolve, reject) => {
|
|
43
|
-
|
|
45
|
+
let command = (0, helpers_1.unEscapeHTML)(input.command);
|
|
46
|
+
// Apply command validation if configured
|
|
47
|
+
if (this.security?.commandValidator) {
|
|
48
|
+
const validated = this.security.commandValidator(command);
|
|
49
|
+
if (validated === null) {
|
|
50
|
+
return reject(new Error(`Command rejected by security policy: ${command}`));
|
|
51
|
+
}
|
|
52
|
+
command = validated;
|
|
53
|
+
}
|
|
44
54
|
try {
|
|
45
55
|
logger.info(`🛠️ Running command: \`${command}\``);
|
|
46
|
-
const output = (0, child_process_1.execSync)(command, {
|
|
56
|
+
const output = (0, child_process_1.execSync)(command, {
|
|
57
|
+
cwd: this.cwd,
|
|
58
|
+
encoding: 'utf-8',
|
|
59
|
+
env: this.security?.env ?? undefined,
|
|
60
|
+
timeout: this.security?.timeoutMs ?? undefined,
|
|
61
|
+
maxBuffer: this.security?.maxBuffer ?? 10 * 1024 * 1024,
|
|
62
|
+
});
|
|
47
63
|
logger.info('```bash\n' + `> ${command}\n` + `${output}\n` + '```\n\n');
|
|
48
64
|
return resolve({
|
|
49
65
|
status: 'success',
|
|
@@ -73,4 +89,4 @@ class PSCommandLineTool extends PSAgentTool_1.PSAgentTool {
|
|
|
73
89
|
}
|
|
74
90
|
}
|
|
75
91
|
exports.PSCommandLineTool = PSCommandLineTool;
|
|
76
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUFNDb21tYW5kTGluZVRvb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xzL1BTQ29tbWFuZExpbmVUb29sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHVEQUF1RDtBQUN2RCxpREFBMkQ7QUFFM0QsK0JBQTJCO0FBRzNCLGdEQUE2QztBQUM3Qyw4Q0FBZ0Q7QUFhaEQsTUFBYSxpQkFBa0IsU0FBUSx5QkFBVztJQUN6QyxNQUFNLENBQVUsUUFBUSxHQUFHLGlCQUFpQixDQUFDO0lBQzVDLEdBQUcsQ0FBUztJQUNaLFFBQVEsQ0FBMEI7SUFDMUMsWUFBWSxPQUEyRDtRQUNyRSxLQUFLLENBQUM7WUFDSixJQUFJLEVBQUUsaUJBQWlCLENBQUMsUUFBUTtZQUNoQyxXQUFXLEVBQUUsMERBQTBEO1lBQ3ZFLElBQUksRUFBRSxLQUFLO1lBQ1gsZUFBZSxFQUFFLElBQUk7WUFDckIsSUFBSSxFQUFFLElBQUk7WUFDVixXQUFXLEVBQUU7Z0JBQ1gsR0FBRyxFQUFFLGtDQUFrQztnQkFDdkMsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsV0FBVyxFQUFFLE1BQUMsQ0FBQyxZQUFZLENBQ3pCLE1BQUM7cUJBQ0UsTUFBTSxDQUFDO29CQUNOLE9BQU8sRUFBRSxNQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDO3dCQUN2QixLQUFLLEVBQUUsU0FBUzt3QkFDaEIsV0FBVyxFQUFFLCtDQUErQztxQkFDN0QsQ0FBQztpQkFDSCxDQUFDO3FCQUNELElBQUksQ0FBQztvQkFDSixLQUFLLEVBQUUsOEJBQThCO29CQUNyQyxXQUFXLEVBQ1QsMkRBQTJEO2lCQUM5RCxDQUFDLEVBQ0osRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQ2hCO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FB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
|