@aliou/pi-processes 0.4.0 → 0.4.3
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/commands/index.ts +1 -12
- package/components/log-stream-component.ts +20 -18
- package/components/process-picker-component.ts +10 -21
- package/components/processes-component.ts +12 -21
- package/hooks/widget.ts +2 -1
- package/index.ts +2 -2
- package/package.json +3 -2
- package/tools/index.ts +106 -103
package/commands/index.ts
CHANGED
|
@@ -48,15 +48,10 @@ function allProcessCompletions(manager: ProcessManager) {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export interface ProcessCommands {
|
|
52
|
-
/** Start streaming logs for a process via the widget. Needs a UI context. */
|
|
53
|
-
streamProcess: (processId: string, ui: ExtensionCommandContext["ui"]) => void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
51
|
export function setupProcessesCommands(
|
|
57
52
|
pi: ExtensionAPI,
|
|
58
53
|
manager: ProcessManager,
|
|
59
|
-
):
|
|
54
|
+
): void {
|
|
60
55
|
let streamingProcessId: string | null = null;
|
|
61
56
|
|
|
62
57
|
// ── /process:list ──────────────────────────────────────────────────
|
|
@@ -304,12 +299,6 @@ export function setupProcessesCommands(
|
|
|
304
299
|
{ placement: "aboveEditor" },
|
|
305
300
|
);
|
|
306
301
|
}
|
|
307
|
-
|
|
308
|
-
return {
|
|
309
|
-
streamProcess: (processId: string, ui: ExtensionCommandContext["ui"]) => {
|
|
310
|
-
startStreaming(ui, manager, processId);
|
|
311
|
-
},
|
|
312
|
-
};
|
|
313
302
|
}
|
|
314
303
|
|
|
315
304
|
async function pickProcess(
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPanelPadder,
|
|
3
|
+
renderPanelRule,
|
|
4
|
+
renderPanelTitleLine,
|
|
5
|
+
} from "@aliou/pi-utils-ui";
|
|
1
6
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
7
|
import {
|
|
3
8
|
type Component,
|
|
@@ -62,26 +67,26 @@ export class LogStreamComponent implements Component {
|
|
|
62
67
|
|
|
63
68
|
const theme = this.theme;
|
|
64
69
|
const dim = (s: string) => theme.fg("dim", s);
|
|
65
|
-
const accent = (s: string) => theme.fg("accent", s);
|
|
66
70
|
const warning = (s: string) => theme.fg("warning", s);
|
|
67
|
-
const border = (s: string) => theme.fg("dim", s);
|
|
68
71
|
const innerWidth = width - 2;
|
|
69
72
|
|
|
73
|
+
const basePadLine = createPanelPadder(width);
|
|
70
74
|
const padLine = (content: string): string => {
|
|
71
75
|
const contentWidth = visibleWidth(content);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
return basePadLine(
|
|
77
|
+
contentWidth > innerWidth
|
|
78
|
+
? truncateToWidth(content, innerWidth)
|
|
79
|
+
: content,
|
|
80
|
+
);
|
|
76
81
|
};
|
|
77
82
|
|
|
78
83
|
const lines: string[] = [];
|
|
79
84
|
const proc = this.manager.get(this.processId);
|
|
80
85
|
|
|
81
86
|
if (!proc) {
|
|
82
|
-
lines.push(
|
|
87
|
+
lines.push(renderPanelRule(width, theme));
|
|
83
88
|
lines.push(padLine(warning("Process not found")));
|
|
84
|
-
lines.push(
|
|
89
|
+
lines.push(renderPanelRule(width, theme));
|
|
85
90
|
this.cachedLines = lines;
|
|
86
91
|
this.cachedWidth = width;
|
|
87
92
|
return this.cachedLines;
|
|
@@ -90,15 +95,12 @@ export class LogStreamComponent implements Component {
|
|
|
90
95
|
// Header
|
|
91
96
|
const icon = statusIcon(proc.status, proc.success);
|
|
92
97
|
const label = statusLabel(proc);
|
|
93
|
-
const headerText = ` ${accent(proc.name)} ${dim(`(${proc.id})`)} ${icon} ${dim(label)} `;
|
|
94
|
-
const headerLen = visibleWidth(headerText);
|
|
95
|
-
const borderLen = Math.max(0, width - headerLen);
|
|
96
|
-
const leftBorder = Math.floor(borderLen / 2);
|
|
97
|
-
const rightBorder = borderLen - leftBorder;
|
|
98
98
|
lines.push(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
renderPanelTitleLine(
|
|
100
|
+
`Process: ${proc.name} (${proc.id}) ${icon} ${label}`,
|
|
101
|
+
width,
|
|
102
|
+
theme,
|
|
103
|
+
),
|
|
102
104
|
);
|
|
103
105
|
|
|
104
106
|
// Log lines (interleaved stdout + stderr in temporal order).
|
|
@@ -127,9 +129,9 @@ export class LogStreamComponent implements Component {
|
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
// Footer hint
|
|
130
|
-
lines.push(
|
|
132
|
+
lines.push(renderPanelRule(width, theme));
|
|
131
133
|
lines.push(padLine(dim("Run /process:stream to dismiss")));
|
|
132
|
-
lines.push(
|
|
134
|
+
lines.push(renderPanelRule(width, theme));
|
|
133
135
|
|
|
134
136
|
this.cachedLines = lines;
|
|
135
137
|
this.cachedWidth = width;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPanelPadder,
|
|
3
|
+
renderPanelRule,
|
|
4
|
+
renderPanelTitleLine,
|
|
5
|
+
} from "@aliou/pi-utils-ui";
|
|
1
6
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { type Component, matchesKey
|
|
7
|
+
import { type Component, matchesKey } from "@mariozechner/pi-tui";
|
|
3
8
|
import type { ProcessInfo } from "../constants";
|
|
4
9
|
import type { ProcessManager } from "../manager";
|
|
5
10
|
import { statusIcon, statusLabel } from "./status-format";
|
|
@@ -105,29 +110,13 @@ export class ProcessPickerComponent implements Component {
|
|
|
105
110
|
const theme = this.theme;
|
|
106
111
|
const dim = (s: string) => theme.fg("dim", s);
|
|
107
112
|
const accent = (s: string) => theme.fg("accent", s);
|
|
108
|
-
const bold = (s: string) => theme.bold(s);
|
|
109
|
-
const border = (s: string) => theme.fg("dim", s);
|
|
110
|
-
const innerWidth = width - 2;
|
|
111
113
|
|
|
112
|
-
const padLine = (
|
|
113
|
-
const len = visibleWidth(content);
|
|
114
|
-
return ` ${content}${" ".repeat(Math.max(0, innerWidth - len))} `;
|
|
115
|
-
};
|
|
114
|
+
const padLine = createPanelPadder(width);
|
|
116
115
|
|
|
117
116
|
const lines: string[] = [];
|
|
118
117
|
const processes = this.getProcesses();
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
const titleText = ` ${this.title} `;
|
|
122
|
-
const titleLen = titleText.length;
|
|
123
|
-
const borderLen = Math.max(0, width - titleLen);
|
|
124
|
-
const leftBorder = Math.floor(borderLen / 2);
|
|
125
|
-
const rightBorder = borderLen - leftBorder;
|
|
126
|
-
lines.push(
|
|
127
|
-
border("─".repeat(leftBorder)) +
|
|
128
|
-
accent(bold(titleText)) +
|
|
129
|
-
border("─".repeat(rightBorder)),
|
|
130
|
-
);
|
|
119
|
+
lines.push(renderPanelTitleLine(this.title, width, theme));
|
|
131
120
|
|
|
132
121
|
if (processes.length === 0) {
|
|
133
122
|
lines.push(padLine(""));
|
|
@@ -151,13 +140,13 @@ export class ProcessPickerComponent implements Component {
|
|
|
151
140
|
}
|
|
152
141
|
|
|
153
142
|
// Footer
|
|
154
|
-
lines.push(
|
|
143
|
+
lines.push(renderPanelRule(width, theme));
|
|
155
144
|
lines.push(
|
|
156
145
|
padLine(
|
|
157
146
|
`${dim("j/k")} select ${dim("enter")} confirm ${dim("q")} cancel`,
|
|
158
147
|
),
|
|
159
148
|
);
|
|
160
|
-
lines.push(
|
|
149
|
+
lines.push(renderPanelRule(width, theme));
|
|
161
150
|
|
|
162
151
|
this.cachedLines = lines;
|
|
163
152
|
this.cachedWidth = width;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPanelPadder,
|
|
3
|
+
renderPanelRule,
|
|
4
|
+
renderPanelTitleLine,
|
|
5
|
+
} from "@aliou/pi-utils-ui";
|
|
1
6
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
7
|
import { type Component, matchesKey, visibleWidth } from "@mariozechner/pi-tui";
|
|
3
8
|
import { configLoader } from "../config";
|
|
@@ -204,28 +209,14 @@ export class ProcessesComponent implements Component {
|
|
|
204
209
|
const dim = (s: string) => theme.fg("dim", s);
|
|
205
210
|
const accent = (s: string) => theme.fg("accent", s);
|
|
206
211
|
const warning = (s: string) => theme.fg("warning", s);
|
|
207
|
-
const bold = (s: string) => theme.bold(s);
|
|
208
|
-
const border = (s: string) => theme.fg("dim", s);
|
|
209
212
|
|
|
210
213
|
const lines: string[] = [];
|
|
211
214
|
const processes = this.manager.list();
|
|
212
215
|
const innerWidth = width - 2;
|
|
213
216
|
|
|
214
|
-
const padLine = (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const title = " Background Processes ";
|
|
220
|
-
const titleLen = title.length;
|
|
221
|
-
const borderLen = Math.max(0, width - titleLen);
|
|
222
|
-
const leftBorder = Math.floor(borderLen / 2);
|
|
223
|
-
const rightBorder = borderLen - leftBorder;
|
|
224
|
-
lines.push(
|
|
225
|
-
border("─".repeat(leftBorder)) +
|
|
226
|
-
accent(bold(title)) +
|
|
227
|
-
border("─".repeat(rightBorder)),
|
|
228
|
-
);
|
|
217
|
+
const padLine = createPanelPadder(width);
|
|
218
|
+
|
|
219
|
+
lines.push(renderPanelTitleLine("Background Processes", width, theme));
|
|
229
220
|
|
|
230
221
|
if (processes.length === 0) {
|
|
231
222
|
lines.push(padLine(""));
|
|
@@ -270,7 +261,7 @@ export class ProcessesComponent implements Component {
|
|
|
270
261
|
dim("Size".padStart(sizeWidth)) +
|
|
271
262
|
(hasProcessScroll ? dim(headerSuffixText) : "");
|
|
272
263
|
lines.push(padLine(header));
|
|
273
|
-
lines.push(
|
|
264
|
+
lines.push(renderPanelRule(width, theme));
|
|
274
265
|
|
|
275
266
|
const visibleProcessCount = Math.min(
|
|
276
267
|
maxVisibleProcesses,
|
|
@@ -321,7 +312,7 @@ export class ProcessesComponent implements Component {
|
|
|
321
312
|
const output = this.manager.getOutput(selected.id, maxPreviewLines * 2);
|
|
322
313
|
const sizes = this.manager.getFileSize(selected.id);
|
|
323
314
|
|
|
324
|
-
lines.push(
|
|
315
|
+
lines.push(renderPanelRule(width, theme));
|
|
325
316
|
|
|
326
317
|
const logTitlePlain = `Output: ${selected.name} (${selected.id})`;
|
|
327
318
|
const sizeInfoPlain = sizes
|
|
@@ -394,7 +385,7 @@ export class ProcessesComponent implements Component {
|
|
|
394
385
|
}
|
|
395
386
|
}
|
|
396
387
|
|
|
397
|
-
lines.push(
|
|
388
|
+
lines.push(renderPanelRule(width, theme));
|
|
398
389
|
|
|
399
390
|
const footerLeft =
|
|
400
391
|
`${dim("enter")} stream ` +
|
|
@@ -421,7 +412,7 @@ export class ProcessesComponent implements Component {
|
|
|
421
412
|
const footer = footerLeft + " ".repeat(footerGap) + footerRight;
|
|
422
413
|
|
|
423
414
|
lines.push(padLine(footer));
|
|
424
|
-
lines.push(
|
|
415
|
+
lines.push(renderPanelRule(width, theme));
|
|
425
416
|
|
|
426
417
|
this.cachedLines = lines;
|
|
427
418
|
this.cachedWidth = width;
|
package/hooks/widget.ts
CHANGED
|
@@ -126,8 +126,9 @@ export function setupProcessWidget(pi: ExtensionAPI, manager: ProcessManager) {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
pi.on("session_start", async (_event, ctx) => {
|
|
129
|
+
// Startup defer: capture context only. First render happens on process
|
|
130
|
+
// manager events or explicit settings updates.
|
|
129
131
|
latestContext = ctx;
|
|
130
|
-
updateWidget();
|
|
131
132
|
});
|
|
132
133
|
|
|
133
134
|
pi.on("session_switch", async (_event, ctx) => {
|
package/index.ts
CHANGED
|
@@ -19,8 +19,8 @@ export default async function (pi: ExtensionAPI) {
|
|
|
19
19
|
const manager = new ProcessManager();
|
|
20
20
|
|
|
21
21
|
const { update: updateWidget } = setupProcessesHooks(pi, manager);
|
|
22
|
-
|
|
23
|
-
setupProcessesTools(pi, manager
|
|
22
|
+
setupProcessesCommands(pi, manager);
|
|
23
|
+
setupProcessesTools(pi, manager);
|
|
24
24
|
registerProcessesSettings(pi, () => {
|
|
25
25
|
updateWidget();
|
|
26
26
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/pi-processes",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@sinclair/typebox": "^0.34.41",
|
|
37
|
-
"@aliou/pi-utils-settings": "0.
|
|
37
|
+
"@aliou/pi-utils-settings": "0.4.0",
|
|
38
|
+
"@aliou/pi-utils-ui": "^0.1.0"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"@mariozechner/pi-coding-agent": ">=0.51.0"
|
package/tools/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ToolBody, ToolCallHeader, ToolFooter } from "@aliou/pi-utils-ui";
|
|
1
2
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
2
3
|
import type {
|
|
3
4
|
AgentToolResult,
|
|
@@ -57,13 +58,7 @@ const ProcessesParams = Type.Object({
|
|
|
57
58
|
|
|
58
59
|
type ProcessesParamsType = Static<typeof ProcessesParams>;
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export function setupProcessesTools(
|
|
63
|
-
pi: ExtensionAPI,
|
|
64
|
-
manager: ProcessManager,
|
|
65
|
-
commands: ProcessCommands,
|
|
66
|
-
) {
|
|
61
|
+
export function setupProcessesTools(pi: ExtensionAPI, manager: ProcessManager) {
|
|
67
62
|
pi.registerTool<typeof ProcessesParams, ProcessesDetails>({
|
|
68
63
|
name: "process",
|
|
69
64
|
label: "Process",
|
|
@@ -85,50 +80,56 @@ Note: User always sees process updates in the UI. The notify flags control wheth
|
|
|
85
80
|
parameters: ProcessesParams,
|
|
86
81
|
|
|
87
82
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
88
|
-
|
|
89
|
-
// Auto-stream logs when a process is started successfully.
|
|
90
|
-
if (
|
|
91
|
-
params.action === "start" &&
|
|
92
|
-
result.details?.success &&
|
|
93
|
-
result.details.process &&
|
|
94
|
-
ctx.hasUI
|
|
95
|
-
) {
|
|
96
|
-
commands.streamProcess(result.details.process.id, ctx.ui);
|
|
97
|
-
}
|
|
98
|
-
return result;
|
|
83
|
+
return executeAction(params, manager, ctx);
|
|
99
84
|
},
|
|
100
85
|
|
|
101
|
-
renderCall(args: ProcessesParamsType, theme: Theme)
|
|
102
|
-
|
|
103
|
-
|
|
86
|
+
renderCall(args: ProcessesParamsType, theme: Theme) {
|
|
87
|
+
const longArgs: Array<{ label?: string; value: string }> = [];
|
|
88
|
+
const optionArgs: Array<{ label: string; value: string }> = [];
|
|
89
|
+
let mainArg: string | undefined;
|
|
104
90
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
text += ` ${theme.fg("accent", `"${args.name}"`)}`;
|
|
109
|
-
}
|
|
110
|
-
if (args.command) {
|
|
111
|
-
text += `\n${theme.fg("muted", `$ ${args.command}`)}`;
|
|
112
|
-
}
|
|
113
|
-
return new Text(text, 0, 0);
|
|
91
|
+
if (args.action === "start") {
|
|
92
|
+
if (args.name) {
|
|
93
|
+
mainArg = `"${args.name}"`;
|
|
114
94
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
95
|
+
|
|
96
|
+
if (args.command) {
|
|
97
|
+
if (!mainArg && args.command.length <= 60) {
|
|
98
|
+
mainArg = args.command;
|
|
99
|
+
} else if (args.command.length <= 60) {
|
|
100
|
+
optionArgs.push({ label: "command", value: args.command });
|
|
101
|
+
} else {
|
|
102
|
+
longArgs.push({ label: "command", value: args.command });
|
|
120
103
|
}
|
|
121
|
-
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (
|
|
108
|
+
(args.action === "output" ||
|
|
109
|
+
args.action === "kill" ||
|
|
110
|
+
args.action === "logs") &&
|
|
111
|
+
args.id
|
|
112
|
+
) {
|
|
113
|
+
mainArg = args.id;
|
|
122
114
|
}
|
|
123
115
|
|
|
124
|
-
return new
|
|
116
|
+
return new ToolCallHeader(
|
|
117
|
+
{
|
|
118
|
+
toolName: "Process",
|
|
119
|
+
action: args.action,
|
|
120
|
+
mainArg,
|
|
121
|
+
optionArgs,
|
|
122
|
+
longArgs,
|
|
123
|
+
},
|
|
124
|
+
theme,
|
|
125
|
+
);
|
|
125
126
|
},
|
|
126
127
|
|
|
127
128
|
renderResult(
|
|
128
129
|
result: AgentToolResult<ProcessesDetails>,
|
|
129
|
-
|
|
130
|
+
options: ToolRenderResultOptions,
|
|
130
131
|
theme: Theme,
|
|
131
|
-
)
|
|
132
|
+
) {
|
|
132
133
|
const { details } = result;
|
|
133
134
|
|
|
134
135
|
if (!details) {
|
|
@@ -140,34 +141,32 @@ Note: User always sees process updates in the UI. The notify flags control wheth
|
|
|
140
141
|
);
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// For start action
|
|
148
|
-
if (details.action === "start" && details.process) {
|
|
149
|
-
const p = details.process;
|
|
150
|
-
return new Text(
|
|
151
|
-
theme.fg("success", "\u2713 Started ") +
|
|
152
|
-
theme.fg("accent", `"${p.name}"`) +
|
|
153
|
-
` (${p.id}, PID: ${p.pid})`,
|
|
154
|
-
0,
|
|
155
|
-
0,
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// For output action
|
|
160
|
-
if (details.action === "output" && details.output) {
|
|
161
|
-
const lines: string[] = [];
|
|
162
|
-
lines.push(theme.fg("muted", details.message));
|
|
144
|
+
const fields: Array<
|
|
145
|
+
{ label: string; value: string; showCollapsed?: boolean } | Text
|
|
146
|
+
> = [];
|
|
163
147
|
|
|
148
|
+
if (!details.success) {
|
|
149
|
+
fields.push({
|
|
150
|
+
label: "Error",
|
|
151
|
+
value: theme.fg("error", details.message),
|
|
152
|
+
showCollapsed: true,
|
|
153
|
+
});
|
|
154
|
+
} else if (details.action === "start" && details.process) {
|
|
155
|
+
const process = details.process;
|
|
156
|
+
fields.push({
|
|
157
|
+
label: "Status",
|
|
158
|
+
value:
|
|
159
|
+
theme.fg("success", "Started") +
|
|
160
|
+
` ${theme.fg("accent", `"${process.name}"`)} (${process.id}, PID: ${process.pid})`,
|
|
161
|
+
showCollapsed: true,
|
|
162
|
+
});
|
|
163
|
+
} else if (details.action === "output" && details.output) {
|
|
164
|
+
const lines: string[] = [theme.fg("muted", details.message)];
|
|
164
165
|
let hadAnsi = false;
|
|
165
166
|
|
|
166
167
|
if (details.output.stdout.length > 0) {
|
|
167
|
-
lines.push("");
|
|
168
|
-
|
|
169
|
-
const stdoutLines = details.output.stdout.slice(-20);
|
|
170
|
-
for (const line of stdoutLines) {
|
|
168
|
+
lines.push("", theme.fg("accent", "stdout:"));
|
|
169
|
+
for (const line of details.output.stdout.slice(-20)) {
|
|
171
170
|
if (!hadAnsi && hasAnsi(line)) hadAnsi = true;
|
|
172
171
|
lines.push(stripAnsi(line));
|
|
173
172
|
}
|
|
@@ -182,10 +181,8 @@ Note: User always sees process updates in the UI. The notify flags control wheth
|
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
if (details.output.stderr.length > 0) {
|
|
185
|
-
lines.push("");
|
|
186
|
-
|
|
187
|
-
const stderrLines = details.output.stderr.slice(-10);
|
|
188
|
-
for (const line of stderrLines) {
|
|
184
|
+
lines.push("", theme.fg("warning", "stderr:"));
|
|
185
|
+
for (const line of details.output.stderr.slice(-10)) {
|
|
189
186
|
if (!hadAnsi && hasAnsi(line)) hadAnsi = true;
|
|
190
187
|
lines.push(theme.fg("warning", stripAnsi(line)));
|
|
191
188
|
}
|
|
@@ -200,28 +197,25 @@ Note: User always sees process updates in the UI. The notify flags control wheth
|
|
|
200
197
|
}
|
|
201
198
|
|
|
202
199
|
if (hadAnsi) {
|
|
203
|
-
lines.push("");
|
|
204
200
|
lines.push(
|
|
201
|
+
"",
|
|
205
202
|
theme.fg("muted", "ANSI escape codes were stripped from output"),
|
|
206
203
|
);
|
|
207
204
|
}
|
|
208
205
|
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// For list action
|
|
213
|
-
if (
|
|
206
|
+
fields.push(new Text(lines.join("\n"), 0, 0));
|
|
207
|
+
} else if (
|
|
214
208
|
details.action === "list" &&
|
|
215
209
|
details.processes &&
|
|
216
210
|
details.processes.length > 0
|
|
217
211
|
) {
|
|
218
|
-
const lines: string[] = [
|
|
219
|
-
lines.push(
|
|
212
|
+
const lines: string[] = [
|
|
220
213
|
theme.fg("success", `${details.processes.length} process(es):`),
|
|
221
|
-
|
|
222
|
-
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
for (const process of details.processes) {
|
|
223
217
|
let status: string;
|
|
224
|
-
switch (
|
|
218
|
+
switch (process.status) {
|
|
225
219
|
case "running":
|
|
226
220
|
status = theme.fg("accent", "running");
|
|
227
221
|
break;
|
|
@@ -235,43 +229,52 @@ Note: User always sees process updates in the UI. The notify flags control wheth
|
|
|
235
229
|
status = theme.fg("warning", "killed");
|
|
236
230
|
break;
|
|
237
231
|
case "exited":
|
|
238
|
-
status =
|
|
232
|
+
status = process.success
|
|
239
233
|
? theme.fg("success", "exit(0)")
|
|
240
|
-
: theme.fg("error", `exit(${
|
|
234
|
+
: theme.fg("error", `exit(${process.exitCode ?? "?"})`);
|
|
241
235
|
break;
|
|
242
236
|
default:
|
|
243
|
-
status = theme.fg("muted",
|
|
237
|
+
status = theme.fg("muted", process.status);
|
|
244
238
|
}
|
|
239
|
+
|
|
245
240
|
lines.push(
|
|
246
|
-
` ${
|
|
241
|
+
` ${process.id} ${theme.fg("accent", `"${process.name}"`)}: ${truncateCmd(process.command)} [${status}] ${formatRuntime(process.startTime, process.endTime)}`,
|
|
247
242
|
);
|
|
248
243
|
}
|
|
249
|
-
return new Text(lines.join("\n"), 0, 0);
|
|
250
|
-
}
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
if (details.action === "logs" && details.logFiles) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
245
|
+
fields.push(new Text(lines.join("\n"), 0, 0));
|
|
246
|
+
} else if (details.action === "logs" && details.logFiles) {
|
|
247
|
+
fields.push(
|
|
248
|
+
new Text(
|
|
249
|
+
[
|
|
250
|
+
theme.fg("success", "Log files:"),
|
|
251
|
+
` stdout: ${theme.fg("accent", details.logFiles.stdoutFile)}`,
|
|
252
|
+
` stderr: ${theme.fg("accent", details.logFiles.stderrFile)}`,
|
|
253
|
+
].join("\n"),
|
|
254
|
+
0,
|
|
255
|
+
0,
|
|
256
|
+
),
|
|
258
257
|
);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
} else {
|
|
259
|
+
fields.push({
|
|
260
|
+
label: "Result",
|
|
261
|
+
value: details.message,
|
|
262
|
+
showCollapsed: true,
|
|
263
|
+
});
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
266
|
+
const footer = new ToolFooter(theme, {
|
|
267
|
+
items: [
|
|
268
|
+
{ label: "action", value: details.action, tone: "accent" },
|
|
269
|
+
{
|
|
270
|
+
label: "status",
|
|
271
|
+
value: details.success ? "ok" : "error",
|
|
272
|
+
tone: details.success ? "success" : "error",
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
});
|
|
273
276
|
|
|
274
|
-
return new
|
|
277
|
+
return new ToolBody({ fields, footer }, options, theme);
|
|
275
278
|
},
|
|
276
279
|
});
|
|
277
280
|
}
|