@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.
Files changed (171) 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 +47 -20
  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 -106
  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 -148
  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.ts +0 -269
  166. package/src/tools/actions/start.ts +0 -245
  167. package/src/tools/actions/write.ts +0 -113
  168. package/src/tools/index.ts +0 -207
  169. package/src/utils/ansi.test.ts +0 -22
  170. package/src/utils/command-executor.test.ts +0 -48
  171. package/src/utils/keybindings.ts +0 -71
@@ -0,0 +1,101 @@
1
+ import type { EventBus } from "@earendil-works/pi-coding-agent";
2
+ import {
3
+ CHANNELS,
4
+ type LogsChunkPayload,
5
+ type LogsSubscribePayload,
6
+ type LogsUnsubscribePayload,
7
+ } from "../../src/protocol";
8
+ import { isRecord } from "../../src/utils/is-record";
9
+
10
+ export type ProcessLogLine = { type: "stdout" | "stderr"; text: string };
11
+
12
+ export interface LogsConnection {
13
+ initialLines: ProcessLogLine[];
14
+ onChunk: (callback: (lines: ProcessLogLine[]) => void) => () => void;
15
+ unsubscribe: () => void;
16
+ }
17
+
18
+ export function connectToProcessLogs(
19
+ events: EventBus,
20
+ processId: string,
21
+ opts: { tailLines?: number } = {},
22
+ ): LogsConnection | { ok: false; error: string } {
23
+ const subscriberId = `processes-logs-${Date.now()}-${Math.random().toString(36).slice(2)}`;
24
+ let initialLines: ProcessLogLine[] = [];
25
+ let error: string | null = null;
26
+ let replied = false;
27
+ let disposed = false;
28
+ const chunkCallbacks = new Set<(lines: ProcessLogLine[]) => void>();
29
+
30
+ const disposeChunkListener = events.on(CHANNELS.LOGS_CHUNK, (raw) => {
31
+ if (disposed) return;
32
+ if (!isLogsChunkPayload(raw)) return;
33
+ const chunk = raw;
34
+ if (chunk.subscriberId !== subscriberId || chunk.processId !== processId)
35
+ return;
36
+
37
+ for (const callback of chunkCallbacks) callback(chunk.lines);
38
+ });
39
+
40
+ const payload: LogsSubscribePayload = {
41
+ subscriberId,
42
+ processId,
43
+ tailLines: opts.tailLines,
44
+ reply: (result) => {
45
+ replied = true;
46
+ if (result.ok) {
47
+ initialLines = result.initialLines;
48
+ } else {
49
+ error = result.error;
50
+ }
51
+ },
52
+ };
53
+
54
+ events.emit(CHANNELS.LOGS_SUBSCRIBE, payload);
55
+
56
+ if (!replied) {
57
+ disposeChunkListener();
58
+ return {
59
+ ok: false,
60
+ error: "processes core extension did not reply to log subscription",
61
+ };
62
+ }
63
+ if (error) {
64
+ disposeChunkListener();
65
+ return { ok: false, error };
66
+ }
67
+
68
+ return {
69
+ initialLines,
70
+ onChunk: (callback) => {
71
+ chunkCallbacks.add(callback);
72
+ return () => chunkCallbacks.delete(callback);
73
+ },
74
+ unsubscribe: () => {
75
+ if (disposed) return;
76
+ disposed = true;
77
+ chunkCallbacks.clear();
78
+ disposeChunkListener();
79
+ const unsubscribePayload: LogsUnsubscribePayload = { subscriberId };
80
+ events.emit(CHANNELS.LOGS_UNSUBSCRIBE, unsubscribePayload);
81
+ },
82
+ };
83
+ }
84
+
85
+ function isLogsChunkPayload(payload: unknown): payload is LogsChunkPayload {
86
+ return (
87
+ isRecord(payload) &&
88
+ typeof payload.subscriberId === "string" &&
89
+ typeof payload.processId === "string" &&
90
+ Array.isArray(payload.lines) &&
91
+ payload.lines.every(isProcessLogLine)
92
+ );
93
+ }
94
+
95
+ function isProcessLogLine(line: unknown): line is ProcessLogLine {
96
+ return (
97
+ isRecord(line) &&
98
+ (line.type === "stdout" || line.type === "stderr") &&
99
+ typeof line.text === "string"
100
+ );
101
+ }
@@ -0,0 +1,35 @@
1
+ export const OUTPUT_DROPPED_MARKER_TYPE = "stderr" as const;
2
+
3
+ export function buildDroppedOutputLine(count: number): {
4
+ type: typeof OUTPUT_DROPPED_MARKER_TYPE;
5
+ text: string;
6
+ } {
7
+ return {
8
+ type: OUTPUT_DROPPED_MARKER_TYPE,
9
+ text: `… ${count} lines dropped (output too fast)`,
10
+ };
11
+ }
12
+
13
+ export function trimToBudget<T>(
14
+ lines: T[],
15
+ maxLines: number,
16
+ maxBytes: number,
17
+ textOf: (line: T) => string = (line) => (line as { text: string }).text,
18
+ ): T[] {
19
+ if (lines.length === 0) return [];
20
+
21
+ const lineLimit = Math.max(1, maxLines);
22
+ const out =
23
+ lines.length > lineLimit ? lines.slice(-lineLimit) : lines.slice();
24
+ let bytes = 0;
25
+
26
+ for (let index = out.length - 1; index >= 0; index--) {
27
+ bytes += Buffer.byteLength(textOf(out[index]), "utf-8");
28
+ if (bytes > maxBytes) {
29
+ // Keep the newest line even when it alone exceeds the whole budget.
30
+ return index === out.length - 1 ? out.slice(index) : out.slice(index + 1);
31
+ }
32
+ }
33
+
34
+ return out;
35
+ }
@@ -0,0 +1,28 @@
1
+ import type { ProcessesOutputChangedPayload } from "../../src/protocol";
2
+ import { isRecord } from "../../src/utils/is-record";
3
+
4
+ export function isOutputChangedPayload(
5
+ payload: unknown,
6
+ ): payload is ProcessesOutputChangedPayload {
7
+ return (
8
+ isRecord(payload) &&
9
+ typeof payload.id === "string" &&
10
+ (payload.appendedText === undefined ||
11
+ (Array.isArray(payload.appendedText) &&
12
+ payload.appendedText.every(isOutputLine))) &&
13
+ (payload.droppedLines === undefined ||
14
+ (typeof payload.droppedLines === "number" &&
15
+ Number.isSafeInteger(payload.droppedLines) &&
16
+ payload.droppedLines > 0))
17
+ );
18
+ }
19
+
20
+ function isOutputLine(
21
+ value: unknown,
22
+ ): value is { type: "stdout" | "stderr"; text: string } {
23
+ return (
24
+ isRecord(value) &&
25
+ (value.type === "stdout" || value.type === "stderr") &&
26
+ typeof value.text === "string"
27
+ );
28
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Shared extension-UI primitives used across the processes, processes-logs,
3
+ * and processes-dock extensions.
4
+ *
5
+ * This module lives outside pi-agnostic `src/` because it depends on the Pi
6
+ * TUI (`Component`, `Theme`). It consolidates the tiny render-component
7
+ * copies and the status-display helpers that were duplicated across the three
8
+ * extensions.
9
+ */
10
+
11
+ import type { Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
12
+ import { type Component, visibleWidth } from "@earendil-works/pi-tui";
13
+
14
+ import { LIVE_STATUSES, type ProcessInfo } from "../../src/types";
15
+ import { formatStatus } from "../../src/utils/format";
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Render components
19
+ // ---------------------------------------------------------------------------
20
+
21
+ /** Render a single line produced by a width-aware callback. */
22
+ export class LineComponent implements Component {
23
+ constructor(private readonly renderLine: (width: number) => string) {}
24
+
25
+ render(width: number): string[] {
26
+ return [this.renderLine(width)];
27
+ }
28
+
29
+ invalidate(): void {}
30
+ }
31
+
32
+ /** Render multiple lines produced by a width-aware callback. */
33
+ export class LinesComponent implements Component {
34
+ constructor(private readonly renderLines: (width: number) => string[]) {}
35
+
36
+ render(width: number): string[] {
37
+ return this.renderLines(width);
38
+ }
39
+
40
+ invalidate(): void {}
41
+ }
42
+
43
+ /** Render a horizontal rule line sized to the available width. */
44
+ export class RuleComponent implements Component {
45
+ constructor(private readonly theme: Theme) {}
46
+
47
+ render(width: number): string[] {
48
+ return [this.theme.fg("dim", "─".repeat(Math.max(0, width)))];
49
+ }
50
+
51
+ invalidate(): void {}
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Name column / tab width
56
+ // ---------------------------------------------------------------------------
57
+
58
+ /** Maximum visible width for a process name or tab label. */
59
+ export const MAX_TAB_NAME = 12;
60
+
61
+ /** Minimum width for the dock log-line sidebar column. */
62
+ export const MIN_NAME_COLUMN = 4;
63
+
64
+ /**
65
+ * Compute the sidebar width for a set of processes: the longest name
66
+ * clamped to [min, max]. Use this instead of hardcoding a fixed width so
67
+ * short names (`api`, `web`) don't get padded to 12 columns.
68
+ */
69
+ export function clampNameColumn(
70
+ processes: ProcessInfo[],
71
+ max: number = MAX_TAB_NAME,
72
+ min: number = MIN_NAME_COLUMN,
73
+ ): number {
74
+ const longest = processes.reduce(
75
+ (acc, p) => Math.max(acc, visibleWidth(p.name)),
76
+ 0,
77
+ );
78
+ return Math.min(Math.max(longest, min), max);
79
+ }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Status formatting
83
+ // ---------------------------------------------------------------------------
84
+
85
+ /**
86
+ * The color a process's status should render in. Shared by the status dot
87
+ * and process name so the dot and the name always agree on color.
88
+ */
89
+ export function statusColor(process: ProcessInfo): ThemeColor {
90
+ if (process.success === false && process.status !== "killed") {
91
+ return "error";
92
+ }
93
+ if (process.status === "terminating") {
94
+ return "warning";
95
+ }
96
+ if (LIVE_STATUSES.has(process.status)) {
97
+ return "accent";
98
+ }
99
+ if (process.status === "exited" && process.success) {
100
+ return "success";
101
+ }
102
+ return "dim";
103
+ }
104
+
105
+ /**
106
+ * Render the status indicator dot for a process.
107
+ *
108
+ * Glyph carries state class; color refines:
109
+ * - `!` (error) for failures/crashes, unless intentionally killed.
110
+ * - `●` (warning) for terminating.
111
+ * - `●`/`○` (accent/dim) for live processes, depending on `active`.
112
+ * - `✓` (success) for a clean exit.
113
+ * - `■` (dim) for other terminal states (e.g. killed).
114
+ */
115
+ export function statusDot(
116
+ process: ProcessInfo,
117
+ active: boolean,
118
+ theme: Theme,
119
+ ): string {
120
+ if (process.success === false && process.status !== "killed") {
121
+ return theme.fg("error", "!");
122
+ }
123
+ if (process.status === "terminating") {
124
+ return theme.fg("warning", "●");
125
+ }
126
+ if (LIVE_STATUSES.has(process.status)) {
127
+ return active ? theme.fg("accent", "●") : theme.fg("dim", "○");
128
+ }
129
+ if (process.status === "exited" && process.success) {
130
+ return theme.fg("success", "✓");
131
+ }
132
+ return theme.fg("dim", "■");
133
+ }
134
+
135
+ /**
136
+ * Build the `description` string for process picker items and autocomplete
137
+ * completions: `"running — pnpm dev"`. Shared so `/ps:kill`, `/ps:logs`,
138
+ * `/ps:pin`, and the logs completions stay consistent.
139
+ */
140
+ export function formatProcessSelectionDescription(
141
+ process: ProcessInfo,
142
+ suffix = "",
143
+ ): string {
144
+ const base = `${formatStatus(process)} — ${process.command}`;
145
+ return suffix ? `${base}${suffix}` : base;
146
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-processes",
3
- "version": "0.9.4",
3
+ "version": "0.10.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,
@@ -16,25 +16,34 @@
16
16
  },
17
17
  "pi": {
18
18
  "extensions": [
19
- "./src/index.ts"
19
+ "./extensions/processes/index.ts",
20
+ "./extensions/processes-logs/index.ts",
21
+ "./extensions/processes-dock/index.ts"
20
22
  ],
21
23
  "skills": [
22
24
  "./skills/pi-processes"
23
25
  ],
24
- "video": "https://assets.aliou.me/github/aliou/pi-processes/demo.mp4"
26
+ "video": "https://assets.aliou.me/pi-extensions/demos/pi-processes.mp4"
25
27
  },
26
28
  "publishConfig": {
27
29
  "access": "public"
28
30
  },
31
+ "engines": {
32
+ "node": ">=22.19.0"
33
+ },
29
34
  "files": [
30
35
  "src",
36
+ "!src/**/*.test.ts",
37
+ "extensions",
38
+ "!extensions/**/*.test.ts",
31
39
  "skills",
40
+ "schema.json",
32
41
  "README.md",
33
42
  "CONTRIBUTING.md"
34
43
  ],
35
44
  "dependencies": {
36
- "@aliou/pi-utils-settings": "^0.15.1",
37
- "@aliou/pi-utils-ui": "^0.4.1",
45
+ "@aliou/pi-utils-settings": "^0.18.0",
46
+ "@aliou/pi-utils-ui": "^0.5.0",
38
47
  "@aliou/sh": "^0.1.0"
39
48
  },
40
49
  "peerDependencies": {
@@ -46,12 +55,40 @@
46
55
  "devDependencies": {
47
56
  "@aliou/biome-plugins": "^0.8.1",
48
57
  "@biomejs/biome": "^2.4.15",
49
- "@changesets/cli": "^2.31.0",
50
- "@types/node": "^25.9.1",
58
+ "@changesets/cli": "^2.27.11",
59
+ "@earendil-works/pi-ai": "0.80.3",
60
+ "@earendil-works/pi-coding-agent": "0.80.3",
61
+ "@earendil-works/pi-tui": "0.80.3",
62
+ "@golevelup/ts-vitest": "^4.0.0",
63
+ "@types/node": "^25.0.10",
51
64
  "husky": "^9.1.7",
52
- "typescript": "^6.0.3",
53
- "vitest": "^4.1.7"
65
+ "memfs": "^4.57.2",
66
+ "ts-json-schema-generator": "^2.9.0",
67
+ "typebox": "1.1.38",
68
+ "typescript": "^5.9.3",
69
+ "vitest": "^4.1.5"
70
+ },
71
+ "pnpm": {
72
+ "overrides": {
73
+ "@earendil-works/pi-ai": "$@earendil-works/pi-coding-agent",
74
+ "@earendil-works/pi-tui": "$@earendil-works/pi-coding-agent"
75
+ }
54
76
  },
77
+ "scripts": {
78
+ "typecheck": "tsc --noEmit",
79
+ "lint": "biome check",
80
+ "format": "biome check --write",
81
+ "gen:schema": "ts-json-schema-generator --path extensions/processes/config/types.ts --type ProcessConfig --no-type-check -o schema.json",
82
+ "check:schema": "ts-json-schema-generator --path extensions/processes/config/types.ts --type ProcessConfig --no-type-check -o /tmp/pi-processes-schema-check.json && diff -q schema.json /tmp/pi-processes-schema-check.json",
83
+ "check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
84
+ "prepare": "[ -d .git ] && husky || true",
85
+ "changeset": "changeset",
86
+ "version": "changeset version",
87
+ "test": "vitest run",
88
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
89
+ "release": "pnpm changeset publish"
90
+ },
91
+ "packageManager": "pnpm@10.26.1",
55
92
  "peerDependenciesMeta": {
56
93
  "@earendil-works/pi-ai": {
57
94
  "optional": true
@@ -65,15 +102,5 @@
65
102
  "typebox": {
66
103
  "optional": true
67
104
  }
68
- },
69
- "scripts": {
70
- "typecheck": "tsc --noEmit",
71
- "lint": "biome check",
72
- "format": "biome check --write",
73
- "check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
74
- "changeset": "changeset",
75
- "version": "changeset version",
76
- "test": "vitest run",
77
- "release": "pnpm changeset publish"
78
105
  }
79
- }
106
+ }
package/schema.json ADDED
@@ -0,0 +1,134 @@
1
+ {
2
+ "$ref": "#/definitions/ProcessConfig",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "definitions": {
5
+ "ExecutionConfig": {
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "shellPath": {
9
+ "description": "Absolute shell executable used to run process commands.",
10
+ "type": "string"
11
+ }
12
+ },
13
+ "type": "object"
14
+ },
15
+ "FollowConfig": {
16
+ "additionalProperties": false,
17
+ "properties": {
18
+ "autoHideOnFinish": {
19
+ "description": "Hide process log interfaces when all managed processes finish.",
20
+ "type": "boolean"
21
+ },
22
+ "enabledByDefault": {
23
+ "description": "Open process log interfaces in follow mode by default.",
24
+ "type": "boolean"
25
+ }
26
+ },
27
+ "type": "object"
28
+ },
29
+ "InterceptionConfig": {
30
+ "additionalProperties": false,
31
+ "properties": {
32
+ "blockBackgroundCommands": {
33
+ "description": "Block shell background patterns and redirect the agent to the process tool.",
34
+ "type": "boolean"
35
+ }
36
+ },
37
+ "type": "object"
38
+ },
39
+ "OutputConfig": {
40
+ "additionalProperties": false,
41
+ "properties": {
42
+ "defaultTailLines": {
43
+ "description": "Default number of recent lines returned by the process output action.",
44
+ "type": "number"
45
+ },
46
+ "maxOutputBytes": {
47
+ "description": "Maximum bytes retained by each process log interface.",
48
+ "type": "number"
49
+ },
50
+ "maxOutputLines": {
51
+ "description": "Maximum lines retained by process log interfaces.",
52
+ "type": "number"
53
+ }
54
+ },
55
+ "type": "object"
56
+ },
57
+ "ProcessConfig": {
58
+ "additionalProperties": false,
59
+ "description": "User-facing pi-processes settings stored on disk.",
60
+ "properties": {
61
+ "$schema": {
62
+ "description": "JSON Schema URL used by editors for validation and autocomplete.",
63
+ "type": "string"
64
+ },
65
+ "execution": {
66
+ "$ref": "#/definitions/ExecutionConfig",
67
+ "description": "Process execution settings."
68
+ },
69
+ "follow": {
70
+ "$ref": "#/definitions/FollowConfig",
71
+ "description": "Live log follow behavior."
72
+ },
73
+ "interception": {
74
+ "$ref": "#/definitions/InterceptionConfig",
75
+ "description": "Shell-command interception settings."
76
+ },
77
+ "output": {
78
+ "$ref": "#/definitions/OutputConfig",
79
+ "description": "Process output retention settings."
80
+ },
81
+ "processList": {
82
+ "$ref": "#/definitions/ProcessListConfig",
83
+ "description": "Process overview and log viewport settings."
84
+ },
85
+ "version": {
86
+ "description": "Config migration marker written after v0.10.0 settings migration.",
87
+ "type": "string"
88
+ },
89
+ "widget": {
90
+ "$ref": "#/definitions/WidgetConfig",
91
+ "description": "Dock and status widget settings."
92
+ }
93
+ },
94
+ "type": "object"
95
+ },
96
+ "ProcessListConfig": {
97
+ "additionalProperties": false,
98
+ "properties": {
99
+ "maxPreviewLines": {
100
+ "description": "Maximum log rows displayed in the overview preview and logs overlay.",
101
+ "type": "number"
102
+ },
103
+ "maxVisibleProcesses": {
104
+ "description": "Maximum process rows displayed in the overview before scrolling.",
105
+ "type": "number"
106
+ }
107
+ },
108
+ "type": "object"
109
+ },
110
+ "WidgetConfig": {
111
+ "additionalProperties": false,
112
+ "properties": {
113
+ "dockDefaultState": {
114
+ "description": "Initial visibility of the process dock.",
115
+ "enum": [
116
+ "closed",
117
+ "collapsed",
118
+ "expanded"
119
+ ],
120
+ "type": "string"
121
+ },
122
+ "dockHeight": {
123
+ "description": "Number of log rows displayed in the expanded process dock.",
124
+ "type": "number"
125
+ },
126
+ "showStatusWidget": {
127
+ "description": "Show a one-line process summary below the editor.",
128
+ "type": "boolean"
129
+ }
130
+ },
131
+ "type": "object"
132
+ }
133
+ }
134
+ }