@aliou/pi-processes 0.9.5 → 0.10.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/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 +29 -10
- 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 +519 -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/process-group.ts +4 -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 -119
- 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 -155
- 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-truncate.ts +0 -187
- package/src/tools/actions/output.test.ts +0 -392
- package/src/tools/actions/output.ts +0 -447
- 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,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type EventBus,
|
|
3
|
+
type ExtensionAPI,
|
|
4
|
+
type ExtensionCommandContext,
|
|
5
|
+
getSelectListTheme,
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import {
|
|
8
|
+
type AutocompleteItem,
|
|
9
|
+
type SelectItem,
|
|
10
|
+
SelectList,
|
|
11
|
+
} from "@earendil-works/pi-tui";
|
|
12
|
+
import { LIVE_STATUSES } from "../../../src/types";
|
|
13
|
+
import { formatProcessSelectionDescription } from "../../shared/ui";
|
|
14
|
+
import { requestKill, requestProcess, requestProcessList } from "../client";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register `/ps:kill`.
|
|
18
|
+
*
|
|
19
|
+
* Stops a running managed process via the kill protocol channel. With no
|
|
20
|
+
* argument it picks a target from the live processes (or kills the sole
|
|
21
|
+
* running one outright); with an explicit id it stops that one. The dock
|
|
22
|
+
* auto-unpins a killed focused process on the next processes-changed tick, so
|
|
23
|
+
* this command does not touch the dock directly.
|
|
24
|
+
*/
|
|
25
|
+
export function registerKillCommand(pi: ExtensionAPI): void {
|
|
26
|
+
const events = pi.events;
|
|
27
|
+
pi.registerCommand("ps:kill", {
|
|
28
|
+
description: "Stop a running managed process.",
|
|
29
|
+
getArgumentCompletions: (prefix: string) => completions(events, prefix),
|
|
30
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
31
|
+
const rawId = args.trim().split(/\s+/, 1)[0];
|
|
32
|
+
const processes = requestProcessList(events);
|
|
33
|
+
const live = processes.filter((process) =>
|
|
34
|
+
LIVE_STATUSES.has(process.status),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let id: string | null = null;
|
|
38
|
+
if (rawId) {
|
|
39
|
+
const proc = requestProcess(events, rawId);
|
|
40
|
+
if (!proc) {
|
|
41
|
+
ctx.ui.notify(`Process not found: ${rawId}`, "warning");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!LIVE_STATUSES.has(proc.status)) {
|
|
45
|
+
ctx.ui.notify(`${proc.name} (${proc.id}) is not running.`, "warning");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
id = proc.id;
|
|
49
|
+
} else if (live.length === 0) {
|
|
50
|
+
ctx.ui.notify("No running processes to kill.", "warning");
|
|
51
|
+
return;
|
|
52
|
+
} else if (live.length === 1 && live[0]) {
|
|
53
|
+
id = live[0].id;
|
|
54
|
+
} else {
|
|
55
|
+
id = await pickTarget(ctx, events, "Select process to kill");
|
|
56
|
+
if (!id) return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!id) return;
|
|
60
|
+
const proc = requestProcess(events, id);
|
|
61
|
+
if (!proc) {
|
|
62
|
+
ctx.ui.notify(`Process not found: ${id}`, "warning");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const signal =
|
|
67
|
+
proc.status === "terminate_timeout" ? "SIGKILL" : "SIGTERM";
|
|
68
|
+
const timeoutMs = signal === "SIGKILL" ? 200 : 3000;
|
|
69
|
+
const result = await requestKill(events, id, { signal, timeoutMs });
|
|
70
|
+
if (result.ok) {
|
|
71
|
+
ctx.ui.notify(`Killed ${proc.name} (${proc.id}).`, "info");
|
|
72
|
+
} else {
|
|
73
|
+
ctx.ui.notify(
|
|
74
|
+
`Failed to kill ${proc.name} (${proc.id}): ${result.reason}.`,
|
|
75
|
+
"warning",
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function pickTarget(
|
|
83
|
+
ctx: ExtensionCommandContext,
|
|
84
|
+
events: EventBus,
|
|
85
|
+
title: string,
|
|
86
|
+
): Promise<string | null> {
|
|
87
|
+
if (ctx.mode !== "tui") {
|
|
88
|
+
ctx.ui.notify("Usage: /ps:kill <process-id>", "warning");
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const items: SelectItem[] = requestProcessList(events)
|
|
93
|
+
.filter((process) => LIVE_STATUSES.has(process.status))
|
|
94
|
+
.map((process) => ({
|
|
95
|
+
label: `${process.name} (${process.id})`,
|
|
96
|
+
value: process.id,
|
|
97
|
+
description: formatProcessSelectionDescription(process),
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
if (items.length === 0) {
|
|
101
|
+
ctx.ui.notify("No running processes to kill.", "warning");
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const result = await ctx.ui.custom<string | null>(
|
|
106
|
+
(tui, theme, _keybindings, done) => {
|
|
107
|
+
const list = new SelectList(
|
|
108
|
+
items,
|
|
109
|
+
Math.min(items.length, 10),
|
|
110
|
+
getSelectListTheme(),
|
|
111
|
+
);
|
|
112
|
+
list.onSelect = (item) => done(String(item.value));
|
|
113
|
+
list.onCancel = () => done(null);
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
render: (width: number) => [
|
|
117
|
+
theme.fg("accent", title),
|
|
118
|
+
theme.fg("muted", "─".repeat(Math.max(0, width))),
|
|
119
|
+
...list.render(width),
|
|
120
|
+
theme.fg("muted", "─".repeat(Math.max(0, width))),
|
|
121
|
+
],
|
|
122
|
+
invalidate: () => list.invalidate(),
|
|
123
|
+
handleInput: (data: string) => {
|
|
124
|
+
list.handleInput(data);
|
|
125
|
+
tui.requestRender();
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
return result ?? null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function completions(
|
|
135
|
+
events: EventBus,
|
|
136
|
+
prefix: string,
|
|
137
|
+
): AutocompleteItem[] | null {
|
|
138
|
+
const normalized = prefix.trim().toLowerCase();
|
|
139
|
+
const items = requestProcessList(events)
|
|
140
|
+
.filter(
|
|
141
|
+
(process) =>
|
|
142
|
+
LIVE_STATUSES.has(process.status) &&
|
|
143
|
+
(process.id.toLowerCase().startsWith(normalized) ||
|
|
144
|
+
process.name.toLowerCase().includes(normalized)),
|
|
145
|
+
)
|
|
146
|
+
.map((process) => ({
|
|
147
|
+
value: process.id,
|
|
148
|
+
label: `${process.name} (${process.id})`,
|
|
149
|
+
description: formatProcessSelectionDescription(process),
|
|
150
|
+
}));
|
|
151
|
+
return items.length > 0 ? items : null;
|
|
152
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EventBus,
|
|
3
|
+
ExtensionAPI,
|
|
4
|
+
ExtensionCommandContext,
|
|
5
|
+
Theme,
|
|
6
|
+
} from "@earendil-works/pi-coding-agent";
|
|
7
|
+
import type { ProcessProtocolConfig } from "../../../src/protocol";
|
|
8
|
+
import type { ProcessInfo } from "../../../src/types";
|
|
9
|
+
import { requestConfig, requestProcess, requestProcessList } from "../client";
|
|
10
|
+
import { OverviewComponent } from "../components/overview-component";
|
|
11
|
+
|
|
12
|
+
export interface OpenOverviewOptions {
|
|
13
|
+
events: EventBus;
|
|
14
|
+
registerOverlay: (overlay: { dispose: () => void }) => () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register the `/ps` overview/control panel.
|
|
19
|
+
*
|
|
20
|
+
* `/ps` replaces the editor while open (non-overlay `ctx.ui.custom`). It lives
|
|
21
|
+
* in the core extension but talks to the manager exclusively over `pi.events`
|
|
22
|
+
* protocol channels, so a future split-out stays cheap.
|
|
23
|
+
*/
|
|
24
|
+
export function registerOverviewCommand(
|
|
25
|
+
pi: Pick<ExtensionAPI, "registerCommand">,
|
|
26
|
+
options: OpenOverviewOptions,
|
|
27
|
+
): void {
|
|
28
|
+
pi.registerCommand("ps", {
|
|
29
|
+
description: "Open the managed process overview panel.",
|
|
30
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
31
|
+
await openOverview(args, ctx, options);
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function openOverview(
|
|
37
|
+
args: string,
|
|
38
|
+
ctx: ExtensionCommandContext,
|
|
39
|
+
options: OpenOverviewOptions,
|
|
40
|
+
): Promise<void> {
|
|
41
|
+
const requestedId = args.trim().split(/\s+/, 1)[0] || undefined;
|
|
42
|
+
const initialProcessId = requestedId
|
|
43
|
+
? requestProcess(options.events, requestedId)?.id
|
|
44
|
+
: undefined;
|
|
45
|
+
|
|
46
|
+
if (requestedId && !initialProcessId) {
|
|
47
|
+
const message = `Process not found: ${requestedId}`;
|
|
48
|
+
if (ctx.hasUI) ctx.ui.notify(message, "warning");
|
|
49
|
+
else console.log(message);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (ctx.mode !== "tui") {
|
|
54
|
+
const processes = requestProcessList(options.events);
|
|
55
|
+
const message = formatPlainProcessList(processes);
|
|
56
|
+
if (ctx.hasUI) ctx.ui.notify(message, "info");
|
|
57
|
+
else console.log(message);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let config: ProcessProtocolConfig;
|
|
62
|
+
try {
|
|
63
|
+
config = requestConfig(options.events);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
ctx.ui.notify(String(error), "error");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const result = await ctx.ui.custom<"closed">(
|
|
70
|
+
(tui, theme: Theme, _keybindings, done) => {
|
|
71
|
+
let unregister: () => void = () => undefined;
|
|
72
|
+
const overlay = new OverviewComponent({
|
|
73
|
+
events: options.events,
|
|
74
|
+
tui,
|
|
75
|
+
theme,
|
|
76
|
+
config,
|
|
77
|
+
initialProcessId,
|
|
78
|
+
onClose: () => {
|
|
79
|
+
unregister();
|
|
80
|
+
done("closed");
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
unregister = options.registerOverlay(overlay);
|
|
84
|
+
return overlay;
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (result === undefined) {
|
|
89
|
+
const processes = requestProcessList(options.events);
|
|
90
|
+
ctx.ui.notify(formatPlainProcessList(processes), "info");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function formatPlainProcessList(processes: ProcessInfo[]): string {
|
|
95
|
+
if (processes.length === 0) return "No managed processes.";
|
|
96
|
+
return processes
|
|
97
|
+
.map(
|
|
98
|
+
(process) =>
|
|
99
|
+
`${process.id}\t${process.name}\t${process.status}\t${process.command}`,
|
|
100
|
+
)
|
|
101
|
+
.join("\n");
|
|
102
|
+
}
|