opencode-rtk-plugin 0.1.0 → 0.1.2
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/index.js +68 -18
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -4,28 +4,74 @@
|
|
|
4
4
|
// model in a token-efficient form. All rewrite logic lives in rtk itself; this
|
|
5
5
|
// plugin is a thin delegating adapter for OpenCode's shell hook.
|
|
6
6
|
//
|
|
7
|
-
// Requires: rtk
|
|
7
|
+
// Requires: rtk (https://github.com/rtk-ai/rtk)
|
|
8
8
|
|
|
9
9
|
import { execFile } from "node:child_process";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
12
|
+
const MAX_TIMEOUT_MS = 600_000;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Run `rtk rewrite <command>` and resolve to the rewritten command, or null.
|
|
16
|
+
*
|
|
17
|
+
* rtk signals the result on STDOUT, not via exit status: since v0.34.0
|
|
18
|
+
* `rtk rewrite` exits 3 with the rewritten command on stdout (its
|
|
19
|
+
* permission-verdict protocol). So the exit code must be ignored and the
|
|
20
|
+
* decision made on stdout alone.
|
|
21
|
+
*
|
|
22
|
+
* Never rejects and never hangs: a spawn failure, timeout, or empty/unchanged
|
|
23
|
+
* output resolves to null so the original command runs.
|
|
24
|
+
*/
|
|
12
25
|
function rewriteCommand(binary, command, timeoutMs) {
|
|
13
26
|
return new Promise((resolve) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
let settled = false;
|
|
28
|
+
let timer;
|
|
29
|
+
const done = (value) => {
|
|
30
|
+
if (settled) return;
|
|
31
|
+
settled = true;
|
|
32
|
+
if (timer) clearTimeout(timer);
|
|
33
|
+
resolve(value);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let child;
|
|
37
|
+
try {
|
|
38
|
+
// timeout: 0 disables execFile's own SIGTERM-only timeout; we enforce a
|
|
39
|
+
// hard SIGKILL deadline below so a SIGTERM-ignoring rtk cannot hang.
|
|
40
|
+
child = execFile(
|
|
41
|
+
binary,
|
|
42
|
+
["rewrite", command],
|
|
43
|
+
{ timeout: 0, encoding: "utf8" },
|
|
44
|
+
(_err, stdout) => {
|
|
45
|
+
const out = String(stdout ?? "").trim();
|
|
46
|
+
done(out && out !== command ? out : null);
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
} catch {
|
|
50
|
+
return done(null);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
child.on("error", () => done(null));
|
|
54
|
+
|
|
55
|
+
timer = setTimeout(() => {
|
|
56
|
+
try {
|
|
57
|
+
child.kill("SIGKILL");
|
|
58
|
+
} catch {
|
|
59
|
+
/* already gone */
|
|
22
60
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
child.on("error", () => resolve(null));
|
|
61
|
+
done(null);
|
|
62
|
+
}, timeoutMs + 250);
|
|
26
63
|
});
|
|
27
64
|
}
|
|
28
65
|
|
|
66
|
+
function resolveBinary(value) {
|
|
67
|
+
return typeof value === "string" && value.trim() !== "" ? value : "rtk";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolveTimeout(value) {
|
|
71
|
+
if (Number.isInteger(value) && value >= 1 && value <= MAX_TIMEOUT_MS) return value;
|
|
72
|
+
return DEFAULT_TIMEOUT_MS;
|
|
73
|
+
}
|
|
74
|
+
|
|
29
75
|
export default {
|
|
30
76
|
id: "rtk",
|
|
31
77
|
|
|
@@ -33,13 +79,17 @@ export default {
|
|
|
33
79
|
const options = ctx.options ?? {};
|
|
34
80
|
if (options.enabled === false) return;
|
|
35
81
|
|
|
36
|
-
const binary =
|
|
37
|
-
const timeoutMs =
|
|
82
|
+
const binary = resolveBinary(options.binary);
|
|
83
|
+
const timeoutMs = resolveTimeout(options.timeoutMs);
|
|
38
84
|
|
|
39
85
|
await ctx.shell.hook("create.before", async (event) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
86
|
+
try {
|
|
87
|
+
if (!event || typeof event.command !== "string" || !event.command) return;
|
|
88
|
+
const rewritten = await rewriteCommand(binary, event.command, timeoutMs);
|
|
89
|
+
if (rewritten) event.command = rewritten;
|
|
90
|
+
} catch {
|
|
91
|
+
// Never fail the shell call: any error leaves the command unchanged.
|
|
92
|
+
}
|
|
43
93
|
});
|
|
44
94
|
},
|
|
45
95
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-rtk-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "OpenCode v2 plugin that rewrites shell commands through rtk to cut LLM token usage by 60-90%.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"lint": "markdownlint-cli2 \"**/*.md\"",
|
|
45
|
-
"test": "node --check index.js && node
|
|
45
|
+
"test": "node --check index.js && node --test test/*.test.mjs",
|
|
46
46
|
"check": "npm run lint && npm test"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|