@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
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ExecuteResult } from "../../constants";
|
|
2
|
-
import type { ProcessManager } from "../../manager";
|
|
3
|
-
|
|
4
|
-
export function executeClear(manager: ProcessManager): ExecuteResult {
|
|
5
|
-
const cleared = manager.clearFinished();
|
|
6
|
-
const message =
|
|
7
|
-
cleared > 0
|
|
8
|
-
? `Cleared ${cleared} finished process(es)`
|
|
9
|
-
: "No finished processes to clear";
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
content: [{ type: "text", text: message }],
|
|
13
|
-
details: {
|
|
14
|
-
action: "clear",
|
|
15
|
-
success: true,
|
|
16
|
-
message,
|
|
17
|
-
cleared,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import type { ExecuteResult, ProcessInfo } from "../../constants";
|
|
4
|
-
|
|
5
|
-
interface DebugParams {
|
|
6
|
-
preview?: "start" | "list" | "output" | "logs" | "error";
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function renderDebugCall(
|
|
10
|
-
args: DebugParams,
|
|
11
|
-
theme: Theme,
|
|
12
|
-
): ToolCallHeader {
|
|
13
|
-
return new ToolCallHeader(
|
|
14
|
-
{
|
|
15
|
-
toolName: "Process",
|
|
16
|
-
action: "debug_preview",
|
|
17
|
-
mainArg: args.preview,
|
|
18
|
-
},
|
|
19
|
-
theme,
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function mockProcess(overrides?: Partial<ProcessInfo>): ProcessInfo {
|
|
24
|
-
const now = Date.now();
|
|
25
|
-
return {
|
|
26
|
-
id: "proc_42",
|
|
27
|
-
name: "demo-server",
|
|
28
|
-
pid: 4242,
|
|
29
|
-
command: "pnpm dev --port 3000",
|
|
30
|
-
cwd: "/tmp/demo",
|
|
31
|
-
startTime: now - 12_000,
|
|
32
|
-
endTime: null,
|
|
33
|
-
status: "running",
|
|
34
|
-
exitCode: null,
|
|
35
|
-
success: null,
|
|
36
|
-
stdoutFile: "/tmp/pi-processes-demo/proc_42-stdout.log",
|
|
37
|
-
stderrFile: "/tmp/pi-processes-demo/proc_42-stderr.log",
|
|
38
|
-
alertOnSuccess: false,
|
|
39
|
-
alertOnFailure: true,
|
|
40
|
-
alertOnKill: false,
|
|
41
|
-
...overrides,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Temporary no-side-effect previews for process tool renderers.
|
|
47
|
-
* Remove before release.
|
|
48
|
-
*/
|
|
49
|
-
export function executeDebugPreview(params: DebugParams): ExecuteResult {
|
|
50
|
-
const preview = params.preview ?? "start";
|
|
51
|
-
|
|
52
|
-
if (preview === "start") {
|
|
53
|
-
const process = mockProcess();
|
|
54
|
-
const message = [
|
|
55
|
-
`Started "${process.name}" (${process.id}, PID: ${process.pid})`,
|
|
56
|
-
"Log files:",
|
|
57
|
-
` stdout: ${process.stdoutFile}`,
|
|
58
|
-
` stderr: ${process.stderrFile}`,
|
|
59
|
-
].join("\n");
|
|
60
|
-
return {
|
|
61
|
-
content: [{ type: "text", text: message }],
|
|
62
|
-
details: {
|
|
63
|
-
action: "start",
|
|
64
|
-
success: true,
|
|
65
|
-
message,
|
|
66
|
-
process,
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (preview === "list") {
|
|
72
|
-
const processes = [
|
|
73
|
-
mockProcess(),
|
|
74
|
-
mockProcess({
|
|
75
|
-
id: "proc_11",
|
|
76
|
-
name: "builder",
|
|
77
|
-
pid: 1011,
|
|
78
|
-
command: "pnpm build --watch",
|
|
79
|
-
}),
|
|
80
|
-
mockProcess({
|
|
81
|
-
id: "proc_10",
|
|
82
|
-
name: "tests",
|
|
83
|
-
pid: 1010,
|
|
84
|
-
command: "pnpm test",
|
|
85
|
-
status: "exited",
|
|
86
|
-
success: false,
|
|
87
|
-
endTime: Date.now() - 3_000,
|
|
88
|
-
exitCode: 1,
|
|
89
|
-
}),
|
|
90
|
-
];
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
content: [{ type: "text", text: "Debug preview: list" }],
|
|
94
|
-
details: {
|
|
95
|
-
action: "list",
|
|
96
|
-
success: true,
|
|
97
|
-
message: "Debug preview: list",
|
|
98
|
-
processes,
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (preview === "output") {
|
|
104
|
-
return {
|
|
105
|
-
content: [{ type: "text", text: "Debug preview: output" }],
|
|
106
|
-
details: {
|
|
107
|
-
action: "output",
|
|
108
|
-
success: true,
|
|
109
|
-
message:
|
|
110
|
-
'"demo-server" (proc_42) [running]: 4 stdout lines, 2 stderr lines',
|
|
111
|
-
output: {
|
|
112
|
-
status: "running",
|
|
113
|
-
stdout: [
|
|
114
|
-
"starting...",
|
|
115
|
-
"loading config",
|
|
116
|
-
"ready on http://localhost:3000",
|
|
117
|
-
"watching for changes",
|
|
118
|
-
],
|
|
119
|
-
stderr: [
|
|
120
|
-
"warn: deprecated option in config",
|
|
121
|
-
"error: simulated stack trace line",
|
|
122
|
-
],
|
|
123
|
-
},
|
|
124
|
-
logFiles: {
|
|
125
|
-
stdoutFile: "/tmp/pi-processes-demo/proc_42-stdout.log",
|
|
126
|
-
stderrFile: "/tmp/pi-processes-demo/proc_42-stderr.log",
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (preview === "logs") {
|
|
133
|
-
return {
|
|
134
|
-
content: [{ type: "text", text: "Debug preview: logs" }],
|
|
135
|
-
details: {
|
|
136
|
-
action: "logs",
|
|
137
|
-
success: true,
|
|
138
|
-
message: "Debug preview: logs",
|
|
139
|
-
logFiles: {
|
|
140
|
-
stdoutFile: "/tmp/pi-processes-demo/proc_42-stdout.log",
|
|
141
|
-
stderrFile: "/tmp/pi-processes-demo/proc_42-stderr.log",
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
throw new Error("Invalid logWatches[0].pattern: Unterminated group");
|
|
148
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { ToolBody, ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type {
|
|
3
|
-
AgentToolResult,
|
|
4
|
-
ExtensionContext,
|
|
5
|
-
Theme,
|
|
6
|
-
ToolRenderResultOptions,
|
|
7
|
-
} from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import type { Component } from "@earendil-works/pi-tui";
|
|
9
|
-
import type {
|
|
10
|
-
ExecuteResult,
|
|
11
|
-
ProcessAction,
|
|
12
|
-
ProcessesDetails,
|
|
13
|
-
} from "../../constants";
|
|
14
|
-
import type { ProcessManager } from "../../manager";
|
|
15
|
-
import { executeClear } from "./clear";
|
|
16
|
-
import { executeDebugPreview, renderDebugCall } from "./debug";
|
|
17
|
-
import { executeKill, renderKillCall } from "./kill";
|
|
18
|
-
import { executeList, renderListResult } from "./list";
|
|
19
|
-
import { executeLogs, renderLogsCall, renderLogsResult } from "./logs";
|
|
20
|
-
import { executeOutput, renderOutputCall, renderOutputResult } from "./output";
|
|
21
|
-
import { executeStart, renderStartCall, renderStartResult } from "./start";
|
|
22
|
-
import { executeWrite, renderWriteCall } from "./write";
|
|
23
|
-
|
|
24
|
-
const DEBUG_PREVIEW_ENABLED = process.env.PI_PROCESSES_DEBUG_PREVIEW === "1";
|
|
25
|
-
|
|
26
|
-
interface ActionParams {
|
|
27
|
-
action: ProcessAction | string;
|
|
28
|
-
command?: string;
|
|
29
|
-
name?: string;
|
|
30
|
-
id?: string;
|
|
31
|
-
input?: string;
|
|
32
|
-
end?: boolean;
|
|
33
|
-
cwd?: string;
|
|
34
|
-
alertOnSuccess?: boolean;
|
|
35
|
-
alertOnFailure?: boolean;
|
|
36
|
-
alertOnKill?: boolean;
|
|
37
|
-
logWatches?: Array<{
|
|
38
|
-
pattern: string;
|
|
39
|
-
stream?: "stdout" | "stderr" | "both";
|
|
40
|
-
repeat?: boolean;
|
|
41
|
-
}>;
|
|
42
|
-
preview?: "start" | "list" | "output" | "logs" | "error";
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function executeAction(
|
|
46
|
-
params: ActionParams,
|
|
47
|
-
manager: ProcessManager,
|
|
48
|
-
ctx: ExtensionContext,
|
|
49
|
-
): Promise<ExecuteResult> {
|
|
50
|
-
switch (params.action) {
|
|
51
|
-
case "start":
|
|
52
|
-
return executeStart(params, manager, ctx);
|
|
53
|
-
case "list":
|
|
54
|
-
return executeList(manager);
|
|
55
|
-
case "output":
|
|
56
|
-
return executeOutput(params, manager);
|
|
57
|
-
case "logs":
|
|
58
|
-
return executeLogs(params, manager);
|
|
59
|
-
case "kill":
|
|
60
|
-
return executeKill(params, manager);
|
|
61
|
-
case "clear":
|
|
62
|
-
return executeClear(manager);
|
|
63
|
-
case "write":
|
|
64
|
-
return executeWrite(params, manager);
|
|
65
|
-
case "debug_preview":
|
|
66
|
-
if (!DEBUG_PREVIEW_ENABLED) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
"Action 'debug_preview' is disabled. Set PI_PROCESSES_DEBUG_PREVIEW=1 to enable.",
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
return executeDebugPreview(params);
|
|
72
|
-
default:
|
|
73
|
-
return {
|
|
74
|
-
content: [{ type: "text", text: `Unknown action: ${params.action}` }],
|
|
75
|
-
details: {
|
|
76
|
-
action: params.action as ProcessAction,
|
|
77
|
-
success: false,
|
|
78
|
-
message: `Unknown action: ${params.action}`,
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function renderActionCall(args: ActionParams, theme: Theme): Component {
|
|
85
|
-
switch (args.action) {
|
|
86
|
-
case "start":
|
|
87
|
-
return renderStartCall(args, theme);
|
|
88
|
-
case "output":
|
|
89
|
-
return renderOutputCall(args, theme);
|
|
90
|
-
case "logs":
|
|
91
|
-
return renderLogsCall(args, theme);
|
|
92
|
-
case "kill":
|
|
93
|
-
return renderKillCall(args, theme);
|
|
94
|
-
case "write":
|
|
95
|
-
return renderWriteCall(args, theme);
|
|
96
|
-
case "debug_preview":
|
|
97
|
-
return renderDebugCall(args, theme);
|
|
98
|
-
default:
|
|
99
|
-
return new ToolCallHeader(
|
|
100
|
-
{ toolName: "Process", action: args.action },
|
|
101
|
-
theme,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function renderActionResult(
|
|
107
|
-
result: AgentToolResult<ProcessesDetails>,
|
|
108
|
-
options: ToolRenderResultOptions,
|
|
109
|
-
theme: Theme,
|
|
110
|
-
): Component {
|
|
111
|
-
const { details } = result;
|
|
112
|
-
|
|
113
|
-
if (!details) {
|
|
114
|
-
return new ToolBody(
|
|
115
|
-
{
|
|
116
|
-
fields: [
|
|
117
|
-
{
|
|
118
|
-
label: "Result",
|
|
119
|
-
value: "No result details available.",
|
|
120
|
-
showCollapsed: true,
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
},
|
|
124
|
-
options,
|
|
125
|
-
theme,
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
switch (details.action) {
|
|
130
|
-
case "start":
|
|
131
|
-
return renderStartResult(result, options, theme);
|
|
132
|
-
case "list":
|
|
133
|
-
return renderListResult(result, options, theme);
|
|
134
|
-
case "output":
|
|
135
|
-
return renderOutputResult(result, options, theme);
|
|
136
|
-
case "logs":
|
|
137
|
-
return renderLogsResult(result, options, theme);
|
|
138
|
-
case "kill":
|
|
139
|
-
case "write":
|
|
140
|
-
case "clear":
|
|
141
|
-
case "debug_preview":
|
|
142
|
-
// Default rendering for these actions
|
|
143
|
-
return new ToolBody(
|
|
144
|
-
{
|
|
145
|
-
fields: [
|
|
146
|
-
{
|
|
147
|
-
label: "Result",
|
|
148
|
-
value: details.message,
|
|
149
|
-
showCollapsed: true,
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
},
|
|
153
|
-
options,
|
|
154
|
-
theme,
|
|
155
|
-
);
|
|
156
|
-
default:
|
|
157
|
-
return new ToolBody(
|
|
158
|
-
{
|
|
159
|
-
fields: [
|
|
160
|
-
{
|
|
161
|
-
label: "Result",
|
|
162
|
-
value: details.message,
|
|
163
|
-
showCollapsed: true,
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
options,
|
|
168
|
-
theme,
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { ToolCallHeader } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import type { ExecuteResult } from "../../constants";
|
|
4
|
-
import type { ProcessManager } from "../../manager";
|
|
5
|
-
|
|
6
|
-
interface KillParams {
|
|
7
|
-
id?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function renderKillCall(args: KillParams, theme: Theme): ToolCallHeader {
|
|
11
|
-
return new ToolCallHeader(
|
|
12
|
-
{
|
|
13
|
-
toolName: "Process",
|
|
14
|
-
action: "kill",
|
|
15
|
-
mainArg: args.id,
|
|
16
|
-
},
|
|
17
|
-
theme,
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function executeKill(
|
|
22
|
-
params: KillParams,
|
|
23
|
-
manager: ProcessManager,
|
|
24
|
-
): Promise<ExecuteResult> {
|
|
25
|
-
if (!params.id) {
|
|
26
|
-
return {
|
|
27
|
-
content: [{ type: "text", text: "Missing required parameter: id" }],
|
|
28
|
-
details: {
|
|
29
|
-
action: "kill",
|
|
30
|
-
success: false,
|
|
31
|
-
message: "Missing required parameter: id",
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const proc = manager.get(params.id);
|
|
37
|
-
if (!proc) {
|
|
38
|
-
const message = `Process not found: ${params.id}`;
|
|
39
|
-
return {
|
|
40
|
-
content: [{ type: "text", text: message }],
|
|
41
|
-
details: {
|
|
42
|
-
action: "kill",
|
|
43
|
-
success: false,
|
|
44
|
-
message,
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const result = await manager.kill(proc.id, {
|
|
50
|
-
signal: "SIGTERM",
|
|
51
|
-
timeoutMs: 3000,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (result.ok) {
|
|
55
|
-
const message = `Terminated "${proc.name}" (${proc.id})`;
|
|
56
|
-
return {
|
|
57
|
-
content: [{ type: "text", text: message }],
|
|
58
|
-
details: {
|
|
59
|
-
action: "kill",
|
|
60
|
-
success: true,
|
|
61
|
-
message,
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (result.reason === "timeout") {
|
|
67
|
-
const message =
|
|
68
|
-
`SIGTERM timed out for "${proc.name}" (${proc.id}). ` +
|
|
69
|
-
"Run /ps and press x on terminate_timeout to force kill (SIGKILL).";
|
|
70
|
-
return {
|
|
71
|
-
content: [{ type: "text", text: message }],
|
|
72
|
-
details: {
|
|
73
|
-
action: "kill",
|
|
74
|
-
success: false,
|
|
75
|
-
message,
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const message = `Failed to terminate "${proc.name}" (${proc.id})`;
|
|
81
|
-
return {
|
|
82
|
-
content: [{ type: "text", text: message }],
|
|
83
|
-
details: {
|
|
84
|
-
action: "kill",
|
|
85
|
-
success: false,
|
|
86
|
-
message,
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { ToolBody, ToolFooter } from "@aliou/pi-utils-ui";
|
|
2
|
-
import type {
|
|
3
|
-
AgentToolResult,
|
|
4
|
-
Theme,
|
|
5
|
-
ToolRenderResultOptions,
|
|
6
|
-
} from "@earendil-works/pi-coding-agent";
|
|
7
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
8
|
-
import type { ExecuteResult, ProcessesDetails } from "../../constants";
|
|
9
|
-
import type { ProcessManager } from "../../manager";
|
|
10
|
-
import {
|
|
11
|
-
formatRuntime,
|
|
12
|
-
formatStatus,
|
|
13
|
-
formatStatusTag,
|
|
14
|
-
formatTimestamp,
|
|
15
|
-
truncateCmd,
|
|
16
|
-
} from "../../utils";
|
|
17
|
-
|
|
18
|
-
export function executeList(manager: ProcessManager): ExecuteResult {
|
|
19
|
-
const processes = manager.list();
|
|
20
|
-
|
|
21
|
-
if (processes.length === 0) {
|
|
22
|
-
return {
|
|
23
|
-
content: [{ type: "text", text: "No background processes running" }],
|
|
24
|
-
details: {
|
|
25
|
-
action: "list",
|
|
26
|
-
success: true,
|
|
27
|
-
message: "No background processes running",
|
|
28
|
-
processes: [],
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const summary = processes
|
|
34
|
-
.map(
|
|
35
|
-
(p) =>
|
|
36
|
-
`${p.id} "${p.name}": ${truncateCmd(p.command)} [${formatStatus(p)}] ${formatRuntime(p.startTime, p.endTime)}`,
|
|
37
|
-
)
|
|
38
|
-
.join("\n");
|
|
39
|
-
|
|
40
|
-
const message = `${processes.length} process(es):\n${summary}`;
|
|
41
|
-
return {
|
|
42
|
-
content: [{ type: "text", text: message }],
|
|
43
|
-
details: {
|
|
44
|
-
action: "list",
|
|
45
|
-
success: true,
|
|
46
|
-
message,
|
|
47
|
-
processes,
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function renderListResult(
|
|
53
|
-
result: AgentToolResult<ProcessesDetails>,
|
|
54
|
-
options: ToolRenderResultOptions,
|
|
55
|
-
theme: Theme,
|
|
56
|
-
): ToolBody {
|
|
57
|
-
const { details } = result;
|
|
58
|
-
|
|
59
|
-
if (!details.processes || details.processes.length === 0) {
|
|
60
|
-
return new ToolBody(
|
|
61
|
-
{
|
|
62
|
-
fields: [
|
|
63
|
-
{
|
|
64
|
-
label: "Processes",
|
|
65
|
-
value: "No background processes running",
|
|
66
|
-
showCollapsed: true,
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
options,
|
|
71
|
-
theme,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const processes = [...details.processes];
|
|
76
|
-
|
|
77
|
-
const statusRank = (status: string): number => {
|
|
78
|
-
switch (status) {
|
|
79
|
-
case "running":
|
|
80
|
-
return 0;
|
|
81
|
-
case "terminating":
|
|
82
|
-
return 1;
|
|
83
|
-
case "terminate_timeout":
|
|
84
|
-
return 2;
|
|
85
|
-
case "killed":
|
|
86
|
-
return 3;
|
|
87
|
-
case "exited":
|
|
88
|
-
return 4;
|
|
89
|
-
default:
|
|
90
|
-
return 5;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
processes.sort((a, b) => {
|
|
95
|
-
const rankDiff = statusRank(a.status) - statusRank(b.status);
|
|
96
|
-
if (rankDiff !== 0) return rankDiff;
|
|
97
|
-
return b.startTime - a.startTime;
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const runningCount = processes.filter(
|
|
101
|
-
(p) => p.status === "running" || p.status === "terminating",
|
|
102
|
-
).length;
|
|
103
|
-
|
|
104
|
-
const lines: string[] = [
|
|
105
|
-
theme.fg(
|
|
106
|
-
"success",
|
|
107
|
-
`${processes.length} process(es), ${runningCount} running/terminating`,
|
|
108
|
-
),
|
|
109
|
-
];
|
|
110
|
-
|
|
111
|
-
for (const process of processes) {
|
|
112
|
-
const status = formatStatusTag(process, theme);
|
|
113
|
-
lines.push(
|
|
114
|
-
[
|
|
115
|
-
`- ${theme.fg("accent", process.name)} ${theme.fg("muted", `(${process.id})`)}`,
|
|
116
|
-
` pid: ${process.pid} status: ${status}`,
|
|
117
|
-
` started: ${theme.fg("muted", formatTimestamp(process.startTime))}`,
|
|
118
|
-
` ended: ${theme.fg("muted", formatTimestamp(process.endTime))}`,
|
|
119
|
-
` runtime: ${theme.fg("muted", formatRuntime(process.startTime, process.endTime))}`,
|
|
120
|
-
].join("\n"),
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const fields: Array<
|
|
125
|
-
{ label: string; value: string; showCollapsed?: boolean } | Text
|
|
126
|
-
> = [new Text(lines.join("\n"), 0, 0)];
|
|
127
|
-
|
|
128
|
-
const running = details.processes.filter(
|
|
129
|
-
(p) => p.status === "running" || p.status === "terminating",
|
|
130
|
-
);
|
|
131
|
-
const finishedOk = details.processes.filter(
|
|
132
|
-
(p) => p.status === "exited" && p.success,
|
|
133
|
-
).length;
|
|
134
|
-
const failed = details.processes.filter(
|
|
135
|
-
(p) => p.status === "exited" && !p.success,
|
|
136
|
-
).length;
|
|
137
|
-
const killed = details.processes.filter((p) => p.status === "killed").length;
|
|
138
|
-
|
|
139
|
-
const runningSummary =
|
|
140
|
-
running.length > 0
|
|
141
|
-
? running
|
|
142
|
-
.slice(0, 3)
|
|
143
|
-
.map(
|
|
144
|
-
(p) =>
|
|
145
|
-
`${theme.fg("accent", `"${p.name}"`)} [${formatStatusTag(p, theme)}]`,
|
|
146
|
-
)
|
|
147
|
-
.join(", ")
|
|
148
|
-
: theme.fg("muted", "no running process");
|
|
149
|
-
|
|
150
|
-
const restParts: string[] = [];
|
|
151
|
-
if (finishedOk > 0) restParts.push(`${finishedOk} finished`);
|
|
152
|
-
if (failed > 0) restParts.push(`${failed} failed`);
|
|
153
|
-
if (killed > 0) restParts.push(`${killed} killed`);
|
|
154
|
-
const restSummary =
|
|
155
|
-
restParts.length > 0 ? theme.fg("muted", ` + ${restParts.join(", ")}`) : "";
|
|
156
|
-
|
|
157
|
-
fields.push({
|
|
158
|
-
label: "Processes",
|
|
159
|
-
value: runningSummary + restSummary,
|
|
160
|
-
showCollapsed: true,
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const footerItems: Array<{
|
|
164
|
-
label: string;
|
|
165
|
-
value: string;
|
|
166
|
-
}> = [];
|
|
167
|
-
if (runningCount > 0) {
|
|
168
|
-
footerItems.push({ label: "running", value: String(runningCount) });
|
|
169
|
-
}
|
|
170
|
-
if (failed > 0) {
|
|
171
|
-
footerItems.push({ label: "failed", value: String(failed) });
|
|
172
|
-
}
|
|
173
|
-
if (killed > 0) {
|
|
174
|
-
footerItems.push({ label: "killed", value: String(killed) });
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return new ToolBody(
|
|
178
|
-
{
|
|
179
|
-
fields,
|
|
180
|
-
footer:
|
|
181
|
-
footerItems.length > 0
|
|
182
|
-
? new ToolFooter(theme, { items: footerItems, separator: " | " })
|
|
183
|
-
: undefined,
|
|
184
|
-
},
|
|
185
|
-
options,
|
|
186
|
-
theme,
|
|
187
|
-
);
|
|
188
|
-
}
|