pi-rtk-optimizer 0.5.4 → 0.6.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.
@@ -1,160 +1,118 @@
1
- import assert from "node:assert/strict";
2
-
3
- import { computeRewriteDecision } from "./command-rewriter.ts";
4
- import { cloneDefaultConfig, runTest } from "./test-helpers.ts";
5
-
6
- function expectedProxyExecutable(base: string): string {
7
- const windowsExecutables = new Set(["npm", "npx", "pnpm", "yarn"]);
8
- return process.platform === "win32" && windowsExecutables.has(base) ? `${base}.cmd` : base;
9
- }
10
-
11
- runTest("pnpm dlx rewrites through RTK proxy instead of generic pnpm wrapper", () => {
12
- const config = cloneDefaultConfig();
13
- const decision = computeRewriteDecision("pnpm dlx create-vite@latest demo --template react-ts", config);
14
-
15
- assert.equal(decision.changed, true);
16
- assert.equal(decision.rule?.id, "pnpm-dlx-proxy");
17
- assert.equal(
18
- decision.rewrittenCommand,
19
- `rtk proxy ${expectedProxyExecutable("pnpm")} dlx create-vite@latest demo --template react-ts`,
20
- );
21
- });
22
-
23
- runTest("docker run with shell command bypasses rewrite when interactive flags are missing", () => {
24
- const config = cloneDefaultConfig();
25
- const decision = computeRewriteDecision("docker run ubuntu bash", config);
26
-
27
- assert.equal(decision.changed, false);
28
- assert.equal(decision.rewrittenCommand, "docker run ubuntu bash");
29
- assert.equal(decision.reason, "no_match");
30
- });
31
-
32
- runTest("docker run with -it keeps container rewrite enabled", () => {
33
- const config = cloneDefaultConfig();
34
- const decision = computeRewriteDecision("docker run -it ubuntu bash", config);
35
-
36
- assert.equal(decision.changed, true);
37
- assert.equal(decision.rule?.id, "docker");
38
- assert.equal(decision.rewrittenCommand, "rtk docker run -it ubuntu bash");
39
- });
40
-
41
- runTest("docker compose exec without -it bypasses interactive shell rewrite", () => {
42
- const config = cloneDefaultConfig();
43
- const decision = computeRewriteDecision("docker compose exec web bash", config);
44
-
45
- assert.equal(decision.changed, false);
46
- assert.equal(decision.rewrittenCommand, "docker compose exec web bash");
47
- });
48
-
49
- runTest("container rewrites stay enabled for scripted shells and non-shell commands", () => {
50
- const config = cloneDefaultConfig();
51
-
52
- const scriptedShell = computeRewriteDecision('docker run ubuntu bash -lc "echo hi"', config);
53
- assert.equal(scriptedShell.changed, true);
54
- assert.equal(scriptedShell.rule?.id, "docker");
55
- assert.equal(scriptedShell.rewrittenCommand, 'rtk docker run ubuntu bash -lc "echo hi"');
56
-
57
- const nonShell = computeRewriteDecision("docker run ubuntu python app.py", config);
58
- assert.equal(nonShell.changed, true);
59
- assert.equal(nonShell.rule?.id, "docker");
60
- assert.equal(nonShell.rewrittenCommand, "rtk docker run ubuntu python app.py");
61
- });
62
-
63
- runTest("kubectl exec requires interactive flags before rewriting shell sessions", () => {
64
- const config = cloneDefaultConfig();
65
- const missingFlagsDecision = computeRewriteDecision("kubectl exec pod-123 -- bash", config);
66
- assert.equal(missingFlagsDecision.changed, false);
67
- assert.equal(missingFlagsDecision.rewrittenCommand, "kubectl exec pod-123 -- bash");
68
-
69
- const interactiveDecision = computeRewriteDecision("kubectl exec -it pod-123 -- bash", config);
70
- assert.equal(interactiveDecision.changed, true);
71
- assert.equal(interactiveDecision.rule?.id, "kubectl");
72
- assert.equal(interactiveDecision.rewrittenCommand, "rtk kubectl exec -it pod-123 -- bash");
73
- });
74
-
75
- runTest("sed scripts keep internal separators intact while later pipe segments still rewrite", () => {
76
- const config = cloneDefaultConfig();
77
- const decision = computeRewriteDecision("sed -e s/a/b/;d file.txt | git status", config);
78
-
79
- assert.equal(decision.changed, true);
80
- assert.equal(decision.rewrittenCommand, "sed -e s/a/b/;d file.txt | rtk git status");
81
- assert.equal(decision.rule?.id, "git-any");
82
- });
83
-
84
- runTest("background operators rewrite both command segments without misreading redirect ampersands", () => {
85
- const config = cloneDefaultConfig();
86
- const backgroundDecision = computeRewriteDecision("git status & cargo test", config);
87
- assert.equal(backgroundDecision.changed, true);
88
- assert.equal(backgroundDecision.rewrittenCommand, "rtk git status & rtk cargo test");
89
-
90
- const redirectDecision = computeRewriteDecision("cargo test 2>&1 | head -5", config);
91
- assert.equal(redirectDecision.changed, true);
92
- assert.equal(redirectDecision.rewrittenCommand, "rtk cargo test 2>&1 | head -5");
93
- assert.equal(redirectDecision.rule?.id, "cargo-any");
94
- });
95
-
96
- runTest("gh structured output commands bypass RTK rewrites", () => {
97
- const config = cloneDefaultConfig();
98
- const structuredCommands = [
99
- "gh pr list --json number,title",
100
- "gh issue list --jq '.[].title'",
101
- "gh pr view 123 --template '{{.title}}'",
102
- ];
103
-
104
- for (const command of structuredCommands) {
105
- const decision = computeRewriteDecision(command, config);
106
- assert.equal(decision.changed, false);
107
- assert.equal(decision.rewrittenCommand, command);
108
- assert.equal(decision.reason, "no_match");
109
- }
110
- });
111
-
112
- runTest("compound find and search shell flows bypass rewrites when RTK parity is unsafe", () => {
113
- const config = cloneDefaultConfig();
114
- const auditedCommands = [
115
- "find src -type f | xargs grep todo",
116
- "find . -name '*.ts' -exec grep -n FIXME {} +",
117
- "grep -R TODO src | head -n 5",
118
- "rg TODO src && wc -l",
119
- ];
120
-
121
- for (const command of auditedCommands) {
122
- const decision = computeRewriteDecision(command, config);
123
- assert.equal(decision.changed, false, command);
124
- assert.equal(decision.rewrittenCommand, command, command);
125
- assert.equal(decision.reason, "no_match", command);
126
- }
127
- });
128
-
129
- runTest("formatting-sensitive ls flows bypass rewrites", () => {
130
- const config = cloneDefaultConfig();
131
- const auditedCommands = ["ls -la", "ls -l src | grep command-rewriter"];
132
-
133
- for (const command of auditedCommands) {
134
- const decision = computeRewriteDecision(command, config);
135
- assert.equal(decision.changed, false, command);
136
- assert.equal(decision.rewrittenCommand, command, command);
137
- assert.equal(decision.reason, "no_match", command);
138
- }
139
- });
140
-
141
- runTest("native bash shell proxy flows bypass rewrites when RTK parity is unsafe", () => {
142
- const config = cloneDefaultConfig();
143
- const command = 'bash -lc "find src -type f | xargs grep todo"';
144
- const decision = computeRewriteDecision(command, config);
145
-
146
- assert.equal(decision.changed, false);
147
- assert.equal(decision.rewrittenCommand, command);
148
- assert.equal(decision.reason, "no_match");
149
- });
150
-
151
- runTest("python proxy rewrites preserve the original executable token", () => {
152
- const config = cloneDefaultConfig();
153
- const decision = computeRewriteDecision('python3.11 -c "print(1)"', config);
154
-
155
- assert.equal(decision.changed, true);
156
- assert.equal(decision.rule?.id, "python-proxy");
157
- assert.equal(decision.rewrittenCommand, `rtk proxy ${expectedProxyExecutable("python3.11")} -c "print(1)"`);
158
- });
159
-
160
- console.log("All command-rewriter tests passed.");
1
+ import assert from "node:assert/strict";
2
+
3
+ import { computeRewriteDecision } from "./command-rewriter.ts";
4
+ import { cloneDefaultConfig, runTest } from "./test-helpers.ts";
5
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
6
+
7
+ function createMockPi(execResult: { code: number; stdout?: string; stderr?: string }): ExtensionAPI {
8
+ return { exec: async () => execResult } as unknown as ExtensionAPI;
9
+ }
10
+
11
+ runTest("empty command unchanged", async () => {
12
+ const config = cloneDefaultConfig();
13
+ const decision = await computeRewriteDecision("", config, createMockPi({ code: 1 }));
14
+ assert.equal(decision.changed, false);
15
+ assert.equal(decision.reason, "empty");
16
+ });
17
+
18
+ runTest("already rtk unchanged", async () => {
19
+ const config = cloneDefaultConfig();
20
+ const decision = await computeRewriteDecision("rtk status", config, createMockPi({ code: 1 }));
21
+ assert.equal(decision.changed, false);
22
+ assert.equal(decision.reason, "already_rtk");
23
+ });
24
+
25
+ runTest("rtk unsupported heredoc result leaves command unchanged", async () => {
26
+ const config = cloneDefaultConfig();
27
+ const decision = await computeRewriteDecision("cat <<EOF", config, createMockPi({ code: 1 }));
28
+ assert.equal(decision.changed, false);
29
+ assert.equal(decision.reason, "no_match");
30
+ });
31
+
32
+ runTest("quoted heredoc marker is delegated to RTK rewrite", async () => {
33
+ const config = cloneDefaultConfig();
34
+ const command = 'echo "<<not heredoc" && git status';
35
+ const decision = await computeRewriteDecision(
36
+ command,
37
+ config,
38
+ createMockPi({ code: 3, stdout: 'echo "<<not heredoc" && rtk git status' }),
39
+ );
40
+ assert.equal(decision.changed, true);
41
+ assert.equal(decision.rewrittenCommand, 'echo "<<not heredoc" && rtk git status');
42
+ assert.equal(decision.reason, "ok");
43
+ });
44
+
45
+ runTest("legacy category toggles do not pre-filter RTK rewrite source of truth", async () => {
46
+ const config = { ...cloneDefaultConfig(), rewriteGitGithub: false };
47
+ const decision = await computeRewriteDecision("git status", config, createMockPi({ code: 3, stdout: "rtk git status" }));
48
+ assert.equal(decision.changed, true);
49
+ assert.equal(decision.rewrittenCommand, "rtk git status");
50
+ assert.equal(decision.reason, "ok");
51
+ });
52
+
53
+ runTest("rtk exit 0 rewrites", async () => {
54
+ const config = cloneDefaultConfig();
55
+ const decision = await computeRewriteDecision("git status", config, createMockPi({ code: 0, stdout: "rtk git status" }));
56
+ assert.equal(decision.changed, true);
57
+ assert.equal(decision.rewrittenCommand, "rtk git status");
58
+ assert.equal(decision.reason, "ok");
59
+ });
60
+
61
+ runTest("rtk exit 3 rewrites", async () => {
62
+ const config = cloneDefaultConfig();
63
+ const decision = await computeRewriteDecision("git status", config, createMockPi({ code: 3, stdout: "rtk git status" }));
64
+ assert.equal(decision.changed, true);
65
+ assert.equal(decision.rewrittenCommand, "rtk git status");
66
+ assert.equal(decision.reason, "ok");
67
+ });
68
+
69
+ runTest("exit 1 leaves unchanged", async () => {
70
+ const config = cloneDefaultConfig();
71
+ const decision = await computeRewriteDecision("git status", config, createMockPi({ code: 1 }));
72
+ assert.equal(decision.changed, false);
73
+ assert.equal(decision.reason, "no_match");
74
+ });
75
+
76
+ runTest("exit 2 leaves unchanged", async () => {
77
+ const config = cloneDefaultConfig();
78
+ const decision = await computeRewriteDecision("git status", config, createMockPi({ code: 2, stderr: "denied" }));
79
+ assert.equal(decision.changed, false);
80
+ assert.equal(decision.reason, "no_match");
81
+ });
82
+
83
+ runTest("unknown category passes through to RTK", async () => {
84
+ const config = cloneDefaultConfig();
85
+ const pi = createMockPi({ code: 0, stdout: "rtk custom" });
86
+ const decision = await computeRewriteDecision("custom-cmd", config, pi);
87
+ assert.equal(decision.changed, true);
88
+ assert.equal(decision.rewrittenCommand, "rtk custom");
89
+ assert.equal(decision.reason, "ok");
90
+ });
91
+
92
+ runTest("exec error/timeout leaves unchanged", async () => {
93
+ const config = cloneDefaultConfig();
94
+ const pi = {
95
+ exec: async () => {
96
+ throw new Error("timeout");
97
+ },
98
+ } as unknown as ExtensionAPI;
99
+ const decision = await computeRewriteDecision("git status", config, pi);
100
+ assert.equal(decision.changed, false);
101
+ assert.equal(decision.reason, "no_match");
102
+ });
103
+
104
+ runTest("compound commands forwarded to RTK", async () => {
105
+ const config = cloneDefaultConfig();
106
+ let capturedArgs: string[] = [];
107
+ const pi = {
108
+ exec: async (_cmd: string, args: string[]) => {
109
+ capturedArgs = args;
110
+ return { code: 0, stdout: "rtk result" };
111
+ },
112
+ } as unknown as ExtensionAPI;
113
+ const decision = await computeRewriteDecision("git status && cargo test", config, pi);
114
+ assert.equal(decision.changed, true);
115
+ assert.deepEqual(capturedArgs, ["rewrite", "git status && cargo test"]);
116
+ });
117
+
118
+ console.log("All command-rewriter tests passed.");