@aliou/pi-processes 0.9.5 → 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.
Files changed (173) 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 +34 -9
  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 +499 -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/shorten-path.ts +11 -0
  114. package/src/utils/signals.ts +22 -0
  115. package/src/commands/clear/command.ts +0 -14
  116. package/src/commands/clear/index.ts +0 -1
  117. package/src/commands/completions.ts +0 -38
  118. package/src/commands/dock/command.ts +0 -29
  119. package/src/commands/dock/index.ts +0 -1
  120. package/src/commands/index.ts +0 -33
  121. package/src/commands/kill/command.ts +0 -69
  122. package/src/commands/kill/index.ts +0 -1
  123. package/src/commands/logs/command.ts +0 -47
  124. package/src/commands/logs/index.ts +0 -1
  125. package/src/commands/pick-process.ts +0 -34
  126. package/src/commands/pin/command.ts +0 -34
  127. package/src/commands/pin/index.ts +0 -1
  128. package/src/commands/processes/command.ts +0 -39
  129. package/src/commands/processes/index.ts +0 -1
  130. package/src/commands/settings/apply-setting-change.ts +0 -72
  131. package/src/commands/settings/build-sections.ts +0 -160
  132. package/src/commands/settings/command.ts +0 -20
  133. package/src/commands/settings/index.ts +0 -1
  134. package/src/components/log-dock-component.test.ts +0 -29
  135. package/src/components/log-dock-component.ts +0 -236
  136. package/src/components/log-file-viewer.ts +0 -317
  137. package/src/components/log-overlay-component.ts +0 -546
  138. package/src/components/panel-helpers.ts +0 -37
  139. package/src/components/process-picker-component.ts +0 -166
  140. package/src/components/processes-component.ts +0 -485
  141. package/src/components/status-format.ts +0 -38
  142. package/src/config.ts +0 -107
  143. package/src/constants/index.ts +0 -16
  144. package/src/constants/types.ts +0 -119
  145. package/src/hooks/background-blocker.ts +0 -66
  146. package/src/hooks/cleanup.ts +0 -10
  147. package/src/hooks/index.ts +0 -32
  148. package/src/hooks/message-renderer.ts +0 -115
  149. package/src/hooks/process-end.ts +0 -69
  150. package/src/hooks/process-watch.ts +0 -85
  151. package/src/hooks/utils.ts +0 -23
  152. package/src/hooks/widget/index.ts +0 -2
  153. package/src/hooks/widget/setup.ts +0 -167
  154. package/src/hooks/widget/status-widget.ts +0 -105
  155. package/src/hooks/widget/types.ts +0 -20
  156. package/src/index.ts +0 -35
  157. package/src/manager.test.ts +0 -331
  158. package/src/manager.ts +0 -758
  159. package/src/tools/actions/clear.ts +0 -20
  160. package/src/tools/actions/debug.ts +0 -155
  161. package/src/tools/actions/index.ts +0 -171
  162. package/src/tools/actions/kill.ts +0 -89
  163. package/src/tools/actions/list.ts +0 -188
  164. package/src/tools/actions/logs.ts +0 -117
  165. package/src/tools/actions/output-truncate.ts +0 -187
  166. package/src/tools/actions/output.test.ts +0 -392
  167. package/src/tools/actions/output.ts +0 -447
  168. package/src/tools/actions/start.ts +0 -245
  169. package/src/tools/actions/write.ts +0 -113
  170. package/src/tools/index.ts +0 -207
  171. package/src/utils/ansi.test.ts +0 -22
  172. package/src/utils/command-executor.test.ts +0 -48
  173. 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
+ }