@aliou/pi-processes 0.4.7 → 0.6.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 (51) hide show
  1. package/README.md +83 -13
  2. package/package.json +10 -4
  3. package/src/commands/clear/command.ts +14 -0
  4. package/src/commands/clear/index.ts +1 -0
  5. package/src/commands/completions.ts +38 -0
  6. package/src/commands/dock/command.ts +29 -0
  7. package/src/commands/dock/index.ts +1 -0
  8. package/src/commands/index.ts +26 -327
  9. package/src/commands/kill/command.ts +69 -0
  10. package/src/commands/kill/index.ts +1 -0
  11. package/src/commands/logs/command.ts +47 -0
  12. package/src/commands/logs/index.ts +1 -0
  13. package/src/commands/pick-process.ts +34 -0
  14. package/src/commands/pin/command.ts +33 -0
  15. package/src/commands/pin/index.ts +1 -0
  16. package/src/commands/processes/command.ts +39 -0
  17. package/src/commands/processes/index.ts +1 -0
  18. package/src/commands/settings/apply-setting-change.ts +72 -0
  19. package/src/commands/settings/build-sections.ts +160 -0
  20. package/src/commands/settings/command.ts +20 -0
  21. package/src/commands/settings/index.ts +1 -0
  22. package/src/components/log-dock-component.ts +238 -0
  23. package/src/components/log-file-viewer.ts +317 -0
  24. package/src/components/log-overlay-component.ts +555 -0
  25. package/src/components/process-picker-component.ts +14 -2
  26. package/src/components/processes-component.ts +41 -21
  27. package/src/config.ts +38 -1
  28. package/src/constants/index.ts +1 -0
  29. package/src/constants/types.ts +7 -1
  30. package/src/hooks/background-blocker.ts +66 -0
  31. package/src/hooks/index.ts +15 -3
  32. package/src/hooks/process-end.ts +3 -30
  33. package/src/hooks/widget/index.ts +2 -0
  34. package/src/hooks/widget/setup.ts +168 -0
  35. package/src/hooks/{widget.ts → widget/status-widget.ts} +27 -68
  36. package/src/hooks/widget/types.ts +21 -0
  37. package/src/index.ts +9 -3
  38. package/src/manager.ts +61 -9
  39. package/src/tools/actions/index.ts +5 -0
  40. package/src/tools/actions/write.ts +87 -0
  41. package/src/tools/index.ts +82 -14
  42. package/src/utils/command-executor.test.ts +2 -1
  43. package/src/utils/command-executor.ts +1 -1
  44. package/src/utils/keybindings.ts +76 -0
  45. package/src/utils/shell-utils.ts +133 -0
  46. package/src/commands/settings-command.ts +0 -157
  47. package/src/components/log-stream-component.ts +0 -149
  48. package/src/test/test-exit-crash.sh +0 -19
  49. package/src/test/test-exit-failure.sh +0 -17
  50. package/src/test/test-exit-success.sh +0 -16
  51. package/src/test/test-output.sh +0 -28
package/src/config.ts CHANGED
@@ -6,6 +6,8 @@
6
6
  */
7
7
 
8
8
  import { ConfigLoader } from "@aliou/pi-utils-settings";
9
+ import type { ProcessesKeybindings } from "./utils/keybindings";
10
+ import { DEFAULT_KEYBINDINGS } from "./utils/keybindings";
9
11
 
10
12
  export interface ProcessesConfig {
11
13
  processList?: {
@@ -27,6 +29,21 @@ export interface ProcessesConfig {
27
29
  widget?: {
28
30
  /** Show the status widget below the editor. */
29
31
  showStatusWidget?: boolean;
32
+ /** Default dock state when follow mode is enabled. */
33
+ dockDefaultState?: "hidden" | "collapsed";
34
+ /** Height of the dock in lines when open. */
35
+ dockHeight?: number;
36
+ };
37
+ follow?: {
38
+ /** Enable follow mode by default when starting processes. */
39
+ enabledByDefault?: boolean;
40
+ /** Auto-hide dock when all processes finish. */
41
+ autoHideOnFinish?: boolean;
42
+ };
43
+ keybindings?: Partial<ProcessesKeybindings>;
44
+ interception?: {
45
+ /** Block background bash commands (&, nohup, disown, setsid) and guide the model to use the process tool. */
46
+ blockBackgroundCommands?: boolean;
30
47
  };
31
48
  }
32
49
 
@@ -44,6 +61,16 @@ export interface ResolvedProcessesConfig {
44
61
  };
45
62
  widget: {
46
63
  showStatusWidget: boolean;
64
+ dockDefaultState: "hidden" | "collapsed";
65
+ dockHeight: number;
66
+ };
67
+ follow: {
68
+ enabledByDefault: boolean;
69
+ autoHideOnFinish: boolean;
70
+ };
71
+ keybindings: ProcessesKeybindings;
72
+ interception: {
73
+ blockBackgroundCommands: boolean;
47
74
  };
48
75
  }
49
76
 
@@ -58,7 +85,17 @@ const DEFAULT_CONFIG: ResolvedProcessesConfig = {
58
85
  },
59
86
  execution: {},
60
87
  widget: {
61
- showStatusWidget: true,
88
+ showStatusWidget: false,
89
+ dockDefaultState: "collapsed",
90
+ dockHeight: 12,
91
+ },
92
+ follow: {
93
+ enabledByDefault: true,
94
+ autoHideOnFinish: true,
95
+ },
96
+ keybindings: DEFAULT_KEYBINDINGS,
97
+ interception: {
98
+ blockBackgroundCommands: false,
62
99
  },
63
100
  };
64
101
 
@@ -6,6 +6,7 @@ export type {
6
6
  ProcessInfo,
7
7
  ProcessStatus,
8
8
  StartOptions,
9
+ WriteResult,
9
10
  } from "./types";
10
11
 
11
12
  export { LIVE_STATUSES, MESSAGE_TYPE_PROCESS_UPDATE } from "./types";
@@ -34,7 +34,6 @@ export interface ProcessInfo {
34
34
 
35
35
  export type ManagerEvent =
36
36
  | { type: "process_started"; info: ProcessInfo }
37
- | { type: "process_status_changed"; info: ProcessInfo; prev: ProcessStatus }
38
37
  | { type: "process_ended"; info: ProcessInfo }
39
38
  | { type: "processes_changed" };
40
39
 
@@ -42,6 +41,13 @@ export type KillResult =
42
41
  | { ok: true; info: ProcessInfo }
43
42
  | { ok: false; info: ProcessInfo; reason: "not_found" | "timeout" | "error" };
44
43
 
44
+ export type WriteResult =
45
+ | { ok: true }
46
+ | {
47
+ ok: false;
48
+ reason: "not_found" | "process_exited" | "stdin_closed" | "write_error";
49
+ };
50
+
45
51
  export interface StartOptions {
46
52
  alertOnSuccess?: boolean;
47
53
  alertOnFailure?: boolean;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Blocks background bash commands (e.g. `cmd &`, `nohup cmd`) and guides
3
+ * the model to use the process tool instead.
4
+ *
5
+ * Opt-in via config: `interception.blockBackgroundCommands`.
6
+ */
7
+
8
+ import { parse } from "@aliou/sh";
9
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ import { walkCommands, wordToString } from "../utils/shell-utils";
11
+
12
+ const BACKGROUND_CMD_NAMES = new Set(["nohup", "disown", "setsid"]);
13
+ const BACKGROUND_PATTERN = /&\s*$/;
14
+
15
+ export function setupBackgroundBlocker(pi: ExtensionAPI): void {
16
+ pi.on("tool_call", async (event, ctx) => {
17
+ if (event.toolName !== "bash") return;
18
+
19
+ const command = String(event.input.command ?? "");
20
+
21
+ let hasBackground = false;
22
+ try {
23
+ const { ast } = parse(command);
24
+
25
+ // Check statement-level background flag (cmd &)
26
+ for (const stmt of ast.body) {
27
+ if (stmt.background) {
28
+ hasBackground = true;
29
+ break;
30
+ }
31
+ }
32
+
33
+ // Check for nohup/disown/setsid as command names
34
+ if (!hasBackground) {
35
+ walkCommands(ast, (cmd) => {
36
+ const name = cmd.words?.[0] ? wordToString(cmd.words[0]) : undefined;
37
+ if (name && BACKGROUND_CMD_NAMES.has(name)) {
38
+ hasBackground = true;
39
+ return true;
40
+ }
41
+ return false;
42
+ });
43
+ }
44
+ } catch {
45
+ // Fallback to regex on parse failure
46
+ hasBackground = BACKGROUND_PATTERN.test(command);
47
+ }
48
+
49
+ if (hasBackground) {
50
+ ctx.ui?.notify(
51
+ "Blocked background command. Use the process tool instead.",
52
+ "warning",
53
+ );
54
+
55
+ return {
56
+ block: true,
57
+ reason:
58
+ "Background commands (&, nohup, disown, setsid) are not supported in bash. " +
59
+ 'Use the "process" tool with action "start" to run commands in the background. ' +
60
+ 'Example: process({ action: "start", name: "my-server", command: "npm run dev" })',
61
+ };
62
+ }
63
+
64
+ return;
65
+ });
66
+ }
@@ -1,16 +1,28 @@
1
1
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ResolvedProcessesConfig } from "../config";
2
3
  import type { ProcessManager } from "../manager";
4
+ import { setupBackgroundBlocker } from "./background-blocker";
3
5
  import { setupCleanupHook } from "./cleanup";
4
6
  import { setupMessageRenderer } from "./message-renderer";
5
7
  import { setupProcessEndHook } from "./process-end";
6
- import { setupProcessWidget } from "./widget";
8
+ import { type DockActions, setupProcessWidget } from "./widget";
7
9
 
8
- export function setupProcessesHooks(pi: ExtensionAPI, manager: ProcessManager) {
10
+ export type { DockActions };
11
+
12
+ export function setupProcessesHooks(
13
+ pi: ExtensionAPI,
14
+ manager: ProcessManager,
15
+ config: ResolvedProcessesConfig,
16
+ ): { update: () => void; dockActions: DockActions } {
9
17
  setupCleanupHook(pi, manager);
10
18
  setupProcessEndHook(pi, manager);
11
19
 
20
+ if (config.interception.blockBackgroundCommands) {
21
+ setupBackgroundBlocker(pi);
22
+ }
23
+
12
24
  // Set up widget AFTER process-end so it chains onto the existing callback
13
- const widget = setupProcessWidget(pi, manager);
25
+ const widget = setupProcessWidget(pi, manager, config);
14
26
 
15
27
  setupMessageRenderer(pi);
16
28
 
@@ -1,7 +1,4 @@
1
- import type {
2
- ExtensionAPI,
3
- ExtensionContext,
4
- } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
5
2
  import { MESSAGE_TYPE_PROCESS_UPDATE, type ProcessInfo } from "../constants";
6
3
  import type { ProcessManager } from "../manager";
7
4
  import { formatRuntime } from "../utils";
@@ -17,21 +14,6 @@ interface ProcessUpdateDetails {
17
14
  }
18
15
 
19
16
  export function setupProcessEndHook(pi: ExtensionAPI, manager: ProcessManager) {
20
- let latestContext: ExtensionContext | null = null;
21
-
22
- // Capture context from session events
23
- pi.on("session_start", async (_event, ctx) => {
24
- latestContext = ctx;
25
- });
26
-
27
- pi.on("turn_start", async (_event, ctx) => {
28
- latestContext = ctx;
29
- });
30
-
31
- pi.on("turn_end", async (_event, ctx) => {
32
- latestContext = ctx;
33
- });
34
-
35
17
  manager.onEvent((event) => {
36
18
  if (event.type !== "process_ended") return;
37
19
 
@@ -47,27 +29,18 @@ export function setupProcessEndHook(pi: ExtensionAPI, manager: ProcessManager) {
47
29
 
48
30
  const runtime = formatRuntime(info.startTime, info.endTime);
49
31
 
50
- // Build notification message
32
+ // Build message
51
33
  let message: string;
52
- let level: "info" | "error" | "warning";
53
34
 
54
35
  if (info.status === "killed") {
55
36
  message = `Process '${info.name}' was terminated (${runtime})`;
56
- level = "warning";
57
37
  } else if (info.success) {
58
38
  message = `Process '${info.name}' completed successfully (${runtime})`;
59
- level = "info";
60
39
  } else {
61
40
  message = `Process '${info.name}' crashed with exit code ${info.exitCode ?? "?"} (${runtime})`;
62
- level = "error";
63
- }
64
-
65
- // Always notify user via UI
66
- if (latestContext?.hasUI) {
67
- latestContext.ui.notify(message, level);
68
41
  }
69
42
 
70
- // Always send the message so it appears in the conversation history.
43
+ // Send the message to the conversation - displayed via custom renderer in UI
71
44
  // Only trigger an agent turn when the notification preferences say so.
72
45
  const details: ProcessUpdateDetails = {
73
46
  processId: info.id,
@@ -0,0 +1,2 @@
1
+ export { setupProcessWidget } from "./setup";
2
+ export type { DockActions } from "./types";
@@ -0,0 +1,168 @@
1
+ import type {
2
+ ExtensionAPI,
3
+ ExtensionContext,
4
+ } from "@mariozechner/pi-coding-agent";
5
+ import { LogDockComponent } from "../../components/log-dock-component";
6
+ import { configLoader, type ResolvedProcessesConfig } from "../../config";
7
+ import { LIVE_STATUSES } from "../../constants";
8
+ import type { ProcessManager } from "../../manager";
9
+ import { renderStatusWidget } from "./status-widget";
10
+ import {
11
+ type DockActions,
12
+ type DockState,
13
+ LOG_DOCK_WIDGET_ID,
14
+ STATUS_WIDGET_ID,
15
+ } from "./types";
16
+
17
+ export function setupProcessWidget(
18
+ pi: ExtensionAPI,
19
+ manager: ProcessManager,
20
+ config: ResolvedProcessesConfig,
21
+ ) {
22
+ let latestContext: ExtensionContext | null = null;
23
+ let logDockComponent: LogDockComponent | null = null;
24
+ let logDockComponentTui: { requestRender(): void } | null = null;
25
+
26
+ const dockState: DockState = {
27
+ visibility: "hidden",
28
+ followEnabled: config.follow.enabledByDefault,
29
+ focusedProcessId: null,
30
+ };
31
+
32
+ function updateWidget() {
33
+ if (!latestContext?.hasUI) return;
34
+
35
+ if (!configLoader.getConfig().widget.showStatusWidget) {
36
+ latestContext.ui.setWidget(STATUS_WIDGET_ID, undefined);
37
+ } else {
38
+ const processes = manager.list();
39
+ const maxWidth = process.stdout.columns || 120;
40
+ const lines = renderStatusWidget(
41
+ processes,
42
+ latestContext.ui.theme,
43
+ maxWidth,
44
+ );
45
+
46
+ if (lines.length === 0) {
47
+ latestContext.ui.setWidget(STATUS_WIDGET_ID, undefined);
48
+ } else {
49
+ latestContext.ui.setWidget(STATUS_WIDGET_ID, lines, {
50
+ placement: "belowEditor",
51
+ });
52
+ }
53
+ }
54
+
55
+ if (dockState.visibility === "hidden") {
56
+ latestContext.ui.setWidget(LOG_DOCK_WIDGET_ID, undefined);
57
+ if (logDockComponent) {
58
+ logDockComponent.dispose();
59
+ logDockComponent = null;
60
+ logDockComponentTui = null;
61
+ }
62
+ return;
63
+ }
64
+
65
+ const mode = dockState.visibility as "collapsed" | "open";
66
+ const height = mode === "collapsed" ? 3 : config.widget.dockHeight;
67
+
68
+ if (logDockComponent && logDockComponentTui) {
69
+ logDockComponent.update({
70
+ mode,
71
+ focusedProcessId: dockState.focusedProcessId,
72
+ dockHeight: height,
73
+ });
74
+ } else {
75
+ const ctx = latestContext;
76
+ ctx.ui.setWidget(
77
+ LOG_DOCK_WIDGET_ID,
78
+ (tui: { requestRender(): void }, theme: typeof ctx.ui.theme) => {
79
+ logDockComponent = new LogDockComponent({
80
+ manager,
81
+ tui,
82
+ theme,
83
+ mode,
84
+ focusedProcessId: dockState.focusedProcessId,
85
+ dockHeight: height,
86
+ });
87
+ logDockComponentTui = tui;
88
+ return logDockComponent;
89
+ },
90
+ { placement: "aboveEditor" },
91
+ );
92
+ }
93
+ }
94
+
95
+ const dockActions: DockActions = {
96
+ getFocusedProcessId: () => dockState.focusedProcessId,
97
+ isFollowEnabled: () => dockState.followEnabled,
98
+ setFocus(id) {
99
+ dockState.focusedProcessId = id;
100
+ if (id && dockState.visibility === "hidden")
101
+ dockState.visibility = "open";
102
+ updateWidget();
103
+ },
104
+ expand() {
105
+ dockState.visibility = "open";
106
+ updateWidget();
107
+ },
108
+ collapse() {
109
+ dockState.visibility = "collapsed";
110
+ updateWidget();
111
+ },
112
+ hide() {
113
+ dockState.visibility = "hidden";
114
+ updateWidget();
115
+ },
116
+ toggle() {
117
+ if (dockState.visibility === "hidden") dockState.visibility = "collapsed";
118
+ else if (dockState.visibility === "collapsed")
119
+ dockState.visibility = "open";
120
+ else dockState.visibility = "collapsed";
121
+ updateWidget();
122
+ },
123
+ toggleFollow() {
124
+ dockState.followEnabled = !dockState.followEnabled;
125
+ updateWidget();
126
+ },
127
+ };
128
+
129
+ manager.onEvent((event) => {
130
+ if (event.type === "process_started") {
131
+ if (dockState.followEnabled && dockState.visibility === "hidden") {
132
+ dockState.visibility = "collapsed";
133
+ }
134
+ }
135
+
136
+ if (event.type === "process_ended") {
137
+ if (dockState.focusedProcessId === event.info.id) {
138
+ dockState.focusedProcessId = null;
139
+ }
140
+ const running = manager.list().filter((p) => LIVE_STATUSES.has(p.status));
141
+ if (
142
+ running.length === 0 &&
143
+ config.follow.autoHideOnFinish &&
144
+ dockState.followEnabled
145
+ ) {
146
+ dockState.visibility = "hidden";
147
+ }
148
+ }
149
+
150
+ updateWidget();
151
+ });
152
+
153
+ pi.on("session_start", async (_event, ctx) => {
154
+ latestContext = ctx;
155
+ });
156
+
157
+ pi.on("session_switch", async (_event, ctx) => {
158
+ if (logDockComponent) {
159
+ logDockComponent.dispose();
160
+ logDockComponent = null;
161
+ logDockComponentTui = null;
162
+ }
163
+ latestContext = ctx;
164
+ updateWidget();
165
+ });
166
+
167
+ return { update: updateWidget, dockActions };
168
+ }
@@ -1,13 +1,6 @@
1
- import type {
2
- ExtensionAPI,
3
- ExtensionContext,
4
- } from "@mariozechner/pi-coding-agent";
5
- import { visibleWidth } from "@mariozechner/pi-tui";
6
- import { configLoader } from "../config";
7
- import type { ProcessInfo } from "../constants";
8
- import type { ProcessManager } from "../manager";
9
-
10
- const WIDGET_ID = "processes-status";
1
+ import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
2
+ import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
3
+ import type { ProcessInfo } from "../../constants";
11
4
 
12
5
  function formatProcessStatus(
13
6
  proc: ProcessInfo,
@@ -35,14 +28,12 @@ function formatProcessStatus(
35
28
  }
36
29
  }
37
30
 
38
- function renderWidget(
31
+ export function renderStatusWidget(
39
32
  processes: ProcessInfo[],
40
33
  theme: ExtensionContext["ui"]["theme"],
41
34
  maxWidth?: number,
42
35
  ): string[] {
43
- if (processes.length === 0) {
44
- return [];
45
- }
36
+ if (processes.length === 0) return [];
46
37
 
47
38
  const aliveish = processes.filter(
48
39
  (p) =>
@@ -75,17 +66,22 @@ function renderWidget(
75
66
  for (const proc of allProcs) {
76
67
  const formatted = formatProcessStatus(proc, theme);
77
68
  const formattedLen = visibleWidth(formatted);
78
-
79
- // Check if adding this part would exceed the width
69
+ const remaining = allProcs.length - includedCount - 1;
80
70
  const needed =
81
71
  includedCount > 0 ? separatorLen + formattedLen : formattedLen;
82
72
 
83
- if (currentLen + needed > effectiveMax && includedCount > 0) {
84
- // Show how many are hidden
85
- const remaining = allProcs.length - includedCount;
86
- if (remaining > 0) {
87
- parts.push(theme.fg("dim", `+${remaining} more`));
88
- }
73
+ let reservedForSuffix = 0;
74
+ if (remaining > 0) {
75
+ const suffixText = `+${remaining} more`;
76
+ reservedForSuffix = separatorLen + visibleWidth(suffixText);
77
+ }
78
+
79
+ if (
80
+ currentLen + needed + reservedForSuffix > effectiveMax &&
81
+ includedCount > 0
82
+ ) {
83
+ const hiddenCount = allProcs.length - includedCount;
84
+ if (hiddenCount > 0) parts.push(theme.fg("dim", `+${hiddenCount} more`));
89
85
  break;
90
86
  }
91
87
 
@@ -94,53 +90,16 @@ function renderWidget(
94
90
  includedCount++;
95
91
  }
96
92
 
97
- if (parts.length === 0) {
98
- return [];
93
+ if (includedCount === 0 && allProcs.length > 0) {
94
+ parts.push(formatProcessStatus(allProcs[0], theme));
99
95
  }
100
96
 
101
- return [prefix + parts.join(separator)];
102
- }
103
-
104
- export function setupProcessWidget(pi: ExtensionAPI, manager: ProcessManager) {
105
- let latestContext: ExtensionContext | null = null;
97
+ if (parts.length === 0) return [];
106
98
 
107
- function updateWidget() {
108
- if (!latestContext?.hasUI) return;
109
-
110
- if (!configLoader.getConfig().widget.showStatusWidget) {
111
- latestContext.ui.setWidget(WIDGET_ID, undefined);
112
- return;
113
- }
114
-
115
- const processes = manager.list();
116
- const maxWidth = process.stdout.columns || 120;
117
- const lines = renderWidget(processes, latestContext.ui.theme, maxWidth);
118
-
119
- if (lines.length === 0) {
120
- latestContext.ui.setWidget(WIDGET_ID, undefined);
121
- } else {
122
- latestContext.ui.setWidget(WIDGET_ID, lines, {
123
- placement: "belowEditor",
124
- });
125
- }
126
- }
127
-
128
- pi.on("session_start", async (_event, ctx) => {
129
- // Startup defer: capture context only. First render happens on process
130
- // manager events or explicit settings updates.
131
- latestContext = ctx;
132
- });
133
-
134
- pi.on("session_switch", async (_event, ctx) => {
135
- latestContext = ctx;
136
- updateWidget();
137
- });
138
-
139
- manager.onEvent(() => {
140
- updateWidget();
141
- });
142
-
143
- return {
144
- update: updateWidget,
145
- };
99
+ const line = prefix + parts.join(separator);
100
+ return [
101
+ visibleWidth(line) > effectiveMax
102
+ ? truncateToWidth(line, effectiveMax)
103
+ : line,
104
+ ];
146
105
  }
@@ -0,0 +1,21 @@
1
+ export type DockVisibility = "hidden" | "collapsed" | "open";
2
+
3
+ export interface DockState {
4
+ visibility: DockVisibility;
5
+ followEnabled: boolean;
6
+ focusedProcessId: string | null;
7
+ }
8
+
9
+ export interface DockActions {
10
+ getFocusedProcessId(): string | null;
11
+ isFollowEnabled(): boolean;
12
+ setFocus(id: string | null): void;
13
+ expand(): void;
14
+ collapse(): void;
15
+ hide(): void;
16
+ toggle(): void;
17
+ toggleFollow(): void;
18
+ }
19
+
20
+ export const STATUS_WIDGET_ID = "processes-status";
21
+ export const LOG_DOCK_WIDGET_ID = "processes-dock";
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
2
  import { setupProcessesCommands } from "./commands";
3
- import { registerProcessesSettings } from "./commands/settings-command";
3
+ import { registerProcessesSettings } from "./commands/settings";
4
4
  import { configLoader } from "./config";
5
5
  import { setupProcessesHooks } from "./hooks";
6
6
  import { ProcessManager } from "./manager";
@@ -20,8 +20,14 @@ export default async function (pi: ExtensionAPI) {
20
20
  getConfiguredShellPath: () => configLoader.getConfig().execution.shellPath,
21
21
  });
22
22
 
23
- const { update: updateWidget } = setupProcessesHooks(pi, manager);
24
- setupProcessesCommands(pi, manager);
23
+ const config = configLoader.getConfig();
24
+
25
+ const { update: updateWidget, dockActions } = setupProcessesHooks(
26
+ pi,
27
+ manager,
28
+ config,
29
+ );
30
+ setupProcessesCommands(pi, manager, dockActions);
25
31
  setupProcessesTools(pi, manager);
26
32
  registerProcessesSettings(pi, () => {
27
33
  updateWidget();