pi-rtk-optimizer 0.7.1 → 0.8.1
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/CHANGELOG.md +14 -0
- package/README.md +6 -3
- package/package.json +67 -67
- package/src/additional-coverage-test.ts +1 -1
- package/src/command-completions.ts +49 -49
- package/src/command-rewriter-test.ts +1 -1
- package/src/command-rewriter.ts +46 -46
- package/src/config-modal-test.ts +2 -2
- package/src/config-modal.ts +78 -9
- package/src/constants.ts +1 -1
- package/src/index-test.ts +2 -2
- package/src/index.ts +1 -1
- package/src/output-compactor-test.ts +208 -3
- package/src/output-compactor.ts +294 -1
- package/src/rtk-executable-resolver.ts +97 -97
- package/src/rtk-rewrite-provider.ts +126 -126
- package/src/types-shims.d.ts +4 -2
- package/src/zellij-modal.ts +137 -30
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.1] - 2026-05-26
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Widened `@earendil-works/pi-coding-agent` and `@earendil-works/pi-tui` peer dependency ranges to `^0.74.0 || ^0.75.0`.
|
|
14
|
+
|
|
15
|
+
## [0.8.0] - 2026-05-22
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Added tabbed `/rtk` settings modal groups with left/right tab navigation and context-aware help for search and value changes.
|
|
19
|
+
- Added anchor-safe `read` compaction that detects hashline/anchored read output and preserves complete edit anchors during source filtering, smart truncation, and hard truncation.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Updated package metadata and lockfile version to `0.8.0` and migrated Pi peer dependency metadata to the `@earendil-works` scope.
|
|
23
|
+
|
|
10
24
|
## [0.7.1] - 2026-05-04
|
|
11
25
|
|
|
12
26
|
### Changed
|
package/README.md
CHANGED
|
@@ -33,11 +33,12 @@ Multi-stage pipeline to reduce token consumption:
|
|
|
33
33
|
| Search Grouping | Groups `grep`/`rg` results by file |
|
|
34
34
|
| Source Code Filtering | `none`, `minimal`, or `aggressive` comment/whitespace removal with userscript metadata preservation |
|
|
35
35
|
| Smart Truncation | Preserves file boundaries and important lines while keeping 80-line reads exact |
|
|
36
|
+
| Anchor-Safe Read Compaction | Detects hashline/anchored `read` output and preserves complete edit anchors when filtering or truncating anchored lines |
|
|
36
37
|
| Hard Truncation | Final character limit enforcement |
|
|
37
38
|
|
|
38
39
|
### Interactive Settings
|
|
39
40
|
|
|
40
|
-
- TUI settings modal via `/rtk` command
|
|
41
|
+
- Tabbed TUI settings modal via `/rtk` command
|
|
41
42
|
- Real-time configuration changes without restart
|
|
42
43
|
- Command completions for all subcommands
|
|
43
44
|
|
|
@@ -82,7 +83,7 @@ Open the interactive settings modal:
|
|
|
82
83
|
/rtk
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
Use
|
|
86
|
+
Use ←/→ to switch tabs, ↑/↓ to navigate settings in the active tab, type to search, Enter/Space to cycle values, and Escape to close.
|
|
86
87
|
|
|
87
88
|
### Subcommands
|
|
88
89
|
|
|
@@ -146,6 +147,8 @@ Bash command support is intentionally resolved by the installed `rtk` binary thr
|
|
|
146
147
|
|
|
147
148
|
Skill-read preservation covers the global Pi skills directory (`~/.pi/agent/skills` by default, or `$PI_CODING_AGENT_DIR/skills` when set), `~/.agents/skills`, project `.pi/skills`, and ancestor `.agents/skills` directories.
|
|
148
149
|
|
|
150
|
+
When `read` output uses Pi hashline/anchor prefixes, the compactor treats each anchored line as an indivisible edit anchor. Source filtering and truncation may omit anchored lines, but retained lines keep their complete anchor prefixes; hard truncation inserts an anchor-safe marker instead of cutting through an anchor.
|
|
151
|
+
|
|
149
152
|
#### Truncation Settings
|
|
150
153
|
|
|
151
154
|
| Option | Type | Default | Range | Description |
|
|
@@ -252,7 +255,7 @@ Automatic fixes applied on Windows:
|
|
|
252
255
|
|
|
253
256
|
### Dependencies
|
|
254
257
|
|
|
255
|
-
- **Peer dependencies:** `@
|
|
258
|
+
- **Peer dependencies:** `@earendil-works/pi-coding-agent`, `@earendil-works/pi-tui`
|
|
256
259
|
- **Runtime:** Node.js ≥20, optional `rtk` binary for command rewriting
|
|
257
260
|
- **Development verification:** Node.js ≥20, npm, and Bun for the test scripts
|
|
258
261
|
|
package/package.json
CHANGED
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-rtk-optimizer",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pi extension that optimizes RTK command rewriting and tool output compaction for the coding agent.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./index.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": "./index.ts"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.ts",
|
|
12
|
-
"src",
|
|
13
|
-
"config/config.example.json",
|
|
14
|
-
"README.md",
|
|
15
|
-
"CHANGELOG.md",
|
|
16
|
-
"LICENSE"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsc -p tsconfig.json --noCheck",
|
|
20
|
-
"typecheck": "tsc -p tsconfig.json",
|
|
21
|
-
"test": "bun ./src/output-compactor-test.ts && bun ./src/command-rewriter-test.ts && bun ./src/runtime-guard-test.ts && bun ./src/additional-coverage-test.ts && bun ./src/config-modal-test.ts && bun ./src/index-test.ts",
|
|
22
|
-
"check": "npm run typecheck && npm run test && npm run build:check",
|
|
23
|
-
"build:check": "esbuild ./index.ts --bundle --platform=node --format=esm --outfile=./.pi-rtk-optimizer-check.mjs --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-tui && node -e \"import { unlinkSync } from 'node:fs'; unlinkSync('./.pi-rtk-optimizer-check.mjs');\""
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"pi-package",
|
|
27
|
-
"pi",
|
|
28
|
-
"pi-extension",
|
|
29
|
-
"pi-coding-agent",
|
|
30
|
-
"coding-agent",
|
|
31
|
-
"rtk",
|
|
32
|
-
"token-optimization",
|
|
33
|
-
"tool-compaction",
|
|
34
|
-
"output-compaction",
|
|
35
|
-
"command-rewrite",
|
|
36
|
-
"optimization"
|
|
37
|
-
],
|
|
38
|
-
"author": "MasuRii",
|
|
39
|
-
"license": "MIT",
|
|
40
|
-
"repository": {
|
|
41
|
-
"type": "git",
|
|
42
|
-
"url": "git+https://github.com/MasuRii/pi-rtk-optimizer.git"
|
|
43
|
-
},
|
|
44
|
-
"bugs": {
|
|
45
|
-
"url": "https://github.com/MasuRii/pi-rtk-optimizer/issues"
|
|
46
|
-
},
|
|
47
|
-
"homepage": "https://github.com/MasuRii/pi-rtk-optimizer#readme",
|
|
48
|
-
"engines": {
|
|
49
|
-
"node": ">=20"
|
|
50
|
-
},
|
|
51
|
-
"publishConfig": {
|
|
52
|
-
"access": "public"
|
|
53
|
-
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"esbuild": "0.28.0",
|
|
56
|
-
"typescript": "
|
|
57
|
-
},
|
|
58
|
-
"pi": {
|
|
59
|
-
"extensions": [
|
|
60
|
-
"./index.ts"
|
|
61
|
-
]
|
|
62
|
-
},
|
|
63
|
-
"peerDependencies": {
|
|
64
|
-
"@
|
|
65
|
-
"@
|
|
66
|
-
}
|
|
67
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-rtk-optimizer",
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"description": "Pi extension that optimizes RTK command rewriting and tool output compaction for the coding agent.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.ts",
|
|
12
|
+
"src",
|
|
13
|
+
"config/config.example.json",
|
|
14
|
+
"README.md",
|
|
15
|
+
"CHANGELOG.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json --noCheck",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
21
|
+
"test": "bun ./src/output-compactor-test.ts && bun ./src/command-rewriter-test.ts && bun ./src/runtime-guard-test.ts && bun ./src/additional-coverage-test.ts && bun ./src/config-modal-test.ts && bun ./src/index-test.ts",
|
|
22
|
+
"check": "npm run typecheck && npm run test && npm run build:check",
|
|
23
|
+
"build:check": "esbuild ./index.ts --bundle --platform=node --format=esm --outfile=./.pi-rtk-optimizer-check.mjs --external:@mariozechner/pi-coding-agent --external:@mariozechner/pi-tui && node -e \"import { unlinkSync } from 'node:fs'; unlinkSync('./.pi-rtk-optimizer-check.mjs');\""
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"pi-package",
|
|
27
|
+
"pi",
|
|
28
|
+
"pi-extension",
|
|
29
|
+
"pi-coding-agent",
|
|
30
|
+
"coding-agent",
|
|
31
|
+
"rtk",
|
|
32
|
+
"token-optimization",
|
|
33
|
+
"tool-compaction",
|
|
34
|
+
"output-compaction",
|
|
35
|
+
"command-rewrite",
|
|
36
|
+
"optimization"
|
|
37
|
+
],
|
|
38
|
+
"author": "MasuRii",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/MasuRii/pi-rtk-optimizer.git"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/MasuRii/pi-rtk-optimizer/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/MasuRii/pi-rtk-optimizer#readme",
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=20"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"esbuild": "0.28.0",
|
|
56
|
+
"typescript": "6.0.3"
|
|
57
|
+
},
|
|
58
|
+
"pi": {
|
|
59
|
+
"extensions": [
|
|
60
|
+
"./index.ts"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@earendil-works/pi-coding-agent": "^0.74.0 || ^0.75.0",
|
|
65
|
+
"@earendil-works/pi-tui": "^0.74.0 || ^0.75.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -13,7 +13,7 @@ import { sanitizeStreamingBashExecutionResult } from "./tool-execution-sanitizer
|
|
|
13
13
|
import { sanitizeRtkEmojiOutput } from "./techniques/emoji.ts";
|
|
14
14
|
import { stripRtkHookWarnings } from "./techniques/rtk.ts";
|
|
15
15
|
|
|
16
|
-
mock.module("@
|
|
16
|
+
mock.module("@earendil-works/pi-coding-agent", () => ({
|
|
17
17
|
getAgentDir: () => "/tmp/.pi/agent",
|
|
18
18
|
}));
|
|
19
19
|
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import type { AutocompleteItem } from "@
|
|
2
|
-
|
|
3
|
-
interface CompletionDefinition {
|
|
4
|
-
name: string;
|
|
5
|
-
description: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const TOP_LEVEL_SUBCOMMANDS: CompletionDefinition[] = [
|
|
9
|
-
{ name: "show", description: "Show current RTK config + runtime summary" },
|
|
10
|
-
{ name: "path", description: "Show RTK config file path" },
|
|
11
|
-
{ name: "verify", description: "Check whether rtk binary is available" },
|
|
12
|
-
{ name: "stats", description: "Show output compaction metrics" },
|
|
13
|
-
{ name: "clear-stats", description: "Clear output compaction metrics" },
|
|
14
|
-
{ name: "reset", description: "Reset RTK settings to defaults" },
|
|
15
|
-
{ name: "help", description: "Show usage help" },
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
function startsWithFilter(value: string, prefix: string): boolean {
|
|
19
|
-
if (!prefix) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
return value.startsWith(prefix);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function mapCompletions(values: CompletionDefinition[]): AutocompleteItem[] {
|
|
26
|
-
return values.map((entry) => ({
|
|
27
|
-
value: entry.name,
|
|
28
|
-
label: entry.name,
|
|
29
|
-
description: entry.description,
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function getRtkArgumentCompletions(argumentPrefix: string): AutocompleteItem[] | null {
|
|
34
|
-
const normalized = argumentPrefix.trimStart().toLowerCase();
|
|
35
|
-
if (!normalized) {
|
|
36
|
-
return mapCompletions(TOP_LEVEL_SUBCOMMANDS);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (normalized.includes(" ")) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const filtered = TOP_LEVEL_SUBCOMMANDS.filter((entry) => startsWithFilter(entry.name, normalized));
|
|
44
|
-
if (filtered.length === 0) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return mapCompletions(filtered);
|
|
49
|
-
}
|
|
1
|
+
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
2
|
+
|
|
3
|
+
interface CompletionDefinition {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const TOP_LEVEL_SUBCOMMANDS: CompletionDefinition[] = [
|
|
9
|
+
{ name: "show", description: "Show current RTK config + runtime summary" },
|
|
10
|
+
{ name: "path", description: "Show RTK config file path" },
|
|
11
|
+
{ name: "verify", description: "Check whether rtk binary is available" },
|
|
12
|
+
{ name: "stats", description: "Show output compaction metrics" },
|
|
13
|
+
{ name: "clear-stats", description: "Clear output compaction metrics" },
|
|
14
|
+
{ name: "reset", description: "Reset RTK settings to defaults" },
|
|
15
|
+
{ name: "help", description: "Show usage help" },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
function startsWithFilter(value: string, prefix: string): boolean {
|
|
19
|
+
if (!prefix) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return value.startsWith(prefix);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function mapCompletions(values: CompletionDefinition[]): AutocompleteItem[] {
|
|
26
|
+
return values.map((entry) => ({
|
|
27
|
+
value: entry.name,
|
|
28
|
+
label: entry.name,
|
|
29
|
+
description: entry.description,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getRtkArgumentCompletions(argumentPrefix: string): AutocompleteItem[] | null {
|
|
34
|
+
const normalized = argumentPrefix.trimStart().toLowerCase();
|
|
35
|
+
if (!normalized) {
|
|
36
|
+
return mapCompletions(TOP_LEVEL_SUBCOMMANDS);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (normalized.includes(" ")) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const filtered = TOP_LEVEL_SUBCOMMANDS.filter((entry) => startsWithFilter(entry.name, normalized));
|
|
44
|
+
if (filtered.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return mapCompletions(filtered);
|
|
49
|
+
}
|
|
@@ -3,7 +3,7 @@ import assert from "node:assert/strict";
|
|
|
3
3
|
import { computeRewriteDecision } from "./command-rewriter.ts";
|
|
4
4
|
import { resolveRtkRewrite } from "./rtk-rewrite-provider.ts";
|
|
5
5
|
import { cloneDefaultConfig, runTest } from "./test-helpers.ts";
|
|
6
|
-
import type { ExtensionAPI } from "@
|
|
6
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
7
7
|
|
|
8
8
|
function createMockPi(execResult: { code: number; stdout?: string; stderr?: string }): ExtensionAPI {
|
|
9
9
|
return {
|
package/src/command-rewriter.ts
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { resolveRtkRewrite, type RtkRewriteProviderOptions } from "./rtk-rewrite-provider.js";
|
|
2
|
-
import type { ExtensionAPI } from "@
|
|
3
|
-
import type { RtkIntegrationConfig } from "./types.js";
|
|
4
|
-
|
|
5
|
-
export interface RewriteDecision {
|
|
6
|
-
changed: boolean;
|
|
7
|
-
originalCommand: string;
|
|
8
|
-
rewrittenCommand: string;
|
|
9
|
-
reason: "ok" | "empty" | "already_rtk" | "no_match";
|
|
10
|
-
warning?: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function computeRewriteDecision(
|
|
14
|
-
command: string,
|
|
15
|
-
_config: RtkIntegrationConfig,
|
|
16
|
-
pi: ExtensionAPI,
|
|
17
|
-
rewriteOptions: RtkRewriteProviderOptions = {},
|
|
18
|
-
): Promise<RewriteDecision> {
|
|
19
|
-
if (!command || !command.trim()) {
|
|
20
|
-
return { changed: false, originalCommand: command, rewrittenCommand: command, reason: "empty" };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const trimmedStart = command.trimStart();
|
|
24
|
-
if (trimmedStart === "rtk" || trimmedStart.startsWith("rtk ")) {
|
|
25
|
-
return { changed: false, originalCommand: command, rewrittenCommand: command, reason: "already_rtk" };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const result = await resolveRtkRewrite(pi, command, rewriteOptions);
|
|
29
|
-
|
|
30
|
-
if (result.changed && result.rewrittenCommand) {
|
|
31
|
-
return {
|
|
32
|
-
changed: true,
|
|
33
|
-
originalCommand: command,
|
|
34
|
-
rewrittenCommand: result.rewrittenCommand,
|
|
35
|
-
reason: "ok",
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
changed: false,
|
|
41
|
-
originalCommand: command,
|
|
42
|
-
rewrittenCommand: command,
|
|
43
|
-
reason: "no_match",
|
|
44
|
-
warning: result.error,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
1
|
+
import { resolveRtkRewrite, type RtkRewriteProviderOptions } from "./rtk-rewrite-provider.js";
|
|
2
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { RtkIntegrationConfig } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export interface RewriteDecision {
|
|
6
|
+
changed: boolean;
|
|
7
|
+
originalCommand: string;
|
|
8
|
+
rewrittenCommand: string;
|
|
9
|
+
reason: "ok" | "empty" | "already_rtk" | "no_match";
|
|
10
|
+
warning?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function computeRewriteDecision(
|
|
14
|
+
command: string,
|
|
15
|
+
_config: RtkIntegrationConfig,
|
|
16
|
+
pi: ExtensionAPI,
|
|
17
|
+
rewriteOptions: RtkRewriteProviderOptions = {},
|
|
18
|
+
): Promise<RewriteDecision> {
|
|
19
|
+
if (!command || !command.trim()) {
|
|
20
|
+
return { changed: false, originalCommand: command, rewrittenCommand: command, reason: "empty" };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const trimmedStart = command.trimStart();
|
|
24
|
+
if (trimmedStart === "rtk" || trimmedStart.startsWith("rtk ")) {
|
|
25
|
+
return { changed: false, originalCommand: command, rewrittenCommand: command, reason: "already_rtk" };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const result = await resolveRtkRewrite(pi, command, rewriteOptions);
|
|
29
|
+
|
|
30
|
+
if (result.changed && result.rewrittenCommand) {
|
|
31
|
+
return {
|
|
32
|
+
changed: true,
|
|
33
|
+
originalCommand: command,
|
|
34
|
+
rewrittenCommand: result.rewrittenCommand,
|
|
35
|
+
reason: "ok",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
changed: false,
|
|
41
|
+
originalCommand: command,
|
|
42
|
+
rewrittenCommand: command,
|
|
43
|
+
reason: "no_match",
|
|
44
|
+
warning: result.error,
|
|
45
|
+
};
|
|
46
|
+
}
|
package/src/config-modal-test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { mock } from "bun:test";
|
|
|
3
3
|
|
|
4
4
|
import { cloneDefaultConfig, runTest } from "./test-helpers.ts";
|
|
5
5
|
|
|
6
|
-
mock.module("@
|
|
6
|
+
mock.module("@earendil-works/pi-coding-agent", () => ({
|
|
7
7
|
getAgentDir: () => "/tmp/.pi/agent",
|
|
8
8
|
getSettingsListTheme: () => ({}),
|
|
9
9
|
}));
|
|
@@ -11,7 +11,7 @@ mock.module("@mariozechner/pi-coding-agent", () => ({
|
|
|
11
11
|
const settingsListInputs: string[] = [];
|
|
12
12
|
const settingsListUpdates: Array<{ id: string; value: string }> = [];
|
|
13
13
|
|
|
14
|
-
mock.module("@
|
|
14
|
+
mock.module("@earendil-works/pi-tui", () => ({
|
|
15
15
|
Box: class {
|
|
16
16
|
addChild(): void {}
|
|
17
17
|
},
|
package/src/config-modal.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ExtensionAPI, ExtensionCommandContext } from "@
|
|
2
|
-
import type { SettingItem } from "@
|
|
1
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { SettingItem } from "@earendil-works/pi-tui";
|
|
3
3
|
import { toOnOff } from "./boolean-format.js";
|
|
4
4
|
import { ZellijModal, ZellijSettingsModal } from "./zellij-modal.js";
|
|
5
5
|
import { getRtkArgumentCompletions } from "./command-completions.js";
|
|
@@ -31,6 +31,70 @@ const TRUNCATE_MAX_CHAR_VALUES = ["4000", "8000", "12000", "20000", "50000", "10
|
|
|
31
31
|
const SMART_TRUNCATE_LINE_VALUES = ["40", "80", "120", "160", "220", "320", "500", "1000", "2000", "4000"];
|
|
32
32
|
const RTK_USAGE_TEXT =
|
|
33
33
|
"Usage: /rtk [show|path|verify|stats|clear-stats|reset|help] (or run /rtk with no args to open settings modal)";
|
|
34
|
+
const SETTINGS_TAB_DEFINITIONS = [
|
|
35
|
+
{
|
|
36
|
+
label: "General",
|
|
37
|
+
settingIds: ["enabled", "mode", "showRewriteNotifications", "guardWhenRtkMissing"],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: "Compaction",
|
|
41
|
+
settingIds: [
|
|
42
|
+
"outputCompactionEnabled",
|
|
43
|
+
"outputStripAnsi",
|
|
44
|
+
"outputAggregateTestOutput",
|
|
45
|
+
"outputFilterBuildOutput",
|
|
46
|
+
"outputCompactGitOutput",
|
|
47
|
+
"outputAggregateLinterOutput",
|
|
48
|
+
"outputGroupSearchOutput",
|
|
49
|
+
"outputTrackSavings",
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
label: "Read & Source",
|
|
54
|
+
settingIds: [
|
|
55
|
+
"outputReadCompactionEnabled",
|
|
56
|
+
"outputSourceFilteringEnabled",
|
|
57
|
+
"outputSourceFiltering",
|
|
58
|
+
"outputPreserveExactSkillReads",
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
label: "Truncation",
|
|
63
|
+
settingIds: [
|
|
64
|
+
"outputTruncateEnabled",
|
|
65
|
+
"outputTruncateMaxChars",
|
|
66
|
+
"outputSmartTruncate",
|
|
67
|
+
"outputSmartTruncateMaxLines",
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
] as const;
|
|
71
|
+
|
|
72
|
+
function buildTabbedSettingGroups(settings: SettingItem[]): Array<{ label: string; settings: SettingItem[] }> {
|
|
73
|
+
const byId = new Map(settings.map((setting) => [setting.id, setting]));
|
|
74
|
+
const assignedIds = new Set<string>();
|
|
75
|
+
|
|
76
|
+
const tabs = SETTINGS_TAB_DEFINITIONS.map(({ label, settingIds }) => ({
|
|
77
|
+
label,
|
|
78
|
+
settings: settingIds.map((id) => {
|
|
79
|
+
const setting = byId.get(id);
|
|
80
|
+
if (!setting) {
|
|
81
|
+
throw new Error(`Missing setting item for tab '${label}': ${id}`);
|
|
82
|
+
}
|
|
83
|
+
if (assignedIds.has(id)) {
|
|
84
|
+
throw new Error(`Setting item assigned to multiple tabs: ${id}`);
|
|
85
|
+
}
|
|
86
|
+
assignedIds.add(id);
|
|
87
|
+
return setting;
|
|
88
|
+
}),
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const unassignedIds = settings.map((setting) => setting.id).filter((id) => !assignedIds.has(id));
|
|
92
|
+
if (unassignedIds.length > 0) {
|
|
93
|
+
throw new Error(`Unassigned setting items: ${unassignedIds.join(", ")}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return tabs;
|
|
97
|
+
}
|
|
34
98
|
|
|
35
99
|
function parseSourceFilterLevel(
|
|
36
100
|
value: string,
|
|
@@ -400,12 +464,14 @@ async function openSettingsModal(ctx: ExtensionCommandContext, controller: RtkIn
|
|
|
400
464
|
(tui, theme, _keybindings, done) => {
|
|
401
465
|
let current = controller.getConfig();
|
|
402
466
|
let settingsModal: ZellijSettingsModal | null = null;
|
|
467
|
+
const allSettings = buildSettingItems(current);
|
|
468
|
+
const tabs = buildTabbedSettingGroups(allSettings);
|
|
403
469
|
|
|
404
470
|
settingsModal = new ZellijSettingsModal(
|
|
405
471
|
{
|
|
406
|
-
title: "RTK
|
|
407
|
-
|
|
408
|
-
|
|
472
|
+
title: "Pi RTK Optimizer",
|
|
473
|
+
tabs,
|
|
474
|
+
activeTabIndex: 0,
|
|
409
475
|
onChange: (id, newValue) => {
|
|
410
476
|
current = applySetting(current, id, newValue);
|
|
411
477
|
controller.setConfig(current, ctx);
|
|
@@ -415,7 +481,7 @@ async function openSettingsModal(ctx: ExtensionCommandContext, controller: RtkIn
|
|
|
415
481
|
}
|
|
416
482
|
},
|
|
417
483
|
onClose: () => done(),
|
|
418
|
-
helpText:
|
|
484
|
+
helpText: `Config: ${controller.getConfigPath()}`,
|
|
419
485
|
enableSearch: true,
|
|
420
486
|
},
|
|
421
487
|
theme,
|
|
@@ -426,11 +492,14 @@ async function openSettingsModal(ctx: ExtensionCommandContext, controller: RtkIn
|
|
|
426
492
|
{
|
|
427
493
|
borderStyle: "rounded",
|
|
428
494
|
titleBar: {
|
|
429
|
-
left: "RTK
|
|
430
|
-
right: "pi-rtk-optimizer",
|
|
495
|
+
left: "Pi RTK Optimizer",
|
|
431
496
|
},
|
|
432
497
|
helpUndertitle: {
|
|
433
|
-
|
|
498
|
+
variants: [
|
|
499
|
+
"←/→ tabs • Type to search • Enter/Space change • Esc close",
|
|
500
|
+
"←/→ tabs • Type to search • Esc close",
|
|
501
|
+
"←/→ tabs • Esc close",
|
|
502
|
+
],
|
|
434
503
|
color: "dim",
|
|
435
504
|
},
|
|
436
505
|
overlay: overlayOptions,
|
package/src/constants.ts
CHANGED
package/src/index-test.ts
CHANGED
|
@@ -3,13 +3,13 @@ import { mock } from "bun:test";
|
|
|
3
3
|
|
|
4
4
|
import { runTest } from "./test-helpers.ts";
|
|
5
5
|
|
|
6
|
-
mock.module("@
|
|
6
|
+
mock.module("@earendil-works/pi-coding-agent", () => ({
|
|
7
7
|
getAgentDir: () => "/tmp/.pi/agent",
|
|
8
8
|
getSettingsListTheme: () => ({}),
|
|
9
9
|
isToolCallEventType: (toolName: string, event: Record<string, unknown>) => event.toolName === toolName,
|
|
10
10
|
}));
|
|
11
11
|
|
|
12
|
-
mock.module("@
|
|
12
|
+
mock.module("@earendil-works/pi-tui", () => ({
|
|
13
13
|
Box: class {},
|
|
14
14
|
Container: class {
|
|
15
15
|
addChild(): void {}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isToolCallEventType, type ExtensionAPI, type ExtensionCommandContext, type ExtensionContext } from "@
|
|
1
|
+
import { isToolCallEventType, type ExtensionAPI, type ExtensionCommandContext, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import {
|
|
3
3
|
ensureConfigExists,
|
|
4
4
|
getRtkIntegrationConfigPath,
|