@aliou/pi-processes 0.10.4 → 0.10.5
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/extensions/processes/message-renderer.ts +109 -14
- package/extensions/processes/tools/components/index.ts +5 -1
- package/extensions/processes/tools/components/watch.ts +12 -1
- package/extensions/processes/tools/output/render.ts +17 -3
- package/extensions/processes-dock/components/log-dock-component.ts +1 -1
- package/extensions/processes-logs/components/log-overlay-component.ts +1 -1
- package/extensions/{process-tabs.ts → shared/process-tabs.ts} +3 -3
- package/package.json +11 -6
|
@@ -2,11 +2,17 @@ import type {
|
|
|
2
2
|
ExtensionAPI,
|
|
3
3
|
MessageRenderOptions,
|
|
4
4
|
Theme,
|
|
5
|
+
ThemeColor,
|
|
5
6
|
} from "@earendil-works/pi-coding-agent";
|
|
6
7
|
import { type Component, Container, Text } from "@earendil-works/pi-tui";
|
|
7
8
|
import { truncateForDisplay } from "../shared/display-text";
|
|
8
9
|
import { MESSAGE_TYPE_PROCESS_NOTIFICATION } from "./constants";
|
|
9
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
Attention,
|
|
12
|
+
ProcessNotificationDetails,
|
|
13
|
+
ProcessNotificationKind,
|
|
14
|
+
} from "./notifications/types";
|
|
15
|
+
import { formatPatternForDisplay, quoteFilter } from "./tools/components";
|
|
10
16
|
|
|
11
17
|
export function registerProcessNotificationRenderer(pi: ExtensionAPI): void {
|
|
12
18
|
pi.registerMessageRenderer<ProcessNotificationDetails>(
|
|
@@ -25,11 +31,17 @@ export function renderProcessNotificationMessage(
|
|
|
25
31
|
return undefined;
|
|
26
32
|
}
|
|
27
33
|
|
|
34
|
+
// outputPad is only populated on Pi 0.82.1+ (see MessageRenderOptions);
|
|
35
|
+
// fall back to 0 so this renderer doesn't break on older Pi builds.
|
|
36
|
+
const outputPad = options.outputPad ?? 0;
|
|
37
|
+
|
|
28
38
|
const container = new Container();
|
|
29
|
-
container.addChild(new Text(formatSummary(details, theme),
|
|
39
|
+
container.addChild(new Text(formatSummary(details, theme), outputPad, 0));
|
|
30
40
|
|
|
31
41
|
if (options.expanded) {
|
|
32
|
-
container.addChild(
|
|
42
|
+
container.addChild(
|
|
43
|
+
new Text(formatDetailLine(details, theme), outputPad, 0),
|
|
44
|
+
);
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
return container;
|
|
@@ -66,17 +78,100 @@ function formatDetailLine(
|
|
|
66
78
|
details: ProcessNotificationDetails,
|
|
67
79
|
theme: Theme,
|
|
68
80
|
): string {
|
|
69
|
-
const parts = [
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
const parts: string[] = [
|
|
82
|
+
field("id", details.processId, theme),
|
|
83
|
+
field("notify", formatAttention(details.attention, theme), theme),
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
if (details.logMatch) {
|
|
87
|
+
const pattern = quoteFilter(
|
|
88
|
+
formatPatternForDisplay(details.logMatch.pattern),
|
|
89
|
+
details.logMatch.mode,
|
|
90
|
+
);
|
|
91
|
+
parts.push(
|
|
92
|
+
field("pattern", theme.fg("accent", pattern), theme),
|
|
93
|
+
field("stream", theme.fg("muted", `[${details.logMatch.stream}]`), theme),
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
if (details.status) {
|
|
97
|
+
parts.push(
|
|
98
|
+
field(
|
|
99
|
+
"status",
|
|
100
|
+
theme.fg(statusTone(details.kind), details.status),
|
|
101
|
+
theme,
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (details.exitCode !== undefined && details.exitCode !== null) {
|
|
107
|
+
parts.push(
|
|
108
|
+
field(
|
|
109
|
+
"exit",
|
|
110
|
+
theme.fg(statusTone(details.kind), String(details.exitCode)),
|
|
111
|
+
theme,
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (details.endReason) {
|
|
117
|
+
parts.push(field("reason", theme.fg("muted", details.endReason), theme));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (details.signal) {
|
|
121
|
+
const number =
|
|
122
|
+
details.signal.number === null
|
|
123
|
+
? ""
|
|
124
|
+
: ` (${details.signal.number}, ${details.signal.description})`;
|
|
125
|
+
parts.push(
|
|
126
|
+
field(
|
|
127
|
+
"signal",
|
|
128
|
+
theme.fg("muted", `${details.signal.name}${number}`),
|
|
129
|
+
theme,
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return parts.join(" ");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** `label:` in muted, matching `buildField` in tools/utils.ts. */
|
|
139
|
+
function field(label: string, value: string, theme: Theme): string {
|
|
140
|
+
return `${theme.fg("muted", `${label}:`)} ${value}`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Plain-language attention level, reusing the tone mapping from
|
|
145
|
+
* `attentionTone` in tools/components/watch.ts (turn/context keep their
|
|
146
|
+
* color; ignore switches from muted to dim to read as "quieter").
|
|
147
|
+
*/
|
|
148
|
+
function formatAttention(attention: Attention, theme: Theme): string {
|
|
149
|
+
switch (attention) {
|
|
150
|
+
case "turn":
|
|
151
|
+
return theme.bold(theme.fg("warning", "now"));
|
|
152
|
+
case "context":
|
|
153
|
+
return theme.bold(theme.fg("success", "next turn"));
|
|
154
|
+
default:
|
|
155
|
+
return theme.bold(theme.fg("dim", "silent"));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Same tone family as `statusColor` in shared/ui.ts: success for a clean
|
|
161
|
+
* exit, error for failure/crash, dim for killed.
|
|
162
|
+
*/
|
|
163
|
+
function statusTone(kind: ProcessNotificationKind): ThemeColor {
|
|
164
|
+
switch (kind) {
|
|
165
|
+
case "success":
|
|
166
|
+
return "success";
|
|
167
|
+
case "failure":
|
|
168
|
+
case "crash":
|
|
169
|
+
return "error";
|
|
170
|
+
case "killed":
|
|
171
|
+
return "dim";
|
|
172
|
+
default:
|
|
173
|
+
return "muted";
|
|
174
|
+
}
|
|
80
175
|
}
|
|
81
176
|
|
|
82
177
|
function summaryVerb(details: ProcessNotificationDetails): string {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { ProcessActionHeader } from "./process-action-header";
|
|
2
2
|
export { ProcessActionTitle } from "./process-action-title";
|
|
3
3
|
export { ToolLayout } from "./tool-layout";
|
|
4
|
-
export {
|
|
4
|
+
export {
|
|
5
|
+
buildMatcherLine,
|
|
6
|
+
formatPatternForDisplay,
|
|
7
|
+
quoteFilter,
|
|
8
|
+
} from "./watch";
|
|
@@ -15,6 +15,8 @@ export function buildMatcherLine(
|
|
|
15
15
|
const attentionTone =
|
|
16
16
|
on === "turn" ? "warning" : on === "context" ? "success" : "muted";
|
|
17
17
|
|
|
18
|
+
const pattern = quoteFilter(formatPatternForDisplay(matcher.pattern), mode);
|
|
19
|
+
|
|
18
20
|
return new Text(
|
|
19
21
|
[
|
|
20
22
|
prefix,
|
|
@@ -22,13 +24,22 @@ export function buildMatcherLine(
|
|
|
22
24
|
" ",
|
|
23
25
|
theme.bold(theme.fg(attentionTone, `${on}${repeat}`)),
|
|
24
26
|
" ",
|
|
25
|
-
theme.fg("accent",
|
|
27
|
+
theme.fg("accent", pattern),
|
|
26
28
|
].join(""),
|
|
27
29
|
0,
|
|
28
30
|
0,
|
|
29
31
|
);
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
export function quoteFilter(
|
|
35
|
+
pattern: string,
|
|
36
|
+
mode: "literal" | "regex",
|
|
37
|
+
): string {
|
|
38
|
+
if (mode === "regex") return `/${pattern}/`;
|
|
39
|
+
if (pattern.includes('"')) return `'${pattern}'`;
|
|
40
|
+
return `"${pattern}"`;
|
|
41
|
+
}
|
|
42
|
+
|
|
32
43
|
export function formatPatternForDisplay(pattern: string): string {
|
|
33
44
|
let formatted = "";
|
|
34
45
|
|
|
@@ -2,7 +2,8 @@ import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
3
|
|
|
4
4
|
import { sanitizeForDisplay } from "../../../shared/display-text";
|
|
5
|
-
import {
|
|
5
|
+
import { truncateToWidth } from "../../../shared/truncate";
|
|
6
|
+
import { ProcessActionHeader, quoteFilter } from "../components";
|
|
6
7
|
import type { ProcessesParamsType } from "../schema";
|
|
7
8
|
import { buildField } from "../utils";
|
|
8
9
|
import type { OutputDetails } from ".";
|
|
@@ -73,9 +74,23 @@ export function buildCollapsed(
|
|
|
73
74
|
),
|
|
74
75
|
);
|
|
75
76
|
|
|
77
|
+
if (details.pattern) {
|
|
78
|
+
const quoted = quoteFilter(details.pattern, details.mode);
|
|
79
|
+
const value = truncateToWidth(sanitizeForDisplay(quoted), 80);
|
|
80
|
+
container.addChild(
|
|
81
|
+
new Text(
|
|
82
|
+
`${theme.fg("muted", "filter:")} ${theme.fg("accent", value)}`,
|
|
83
|
+
0,
|
|
84
|
+
0,
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
76
89
|
const bodyLines = extractOutputBody(contentText, details);
|
|
77
90
|
const preview = bodyLines.slice(-2).map(sanitizeForDisplay).join("\n");
|
|
78
91
|
|
|
92
|
+
container.addChild(new Spacer(1));
|
|
93
|
+
|
|
79
94
|
if (preview) {
|
|
80
95
|
container.addChild(new Text(theme.fg("muted", preview), 0, 0));
|
|
81
96
|
} else {
|
|
@@ -119,9 +134,8 @@ function buildOutputMeta(details: OutputDetails, theme: Theme): Container {
|
|
|
119
134
|
container.addChild(buildField("stream", details.stream, theme));
|
|
120
135
|
|
|
121
136
|
if (details.pattern) {
|
|
122
|
-
const modeTag = details.mode === "regex" ? " (regex)" : "";
|
|
123
137
|
container.addChild(
|
|
124
|
-
buildField("filter",
|
|
138
|
+
buildField("filter", quoteFilter(details.pattern, details.mode), theme),
|
|
125
139
|
);
|
|
126
140
|
}
|
|
127
141
|
|
|
@@ -3,9 +3,9 @@ import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import { type Component, visibleWidth } from "@earendil-works/pi-tui";
|
|
4
4
|
import type { ProcessInfo } from "../../../src/types";
|
|
5
5
|
import { LIVE_STATUSES } from "../../../src/types";
|
|
6
|
-
import { renderProcessTab } from "../../process-tabs";
|
|
7
6
|
import { sanitizeForDisplay } from "../../shared/display-text";
|
|
8
7
|
import { displayTextOf, renderLogLine } from "../../shared/log-line";
|
|
8
|
+
import { renderProcessTab } from "../../shared/process-tabs";
|
|
9
9
|
import { truncateToWidth } from "../../shared/truncate";
|
|
10
10
|
import {
|
|
11
11
|
clampNameColumn,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
import { LIVE_STATUSES, type ProcessInfo } from "../../../src/types";
|
|
18
18
|
import { formatRuntime } from "../../../src/utils/format";
|
|
19
19
|
import { isRecord } from "../../../src/utils/is-record";
|
|
20
|
-
import { renderProcessTab } from "../../process-tabs";
|
|
21
20
|
import { truncateForDisplay } from "../../shared/display-text";
|
|
21
|
+
import { renderProcessTab } from "../../shared/process-tabs";
|
|
22
22
|
import { truncateToWidth } from "../../shared/truncate";
|
|
23
23
|
import { LineComponent, LinesComponent, RuleComponent } from "../../shared/ui";
|
|
24
24
|
import { requestProcessList } from "../client";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
|
-
import type { ProcessInfo } from "
|
|
4
|
-
import { truncateForDisplay } from "./
|
|
5
|
-
import { MAX_TAB_NAME, statusDot } from "./
|
|
3
|
+
import type { ProcessInfo } from "../../src/types";
|
|
4
|
+
import { truncateForDisplay } from "./display-text";
|
|
5
|
+
import { MAX_TAB_NAME, statusDot } from "./ui";
|
|
6
6
|
|
|
7
7
|
export { MAX_TAB_NAME, statusDot as renderProcessTabDot };
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/pi-processes",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"skills": [
|
|
24
24
|
"./skills/pi-processes"
|
|
25
25
|
],
|
|
26
|
-
"
|
|
26
|
+
"image": "https://assets.aliou.me/github/aliou/pi-processes/banner-v0.10.x.png",
|
|
27
|
+
"video": "https://assets.aliou.me/pi-extensions/demos/processes/v0.10.0/agent-starts-processes.mp4"
|
|
27
28
|
},
|
|
28
29
|
"publishConfig": {
|
|
29
30
|
"access": "public"
|
|
@@ -56,9 +57,9 @@
|
|
|
56
57
|
"@aliou/biome-plugins": "^0.8.1",
|
|
57
58
|
"@biomejs/biome": "^2.4.15",
|
|
58
59
|
"@changesets/cli": "^2.27.11",
|
|
59
|
-
"@earendil-works/pi-ai": "0.
|
|
60
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
61
|
-
"@earendil-works/pi-tui": "0.
|
|
60
|
+
"@earendil-works/pi-ai": "0.84.1",
|
|
61
|
+
"@earendil-works/pi-coding-agent": "0.84.1",
|
|
62
|
+
"@earendil-works/pi-tui": "0.84.1",
|
|
62
63
|
"@golevelup/ts-vitest": "^4.0.0",
|
|
63
64
|
"@types/node": "^25.0.10",
|
|
64
65
|
"husky": "^9.1.7",
|
|
@@ -66,20 +67,24 @@
|
|
|
66
67
|
"ts-json-schema-generator": "^2.9.0",
|
|
67
68
|
"typebox": "1.1.38",
|
|
68
69
|
"typescript": "^5.9.3",
|
|
69
|
-
"vitest": "^4.1.5"
|
|
70
|
+
"vitest": "^4.1.5",
|
|
71
|
+
"vitest-evals": "0.15.0"
|
|
70
72
|
},
|
|
71
73
|
"scripts": {
|
|
72
74
|
"typecheck": "tsc --noEmit",
|
|
75
|
+
"typecheck:evals": "tsc --noEmit -p tests/evals/tsconfig.json",
|
|
73
76
|
"lint": "biome check",
|
|
74
77
|
"format": "biome check --write",
|
|
75
78
|
"gen:schema": "ts-json-schema-generator --path extensions/processes/config/types.ts --type ProcessConfig --no-type-check -o schema.json",
|
|
76
79
|
"check:schema": "ts-json-schema-generator --path extensions/processes/config/types.ts --type ProcessConfig --no-type-check -o /tmp/pi-processes-schema-check.json && diff -q schema.json /tmp/pi-processes-schema-check.json",
|
|
80
|
+
"check:changesets": "node scripts/check-changesets.ts",
|
|
77
81
|
"check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
|
|
78
82
|
"prepare": "[ -d .git ] && husky || true",
|
|
79
83
|
"changeset": "changeset",
|
|
80
84
|
"version": "changeset version",
|
|
81
85
|
"test": "vitest run",
|
|
82
86
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
87
|
+
"test:evals": "vitest run --config tests/evals/vitest.config.ts",
|
|
83
88
|
"release": "pnpm changeset publish"
|
|
84
89
|
},
|
|
85
90
|
"packageManager": "pnpm@11.5.1",
|