@aliou/pi-processes 0.9.0 → 0.9.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/README.md +1 -1
- package/package.json +18 -17
- package/src/commands/clear/command.ts +1 -1
- package/src/commands/dock/command.ts +1 -1
- package/src/commands/index.ts +1 -1
- package/src/commands/kill/command.ts +1 -1
- package/src/commands/logs/command.ts +1 -1
- package/src/commands/pick-process.ts +1 -1
- package/src/commands/pin/command.ts +1 -1
- package/src/commands/processes/command.ts +1 -1
- package/src/commands/settings/command.ts +1 -1
- package/src/components/log-dock-component.ts +20 -16
- package/src/components/log-file-viewer.ts +2 -2
- package/src/components/log-overlay-component.ts +2 -2
- package/src/components/panel-helpers.ts +37 -0
- package/src/components/process-picker-component.ts +8 -9
- package/src/components/processes-component.ts +9 -10
- package/src/hooks/background-blocker.ts +1 -1
- package/src/hooks/cleanup.ts +1 -1
- package/src/hooks/index.ts +1 -1
- package/src/hooks/message-renderer.ts +2 -2
- package/src/hooks/process-end.ts +1 -1
- package/src/hooks/process-watch.ts +1 -1
- package/src/hooks/utils.ts +1 -1
- package/src/hooks/widget/setup.ts +1 -1
- package/src/hooks/widget/status-widget.ts +2 -2
- package/src/index.ts +1 -1
- package/src/manager.ts +2 -2
- package/src/tools/actions/debug.ts +1 -1
- package/src/tools/actions/index.ts +2 -2
- package/src/tools/actions/kill.ts +1 -1
- package/src/tools/actions/list.ts +2 -2
- package/src/tools/actions/logs.ts +2 -2
- package/src/tools/actions/output.ts +2 -2
- package/src/tools/actions/start.ts +2 -2
- package/src/tools/actions/write.ts +1 -1
- package/src/tools/index.ts +3 -3
- package/src/utils/ansi.test.ts +22 -0
- package/src/utils/ansi.ts +28 -19
- package/src/utils/format.ts +1 -1
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/pi-processes",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"skills": [
|
|
22
22
|
"./skills/pi-processes"
|
|
23
23
|
],
|
|
24
|
-
"video": "https://assets.aliou.me/
|
|
24
|
+
"video": "https://assets.aliou.me/github/aliou/pi-processes/demo.mp4"
|
|
25
25
|
},
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
@@ -33,31 +33,32 @@
|
|
|
33
33
|
"CONTRIBUTING.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@aliou/pi-utils-settings": "^0.
|
|
37
|
-
"@aliou/pi-utils-ui": "^0.1
|
|
36
|
+
"@aliou/pi-utils-settings": "^0.15.1",
|
|
37
|
+
"@aliou/pi-utils-ui": "^0.4.1",
|
|
38
38
|
"@aliou/sh": "^0.1.0",
|
|
39
|
-
"typebox": "^1.
|
|
39
|
+
"typebox": "^1.1.38"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@
|
|
43
|
-
"@
|
|
42
|
+
"@earendil-works/pi-coding-agent": "^0.75.3",
|
|
43
|
+
"@earendil-works/pi-tui": "^0.75.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@aliou/biome-plugins": "^0.
|
|
47
|
-
"@biomejs/biome": "^2.
|
|
48
|
-
"@changesets/cli": "^2.
|
|
49
|
-
"@
|
|
50
|
-
"@mariozechner/pi-coding-agent": "0.72.1",
|
|
51
|
-
"@types/node": "^25.0.10",
|
|
46
|
+
"@aliou/biome-plugins": "^0.8.1",
|
|
47
|
+
"@biomejs/biome": "^2.4.15",
|
|
48
|
+
"@changesets/cli": "^2.31.0",
|
|
49
|
+
"@types/node": "^25.9.1",
|
|
52
50
|
"husky": "^9.1.7",
|
|
53
|
-
"typescript": "^
|
|
54
|
-
"vitest": "^4.
|
|
51
|
+
"typescript": "^6.0.3",
|
|
52
|
+
"vitest": "^4.1.7",
|
|
53
|
+
"@earendil-works/pi-ai": "^0.75.3",
|
|
54
|
+
"@earendil-works/pi-coding-agent": "^0.75.3",
|
|
55
|
+
"@earendil-works/pi-tui": "^0.75.3"
|
|
55
56
|
},
|
|
56
57
|
"peerDependenciesMeta": {
|
|
57
|
-
"@
|
|
58
|
+
"@earendil-works/pi-coding-agent": {
|
|
58
59
|
"optional": true
|
|
59
60
|
},
|
|
60
|
-
"@
|
|
61
|
+
"@earendil-works/pi-tui": {
|
|
61
62
|
"optional": true
|
|
62
63
|
}
|
|
63
64
|
},
|
package/src/commands/index.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* /ps:dock [show|hide|toggle] - Control dock visibility
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { ExtensionAPI } from "@
|
|
12
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
import type { DockActions } from "../hooks/widget";
|
|
14
14
|
import type { ProcessManager } from "../manager";
|
|
15
15
|
import { registerPsClearCommand } from "./clear";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { LIVE_STATUSES } from "../../constants";
|
|
3
3
|
import type { DockActions } from "../../hooks/widget";
|
|
4
4
|
import type { ProcessManager } from "../../manager";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { LogOverlayComponent } from "../../components/log-overlay-component";
|
|
3
3
|
import type { ProcessManager } from "../../manager";
|
|
4
4
|
import { allProcessCompletions } from "../completions";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionCommandContext } from "@
|
|
1
|
+
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { ProcessPickerComponent } from "../components/process-picker-component";
|
|
3
3
|
import type { ProcessInfo } from "../constants";
|
|
4
4
|
import type { ProcessManager } from "../manager";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { DockActions } from "../../hooks/widget";
|
|
3
3
|
import type { ProcessManager } from "../../manager";
|
|
4
4
|
import { allProcessCompletions } from "../completions";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { ProcessesComponent } from "../../components/processes-component";
|
|
3
3
|
import type { DockActions } from "../../hooks/widget";
|
|
4
4
|
import type { ProcessManager } from "../../manager";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { registerSettingsCommand } from "@aliou/pi-utils-settings";
|
|
2
|
-
import type { ExtensionAPI } from "@
|
|
2
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import type { ProcessesConfig, ResolvedProcessesConfig } from "../../config";
|
|
4
4
|
import { configLoader } from "../../config";
|
|
5
5
|
import { applySettingChange } from "./apply-setting-change";
|
|
@@ -5,17 +5,18 @@
|
|
|
5
5
|
* Open view: LogFileViewer for the focused process (or first running), follow mode on.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import type { Component } from "@earendil-works/pi-tui";
|
|
10
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
11
|
+
import { LIVE_STATUSES } from "../constants";
|
|
12
|
+
import type { ProcessManager } from "../manager";
|
|
13
|
+
import { stripAnsi } from "../utils";
|
|
14
|
+
import { LogFileViewer } from "./log-file-viewer";
|
|
8
15
|
import {
|
|
9
16
|
createPanelPadder,
|
|
10
17
|
renderPanelRule,
|
|
11
18
|
renderPanelTitleLine,
|
|
12
|
-
} from "
|
|
13
|
-
import type { Theme, ThemeColor } from "@mariozechner/pi-coding-agent";
|
|
14
|
-
import type { Component } from "@mariozechner/pi-tui";
|
|
15
|
-
import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
16
|
-
import { LIVE_STATUSES } from "../constants";
|
|
17
|
-
import type { ProcessManager } from "../manager";
|
|
18
|
-
import { LogFileViewer } from "./log-file-viewer";
|
|
19
|
+
} from "./panel-helpers";
|
|
19
20
|
|
|
20
21
|
const PROCESS_COLORS: ThemeColor[] = [
|
|
21
22
|
"accent",
|
|
@@ -121,9 +122,10 @@ export class LogDockComponent implements Component {
|
|
|
121
122
|
const processes = this.manager.list();
|
|
122
123
|
const innerWidth = width - 2;
|
|
123
124
|
const padLine = (content: string) => {
|
|
124
|
-
const w = visibleWidth(content);
|
|
125
125
|
const line =
|
|
126
|
-
|
|
126
|
+
visibleWidth(content) > innerWidth
|
|
127
|
+
? truncateToWidth(content, innerWidth, "", true)
|
|
128
|
+
: content;
|
|
127
129
|
return ` ${line}${" ".repeat(Math.max(0, width - 1 - visibleWidth(line)))}`;
|
|
128
130
|
};
|
|
129
131
|
|
|
@@ -146,15 +148,17 @@ export class LogDockComponent implements Component {
|
|
|
146
148
|
const firstLine = parts.join(" | ");
|
|
147
149
|
const lines = [
|
|
148
150
|
renderPanelRule(width, theme),
|
|
149
|
-
padLine(truncateToWidth(firstLine, innerWidth)),
|
|
151
|
+
padLine(truncateToWidth(firstLine, innerWidth, "", true)),
|
|
150
152
|
];
|
|
151
153
|
|
|
152
154
|
if (running.length > 0) {
|
|
153
155
|
const lastLogs = this.manager.getCombinedOutput(running[0].id, 1);
|
|
154
156
|
if (lastLogs && lastLogs.length > 0) {
|
|
155
157
|
const lastLog = truncateToWidth(
|
|
156
|
-
lastLogs[lastLogs.length - 1].text,
|
|
158
|
+
stripAnsi(lastLogs[lastLogs.length - 1].text),
|
|
157
159
|
innerWidth,
|
|
160
|
+
"",
|
|
161
|
+
true,
|
|
158
162
|
);
|
|
159
163
|
lines.push(padLine(dim(lastLog)));
|
|
160
164
|
}
|
|
@@ -169,12 +173,12 @@ export class LogDockComponent implements Component {
|
|
|
169
173
|
|
|
170
174
|
const innerWidth = width - 2;
|
|
171
175
|
const basePadLine = createPanelPadder(width);
|
|
172
|
-
const padLine = (content: string): string =>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
const padLine = (content: string): string =>
|
|
177
|
+
basePadLine(
|
|
178
|
+
visibleWidth(content) > innerWidth
|
|
179
|
+
? truncateToWidth(content, innerWidth, "", true)
|
|
180
|
+
: content,
|
|
176
181
|
);
|
|
177
|
-
};
|
|
178
182
|
|
|
179
183
|
const processes = this.manager.list();
|
|
180
184
|
const running = processes.filter((p) => LIVE_STATUSES.has(p.status));
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
|
-
import type { Theme } from "@
|
|
12
|
-
import { truncateToWidth, visibleWidth } from "@
|
|
11
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
13
13
|
import { stripAnsi } from "../utils";
|
|
14
14
|
|
|
15
15
|
export type StreamFilter = "combined" | "stdout" | "stderr";
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ╰───────────────────────────────────────╯
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import type { Theme } from "@
|
|
17
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
18
18
|
import {
|
|
19
19
|
type Component,
|
|
20
20
|
Input,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
type TUI,
|
|
23
23
|
truncateToWidth,
|
|
24
24
|
visibleWidth,
|
|
25
|
-
} from "@
|
|
25
|
+
} from "@earendil-works/pi-tui";
|
|
26
26
|
import { LIVE_STATUSES, type ProcessInfo } from "../constants";
|
|
27
27
|
import type { ProcessManager } from "../manager";
|
|
28
28
|
import { LogFileViewer } from "./log-file-viewer";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
|
|
4
|
+
export function createPanelPadder(width: number): (content: string) => string {
|
|
5
|
+
const innerWidth = Math.max(0, width - 2);
|
|
6
|
+
|
|
7
|
+
return (content: string): string => {
|
|
8
|
+
const truncated = truncateToWidth(content, innerWidth, "", true);
|
|
9
|
+
const padding = " ".repeat(
|
|
10
|
+
Math.max(0, innerWidth - visibleWidth(truncated)),
|
|
11
|
+
);
|
|
12
|
+
return `│${truncated}${padding}│`;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function renderPanelRule(width: number, theme: Theme): string {
|
|
17
|
+
if (width <= 0) return "";
|
|
18
|
+
if (width === 1) return theme.fg("dim", "─");
|
|
19
|
+
|
|
20
|
+
return theme.fg("dim", `├${"─".repeat(Math.max(0, width - 2))}┤`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function renderPanelTitleLine(
|
|
24
|
+
title: string,
|
|
25
|
+
width: number,
|
|
26
|
+
theme: Theme,
|
|
27
|
+
): string {
|
|
28
|
+
if (width <= 0) return "";
|
|
29
|
+
if (width === 1) return theme.fg("dim", "─");
|
|
30
|
+
|
|
31
|
+
const innerWidth = Math.max(0, width - 2);
|
|
32
|
+
const label = ` ${title} `;
|
|
33
|
+
const truncated = truncateToWidth(label, innerWidth, "", true);
|
|
34
|
+
const remaining = Math.max(0, innerWidth - visibleWidth(truncated));
|
|
35
|
+
|
|
36
|
+
return theme.fg("dim", `┌${truncated}${"─".repeat(remaining)}┐`);
|
|
37
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createPanelPadder,
|
|
3
|
-
renderPanelRule,
|
|
4
|
-
renderPanelTitleLine,
|
|
5
|
-
} from "@aliou/pi-utils-ui";
|
|
6
|
-
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
1
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
7
2
|
import {
|
|
8
3
|
type Component,
|
|
9
4
|
matchesKey,
|
|
10
5
|
truncateToWidth,
|
|
11
6
|
visibleWidth,
|
|
12
|
-
} from "@
|
|
7
|
+
} from "@earendil-works/pi-tui";
|
|
13
8
|
import type { ProcessInfo } from "../constants";
|
|
14
9
|
import type { ProcessManager } from "../manager";
|
|
10
|
+
import {
|
|
11
|
+
createPanelPadder,
|
|
12
|
+
renderPanelRule,
|
|
13
|
+
renderPanelTitleLine,
|
|
14
|
+
} from "./panel-helpers";
|
|
15
15
|
import { statusIcon, statusLabel } from "./status-format";
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -121,7 +121,7 @@ export class ProcessPickerComponent implements Component {
|
|
|
121
121
|
const padLine = (content: string): string =>
|
|
122
122
|
basePadLine(
|
|
123
123
|
visibleWidth(content) > innerWidth
|
|
124
|
-
? truncateToWidth(content, innerWidth)
|
|
124
|
+
? truncateToWidth(content, innerWidth, "", true)
|
|
125
125
|
: content,
|
|
126
126
|
);
|
|
127
127
|
|
|
@@ -151,7 +151,6 @@ export class ProcessPickerComponent implements Component {
|
|
|
151
151
|
lines.push(padLine(""));
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
// Footer
|
|
155
154
|
lines.push(renderPanelRule(width, theme));
|
|
156
155
|
lines.push(
|
|
157
156
|
padLine(
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createPanelPadder,
|
|
3
|
-
renderPanelRule,
|
|
4
|
-
renderPanelTitleLine,
|
|
5
|
-
} from "@aliou/pi-utils-ui";
|
|
6
|
-
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
1
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
7
2
|
import {
|
|
8
3
|
type Component,
|
|
9
4
|
matchesKey,
|
|
10
5
|
truncateToWidth,
|
|
11
6
|
visibleWidth,
|
|
12
|
-
} from "@
|
|
7
|
+
} from "@earendil-works/pi-tui";
|
|
13
8
|
import { configLoader } from "../config";
|
|
14
9
|
import type { ProcessInfo } from "../constants";
|
|
15
10
|
import type { ProcessManager } from "../manager";
|
|
16
11
|
import { stripAnsi } from "../utils";
|
|
12
|
+
import {
|
|
13
|
+
createPanelPadder,
|
|
14
|
+
renderPanelRule,
|
|
15
|
+
renderPanelTitleLine,
|
|
16
|
+
} from "./panel-helpers";
|
|
17
17
|
import { statusIcon, statusLabel } from "./status-format";
|
|
18
18
|
|
|
19
19
|
function formatRuntime(startTime: number, endTime: number | null): string {
|
|
@@ -236,7 +236,7 @@ export class ProcessesComponent implements Component {
|
|
|
236
236
|
const padLine = (content: string): string =>
|
|
237
237
|
basePadLine(
|
|
238
238
|
visibleWidth(content) > innerWidth
|
|
239
|
-
? truncateToWidth(content, innerWidth)
|
|
239
|
+
? truncateToWidth(content, innerWidth, "", true)
|
|
240
240
|
: content,
|
|
241
241
|
);
|
|
242
242
|
|
|
@@ -417,8 +417,6 @@ export class ProcessesComponent implements Component {
|
|
|
417
417
|
}
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
-
lines.push(renderPanelRule(width, theme));
|
|
421
|
-
|
|
422
420
|
const footerLeft =
|
|
423
421
|
`${dim("enter")} stream ` +
|
|
424
422
|
`${dim("j/k")} select ` +
|
|
@@ -448,6 +446,7 @@ export class ProcessesComponent implements Component {
|
|
|
448
446
|
footer = truncateToWidth(footer, innerWidth);
|
|
449
447
|
}
|
|
450
448
|
|
|
449
|
+
lines.push(renderPanelRule(width, theme));
|
|
451
450
|
lines.push(padLine(footer));
|
|
452
451
|
|
|
453
452
|
this.cachedLines = lines;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { parse } from "@aliou/sh";
|
|
9
|
-
import type { ExtensionAPI } from "@
|
|
9
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { walkCommands, wordToString } from "../utils/shell-utils";
|
|
11
11
|
|
|
12
12
|
const BACKGROUND_CMD_NAMES = new Set(["nohup", "disown", "setsid"]);
|
package/src/hooks/cleanup.ts
CHANGED
package/src/hooks/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { ResolvedProcessesConfig } from "../config";
|
|
3
3
|
import type { ProcessManager } from "../manager";
|
|
4
4
|
import { setupBackgroundBlocker } from "./background-blocker";
|
|
@@ -2,8 +2,8 @@ import type {
|
|
|
2
2
|
ExtensionAPI,
|
|
3
3
|
MessageRenderOptions,
|
|
4
4
|
Theme,
|
|
5
|
-
} from "@
|
|
6
|
-
import { Text } from "@
|
|
5
|
+
} from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
7
7
|
import { MESSAGE_TYPE_PROCESS_UPDATE } from "../constants";
|
|
8
8
|
|
|
9
9
|
interface ProcessLifecycleDetails {
|
package/src/hooks/process-end.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { MESSAGE_TYPE_PROCESS_UPDATE, type ProcessInfo } from "../constants";
|
|
3
3
|
import type { ProcessManager } from "../manager";
|
|
4
4
|
import { formatRuntime } from "../utils";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { MESSAGE_TYPE_PROCESS_UPDATE } from "../constants";
|
|
3
3
|
import type { ProcessManager } from "../manager";
|
|
4
4
|
import { safeSendMessage } from "./utils";
|
package/src/hooks/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ExtensionAPI,
|
|
3
3
|
ExtensionContext,
|
|
4
|
-
} from "@
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { LogDockComponent } from "../../components/log-dock-component";
|
|
6
6
|
import { configLoader, type ResolvedProcessesConfig } from "../../config";
|
|
7
7
|
import { LIVE_STATUSES } from "../../constants";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ExtensionContext } from "@
|
|
2
|
-
import { truncateToWidth, visibleWidth } from "@
|
|
1
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
import type { ProcessInfo } from "../../constants";
|
|
4
4
|
|
|
5
5
|
function formatProcessStatus(
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { setupProcessesCommands } from "./commands";
|
|
3
3
|
import { registerProcessesSettings } from "./commands/settings";
|
|
4
4
|
import { configLoader } from "./config";
|
package/src/manager.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type { Theme } from "@
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import type { ExecuteResult, ProcessInfo } from "../../constants";
|
|
4
4
|
|
|
5
5
|
interface DebugParams {
|
|
@@ -4,8 +4,8 @@ import type {
|
|
|
4
4
|
ExtensionContext,
|
|
5
5
|
Theme,
|
|
6
6
|
ToolRenderResultOptions,
|
|
7
|
-
} from "@
|
|
8
|
-
import type { Component } from "@
|
|
7
|
+
} from "@earendil-works/pi-coding-agent";
|
|
8
|
+
import type { Component } from "@earendil-works/pi-tui";
|
|
9
9
|
import type {
|
|
10
10
|
ExecuteResult,
|
|
11
11
|
ProcessAction,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type { Theme } from "@
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import type { ExecuteResult } from "../../constants";
|
|
4
4
|
import type { ProcessManager } from "../../manager";
|
|
5
5
|
|
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
AgentToolResult,
|
|
4
4
|
Theme,
|
|
5
5
|
ToolRenderResultOptions,
|
|
6
|
-
} from "@
|
|
7
|
-
import { Text } from "@
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
8
8
|
import type { ExecuteResult, ProcessesDetails } from "../../constants";
|
|
9
9
|
import type { ProcessManager } from "../../manager";
|
|
10
10
|
import {
|
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
AgentToolResult,
|
|
4
4
|
Theme,
|
|
5
5
|
ToolRenderResultOptions,
|
|
6
|
-
} from "@
|
|
7
|
-
import { Text } from "@
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
8
8
|
import type { ExecuteResult, ProcessesDetails } from "../../constants";
|
|
9
9
|
import type { ProcessManager } from "../../manager";
|
|
10
10
|
|
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
AgentToolResult,
|
|
4
4
|
Theme,
|
|
5
5
|
ToolRenderResultOptions,
|
|
6
|
-
} from "@
|
|
7
|
-
import { Text } from "@
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
8
8
|
import { configLoader } from "../../config";
|
|
9
9
|
import type { ExecuteResult, ProcessesDetails } from "../../constants";
|
|
10
10
|
import type { ProcessManager } from "../../manager";
|
|
@@ -4,8 +4,8 @@ import type {
|
|
|
4
4
|
ExtensionContext,
|
|
5
5
|
Theme,
|
|
6
6
|
ToolRenderResultOptions,
|
|
7
|
-
} from "@
|
|
8
|
-
import { Text } from "@
|
|
7
|
+
} from "@earendil-works/pi-coding-agent";
|
|
8
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
9
9
|
import type { ExecuteResult, ProcessesDetails } from "../../constants";
|
|
10
10
|
import type { ProcessManager } from "../../manager";
|
|
11
11
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type { Theme } from "@
|
|
2
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
import type { ExecuteResult } from "../../constants";
|
|
4
4
|
import type { ProcessManager } from "../../manager";
|
|
5
5
|
|
package/src/tools/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ToolBody } from "@aliou/pi-utils-ui";
|
|
2
|
-
import { StringEnum } from "@
|
|
2
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
3
3
|
import type {
|
|
4
4
|
AgentToolResult,
|
|
5
5
|
ExtensionAPI,
|
|
6
6
|
Theme,
|
|
7
7
|
ToolRenderResultOptions,
|
|
8
|
-
} from "@
|
|
9
|
-
import { Text } from "@
|
|
8
|
+
} from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
10
10
|
import { type Static, Type } from "typebox";
|
|
11
11
|
import type { ProcessesDetails } from "../constants";
|
|
12
12
|
import type { ProcessManager } from "../manager";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { stripAnsi } from "./ansi";
|
|
3
|
+
|
|
4
|
+
describe("stripAnsi", () => {
|
|
5
|
+
it("strips CSI styling sequences", () => {
|
|
6
|
+
expect(stripAnsi("\u001b[31mred\u001b[0m")).toBe("red");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("strips generic OSC sequences", () => {
|
|
10
|
+
expect(stripAnsi("\u001b]0;title\u0007hello")).toBe("hello");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("strips carriage returns and other control chars that can corrupt TUI rendering", () => {
|
|
14
|
+
expect(stripAnsi("step 1\rstep 2\b\b done")).toBe("step 1step 2 done");
|
|
15
|
+
expect(stripAnsi("null\u0000byte")).toBe("nullbyte");
|
|
16
|
+
expect(stripAnsi("delete\u007fchar")).toBe("deletechar");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("preserves tabs and newlines", () => {
|
|
20
|
+
expect(stripAnsi("one\ttwo\nthree")).toBe("one\ttwo\nthree");
|
|
21
|
+
});
|
|
22
|
+
});
|
package/src/utils/ansi.ts
CHANGED
|
@@ -1,36 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Strip ANSI escape codes from a string.
|
|
2
|
+
* Strip ANSI escape codes and other terminal control characters from a string.
|
|
3
3
|
*
|
|
4
4
|
* Removes:
|
|
5
5
|
* - All CSI sequences (\x1b[...X) - SGR, cursor movement, erase, scroll, etc.
|
|
6
|
-
* - OSC
|
|
6
|
+
* - OSC sequences (\x1b]...\x07 or \x1b]...\x1b\\)
|
|
7
7
|
* - APC sequences (\x1b_...\x07 or \x1b_...\x1b\\)
|
|
8
|
+
* - Remaining C0 control chars except tab/newline
|
|
8
9
|
*/
|
|
10
|
+
const ESC = String.fromCodePoint(0x001b);
|
|
11
|
+
const BEL = String.fromCodePoint(0x0007);
|
|
12
|
+
|
|
13
|
+
const ANSI_REPLACEMENTS: RegExp[] = [
|
|
14
|
+
// CSI sequences: SGR, cursor movement, erase, scroll, etc.
|
|
15
|
+
new RegExp(`${ESC}\\[[0-9;]*[A-Za-z]`, "gu"),
|
|
16
|
+
// OSC sequences: ESC]...<BEL> or ESC]...<ESC>\\.
|
|
17
|
+
new RegExp(`${ESC}\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)`, "gu"),
|
|
18
|
+
// APC sequences: ESC_...<BEL> or ESC_...<ESC>\\.
|
|
19
|
+
new RegExp(`${ESC}_[^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)`, "gu"),
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
// Strip C0 terminal control characters that can corrupt TUI layout when
|
|
23
|
+
// rendered back into pi, such as carriage return and backspace. Keep tabs and
|
|
24
|
+
// newlines because logs use them as printable whitespace/line breaks.
|
|
25
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: this regex intentionally targets terminal control characters.
|
|
26
|
+
const TERMINAL_CONTROL_CHARS = /[\u0000-\u0008\u000b-\u001f\u007f]/gu;
|
|
27
|
+
|
|
9
28
|
/**
|
|
10
29
|
* Check if a string contains ANSI escape codes.
|
|
11
30
|
*/
|
|
12
31
|
export function hasAnsi(str: string): boolean {
|
|
13
|
-
return str.includes(
|
|
32
|
+
return str.includes(ESC);
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
export function stripAnsi(str: string): string {
|
|
17
|
-
|
|
18
|
-
const ESC = String.fromCodePoint(0x001b);
|
|
19
|
-
const BEL = String.fromCodePoint(0x0007);
|
|
36
|
+
let clean = str;
|
|
20
37
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
38
|
+
if (str.includes(ESC)) {
|
|
39
|
+
for (const pattern of ANSI_REPLACEMENTS) {
|
|
40
|
+
clean = clean.replace(pattern, "");
|
|
41
|
+
}
|
|
23
42
|
}
|
|
24
43
|
|
|
25
|
-
|
|
26
|
-
let clean = str.replace(new RegExp(`${ESC}\\[[0-9;]*[A-Za-z]`, "gu"), "");
|
|
27
|
-
// Strip OSC 8 hyperlinks: ESC]8;;URL<BEL> and ESC]8;;<BEL>
|
|
28
|
-
clean = clean.replace(new RegExp(`${ESC}\\]8;;[^${BEL}]*${BEL}`, "gu"), "");
|
|
29
|
-
// Strip APC sequences: ESC_...<BEL> or ESC_...<ESC>\\ (used for cursor marker)
|
|
30
|
-
clean = clean.replace(
|
|
31
|
-
new RegExp(`${ESC}_[^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)`, "gu"),
|
|
32
|
-
"",
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
return clean;
|
|
44
|
+
return clean.replace(TERMINAL_CONTROL_CHARS, "");
|
|
36
45
|
}
|
package/src/utils/format.ts
CHANGED