@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.
Files changed (174) hide show
  1. package/CONTRIBUTING.md +40 -42
  2. package/README.md +54 -84
  3. package/extensions/process-tabs.ts +26 -0
  4. package/extensions/processes/client.ts +194 -0
  5. package/extensions/processes/commands/clear.ts +29 -0
  6. package/extensions/processes/commands/kill.ts +152 -0
  7. package/extensions/processes/commands/overview.ts +102 -0
  8. package/extensions/processes/components/overview-component.ts +729 -0
  9. package/extensions/processes/components/overview-panel.ts +177 -0
  10. package/extensions/processes/config/defaults.ts +28 -0
  11. package/extensions/processes/config/index.ts +13 -0
  12. package/extensions/processes/config/loader.ts +62 -0
  13. package/extensions/processes/config/migrations/000-import-legacy-process-config.ts +113 -0
  14. package/extensions/processes/config/migrations/001-v0-9-4-to-v0-10-0-config.ts +184 -0
  15. package/extensions/processes/config/migrations/002-stamp-v0-10-0-config-version.ts +21 -0
  16. package/extensions/processes/config/migrations/index.ts +25 -0
  17. package/extensions/processes/config/schema.ts +9 -0
  18. package/extensions/processes/config/types.ts +72 -0
  19. package/extensions/processes/constants.ts +1 -0
  20. package/extensions/processes/handlers/commands.ts +113 -0
  21. package/extensions/processes/handlers/kill-process.ts +31 -0
  22. package/extensions/processes/handlers/notifications.ts +147 -0
  23. package/extensions/processes/handlers/requests.ts +114 -0
  24. package/extensions/processes/handlers/subscriptions.ts +144 -0
  25. package/extensions/processes/hooks/background-blocker.ts +201 -0
  26. package/extensions/processes/hooks/cleanup.ts +43 -0
  27. package/extensions/processes/hooks/event-bridge.ts +32 -0
  28. package/extensions/processes/i18n/index.ts +3 -0
  29. package/extensions/processes/i18n/messages.ts +27 -0
  30. package/extensions/processes/i18n/translator.ts +49 -0
  31. package/extensions/processes/index.ts +109 -0
  32. package/extensions/processes/message-renderer.ts +117 -0
  33. package/extensions/processes/notification-sender.ts +43 -0
  34. package/extensions/processes/notifications/classify.ts +27 -0
  35. package/extensions/processes/notifications/log-matchers.ts +146 -0
  36. package/extensions/processes/notifications/registry.ts +225 -0
  37. package/extensions/processes/notifications/render-content.ts +122 -0
  38. package/extensions/processes/notifications/service.ts +336 -0
  39. package/extensions/processes/notifications/types.ts +11 -0
  40. package/extensions/processes/settings/apply-setting-change.ts +30 -0
  41. package/extensions/processes/settings/build-sections.ts +420 -0
  42. package/extensions/processes/settings/index.ts +42 -0
  43. package/extensions/processes/tools/clear/index.ts +21 -0
  44. package/extensions/processes/tools/clear/render.ts +40 -0
  45. package/extensions/processes/tools/components/index.ts +4 -0
  46. package/extensions/processes/tools/components/process-action-header.ts +31 -0
  47. package/extensions/processes/tools/components/process-action-title.ts +17 -0
  48. package/extensions/processes/tools/components/tool-layout.ts +70 -0
  49. package/extensions/processes/tools/components/watch.ts +53 -0
  50. package/extensions/processes/tools/index.ts +265 -0
  51. package/extensions/processes/tools/list/index.ts +157 -0
  52. package/extensions/processes/tools/list/render.ts +211 -0
  53. package/extensions/processes/tools/notify.ts +191 -0
  54. package/extensions/processes/tools/output/index.ts +307 -0
  55. package/extensions/processes/tools/output/render.ts +229 -0
  56. package/extensions/processes/tools/schema.ts +263 -0
  57. package/extensions/processes/tools/start/index.ts +64 -0
  58. package/extensions/processes/tools/start/render.ts +67 -0
  59. package/extensions/processes/tools/stop/index.ts +35 -0
  60. package/extensions/processes/tools/stop/render.ts +43 -0
  61. package/extensions/processes/tools/update/index.ts +320 -0
  62. package/extensions/processes/tools/update/render.ts +251 -0
  63. package/extensions/processes/tools/utils.ts +112 -0
  64. package/extensions/processes/tools/watch-format.ts +14 -0
  65. package/extensions/processes/tools/write/index.ts +75 -0
  66. package/extensions/processes/tools/write/render.ts +68 -0
  67. package/extensions/processes/utils/truncate.ts +285 -0
  68. package/extensions/processes-dock/client.ts +60 -0
  69. package/extensions/processes-dock/commands/dock.ts +70 -0
  70. package/extensions/processes-dock/commands/pin.ts +166 -0
  71. package/extensions/processes-dock/components/log-dock-component.ts +375 -0
  72. package/extensions/processes-dock/dock-state.ts +33 -0
  73. package/extensions/processes-dock/index.ts +28 -0
  74. package/extensions/processes-dock/logs-client.ts +5 -0
  75. package/extensions/processes-dock/widget/setup.ts +520 -0
  76. package/extensions/processes-dock/widget/status.ts +149 -0
  77. package/extensions/processes-dock/widget/types.ts +16 -0
  78. package/extensions/processes-logs/client.ts +51 -0
  79. package/extensions/processes-logs/commands/logs.ts +108 -0
  80. package/extensions/processes-logs/completions.ts +31 -0
  81. package/extensions/processes-logs/components/log-file-viewer.ts +274 -0
  82. package/extensions/processes-logs/components/log-overlay-component.ts +685 -0
  83. package/extensions/processes-logs/index.ts +27 -0
  84. package/extensions/processes-logs/logs-client.ts +101 -0
  85. package/extensions/shared/line-buffer.ts +35 -0
  86. package/extensions/shared/output-payload.ts +28 -0
  87. package/extensions/shared/ui.ts +146 -0
  88. package/package.json +29 -10
  89. package/schema.json +134 -0
  90. package/skills/pi-processes/SKILL.md +496 -25
  91. package/src/get-manager.ts +15 -0
  92. package/src/manager/index.ts +182 -0
  93. package/src/manager/internal-types.ts +130 -0
  94. package/src/manager/limits.ts +15 -0
  95. package/src/manager/process-log-store.ts +422 -0
  96. package/src/manager/process-output.ts +345 -0
  97. package/src/manager/process-registry.ts +78 -0
  98. package/src/manager/process-runtime-controller.ts +519 -0
  99. package/src/protocol/broadcasts.ts +14 -0
  100. package/src/protocol/channels.ts +30 -0
  101. package/src/protocol/commands.ts +24 -0
  102. package/src/protocol/index.ts +34 -0
  103. package/src/protocol/logs.ts +23 -0
  104. package/src/protocol/notifications.ts +48 -0
  105. package/src/protocol/requests.ts +76 -0
  106. package/src/types.ts +66 -0
  107. package/src/utils/ansi.ts +2 -4
  108. package/src/utils/format.ts +24 -32
  109. package/src/utils/index.ts +5 -1
  110. package/src/utils/is-record.ts +3 -0
  111. package/src/utils/match-line.ts +32 -0
  112. package/src/utils/platform.ts +13 -0
  113. package/src/utils/process-group.ts +4 -0
  114. package/src/utils/shorten-path.ts +11 -0
  115. package/src/utils/signals.ts +22 -0
  116. package/src/commands/clear/command.ts +0 -14
  117. package/src/commands/clear/index.ts +0 -1
  118. package/src/commands/completions.ts +0 -38
  119. package/src/commands/dock/command.ts +0 -29
  120. package/src/commands/dock/index.ts +0 -1
  121. package/src/commands/index.ts +0 -33
  122. package/src/commands/kill/command.ts +0 -69
  123. package/src/commands/kill/index.ts +0 -1
  124. package/src/commands/logs/command.ts +0 -47
  125. package/src/commands/logs/index.ts +0 -1
  126. package/src/commands/pick-process.ts +0 -34
  127. package/src/commands/pin/command.ts +0 -34
  128. package/src/commands/pin/index.ts +0 -1
  129. package/src/commands/processes/command.ts +0 -39
  130. package/src/commands/processes/index.ts +0 -1
  131. package/src/commands/settings/apply-setting-change.ts +0 -72
  132. package/src/commands/settings/build-sections.ts +0 -160
  133. package/src/commands/settings/command.ts +0 -20
  134. package/src/commands/settings/index.ts +0 -1
  135. package/src/components/log-dock-component.test.ts +0 -29
  136. package/src/components/log-dock-component.ts +0 -236
  137. package/src/components/log-file-viewer.ts +0 -317
  138. package/src/components/log-overlay-component.ts +0 -546
  139. package/src/components/panel-helpers.ts +0 -37
  140. package/src/components/process-picker-component.ts +0 -166
  141. package/src/components/processes-component.ts +0 -485
  142. package/src/components/status-format.ts +0 -38
  143. package/src/config.ts +0 -107
  144. package/src/constants/index.ts +0 -16
  145. package/src/constants/types.ts +0 -119
  146. package/src/hooks/background-blocker.ts +0 -66
  147. package/src/hooks/cleanup.ts +0 -10
  148. package/src/hooks/index.ts +0 -32
  149. package/src/hooks/message-renderer.ts +0 -115
  150. package/src/hooks/process-end.ts +0 -69
  151. package/src/hooks/process-watch.ts +0 -85
  152. package/src/hooks/utils.ts +0 -23
  153. package/src/hooks/widget/index.ts +0 -2
  154. package/src/hooks/widget/setup.ts +0 -167
  155. package/src/hooks/widget/status-widget.ts +0 -105
  156. package/src/hooks/widget/types.ts +0 -20
  157. package/src/index.ts +0 -35
  158. package/src/manager.test.ts +0 -331
  159. package/src/manager.ts +0 -758
  160. package/src/tools/actions/clear.ts +0 -20
  161. package/src/tools/actions/debug.ts +0 -155
  162. package/src/tools/actions/index.ts +0 -171
  163. package/src/tools/actions/kill.ts +0 -89
  164. package/src/tools/actions/list.ts +0 -188
  165. package/src/tools/actions/logs.ts +0 -117
  166. package/src/tools/actions/output-truncate.ts +0 -187
  167. package/src/tools/actions/output.test.ts +0 -392
  168. package/src/tools/actions/output.ts +0 -447
  169. package/src/tools/actions/start.ts +0 -245
  170. package/src/tools/actions/write.ts +0 -113
  171. package/src/tools/index.ts +0 -207
  172. package/src/utils/ansi.test.ts +0 -22
  173. package/src/utils/command-executor.test.ts +0 -48
  174. 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
+ }