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.
@@ -1,97 +1,97 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
-
3
- export type RtkExecutableResolverName = "where" | "which";
4
-
5
- export interface RtkExecutableResolution {
6
- command: string;
7
- resolvedPath?: string;
8
- resolver: RtkExecutableResolverName;
9
- warning?: string;
10
- }
11
-
12
- interface ResolverCommand {
13
- command: RtkExecutableResolverName;
14
- args: string[];
15
- }
16
-
17
- export interface ResolveRtkExecutableOptions {
18
- platform?: typeof process.platform;
19
- timeoutMs?: number;
20
- }
21
-
22
- function trimResolutionDetail(value: string | undefined): string {
23
- return (value ?? "").replace(/\s+/g, " ").trim();
24
- }
25
-
26
- function stripWrappingQuotes(value: string): string {
27
- if (value.length < 2) {
28
- return value;
29
- }
30
-
31
- const first = value[0];
32
- const last = value[value.length - 1];
33
- if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
34
- return value.slice(1, -1);
35
- }
36
-
37
- return value;
38
- }
39
-
40
- export function parseRtkExecutablePath(stdout: string): string | undefined {
41
- for (const line of stdout.split(/\r?\n/)) {
42
- const candidate = stripWrappingQuotes(line.trim());
43
- if (candidate) {
44
- return candidate;
45
- }
46
- }
47
-
48
- return undefined;
49
- }
50
-
51
- function getResolverCommand(platform: typeof process.platform): ResolverCommand {
52
- if (platform === "win32") {
53
- return { command: "where", args: ["rtk"] };
54
- }
55
-
56
- return { command: "which", args: ["rtk"] };
57
- }
58
-
59
- function fallbackResolution(resolver: RtkExecutableResolverName, warning: string): RtkExecutableResolution {
60
- return {
61
- command: "rtk",
62
- resolver,
63
- warning,
64
- };
65
- }
66
-
67
- export async function resolveRtkExecutable(
68
- pi: ExtensionAPI,
69
- options: ResolveRtkExecutableOptions = {},
70
- ): Promise<RtkExecutableResolution> {
71
- const resolver = getResolverCommand(options.platform ?? process.platform);
72
- const timeout = options.timeoutMs ?? 1000;
73
-
74
- try {
75
- const result = await pi.exec(resolver.command, resolver.args, { timeout });
76
- const resolvedPath = parseRtkExecutablePath(result.stdout ?? "");
77
- if (result.code === 0 && resolvedPath) {
78
- return {
79
- command: resolvedPath,
80
- resolvedPath,
81
- resolver: resolver.command,
82
- };
83
- }
84
-
85
- const detail = trimResolutionDetail(result.stderr || result.stdout || `exit ${result.code}`);
86
- return fallbackResolution(
87
- resolver.command,
88
- `rtk executable path resolution via ${resolver.command} failed${detail ? `: ${detail}` : ""}`,
89
- );
90
- } catch (error) {
91
- const message = error instanceof Error ? error.message : String(error);
92
- return fallbackResolution(
93
- resolver.command,
94
- `rtk executable path resolution via ${resolver.command} failed: ${trimResolutionDetail(message)}`,
95
- );
96
- }
97
- }
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ export type RtkExecutableResolverName = "where" | "which";
4
+
5
+ export interface RtkExecutableResolution {
6
+ command: string;
7
+ resolvedPath?: string;
8
+ resolver: RtkExecutableResolverName;
9
+ warning?: string;
10
+ }
11
+
12
+ interface ResolverCommand {
13
+ command: RtkExecutableResolverName;
14
+ args: string[];
15
+ }
16
+
17
+ export interface ResolveRtkExecutableOptions {
18
+ platform?: typeof process.platform;
19
+ timeoutMs?: number;
20
+ }
21
+
22
+ function trimResolutionDetail(value: string | undefined): string {
23
+ return (value ?? "").replace(/\s+/g, " ").trim();
24
+ }
25
+
26
+ function stripWrappingQuotes(value: string): string {
27
+ if (value.length < 2) {
28
+ return value;
29
+ }
30
+
31
+ const first = value[0];
32
+ const last = value[value.length - 1];
33
+ if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
34
+ return value.slice(1, -1);
35
+ }
36
+
37
+ return value;
38
+ }
39
+
40
+ export function parseRtkExecutablePath(stdout: string): string | undefined {
41
+ for (const line of stdout.split(/\r?\n/)) {
42
+ const candidate = stripWrappingQuotes(line.trim());
43
+ if (candidate) {
44
+ return candidate;
45
+ }
46
+ }
47
+
48
+ return undefined;
49
+ }
50
+
51
+ function getResolverCommand(platform: typeof process.platform): ResolverCommand {
52
+ if (platform === "win32") {
53
+ return { command: "where", args: ["rtk"] };
54
+ }
55
+
56
+ return { command: "which", args: ["rtk"] };
57
+ }
58
+
59
+ function fallbackResolution(resolver: RtkExecutableResolverName, warning: string): RtkExecutableResolution {
60
+ return {
61
+ command: "rtk",
62
+ resolver,
63
+ warning,
64
+ };
65
+ }
66
+
67
+ export async function resolveRtkExecutable(
68
+ pi: ExtensionAPI,
69
+ options: ResolveRtkExecutableOptions = {},
70
+ ): Promise<RtkExecutableResolution> {
71
+ const resolver = getResolverCommand(options.platform ?? process.platform);
72
+ const timeout = options.timeoutMs ?? 1000;
73
+
74
+ try {
75
+ const result = await pi.exec(resolver.command, resolver.args, { timeout });
76
+ const resolvedPath = parseRtkExecutablePath(result.stdout ?? "");
77
+ if (result.code === 0 && resolvedPath) {
78
+ return {
79
+ command: resolvedPath,
80
+ resolvedPath,
81
+ resolver: resolver.command,
82
+ };
83
+ }
84
+
85
+ const detail = trimResolutionDetail(result.stderr || result.stdout || `exit ${result.code}`);
86
+ return fallbackResolution(
87
+ resolver.command,
88
+ `rtk executable path resolution via ${resolver.command} failed${detail ? `: ${detail}` : ""}`,
89
+ );
90
+ } catch (error) {
91
+ const message = error instanceof Error ? error.message : String(error);
92
+ return fallbackResolution(
93
+ resolver.command,
94
+ `rtk executable path resolution via ${resolver.command} failed: ${trimResolutionDetail(message)}`,
95
+ );
96
+ }
97
+ }
@@ -1,126 +1,126 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import { resolveRtkExecutable, type RtkExecutableResolution } from "./rtk-executable-resolver.js";
3
-
4
- export interface RtkRewriteProviderResult {
5
- changed: boolean;
6
- originalCommand: string;
7
- rewrittenCommand: string;
8
- exitCode: number;
9
- error?: string;
10
- executableResolution?: RtkExecutableResolution;
11
- }
12
-
13
- export interface RtkRewriteProviderOptions {
14
- timeoutMs?: number;
15
- resolverTimeoutMs?: number;
16
- platform?: typeof process.platform;
17
- executableResolution?: RtkExecutableResolution;
18
- }
19
-
20
- function isAlreadyRtk(command: string): boolean {
21
- const trimmed = command.trimStart();
22
- return trimmed === "rtk" || trimmed.startsWith("rtk ");
23
- }
24
-
25
- function normalizeOptions(optionsOrTimeout: number | RtkRewriteProviderOptions): RtkRewriteProviderOptions {
26
- if (typeof optionsOrTimeout === "number") {
27
- return { timeoutMs: optionsOrTimeout };
28
- }
29
- return optionsOrTimeout;
30
- }
31
-
32
- export async function resolveRtkRewrite(
33
- pi: ExtensionAPI,
34
- command: string,
35
- optionsOrTimeout: number | RtkRewriteProviderOptions = {},
36
- ): Promise<RtkRewriteProviderResult> {
37
- const options = normalizeOptions(optionsOrTimeout);
38
- const timeoutMs = options.timeoutMs ?? 3000;
39
-
40
- if (!command || !command.trim()) {
41
- return { changed: false, originalCommand: command, rewrittenCommand: command, exitCode: 1 };
42
- }
43
-
44
- if (isAlreadyRtk(command)) {
45
- return { changed: false, originalCommand: command, rewrittenCommand: command, exitCode: 1 };
46
- }
47
-
48
- try {
49
- const executableResolution =
50
- options.executableResolution ??
51
- (await resolveRtkExecutable(pi, {
52
- platform: options.platform,
53
- timeoutMs: options.resolverTimeoutMs,
54
- }));
55
- const result = await pi.exec(executableResolution.command, ["rewrite", command], { timeout: timeoutMs });
56
-
57
- if (result.code === 1) {
58
- return {
59
- changed: false,
60
- originalCommand: command,
61
- rewrittenCommand: command,
62
- exitCode: 1,
63
- executableResolution,
64
- };
65
- }
66
-
67
- if (result.code === 2) {
68
- return {
69
- changed: false,
70
- originalCommand: command,
71
- rewrittenCommand: command,
72
- exitCode: 2,
73
- error: result.stderr?.trim() || "rtk denied rewrite",
74
- executableResolution,
75
- };
76
- }
77
-
78
- if (result.code === 0 || result.code === 3) {
79
- const rewritten = result.stdout?.trim();
80
- if (!rewritten) {
81
- return {
82
- changed: false,
83
- originalCommand: command,
84
- rewrittenCommand: command,
85
- exitCode: result.code,
86
- error: "rtk returned empty output",
87
- executableResolution,
88
- };
89
- }
90
- if (rewritten === command) {
91
- return {
92
- changed: false,
93
- originalCommand: command,
94
- rewrittenCommand: command,
95
- exitCode: result.code,
96
- executableResolution,
97
- };
98
- }
99
- return {
100
- changed: true,
101
- originalCommand: command,
102
- rewrittenCommand: rewritten,
103
- exitCode: result.code,
104
- executableResolution,
105
- };
106
- }
107
-
108
- return {
109
- changed: false,
110
- originalCommand: command,
111
- rewrittenCommand: command,
112
- exitCode: result.code,
113
- error: `unexpected exit code ${result.code}`,
114
- executableResolution,
115
- };
116
- } catch (error) {
117
- const message = error instanceof Error ? error.message : String(error);
118
- return {
119
- changed: false,
120
- originalCommand: command,
121
- rewrittenCommand: command,
122
- exitCode: -1,
123
- error: message,
124
- };
125
- }
126
- }
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { resolveRtkExecutable, type RtkExecutableResolution } from "./rtk-executable-resolver.js";
3
+
4
+ export interface RtkRewriteProviderResult {
5
+ changed: boolean;
6
+ originalCommand: string;
7
+ rewrittenCommand: string;
8
+ exitCode: number;
9
+ error?: string;
10
+ executableResolution?: RtkExecutableResolution;
11
+ }
12
+
13
+ export interface RtkRewriteProviderOptions {
14
+ timeoutMs?: number;
15
+ resolverTimeoutMs?: number;
16
+ platform?: typeof process.platform;
17
+ executableResolution?: RtkExecutableResolution;
18
+ }
19
+
20
+ function isAlreadyRtk(command: string): boolean {
21
+ const trimmed = command.trimStart();
22
+ return trimmed === "rtk" || trimmed.startsWith("rtk ");
23
+ }
24
+
25
+ function normalizeOptions(optionsOrTimeout: number | RtkRewriteProviderOptions): RtkRewriteProviderOptions {
26
+ if (typeof optionsOrTimeout === "number") {
27
+ return { timeoutMs: optionsOrTimeout };
28
+ }
29
+ return optionsOrTimeout;
30
+ }
31
+
32
+ export async function resolveRtkRewrite(
33
+ pi: ExtensionAPI,
34
+ command: string,
35
+ optionsOrTimeout: number | RtkRewriteProviderOptions = {},
36
+ ): Promise<RtkRewriteProviderResult> {
37
+ const options = normalizeOptions(optionsOrTimeout);
38
+ const timeoutMs = options.timeoutMs ?? 3000;
39
+
40
+ if (!command || !command.trim()) {
41
+ return { changed: false, originalCommand: command, rewrittenCommand: command, exitCode: 1 };
42
+ }
43
+
44
+ if (isAlreadyRtk(command)) {
45
+ return { changed: false, originalCommand: command, rewrittenCommand: command, exitCode: 1 };
46
+ }
47
+
48
+ try {
49
+ const executableResolution =
50
+ options.executableResolution ??
51
+ (await resolveRtkExecutable(pi, {
52
+ platform: options.platform,
53
+ timeoutMs: options.resolverTimeoutMs,
54
+ }));
55
+ const result = await pi.exec(executableResolution.command, ["rewrite", command], { timeout: timeoutMs });
56
+
57
+ if (result.code === 1) {
58
+ return {
59
+ changed: false,
60
+ originalCommand: command,
61
+ rewrittenCommand: command,
62
+ exitCode: 1,
63
+ executableResolution,
64
+ };
65
+ }
66
+
67
+ if (result.code === 2) {
68
+ return {
69
+ changed: false,
70
+ originalCommand: command,
71
+ rewrittenCommand: command,
72
+ exitCode: 2,
73
+ error: result.stderr?.trim() || "rtk denied rewrite",
74
+ executableResolution,
75
+ };
76
+ }
77
+
78
+ if (result.code === 0 || result.code === 3) {
79
+ const rewritten = result.stdout?.trim();
80
+ if (!rewritten) {
81
+ return {
82
+ changed: false,
83
+ originalCommand: command,
84
+ rewrittenCommand: command,
85
+ exitCode: result.code,
86
+ error: "rtk returned empty output",
87
+ executableResolution,
88
+ };
89
+ }
90
+ if (rewritten === command) {
91
+ return {
92
+ changed: false,
93
+ originalCommand: command,
94
+ rewrittenCommand: command,
95
+ exitCode: result.code,
96
+ executableResolution,
97
+ };
98
+ }
99
+ return {
100
+ changed: true,
101
+ originalCommand: command,
102
+ rewrittenCommand: rewritten,
103
+ exitCode: result.code,
104
+ executableResolution,
105
+ };
106
+ }
107
+
108
+ return {
109
+ changed: false,
110
+ originalCommand: command,
111
+ rewrittenCommand: command,
112
+ exitCode: result.code,
113
+ error: `unexpected exit code ${result.code}`,
114
+ executableResolution,
115
+ };
116
+ } catch (error) {
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ return {
119
+ changed: false,
120
+ originalCommand: command,
121
+ rewrittenCommand: command,
122
+ exitCode: -1,
123
+ error: message,
124
+ };
125
+ }
126
+ }
@@ -1,4 +1,4 @@
1
- declare module "@mariozechner/pi-tui" {
1
+ declare module "@earendil-works/pi-tui" {
2
2
  export interface SettingItem {
3
3
  id: string;
4
4
  label: string;
@@ -27,6 +27,8 @@ declare module "@mariozechner/pi-tui" {
27
27
 
28
28
  export class SettingsList {
29
29
  constructor(...args: unknown[]);
30
+ render(width: number): string[];
31
+ invalidate(): void;
30
32
  handleInput(data: string): void;
31
33
  updateValue(id: string, value: string): void;
32
34
  }
@@ -43,7 +45,7 @@ declare module "@mariozechner/pi-tui" {
43
45
  export function visibleWidth(text: string): number;
44
46
  }
45
47
 
46
- declare module "@mariozechner/pi-coding-agent" {
48
+ declare module "@earendil-works/pi-coding-agent" {
47
49
  interface UiLike {
48
50
  notify(message: string, level: "info" | "warning" | "error"): void;
49
51
  custom<T>(