@aliou/pi-processes 0.9.4 → 0.10.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.
- package/CONTRIBUTING.md +40 -42
- package/README.md +54 -84
- package/extensions/process-tabs.ts +26 -0
- package/extensions/processes/client.ts +194 -0
- package/extensions/processes/commands/clear.ts +29 -0
- package/extensions/processes/commands/kill.ts +152 -0
- package/extensions/processes/commands/overview.ts +102 -0
- package/extensions/processes/components/overview-component.ts +729 -0
- package/extensions/processes/components/overview-panel.ts +177 -0
- package/extensions/processes/config/defaults.ts +28 -0
- package/extensions/processes/config/index.ts +13 -0
- package/extensions/processes/config/loader.ts +62 -0
- package/extensions/processes/config/migrations/000-import-legacy-process-config.ts +113 -0
- package/extensions/processes/config/migrations/001-v0-9-4-to-v0-10-0-config.ts +184 -0
- package/extensions/processes/config/migrations/002-stamp-v0-10-0-config-version.ts +21 -0
- package/extensions/processes/config/migrations/index.ts +25 -0
- package/extensions/processes/config/schema.ts +9 -0
- package/extensions/processes/config/types.ts +72 -0
- package/extensions/processes/constants.ts +1 -0
- package/extensions/processes/handlers/commands.ts +113 -0
- package/extensions/processes/handlers/kill-process.ts +31 -0
- package/extensions/processes/handlers/notifications.ts +147 -0
- package/extensions/processes/handlers/requests.ts +114 -0
- package/extensions/processes/handlers/subscriptions.ts +144 -0
- package/extensions/processes/hooks/background-blocker.ts +201 -0
- package/extensions/processes/hooks/cleanup.ts +43 -0
- package/extensions/processes/hooks/event-bridge.ts +32 -0
- package/extensions/processes/i18n/index.ts +3 -0
- package/extensions/processes/i18n/messages.ts +27 -0
- package/extensions/processes/i18n/translator.ts +49 -0
- package/extensions/processes/index.ts +109 -0
- package/extensions/processes/message-renderer.ts +117 -0
- package/extensions/processes/notification-sender.ts +43 -0
- package/extensions/processes/notifications/classify.ts +27 -0
- package/extensions/processes/notifications/log-matchers.ts +146 -0
- package/extensions/processes/notifications/registry.ts +225 -0
- package/extensions/processes/notifications/render-content.ts +122 -0
- package/extensions/processes/notifications/service.ts +336 -0
- package/extensions/processes/notifications/types.ts +11 -0
- package/extensions/processes/settings/apply-setting-change.ts +30 -0
- package/extensions/processes/settings/build-sections.ts +420 -0
- package/extensions/processes/settings/index.ts +42 -0
- package/extensions/processes/tools/clear/index.ts +21 -0
- package/extensions/processes/tools/clear/render.ts +40 -0
- package/extensions/processes/tools/components/index.ts +4 -0
- package/extensions/processes/tools/components/process-action-header.ts +31 -0
- package/extensions/processes/tools/components/process-action-title.ts +17 -0
- package/extensions/processes/tools/components/tool-layout.ts +70 -0
- package/extensions/processes/tools/components/watch.ts +53 -0
- package/extensions/processes/tools/index.ts +265 -0
- package/extensions/processes/tools/list/index.ts +157 -0
- package/extensions/processes/tools/list/render.ts +211 -0
- package/extensions/processes/tools/notify.ts +191 -0
- package/extensions/processes/tools/output/index.ts +307 -0
- package/extensions/processes/tools/output/render.ts +229 -0
- package/extensions/processes/tools/schema.ts +263 -0
- package/extensions/processes/tools/start/index.ts +64 -0
- package/extensions/processes/tools/start/render.ts +67 -0
- package/extensions/processes/tools/stop/index.ts +35 -0
- package/extensions/processes/tools/stop/render.ts +43 -0
- package/extensions/processes/tools/update/index.ts +320 -0
- package/extensions/processes/tools/update/render.ts +251 -0
- package/extensions/processes/tools/utils.ts +112 -0
- package/extensions/processes/tools/watch-format.ts +14 -0
- package/extensions/processes/tools/write/index.ts +75 -0
- package/extensions/processes/tools/write/render.ts +68 -0
- package/extensions/processes/utils/truncate.ts +285 -0
- package/extensions/processes-dock/client.ts +60 -0
- package/extensions/processes-dock/commands/dock.ts +70 -0
- package/extensions/processes-dock/commands/pin.ts +166 -0
- package/extensions/processes-dock/components/log-dock-component.ts +375 -0
- package/extensions/processes-dock/dock-state.ts +33 -0
- package/extensions/processes-dock/index.ts +28 -0
- package/extensions/processes-dock/logs-client.ts +5 -0
- package/extensions/processes-dock/widget/setup.ts +520 -0
- package/extensions/processes-dock/widget/status.ts +149 -0
- package/extensions/processes-dock/widget/types.ts +16 -0
- package/extensions/processes-logs/client.ts +51 -0
- package/extensions/processes-logs/commands/logs.ts +108 -0
- package/extensions/processes-logs/completions.ts +31 -0
- package/extensions/processes-logs/components/log-file-viewer.ts +274 -0
- package/extensions/processes-logs/components/log-overlay-component.ts +685 -0
- package/extensions/processes-logs/index.ts +27 -0
- package/extensions/processes-logs/logs-client.ts +101 -0
- package/extensions/shared/line-buffer.ts +35 -0
- package/extensions/shared/output-payload.ts +28 -0
- package/extensions/shared/ui.ts +146 -0
- package/package.json +47 -20
- package/schema.json +134 -0
- package/skills/pi-processes/SKILL.md +496 -25
- package/src/get-manager.ts +15 -0
- package/src/manager/index.ts +182 -0
- package/src/manager/internal-types.ts +130 -0
- package/src/manager/limits.ts +15 -0
- package/src/manager/process-log-store.ts +422 -0
- package/src/manager/process-output.ts +345 -0
- package/src/manager/process-registry.ts +78 -0
- package/src/manager/process-runtime-controller.ts +499 -0
- package/src/protocol/broadcasts.ts +14 -0
- package/src/protocol/channels.ts +30 -0
- package/src/protocol/commands.ts +24 -0
- package/src/protocol/index.ts +34 -0
- package/src/protocol/logs.ts +23 -0
- package/src/protocol/notifications.ts +48 -0
- package/src/protocol/requests.ts +76 -0
- package/src/types.ts +66 -0
- package/src/utils/ansi.ts +2 -4
- package/src/utils/format.ts +24 -32
- package/src/utils/index.ts +5 -1
- package/src/utils/is-record.ts +3 -0
- package/src/utils/match-line.ts +32 -0
- package/src/utils/platform.ts +13 -0
- package/src/utils/shorten-path.ts +11 -0
- package/src/utils/signals.ts +22 -0
- package/src/commands/clear/command.ts +0 -14
- package/src/commands/clear/index.ts +0 -1
- package/src/commands/completions.ts +0 -38
- package/src/commands/dock/command.ts +0 -29
- package/src/commands/dock/index.ts +0 -1
- package/src/commands/index.ts +0 -33
- package/src/commands/kill/command.ts +0 -69
- package/src/commands/kill/index.ts +0 -1
- package/src/commands/logs/command.ts +0 -47
- package/src/commands/logs/index.ts +0 -1
- package/src/commands/pick-process.ts +0 -34
- package/src/commands/pin/command.ts +0 -34
- package/src/commands/pin/index.ts +0 -1
- package/src/commands/processes/command.ts +0 -39
- package/src/commands/processes/index.ts +0 -1
- package/src/commands/settings/apply-setting-change.ts +0 -72
- package/src/commands/settings/build-sections.ts +0 -160
- package/src/commands/settings/command.ts +0 -20
- package/src/commands/settings/index.ts +0 -1
- package/src/components/log-dock-component.test.ts +0 -29
- package/src/components/log-dock-component.ts +0 -236
- package/src/components/log-file-viewer.ts +0 -317
- package/src/components/log-overlay-component.ts +0 -546
- package/src/components/panel-helpers.ts +0 -37
- package/src/components/process-picker-component.ts +0 -166
- package/src/components/processes-component.ts +0 -485
- package/src/components/status-format.ts +0 -38
- package/src/config.ts +0 -107
- package/src/constants/index.ts +0 -16
- package/src/constants/types.ts +0 -106
- package/src/hooks/background-blocker.ts +0 -66
- package/src/hooks/cleanup.ts +0 -10
- package/src/hooks/index.ts +0 -32
- package/src/hooks/message-renderer.ts +0 -115
- package/src/hooks/process-end.ts +0 -69
- package/src/hooks/process-watch.ts +0 -85
- package/src/hooks/utils.ts +0 -23
- package/src/hooks/widget/index.ts +0 -2
- package/src/hooks/widget/setup.ts +0 -167
- package/src/hooks/widget/status-widget.ts +0 -105
- package/src/hooks/widget/types.ts +0 -20
- package/src/index.ts +0 -35
- package/src/manager.test.ts +0 -331
- package/src/manager.ts +0 -758
- package/src/tools/actions/clear.ts +0 -20
- package/src/tools/actions/debug.ts +0 -148
- package/src/tools/actions/index.ts +0 -171
- package/src/tools/actions/kill.ts +0 -89
- package/src/tools/actions/list.ts +0 -188
- package/src/tools/actions/logs.ts +0 -117
- package/src/tools/actions/output.ts +0 -269
- package/src/tools/actions/start.ts +0 -245
- package/src/tools/actions/write.ts +0 -113
- package/src/tools/index.ts +0 -207
- package/src/utils/ansi.test.ts +0 -22
- package/src/utils/command-executor.test.ts +0 -48
- package/src/utils/keybindings.ts +0 -71
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { EventBus } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import {
|
|
3
|
+
CHANNELS,
|
|
4
|
+
type LogsChunkPayload,
|
|
5
|
+
type LogsSubscribePayload,
|
|
6
|
+
type LogsUnsubscribePayload,
|
|
7
|
+
} from "../../src/protocol";
|
|
8
|
+
import { isRecord } from "../../src/utils/is-record";
|
|
9
|
+
|
|
10
|
+
export type ProcessLogLine = { type: "stdout" | "stderr"; text: string };
|
|
11
|
+
|
|
12
|
+
export interface LogsConnection {
|
|
13
|
+
initialLines: ProcessLogLine[];
|
|
14
|
+
onChunk: (callback: (lines: ProcessLogLine[]) => void) => () => void;
|
|
15
|
+
unsubscribe: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function connectToProcessLogs(
|
|
19
|
+
events: EventBus,
|
|
20
|
+
processId: string,
|
|
21
|
+
opts: { tailLines?: number } = {},
|
|
22
|
+
): LogsConnection | { ok: false; error: string } {
|
|
23
|
+
const subscriberId = `processes-logs-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
24
|
+
let initialLines: ProcessLogLine[] = [];
|
|
25
|
+
let error: string | null = null;
|
|
26
|
+
let replied = false;
|
|
27
|
+
let disposed = false;
|
|
28
|
+
const chunkCallbacks = new Set<(lines: ProcessLogLine[]) => void>();
|
|
29
|
+
|
|
30
|
+
const disposeChunkListener = events.on(CHANNELS.LOGS_CHUNK, (raw) => {
|
|
31
|
+
if (disposed) return;
|
|
32
|
+
if (!isLogsChunkPayload(raw)) return;
|
|
33
|
+
const chunk = raw;
|
|
34
|
+
if (chunk.subscriberId !== subscriberId || chunk.processId !== processId)
|
|
35
|
+
return;
|
|
36
|
+
|
|
37
|
+
for (const callback of chunkCallbacks) callback(chunk.lines);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const payload: LogsSubscribePayload = {
|
|
41
|
+
subscriberId,
|
|
42
|
+
processId,
|
|
43
|
+
tailLines: opts.tailLines,
|
|
44
|
+
reply: (result) => {
|
|
45
|
+
replied = true;
|
|
46
|
+
if (result.ok) {
|
|
47
|
+
initialLines = result.initialLines;
|
|
48
|
+
} else {
|
|
49
|
+
error = result.error;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
events.emit(CHANNELS.LOGS_SUBSCRIBE, payload);
|
|
55
|
+
|
|
56
|
+
if (!replied) {
|
|
57
|
+
disposeChunkListener();
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: "processes core extension did not reply to log subscription",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (error) {
|
|
64
|
+
disposeChunkListener();
|
|
65
|
+
return { ok: false, error };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
initialLines,
|
|
70
|
+
onChunk: (callback) => {
|
|
71
|
+
chunkCallbacks.add(callback);
|
|
72
|
+
return () => chunkCallbacks.delete(callback);
|
|
73
|
+
},
|
|
74
|
+
unsubscribe: () => {
|
|
75
|
+
if (disposed) return;
|
|
76
|
+
disposed = true;
|
|
77
|
+
chunkCallbacks.clear();
|
|
78
|
+
disposeChunkListener();
|
|
79
|
+
const unsubscribePayload: LogsUnsubscribePayload = { subscriberId };
|
|
80
|
+
events.emit(CHANNELS.LOGS_UNSUBSCRIBE, unsubscribePayload);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isLogsChunkPayload(payload: unknown): payload is LogsChunkPayload {
|
|
86
|
+
return (
|
|
87
|
+
isRecord(payload) &&
|
|
88
|
+
typeof payload.subscriberId === "string" &&
|
|
89
|
+
typeof payload.processId === "string" &&
|
|
90
|
+
Array.isArray(payload.lines) &&
|
|
91
|
+
payload.lines.every(isProcessLogLine)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isProcessLogLine(line: unknown): line is ProcessLogLine {
|
|
96
|
+
return (
|
|
97
|
+
isRecord(line) &&
|
|
98
|
+
(line.type === "stdout" || line.type === "stderr") &&
|
|
99
|
+
typeof line.text === "string"
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const OUTPUT_DROPPED_MARKER_TYPE = "stderr" as const;
|
|
2
|
+
|
|
3
|
+
export function buildDroppedOutputLine(count: number): {
|
|
4
|
+
type: typeof OUTPUT_DROPPED_MARKER_TYPE;
|
|
5
|
+
text: string;
|
|
6
|
+
} {
|
|
7
|
+
return {
|
|
8
|
+
type: OUTPUT_DROPPED_MARKER_TYPE,
|
|
9
|
+
text: `… ${count} lines dropped (output too fast)`,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function trimToBudget<T>(
|
|
14
|
+
lines: T[],
|
|
15
|
+
maxLines: number,
|
|
16
|
+
maxBytes: number,
|
|
17
|
+
textOf: (line: T) => string = (line) => (line as { text: string }).text,
|
|
18
|
+
): T[] {
|
|
19
|
+
if (lines.length === 0) return [];
|
|
20
|
+
|
|
21
|
+
const lineLimit = Math.max(1, maxLines);
|
|
22
|
+
const out =
|
|
23
|
+
lines.length > lineLimit ? lines.slice(-lineLimit) : lines.slice();
|
|
24
|
+
let bytes = 0;
|
|
25
|
+
|
|
26
|
+
for (let index = out.length - 1; index >= 0; index--) {
|
|
27
|
+
bytes += Buffer.byteLength(textOf(out[index]), "utf-8");
|
|
28
|
+
if (bytes > maxBytes) {
|
|
29
|
+
// Keep the newest line even when it alone exceeds the whole budget.
|
|
30
|
+
return index === out.length - 1 ? out.slice(index) : out.slice(index + 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ProcessesOutputChangedPayload } from "../../src/protocol";
|
|
2
|
+
import { isRecord } from "../../src/utils/is-record";
|
|
3
|
+
|
|
4
|
+
export function isOutputChangedPayload(
|
|
5
|
+
payload: unknown,
|
|
6
|
+
): payload is ProcessesOutputChangedPayload {
|
|
7
|
+
return (
|
|
8
|
+
isRecord(payload) &&
|
|
9
|
+
typeof payload.id === "string" &&
|
|
10
|
+
(payload.appendedText === undefined ||
|
|
11
|
+
(Array.isArray(payload.appendedText) &&
|
|
12
|
+
payload.appendedText.every(isOutputLine))) &&
|
|
13
|
+
(payload.droppedLines === undefined ||
|
|
14
|
+
(typeof payload.droppedLines === "number" &&
|
|
15
|
+
Number.isSafeInteger(payload.droppedLines) &&
|
|
16
|
+
payload.droppedLines > 0))
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isOutputLine(
|
|
21
|
+
value: unknown,
|
|
22
|
+
): value is { type: "stdout" | "stderr"; text: string } {
|
|
23
|
+
return (
|
|
24
|
+
isRecord(value) &&
|
|
25
|
+
(value.type === "stdout" || value.type === "stderr") &&
|
|
26
|
+
typeof value.text === "string"
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared extension-UI primitives used across the processes, processes-logs,
|
|
3
|
+
* and processes-dock extensions.
|
|
4
|
+
*
|
|
5
|
+
* This module lives outside pi-agnostic `src/` because it depends on the Pi
|
|
6
|
+
* TUI (`Component`, `Theme`). It consolidates the tiny render-component
|
|
7
|
+
* copies and the status-display helpers that were duplicated across the three
|
|
8
|
+
* extensions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { type Component, visibleWidth } from "@earendil-works/pi-tui";
|
|
13
|
+
|
|
14
|
+
import { LIVE_STATUSES, type ProcessInfo } from "../../src/types";
|
|
15
|
+
import { formatStatus } from "../../src/utils/format";
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Render components
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/** Render a single line produced by a width-aware callback. */
|
|
22
|
+
export class LineComponent implements Component {
|
|
23
|
+
constructor(private readonly renderLine: (width: number) => string) {}
|
|
24
|
+
|
|
25
|
+
render(width: number): string[] {
|
|
26
|
+
return [this.renderLine(width)];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
invalidate(): void {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Render multiple lines produced by a width-aware callback. */
|
|
33
|
+
export class LinesComponent implements Component {
|
|
34
|
+
constructor(private readonly renderLines: (width: number) => string[]) {}
|
|
35
|
+
|
|
36
|
+
render(width: number): string[] {
|
|
37
|
+
return this.renderLines(width);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
invalidate(): void {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Render a horizontal rule line sized to the available width. */
|
|
44
|
+
export class RuleComponent implements Component {
|
|
45
|
+
constructor(private readonly theme: Theme) {}
|
|
46
|
+
|
|
47
|
+
render(width: number): string[] {
|
|
48
|
+
return [this.theme.fg("dim", "─".repeat(Math.max(0, width)))];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
invalidate(): void {}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Name column / tab width
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
/** Maximum visible width for a process name or tab label. */
|
|
59
|
+
export const MAX_TAB_NAME = 12;
|
|
60
|
+
|
|
61
|
+
/** Minimum width for the dock log-line sidebar column. */
|
|
62
|
+
export const MIN_NAME_COLUMN = 4;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Compute the sidebar width for a set of processes: the longest name
|
|
66
|
+
* clamped to [min, max]. Use this instead of hardcoding a fixed width so
|
|
67
|
+
* short names (`api`, `web`) don't get padded to 12 columns.
|
|
68
|
+
*/
|
|
69
|
+
export function clampNameColumn(
|
|
70
|
+
processes: ProcessInfo[],
|
|
71
|
+
max: number = MAX_TAB_NAME,
|
|
72
|
+
min: number = MIN_NAME_COLUMN,
|
|
73
|
+
): number {
|
|
74
|
+
const longest = processes.reduce(
|
|
75
|
+
(acc, p) => Math.max(acc, visibleWidth(p.name)),
|
|
76
|
+
0,
|
|
77
|
+
);
|
|
78
|
+
return Math.min(Math.max(longest, min), max);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Status formatting
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The color a process's status should render in. Shared by the status dot
|
|
87
|
+
* and process name so the dot and the name always agree on color.
|
|
88
|
+
*/
|
|
89
|
+
export function statusColor(process: ProcessInfo): ThemeColor {
|
|
90
|
+
if (process.success === false && process.status !== "killed") {
|
|
91
|
+
return "error";
|
|
92
|
+
}
|
|
93
|
+
if (process.status === "terminating") {
|
|
94
|
+
return "warning";
|
|
95
|
+
}
|
|
96
|
+
if (LIVE_STATUSES.has(process.status)) {
|
|
97
|
+
return "accent";
|
|
98
|
+
}
|
|
99
|
+
if (process.status === "exited" && process.success) {
|
|
100
|
+
return "success";
|
|
101
|
+
}
|
|
102
|
+
return "dim";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Render the status indicator dot for a process.
|
|
107
|
+
*
|
|
108
|
+
* Glyph carries state class; color refines:
|
|
109
|
+
* - `!` (error) for failures/crashes, unless intentionally killed.
|
|
110
|
+
* - `●` (warning) for terminating.
|
|
111
|
+
* - `●`/`○` (accent/dim) for live processes, depending on `active`.
|
|
112
|
+
* - `✓` (success) for a clean exit.
|
|
113
|
+
* - `■` (dim) for other terminal states (e.g. killed).
|
|
114
|
+
*/
|
|
115
|
+
export function statusDot(
|
|
116
|
+
process: ProcessInfo,
|
|
117
|
+
active: boolean,
|
|
118
|
+
theme: Theme,
|
|
119
|
+
): string {
|
|
120
|
+
if (process.success === false && process.status !== "killed") {
|
|
121
|
+
return theme.fg("error", "!");
|
|
122
|
+
}
|
|
123
|
+
if (process.status === "terminating") {
|
|
124
|
+
return theme.fg("warning", "●");
|
|
125
|
+
}
|
|
126
|
+
if (LIVE_STATUSES.has(process.status)) {
|
|
127
|
+
return active ? theme.fg("accent", "●") : theme.fg("dim", "○");
|
|
128
|
+
}
|
|
129
|
+
if (process.status === "exited" && process.success) {
|
|
130
|
+
return theme.fg("success", "✓");
|
|
131
|
+
}
|
|
132
|
+
return theme.fg("dim", "■");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Build the `description` string for process picker items and autocomplete
|
|
137
|
+
* completions: `"running — pnpm dev"`. Shared so `/ps:kill`, `/ps:logs`,
|
|
138
|
+
* `/ps:pin`, and the logs completions stay consistent.
|
|
139
|
+
*/
|
|
140
|
+
export function formatProcessSelectionDescription(
|
|
141
|
+
process: ProcessInfo,
|
|
142
|
+
suffix = "",
|
|
143
|
+
): string {
|
|
144
|
+
const base = `${formatStatus(process)} — ${process.command}`;
|
|
145
|
+
return suffix ? `${base}${suffix}` : base;
|
|
146
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/pi-processes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -16,25 +16,34 @@
|
|
|
16
16
|
},
|
|
17
17
|
"pi": {
|
|
18
18
|
"extensions": [
|
|
19
|
-
"./
|
|
19
|
+
"./extensions/processes/index.ts",
|
|
20
|
+
"./extensions/processes-logs/index.ts",
|
|
21
|
+
"./extensions/processes-dock/index.ts"
|
|
20
22
|
],
|
|
21
23
|
"skills": [
|
|
22
24
|
"./skills/pi-processes"
|
|
23
25
|
],
|
|
24
|
-
"video": "https://assets.aliou.me/
|
|
26
|
+
"video": "https://assets.aliou.me/pi-extensions/demos/pi-processes.mp4"
|
|
25
27
|
},
|
|
26
28
|
"publishConfig": {
|
|
27
29
|
"access": "public"
|
|
28
30
|
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=22.19.0"
|
|
33
|
+
},
|
|
29
34
|
"files": [
|
|
30
35
|
"src",
|
|
36
|
+
"!src/**/*.test.ts",
|
|
37
|
+
"extensions",
|
|
38
|
+
"!extensions/**/*.test.ts",
|
|
31
39
|
"skills",
|
|
40
|
+
"schema.json",
|
|
32
41
|
"README.md",
|
|
33
42
|
"CONTRIBUTING.md"
|
|
34
43
|
],
|
|
35
44
|
"dependencies": {
|
|
36
|
-
"@aliou/pi-utils-settings": "^0.
|
|
37
|
-
"@aliou/pi-utils-ui": "^0.
|
|
45
|
+
"@aliou/pi-utils-settings": "^0.18.0",
|
|
46
|
+
"@aliou/pi-utils-ui": "^0.5.0",
|
|
38
47
|
"@aliou/sh": "^0.1.0"
|
|
39
48
|
},
|
|
40
49
|
"peerDependencies": {
|
|
@@ -46,12 +55,40 @@
|
|
|
46
55
|
"devDependencies": {
|
|
47
56
|
"@aliou/biome-plugins": "^0.8.1",
|
|
48
57
|
"@biomejs/biome": "^2.4.15",
|
|
49
|
-
"@changesets/cli": "^2.
|
|
50
|
-
"@
|
|
58
|
+
"@changesets/cli": "^2.27.11",
|
|
59
|
+
"@earendil-works/pi-ai": "0.80.3",
|
|
60
|
+
"@earendil-works/pi-coding-agent": "0.80.3",
|
|
61
|
+
"@earendil-works/pi-tui": "0.80.3",
|
|
62
|
+
"@golevelup/ts-vitest": "^4.0.0",
|
|
63
|
+
"@types/node": "^25.0.10",
|
|
51
64
|
"husky": "^9.1.7",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
65
|
+
"memfs": "^4.57.2",
|
|
66
|
+
"ts-json-schema-generator": "^2.9.0",
|
|
67
|
+
"typebox": "1.1.38",
|
|
68
|
+
"typescript": "^5.9.3",
|
|
69
|
+
"vitest": "^4.1.5"
|
|
70
|
+
},
|
|
71
|
+
"pnpm": {
|
|
72
|
+
"overrides": {
|
|
73
|
+
"@earendil-works/pi-ai": "$@earendil-works/pi-coding-agent",
|
|
74
|
+
"@earendil-works/pi-tui": "$@earendil-works/pi-coding-agent"
|
|
75
|
+
}
|
|
54
76
|
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"typecheck": "tsc --noEmit",
|
|
79
|
+
"lint": "biome check",
|
|
80
|
+
"format": "biome check --write",
|
|
81
|
+
"gen:schema": "ts-json-schema-generator --path extensions/processes/config/types.ts --type ProcessConfig --no-type-check -o schema.json",
|
|
82
|
+
"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",
|
|
83
|
+
"check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
|
|
84
|
+
"prepare": "[ -d .git ] && husky || true",
|
|
85
|
+
"changeset": "changeset",
|
|
86
|
+
"version": "changeset version",
|
|
87
|
+
"test": "vitest run",
|
|
88
|
+
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
89
|
+
"release": "pnpm changeset publish"
|
|
90
|
+
},
|
|
91
|
+
"packageManager": "pnpm@10.26.1",
|
|
55
92
|
"peerDependenciesMeta": {
|
|
56
93
|
"@earendil-works/pi-ai": {
|
|
57
94
|
"optional": true
|
|
@@ -65,15 +102,5 @@
|
|
|
65
102
|
"typebox": {
|
|
66
103
|
"optional": true
|
|
67
104
|
}
|
|
68
|
-
},
|
|
69
|
-
"scripts": {
|
|
70
|
-
"typecheck": "tsc --noEmit",
|
|
71
|
-
"lint": "biome check",
|
|
72
|
-
"format": "biome check --write",
|
|
73
|
-
"check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
|
|
74
|
-
"changeset": "changeset",
|
|
75
|
-
"version": "changeset version",
|
|
76
|
-
"test": "vitest run",
|
|
77
|
-
"release": "pnpm changeset publish"
|
|
78
105
|
}
|
|
79
|
-
}
|
|
106
|
+
}
|
package/schema.json
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$ref": "#/definitions/ProcessConfig",
|
|
3
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
+
"definitions": {
|
|
5
|
+
"ExecutionConfig": {
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"shellPath": {
|
|
9
|
+
"description": "Absolute shell executable used to run process commands.",
|
|
10
|
+
"type": "string"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"type": "object"
|
|
14
|
+
},
|
|
15
|
+
"FollowConfig": {
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"autoHideOnFinish": {
|
|
19
|
+
"description": "Hide process log interfaces when all managed processes finish.",
|
|
20
|
+
"type": "boolean"
|
|
21
|
+
},
|
|
22
|
+
"enabledByDefault": {
|
|
23
|
+
"description": "Open process log interfaces in follow mode by default.",
|
|
24
|
+
"type": "boolean"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"type": "object"
|
|
28
|
+
},
|
|
29
|
+
"InterceptionConfig": {
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"blockBackgroundCommands": {
|
|
33
|
+
"description": "Block shell background patterns and redirect the agent to the process tool.",
|
|
34
|
+
"type": "boolean"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"type": "object"
|
|
38
|
+
},
|
|
39
|
+
"OutputConfig": {
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"properties": {
|
|
42
|
+
"defaultTailLines": {
|
|
43
|
+
"description": "Default number of recent lines returned by the process output action.",
|
|
44
|
+
"type": "number"
|
|
45
|
+
},
|
|
46
|
+
"maxOutputBytes": {
|
|
47
|
+
"description": "Maximum bytes retained by each process log interface.",
|
|
48
|
+
"type": "number"
|
|
49
|
+
},
|
|
50
|
+
"maxOutputLines": {
|
|
51
|
+
"description": "Maximum lines retained by process log interfaces.",
|
|
52
|
+
"type": "number"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"type": "object"
|
|
56
|
+
},
|
|
57
|
+
"ProcessConfig": {
|
|
58
|
+
"additionalProperties": false,
|
|
59
|
+
"description": "User-facing pi-processes settings stored on disk.",
|
|
60
|
+
"properties": {
|
|
61
|
+
"$schema": {
|
|
62
|
+
"description": "JSON Schema URL used by editors for validation and autocomplete.",
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"execution": {
|
|
66
|
+
"$ref": "#/definitions/ExecutionConfig",
|
|
67
|
+
"description": "Process execution settings."
|
|
68
|
+
},
|
|
69
|
+
"follow": {
|
|
70
|
+
"$ref": "#/definitions/FollowConfig",
|
|
71
|
+
"description": "Live log follow behavior."
|
|
72
|
+
},
|
|
73
|
+
"interception": {
|
|
74
|
+
"$ref": "#/definitions/InterceptionConfig",
|
|
75
|
+
"description": "Shell-command interception settings."
|
|
76
|
+
},
|
|
77
|
+
"output": {
|
|
78
|
+
"$ref": "#/definitions/OutputConfig",
|
|
79
|
+
"description": "Process output retention settings."
|
|
80
|
+
},
|
|
81
|
+
"processList": {
|
|
82
|
+
"$ref": "#/definitions/ProcessListConfig",
|
|
83
|
+
"description": "Process overview and log viewport settings."
|
|
84
|
+
},
|
|
85
|
+
"version": {
|
|
86
|
+
"description": "Config migration marker written after v0.10.0 settings migration.",
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"widget": {
|
|
90
|
+
"$ref": "#/definitions/WidgetConfig",
|
|
91
|
+
"description": "Dock and status widget settings."
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"type": "object"
|
|
95
|
+
},
|
|
96
|
+
"ProcessListConfig": {
|
|
97
|
+
"additionalProperties": false,
|
|
98
|
+
"properties": {
|
|
99
|
+
"maxPreviewLines": {
|
|
100
|
+
"description": "Maximum log rows displayed in the overview preview and logs overlay.",
|
|
101
|
+
"type": "number"
|
|
102
|
+
},
|
|
103
|
+
"maxVisibleProcesses": {
|
|
104
|
+
"description": "Maximum process rows displayed in the overview before scrolling.",
|
|
105
|
+
"type": "number"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"type": "object"
|
|
109
|
+
},
|
|
110
|
+
"WidgetConfig": {
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"properties": {
|
|
113
|
+
"dockDefaultState": {
|
|
114
|
+
"description": "Initial visibility of the process dock.",
|
|
115
|
+
"enum": [
|
|
116
|
+
"closed",
|
|
117
|
+
"collapsed",
|
|
118
|
+
"expanded"
|
|
119
|
+
],
|
|
120
|
+
"type": "string"
|
|
121
|
+
},
|
|
122
|
+
"dockHeight": {
|
|
123
|
+
"description": "Number of log rows displayed in the expanded process dock.",
|
|
124
|
+
"type": "number"
|
|
125
|
+
},
|
|
126
|
+
"showStatusWidget": {
|
|
127
|
+
"description": "Show a one-line process summary below the editor.",
|
|
128
|
+
"type": "boolean"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"type": "object"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|