pi-rtk-optimizer 0.3.3 → 0.5.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +102 -67
  2. package/README.md +292 -290
  3. package/config/config.example.json +36 -35
  4. package/package.json +4 -4
  5. package/src/additional-coverage-test.ts +278 -0
  6. package/src/boolean-format.ts +3 -0
  7. package/src/command-rewriter-test.ts +160 -120
  8. package/src/command-rewriter.ts +594 -585
  9. package/src/config-modal-test.ts +168 -0
  10. package/src/config-modal.ts +613 -600
  11. package/src/config-store.ts +224 -217
  12. package/src/index-test.ts +54 -0
  13. package/src/index.ts +410 -289
  14. package/src/output-compactor-test.ts +500 -158
  15. package/src/output-compactor.ts +432 -349
  16. package/src/record-utils.ts +6 -0
  17. package/src/rewrite-bypass.ts +332 -173
  18. package/src/rewrite-pipeline-safety.ts +154 -0
  19. package/src/rewrite-rules.ts +255 -255
  20. package/src/rtk-command-environment.ts +64 -0
  21. package/src/runtime-guard-test.ts +42 -50
  22. package/src/runtime-guard.ts +14 -14
  23. package/src/techniques/build.ts +155 -155
  24. package/src/techniques/emoji.ts +91 -0
  25. package/src/techniques/git.ts +231 -229
  26. package/src/techniques/index.ts +10 -16
  27. package/src/techniques/linter.ts +151 -161
  28. package/src/techniques/path-utils.ts +67 -0
  29. package/src/techniques/rtk.ts +136 -0
  30. package/src/techniques/search.ts +67 -76
  31. package/src/techniques/source.ts +253 -253
  32. package/src/techniques/test-output.ts +172 -172
  33. package/src/test-helpers.ts +10 -0
  34. package/src/tool-execution-sanitizer.ts +69 -0
  35. package/src/types-shims.d.ts +192 -183
  36. package/src/types.ts +103 -114
  37. package/src/zellij-modal.ts +1001 -1001
  38. package/src/compat-commands.ts +0 -207
@@ -0,0 +1,168 @@
1
+ import assert from "node:assert/strict";
2
+ import { mock } from "bun:test";
3
+
4
+ import { cloneDefaultConfig, runTest } from "./test-helpers.ts";
5
+
6
+ mock.module("@mariozechner/pi-coding-agent", () => ({
7
+ getSettingsListTheme: () => ({}),
8
+ }));
9
+
10
+ mock.module("@mariozechner/pi-tui", () => ({
11
+ Box: class {},
12
+ Container: class {
13
+ addChild(): void {}
14
+ render(): string[] {
15
+ return [];
16
+ }
17
+ invalidate(): void {}
18
+ },
19
+ SettingsList: class {
20
+ handleInput(): void {}
21
+ updateValue(): void {}
22
+ },
23
+ Spacer: class {},
24
+ Text: class {},
25
+ truncateToWidth: (text: string) => text,
26
+ visibleWidth: (text: string) => text.length,
27
+ }));
28
+
29
+ const { registerRtkIntegrationCommand } = await import("./config-modal.ts");
30
+ const { getRtkArgumentCompletions } = await import("./command-completions.ts");
31
+
32
+ type Notification = { message: string; level: "info" | "warning" | "error" };
33
+
34
+ interface CommandContextStub {
35
+ hasUI: boolean;
36
+ ui: {
37
+ notify(message: string, level: "info" | "warning" | "error"): void;
38
+ custom<T>(): Promise<T>;
39
+ };
40
+ }
41
+
42
+ function createNotifyContext(hasUI: boolean): { ctx: CommandContextStub; notifications: Notification[] } {
43
+ const notifications: Notification[] = [];
44
+ return {
45
+ ctx: {
46
+ hasUI,
47
+ ui: {
48
+ notify(message: string, level: "info" | "warning" | "error") {
49
+ notifications.push({ message, level });
50
+ },
51
+ async custom<T>(): Promise<T> {
52
+ throw new Error("custom UI should not be invoked in config-modal tests");
53
+ },
54
+ },
55
+ },
56
+ notifications,
57
+ };
58
+ }
59
+
60
+ function lastNotification(notifications: Notification[]): Notification {
61
+ return notifications[notifications.length - 1] as Notification;
62
+ }
63
+
64
+ runTest("command completions return top-level and filtered RTK subcommands", () => {
65
+ const topLevel = getRtkArgumentCompletions("");
66
+ assert.ok(Array.isArray(topLevel));
67
+ assert.ok(topLevel.some((item) => item.value === "show"));
68
+ assert.ok(topLevel.some((item) => item.value === "clear-stats"));
69
+
70
+ const filtered = getRtkArgumentCompletions("st");
71
+ assert.deepEqual(
72
+ filtered?.map((item) => item.value),
73
+ ["stats"],
74
+ );
75
+ assert.equal(getRtkArgumentCompletions("show extra"), null);
76
+ assert.equal(getRtkArgumentCompletions("zzz"), null);
77
+ });
78
+
79
+ async function runAsyncTest(name: string, testFn: () => Promise<void>): Promise<void> {
80
+ await testFn();
81
+ console.log(`[PASS] ${name}`);
82
+ }
83
+
84
+ await runAsyncTest("config modal command handlers route RTK subcommands to controller actions", async () => {
85
+ const config = cloneDefaultConfig();
86
+ const controllerState = {
87
+ config,
88
+ cleared: 0,
89
+ refreshed: 0,
90
+ lastSavedMode: "",
91
+ };
92
+
93
+ const controller = {
94
+ getConfig: () => controllerState.config,
95
+ setConfig: (next: typeof config, _ctx: unknown) => {
96
+ controllerState.config = next;
97
+ controllerState.lastSavedMode = next.mode;
98
+ },
99
+ getConfigPath: () => "C:/tmp/pi-rtk-optimizer/config.json",
100
+ getRuntimeStatus: () => ({ rtkAvailable: false, lastError: "not found" }),
101
+ refreshRuntimeStatus: async () => {
102
+ controllerState.refreshed += 1;
103
+ return { rtkAvailable: false, lastError: "not found" };
104
+ },
105
+ getMetricsSummary: () => "metrics summary",
106
+ clearMetrics: () => {
107
+ controllerState.cleared += 1;
108
+ },
109
+ };
110
+
111
+ let registeredName = "";
112
+ let definition: {
113
+ description: string;
114
+ getArgumentCompletions?: (argumentPrefix: string) => Array<{ value: string; label: string; description?: string }> | null;
115
+ handler: (args: string, ctx: CommandContextStub) => Promise<void>;
116
+ } | null = null;
117
+
118
+ registerRtkIntegrationCommand(
119
+ {
120
+ registerCommand(name: string, nextDefinition: typeof definition) {
121
+ registeredName = name;
122
+ definition = nextDefinition;
123
+ },
124
+ } as never,
125
+ controller as never,
126
+ );
127
+
128
+ assert.equal(registeredName, "rtk");
129
+ assert.ok(definition !== null);
130
+ assert.ok((definition?.description ?? "").includes("Configure RTK rewrite"));
131
+ assert.ok(typeof definition?.getArgumentCompletions === "function");
132
+
133
+ const infoCtx = createNotifyContext(true);
134
+ await definition?.handler("help", infoCtx.ctx);
135
+ assert.ok(lastNotification(infoCtx.notifications).message.includes("Usage: /rtk"));
136
+
137
+ await definition?.handler("show", infoCtx.ctx);
138
+ assert.ok(lastNotification(infoCtx.notifications).message.includes("mode=rewrite"));
139
+
140
+ await definition?.handler("path", infoCtx.ctx);
141
+ assert.equal(lastNotification(infoCtx.notifications).message, "rtk config: C:/tmp/pi-rtk-optimizer/config.json");
142
+
143
+ await definition?.handler("verify", infoCtx.ctx);
144
+ assert.equal(controllerState.refreshed, 1);
145
+ assert.equal(lastNotification(infoCtx.notifications).level, "warning");
146
+ assert.ok(lastNotification(infoCtx.notifications).message.includes("not available: not found"));
147
+
148
+ await definition?.handler("stats", infoCtx.ctx);
149
+ assert.equal(lastNotification(infoCtx.notifications).message, "metrics summary");
150
+
151
+ await definition?.handler("clear-stats", infoCtx.ctx);
152
+ assert.equal(controllerState.cleared, 1);
153
+ assert.equal(lastNotification(infoCtx.notifications).message, "RTK metrics cleared.");
154
+
155
+ await definition?.handler("reset", infoCtx.ctx);
156
+ assert.equal(controllerState.lastSavedMode, "rewrite");
157
+ assert.equal(lastNotification(infoCtx.notifications).message, "RTK integration settings reset to defaults.");
158
+
159
+ await definition?.handler("unknown", infoCtx.ctx);
160
+ assert.equal(lastNotification(infoCtx.notifications).level, "warning");
161
+ assert.ok(lastNotification(infoCtx.notifications).message.includes("Usage: /rtk"));
162
+
163
+ const headlessCtx = createNotifyContext(false);
164
+ await definition?.handler("", headlessCtx.ctx);
165
+ assert.equal(lastNotification(headlessCtx.notifications).message, "/rtk requires interactive TUI mode.");
166
+ });
167
+
168
+ console.log("All config-modal tests passed.");