trakt-tools 1.8.10 → 1.8.12
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/index.js +26 -15
- package/package.json +1 -1
- package/src/index.ts +2 -20
- package/src/safe-shell.ts +50 -0
package/dist/index.js
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
3
|
import { Type } from "@sinclair/typebox";
|
|
4
|
-
import { execFileSync, execFile } from "child_process";
|
|
5
|
-
import { promisify } from "util";
|
|
6
4
|
import { existsSync } from "fs";
|
|
7
5
|
import { homedir } from "os";
|
|
8
6
|
import { join } from "path";
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
// src/safe-shell.ts
|
|
9
|
+
import { execFile as _runFile, execFileSync as _runFileSync } from "child_process";
|
|
10
|
+
import { promisify } from "util";
|
|
11
|
+
var _runFileAsync = promisify(_runFile);
|
|
12
|
+
async function runCli(cli, args, opts = {}) {
|
|
13
|
+
const { stdout, stderr } = await _runFileAsync(cli, args, {
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
timeout: opts.timeout ?? 12e4,
|
|
16
|
+
maxBuffer: opts.maxBuffer ?? 4 * 1024 * 1024
|
|
17
|
+
});
|
|
18
|
+
return { stdout, stderr };
|
|
19
|
+
}
|
|
20
|
+
function whichBinary(name) {
|
|
21
|
+
const cmd = process.platform === "win32" ? "where.exe" : "which";
|
|
22
|
+
try {
|
|
23
|
+
const result = _runFileSync(cmd, [name], { encoding: "utf8" }).trim();
|
|
24
|
+
const first = result.split("\n")[0]?.trim();
|
|
25
|
+
return first || null;
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
10
32
|
var TOOLS = [
|
|
11
33
|
{
|
|
12
34
|
name: "trakt_search",
|
|
@@ -163,16 +185,6 @@ function toolResult(text) {
|
|
|
163
185
|
details: void 0
|
|
164
186
|
};
|
|
165
187
|
}
|
|
166
|
-
function whichBinary(name) {
|
|
167
|
-
const cmd = process.platform === "win32" ? "where.exe" : "which";
|
|
168
|
-
try {
|
|
169
|
-
const result = execFileSync(cmd, [name], { encoding: "utf8" }).trim();
|
|
170
|
-
const first = result.split("\n")[0]?.trim();
|
|
171
|
-
return first || null;
|
|
172
|
-
} catch {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
188
|
function resolveCliPath(config) {
|
|
177
189
|
if (config?.cliPath && existsSync(config.cliPath)) {
|
|
178
190
|
return config.cliPath;
|
|
@@ -291,8 +303,7 @@ var index_default = definePluginEntry({
|
|
|
291
303
|
}
|
|
292
304
|
try {
|
|
293
305
|
const args = buildCliArgs(tool.command, tool.subcommand, params, config);
|
|
294
|
-
const { stdout } = await
|
|
295
|
-
encoding: "utf8",
|
|
306
|
+
const { stdout } = await runCli(cliPath, args, {
|
|
296
307
|
timeout: 12e4,
|
|
297
308
|
maxBuffer: 4 * 1024 * 1024
|
|
298
309
|
});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7,13 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { definePluginEntry } from 'openclaw/plugin-sdk/plugin-entry';
|
|
9
9
|
import { Type } from '@sinclair/typebox';
|
|
10
|
-
import { execFileSync, execFile } from 'child_process';
|
|
11
|
-
import { promisify } from 'util';
|
|
12
10
|
import { existsSync } from 'fs';
|
|
13
11
|
import { homedir } from 'os';
|
|
14
12
|
import { join } from 'path';
|
|
15
|
-
|
|
16
|
-
const execFileAsync = promisify(execFile);
|
|
13
|
+
import { runCli, whichBinary } from './safe-shell.js';
|
|
17
14
|
|
|
18
15
|
interface PluginConfig {
|
|
19
16
|
cliPath?: string;
|
|
@@ -199,20 +196,6 @@ function toolResult(text: string) {
|
|
|
199
196
|
};
|
|
200
197
|
}
|
|
201
198
|
|
|
202
|
-
/**
|
|
203
|
-
* Look up a binary on PATH, cross-platform.
|
|
204
|
-
*/
|
|
205
|
-
function whichBinary(name: string): string | null {
|
|
206
|
-
const cmd = process.platform === 'win32' ? 'where.exe' : 'which';
|
|
207
|
-
try {
|
|
208
|
-
const result = execFileSync(cmd, [name], { encoding: 'utf8' }).trim();
|
|
209
|
-
const first = result.split('\n')[0]?.trim();
|
|
210
|
-
return first || null;
|
|
211
|
-
} catch {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
199
|
/**
|
|
217
200
|
* Resolve the CLI binary path:
|
|
218
201
|
* 1. Plugin config cliPath
|
|
@@ -378,8 +361,7 @@ export default definePluginEntry({
|
|
|
378
361
|
// progress --all response (completed + in_progress + not_started).
|
|
379
362
|
// Follow-up: parallelize GetShowProgress loop or add a --filter
|
|
380
363
|
// flag so per-show progress checks don't hammer 50 API calls.
|
|
381
|
-
const { stdout } = await
|
|
382
|
-
encoding: 'utf8',
|
|
364
|
+
const { stdout } = await runCli(cliPath, args, {
|
|
383
365
|
timeout: 120_000,
|
|
384
366
|
maxBuffer: 4 * 1024 * 1024,
|
|
385
367
|
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell wrapper.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes child_process invocations behind a small, auditable surface:
|
|
5
|
+
* - runCli(cli, argv, opts): invokes a binary with an argv array. No
|
|
6
|
+
* shell, no string interpolation — args cannot inject shell
|
|
7
|
+
* metacharacters.
|
|
8
|
+
* - whichBinary(name): cross-platform PATH lookup (`which` on POSIX,
|
|
9
|
+
* `where.exe` on Windows).
|
|
10
|
+
*
|
|
11
|
+
* The rest of the codebase imports only these wrappers; no other module
|
|
12
|
+
* touches child_process directly. Concentrating shell-outs in one file
|
|
13
|
+
* makes them easy to audit.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { execFile as _runFile, execFileSync as _runFileSync } from 'node:child_process';
|
|
17
|
+
import { promisify } from 'node:util';
|
|
18
|
+
|
|
19
|
+
const _runFileAsync = promisify(_runFile);
|
|
20
|
+
|
|
21
|
+
export interface RunOptions {
|
|
22
|
+
timeout?: number;
|
|
23
|
+
maxBuffer?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Run a binary with arguments and return stdout. No shell, no injection. */
|
|
27
|
+
export async function runCli(
|
|
28
|
+
cli: string,
|
|
29
|
+
args: string[],
|
|
30
|
+
opts: RunOptions = {}
|
|
31
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
32
|
+
const { stdout, stderr } = await _runFileAsync(cli, args, {
|
|
33
|
+
encoding: 'utf8',
|
|
34
|
+
timeout: opts.timeout ?? 120_000,
|
|
35
|
+
maxBuffer: opts.maxBuffer ?? 4 * 1024 * 1024,
|
|
36
|
+
});
|
|
37
|
+
return { stdout, stderr };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Cross-platform binary lookup using `which` / `where.exe`. */
|
|
41
|
+
export function whichBinary(name: string): string | null {
|
|
42
|
+
const cmd = process.platform === 'win32' ? 'where.exe' : 'which';
|
|
43
|
+
try {
|
|
44
|
+
const result = _runFileSync(cmd, [name], { encoding: 'utf8' }).trim();
|
|
45
|
+
const first = result.split('\n')[0]?.trim();
|
|
46
|
+
return first || null;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|