@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,113 +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 WriteParams {
|
|
7
|
-
id?: string;
|
|
8
|
-
input?: string;
|
|
9
|
-
end?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function renderWriteCall(
|
|
13
|
-
args: WriteParams,
|
|
14
|
-
theme: Theme,
|
|
15
|
-
): ToolCallHeader {
|
|
16
|
-
const optionArgs: Array<{ label: string; value: string }> = [];
|
|
17
|
-
|
|
18
|
-
if (args.input) {
|
|
19
|
-
optionArgs.push({ label: "input", value: args.input });
|
|
20
|
-
if (args.end) {
|
|
21
|
-
optionArgs.push({ label: "end", value: "true" });
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return new ToolCallHeader(
|
|
26
|
-
{
|
|
27
|
-
toolName: "Process",
|
|
28
|
-
action: "write",
|
|
29
|
-
mainArg: args.id,
|
|
30
|
-
optionArgs,
|
|
31
|
-
},
|
|
32
|
-
theme,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function executeWrite(
|
|
37
|
-
params: WriteParams,
|
|
38
|
-
manager: ProcessManager,
|
|
39
|
-
): ExecuteResult {
|
|
40
|
-
const { id, input, end } = params;
|
|
41
|
-
|
|
42
|
-
if (!id) {
|
|
43
|
-
return {
|
|
44
|
-
content: [{ type: "text", text: "Missing required parameter: id" }],
|
|
45
|
-
details: {
|
|
46
|
-
action: "write",
|
|
47
|
-
success: false,
|
|
48
|
-
message: "Missing required parameter: id",
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (input === undefined) {
|
|
54
|
-
return {
|
|
55
|
-
content: [{ type: "text", text: "Missing required parameter: input" }],
|
|
56
|
-
details: {
|
|
57
|
-
action: "write",
|
|
58
|
-
success: false,
|
|
59
|
-
message: "Missing required parameter: input",
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const process = manager.get(id);
|
|
65
|
-
if (!process) {
|
|
66
|
-
return {
|
|
67
|
-
content: [{ type: "text", text: `Process not found: ${id}` }],
|
|
68
|
-
details: {
|
|
69
|
-
action: "write",
|
|
70
|
-
success: false,
|
|
71
|
-
message: `Process not found: ${id}`,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const result = manager.writeToStdin(process.id, input, { end });
|
|
77
|
-
|
|
78
|
-
if (!result.ok) {
|
|
79
|
-
const messages: Record<string, string> = {
|
|
80
|
-
not_found: `Process not found: ${process.id}`,
|
|
81
|
-
process_exited: `Process has already exited: ${process.id}`,
|
|
82
|
-
stdin_closed: `Stdin already closed for process: ${process.id}`,
|
|
83
|
-
write_error: `Failed to write to stdin for process: ${process.id}`,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const message =
|
|
87
|
-
messages[result.reason] || `Unknown error: ${result.reason}`;
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
content: [{ type: "text", text: message }],
|
|
91
|
-
details: {
|
|
92
|
-
action: "write",
|
|
93
|
-
success: false,
|
|
94
|
-
message,
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const suffix = end ? " (stdin closed)" : "";
|
|
100
|
-
return {
|
|
101
|
-
content: [
|
|
102
|
-
{
|
|
103
|
-
type: "text",
|
|
104
|
-
text: `Wrote ${input.length} bytes to "${process.name}" (${process.id})${suffix}`,
|
|
105
|
-
},
|
|
106
|
-
],
|
|
107
|
-
details: {
|
|
108
|
-
action: "write",
|
|
109
|
-
success: true,
|
|
110
|
-
message: `Wrote ${input.length} bytes to process stdin${suffix}`,
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
}
|
package/src/tools/index.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { ToolBody } from "@aliou/pi-utils-ui";
|
|
2
|
-
import { StringEnum } from "@earendil-works/pi-ai";
|
|
3
|
-
import type {
|
|
4
|
-
AgentToolResult,
|
|
5
|
-
ExtensionAPI,
|
|
6
|
-
Theme,
|
|
7
|
-
ToolRenderResultOptions,
|
|
8
|
-
} from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
10
|
-
import { type Static, Type } from "typebox";
|
|
11
|
-
import type { ProcessesDetails } from "../constants";
|
|
12
|
-
import type { ProcessManager } from "../manager";
|
|
13
|
-
import { executeAction, renderActionCall, renderActionResult } from "./actions";
|
|
14
|
-
|
|
15
|
-
const DEBUG_PREVIEW_ENABLED = process.env.PI_PROCESSES_DEBUG_PREVIEW === "1";
|
|
16
|
-
|
|
17
|
-
const PROCESS_ACTIONS = [
|
|
18
|
-
"start",
|
|
19
|
-
"list",
|
|
20
|
-
"output",
|
|
21
|
-
"logs",
|
|
22
|
-
"kill",
|
|
23
|
-
"clear",
|
|
24
|
-
"write",
|
|
25
|
-
...(DEBUG_PREVIEW_ENABLED ? (["debug_preview"] as const) : []),
|
|
26
|
-
] as const;
|
|
27
|
-
|
|
28
|
-
const ProcessesParams = Type.Object({
|
|
29
|
-
action: StringEnum(PROCESS_ACTIONS, {
|
|
30
|
-
description: DEBUG_PREVIEW_ENABLED
|
|
31
|
-
? "Action: start (run command), list (show all), output (get recent output), logs (get log file paths), kill (terminate), clear (remove finished), write (write to stdin), debug_preview (temporary UI preview, no side effects)"
|
|
32
|
-
: "Action: start (run command), list (show all), output (get recent output), logs (get log file paths), kill (terminate), clear (remove finished), write (write to stdin)",
|
|
33
|
-
}),
|
|
34
|
-
command: Type.Optional(
|
|
35
|
-
Type.String({ description: "Command to run (required for start)" }),
|
|
36
|
-
),
|
|
37
|
-
name: Type.Optional(
|
|
38
|
-
Type.String({
|
|
39
|
-
description:
|
|
40
|
-
"Friendly name for the process (required for start, e.g. 'backend-dev', 'test-runner')",
|
|
41
|
-
}),
|
|
42
|
-
),
|
|
43
|
-
id: Type.Optional(
|
|
44
|
-
Type.String({
|
|
45
|
-
description:
|
|
46
|
-
"Process ID, returned by start and list actions (required for output/kill/logs/write)",
|
|
47
|
-
}),
|
|
48
|
-
),
|
|
49
|
-
input: Type.Optional(
|
|
50
|
-
Type.String({
|
|
51
|
-
description: "Data to write to process stdin (required for write action)",
|
|
52
|
-
}),
|
|
53
|
-
),
|
|
54
|
-
end: Type.Optional(
|
|
55
|
-
Type.Boolean({
|
|
56
|
-
description:
|
|
57
|
-
"Close stdin after writing (optional for write action, use for programs reading until EOF)",
|
|
58
|
-
}),
|
|
59
|
-
),
|
|
60
|
-
alertOnSuccess: Type.Optional(
|
|
61
|
-
Type.Boolean({
|
|
62
|
-
description:
|
|
63
|
-
"Get a turn to react when process completes successfully (default: false). Use for builds/tests where you need confirmation.",
|
|
64
|
-
}),
|
|
65
|
-
),
|
|
66
|
-
alertOnFailure: Type.Optional(
|
|
67
|
-
Type.Boolean({
|
|
68
|
-
description:
|
|
69
|
-
"Get a turn to react when process fails/crashes (default: true). Use to be alerted of unexpected failures.",
|
|
70
|
-
}),
|
|
71
|
-
),
|
|
72
|
-
alertOnKill: Type.Optional(
|
|
73
|
-
Type.Boolean({
|
|
74
|
-
description:
|
|
75
|
-
"Get a turn to react when process is killed by external signal (default: false). Note: killing via tool never triggers a turn.",
|
|
76
|
-
}),
|
|
77
|
-
),
|
|
78
|
-
preview: Type.Optional(
|
|
79
|
-
StringEnum(["start", "list", "output", "logs", "error"] as const, {
|
|
80
|
-
description:
|
|
81
|
-
"For action=debug_preview only: which rendered result variant to preview (default: start)",
|
|
82
|
-
}),
|
|
83
|
-
),
|
|
84
|
-
cwd: Type.Optional(
|
|
85
|
-
Type.String({
|
|
86
|
-
description:
|
|
87
|
-
"Working directory for the command (for start action). Defaults to the session working directory. Prefer this over 'cd dir && command' shell wrappers.",
|
|
88
|
-
}),
|
|
89
|
-
),
|
|
90
|
-
logWatches: Type.Optional(
|
|
91
|
-
Type.Array(
|
|
92
|
-
Type.Object(
|
|
93
|
-
{
|
|
94
|
-
pattern: Type.String({
|
|
95
|
-
description:
|
|
96
|
-
"Regular expression pattern to match against process output lines",
|
|
97
|
-
}),
|
|
98
|
-
stream: Type.Optional(
|
|
99
|
-
StringEnum(["stdout", "stderr", "both"] as const, {
|
|
100
|
-
description:
|
|
101
|
-
"Which stream to watch (default: both). Use stdout/stderr to reduce noise.",
|
|
102
|
-
}),
|
|
103
|
-
),
|
|
104
|
-
repeat: Type.Optional(
|
|
105
|
-
Type.Boolean({
|
|
106
|
-
description:
|
|
107
|
-
"Trigger every time this pattern matches (default: false, one-time)",
|
|
108
|
-
}),
|
|
109
|
-
),
|
|
110
|
-
},
|
|
111
|
-
{ additionalProperties: false },
|
|
112
|
-
),
|
|
113
|
-
),
|
|
114
|
-
),
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
type ProcessesParamsType = Static<typeof ProcessesParams>;
|
|
118
|
-
|
|
119
|
-
export function setupProcessesTools(pi: ExtensionAPI, manager: ProcessManager) {
|
|
120
|
-
pi.registerTool<typeof ProcessesParams, ProcessesDetails>({
|
|
121
|
-
name: "process",
|
|
122
|
-
label: "Process",
|
|
123
|
-
description: `Manage background processes. Actions:
|
|
124
|
-
- start: Run command in background (requires 'name' and 'command')
|
|
125
|
-
- cwd (optional): Working directory for the command. Defaults to the session working directory. Use the cwd parameter instead of 'cd dir && command' shell wrappers.
|
|
126
|
-
- alertOnSuccess (default: false): Get a turn to react when process completes successfully
|
|
127
|
-
- alertOnFailure (default: true): Get a turn to react when process crashes/fails
|
|
128
|
-
- alertOnKill (default: false): Get a turn to react if killed by external signal (killing via tool never triggers a turn)
|
|
129
|
-
- logWatches (optional): Runtime output watches that trigger immediate alerts while running
|
|
130
|
-
- pattern: regex string to match per output line
|
|
131
|
-
- stream: stdout | stderr | both (default both)
|
|
132
|
-
- repeat: false by default (single-fire). Set true for repeat alerts
|
|
133
|
-
- list: Show all managed processes with their IDs and names
|
|
134
|
-
- output: Get recent stdout/stderr (requires 'id')
|
|
135
|
-
- logs: Get log file paths to inspect with read tool (requires 'id')
|
|
136
|
-
- kill: Terminate a process (requires 'id')
|
|
137
|
-
- clear: Remove all finished processes from the list
|
|
138
|
-
- write: Write to process stdin (requires 'id' and 'input', optional 'end' to close stdin)
|
|
139
|
-
${
|
|
140
|
-
DEBUG_PREVIEW_ENABLED
|
|
141
|
-
? "- debug_preview: Temporary renderer preview for process tool UIs (no process side effects)\n - preview: start | list | output | logs | error (default: start)\n"
|
|
142
|
-
: ""
|
|
143
|
-
}
|
|
144
|
-
Important: You DON'T need to poll or wait for processes. Notifications arrive automatically based on your preferences. Start processes and continue with other work - you'll be informed if something requires attention.
|
|
145
|
-
|
|
146
|
-
Note: User always sees process updates in the UI. The notify flags control whether YOU (the agent) get a turn to react (e.g. check results, fix code, restart).`,
|
|
147
|
-
promptSnippet:
|
|
148
|
-
"Manage background processes without blocking the conversation",
|
|
149
|
-
promptGuidelines: [
|
|
150
|
-
"Use the process tool for long-running commands such as dev servers, test watchers, build watchers, and log tails instead of bash.",
|
|
151
|
-
"Avoid shell background patterns such as &, nohup, disown, or setsid when the process tool fits.",
|
|
152
|
-
"After starting a process, continue other work instead of waiting for it.",
|
|
153
|
-
"Use the pi-processes skill for examples and best practices when a task depends on background processes.",
|
|
154
|
-
],
|
|
155
|
-
|
|
156
|
-
parameters: ProcessesParams,
|
|
157
|
-
|
|
158
|
-
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
159
|
-
return executeAction(params, manager, ctx);
|
|
160
|
-
},
|
|
161
|
-
|
|
162
|
-
renderCall(args: ProcessesParamsType, theme: Theme, _context) {
|
|
163
|
-
return renderActionCall(args, theme);
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
renderResult(
|
|
167
|
-
result: AgentToolResult<ProcessesDetails>,
|
|
168
|
-
options: ToolRenderResultOptions,
|
|
169
|
-
theme: Theme,
|
|
170
|
-
_context,
|
|
171
|
-
) {
|
|
172
|
-
if (options.isPartial) {
|
|
173
|
-
return new Text(theme.fg("muted", "Process: running..."), 0, 0);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const { details } = result;
|
|
177
|
-
|
|
178
|
-
// Framework sets details to {} when tool throws.
|
|
179
|
-
// Detect by checking for missing expected fields.
|
|
180
|
-
if (!details?.action) {
|
|
181
|
-
const textBlock = result.content.find((c) => c.type === "text");
|
|
182
|
-
const errorMsg =
|
|
183
|
-
(textBlock?.type === "text" && textBlock.text) ||
|
|
184
|
-
"Tool execution failed";
|
|
185
|
-
return new Text(theme.fg("error", errorMsg), 0, 0);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (!details.success) {
|
|
189
|
-
return new ToolBody(
|
|
190
|
-
{
|
|
191
|
-
fields: [
|
|
192
|
-
{
|
|
193
|
-
label: "Error",
|
|
194
|
-
value: theme.fg("error", details.message),
|
|
195
|
-
showCollapsed: true,
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
|
-
},
|
|
199
|
-
options,
|
|
200
|
-
theme,
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return renderActionResult(result, options, theme);
|
|
205
|
-
},
|
|
206
|
-
});
|
|
207
|
-
}
|
package/src/utils/ansi.test.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { stripAnsi } from "./ansi";
|
|
3
|
-
|
|
4
|
-
describe("stripAnsi", () => {
|
|
5
|
-
it("strips CSI styling sequences", () => {
|
|
6
|
-
expect(stripAnsi("\u001b[31mred\u001b[0m")).toBe("red");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it("strips generic OSC sequences", () => {
|
|
10
|
-
expect(stripAnsi("\u001b]0;title\u0007hello")).toBe("hello");
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("strips carriage returns and other control chars that can corrupt TUI rendering", () => {
|
|
14
|
-
expect(stripAnsi("step 1\rstep 2\b\b done")).toBe("step 1step 2 done");
|
|
15
|
-
expect(stripAnsi("null\u0000byte")).toBe("nullbyte");
|
|
16
|
-
expect(stripAnsi("delete\u007fchar")).toBe("deletechar");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("preserves tabs and newlines", () => {
|
|
20
|
-
expect(stripAnsi("one\ttwo\nthree")).toBe("one\ttwo\nthree");
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type * as nodeFs from "node:fs";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { resolveShellExecutable } from "./command-executor";
|
|
5
|
-
|
|
6
|
-
vi.mock("node:fs", async (importOriginal) => {
|
|
7
|
-
const actual = await importOriginal<typeof nodeFs>();
|
|
8
|
-
return { ...actual, existsSync: vi.fn() };
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const existsSyncMock = vi.mocked(existsSync);
|
|
12
|
-
|
|
13
|
-
describe("resolveShellExecutable", () => {
|
|
14
|
-
it("prefers shell configured in settings when it is an existing absolute path", () => {
|
|
15
|
-
existsSyncMock.mockImplementation(
|
|
16
|
-
(path) => path === "/nix/store/abc-bash-5.3/bin/bash",
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
const resolved = resolveShellExecutable({
|
|
20
|
-
configuredShell: "/nix/store/abc-bash-5.3/bin/bash",
|
|
21
|
-
knownPaths: ["/bin/bash", "/usr/bin/bash"],
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
expect(resolved).toBe("/nix/store/abc-bash-5.3/bin/bash");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("falls back to first existing known shell path", () => {
|
|
28
|
-
existsSyncMock.mockImplementation((path) => path === "/usr/bin/bash");
|
|
29
|
-
|
|
30
|
-
const resolved = resolveShellExecutable({
|
|
31
|
-
configuredShell: undefined,
|
|
32
|
-
knownPaths: ["/bin/bash", "/usr/bin/bash", "/usr/local/bin/bash"],
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
expect(resolved).toBe("/usr/bin/bash");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("throws when no configured/known shell path exists", () => {
|
|
39
|
-
existsSyncMock.mockReturnValue(false);
|
|
40
|
-
|
|
41
|
-
expect(() =>
|
|
42
|
-
resolveShellExecutable({
|
|
43
|
-
configuredShell: undefined,
|
|
44
|
-
knownPaths: ["/bin/bash", "/usr/bin/bash"],
|
|
45
|
-
}),
|
|
46
|
-
).toThrow(/shell/i);
|
|
47
|
-
});
|
|
48
|
-
});
|
package/src/utils/keybindings.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Keyboard shortcuts configuration for the Process Dock.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface ProcessesKeybindings {
|
|
6
|
-
/** Toggle dock visibility (global) */
|
|
7
|
-
toggleDock: string;
|
|
8
|
-
/** Scroll logs up */
|
|
9
|
-
scrollUp: string;
|
|
10
|
-
/** Scroll logs down */
|
|
11
|
-
scrollDown: string;
|
|
12
|
-
/** Focus previous process */
|
|
13
|
-
prevProcess: string;
|
|
14
|
-
/** Focus next process */
|
|
15
|
-
nextProcess: string;
|
|
16
|
-
/** Toggle focus mode */
|
|
17
|
-
toggleFocus: string;
|
|
18
|
-
/** Kill focused process */
|
|
19
|
-
killProcess: string;
|
|
20
|
-
/** Clear finished processes */
|
|
21
|
-
clearFinished: string;
|
|
22
|
-
/** Collapse/close dock */
|
|
23
|
-
closeDock: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const DEFAULT_KEYBINDINGS: ProcessesKeybindings = {
|
|
27
|
-
toggleDock: "", // Disabled - conflicts with editor shortcuts
|
|
28
|
-
scrollUp: "k",
|
|
29
|
-
scrollDown: "j",
|
|
30
|
-
prevProcess: "h",
|
|
31
|
-
nextProcess: "l",
|
|
32
|
-
toggleFocus: "f",
|
|
33
|
-
killProcess: "x",
|
|
34
|
-
clearFinished: "c",
|
|
35
|
-
closeDock: "q",
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Interface for config that may contain keybindings overrides
|
|
40
|
-
*/
|
|
41
|
-
export interface ProcessesConfigKeybindings {
|
|
42
|
-
toggleDock?: string;
|
|
43
|
-
scrollUp?: string;
|
|
44
|
-
scrollDown?: string;
|
|
45
|
-
prevProcess?: string;
|
|
46
|
-
nextProcess?: string;
|
|
47
|
-
toggleFocus?: string;
|
|
48
|
-
killProcess?: string;
|
|
49
|
-
clearFinished?: string;
|
|
50
|
-
closeDock?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Load keybindings from config, falling back to defaults.
|
|
55
|
-
*/
|
|
56
|
-
export function loadKeybindings(config: {
|
|
57
|
-
keybindings?: ProcessesConfigKeybindings;
|
|
58
|
-
}): ProcessesKeybindings {
|
|
59
|
-
const user = config.keybindings ?? {};
|
|
60
|
-
return {
|
|
61
|
-
toggleDock: user.toggleDock ?? DEFAULT_KEYBINDINGS.toggleDock,
|
|
62
|
-
scrollUp: user.scrollUp ?? DEFAULT_KEYBINDINGS.scrollUp,
|
|
63
|
-
scrollDown: user.scrollDown ?? DEFAULT_KEYBINDINGS.scrollDown,
|
|
64
|
-
prevProcess: user.prevProcess ?? DEFAULT_KEYBINDINGS.prevProcess,
|
|
65
|
-
nextProcess: user.nextProcess ?? DEFAULT_KEYBINDINGS.nextProcess,
|
|
66
|
-
toggleFocus: user.toggleFocus ?? DEFAULT_KEYBINDINGS.toggleFocus,
|
|
67
|
-
killProcess: user.killProcess ?? DEFAULT_KEYBINDINGS.killProcess,
|
|
68
|
-
clearFinished: user.clearFinished ?? DEFAULT_KEYBINDINGS.clearFinished,
|
|
69
|
-
closeDock: user.closeDock ?? DEFAULT_KEYBINDINGS.closeDock,
|
|
70
|
-
};
|
|
71
|
-
}
|