pi-kot 0.1.39 → 0.1.40

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 (84) hide show
  1. package/dist/client/assets/index-DH1DarDy.js +196 -0
  2. package/dist/client/assets/index-DH1DarDy.js.map +1 -0
  3. package/dist/client/assets/index-DYWeNL-y.css +1 -0
  4. package/dist/client/assets/vendor-icons-BpFAkgBQ.js +2 -0
  5. package/dist/client/assets/vendor-icons-BpFAkgBQ.js.map +1 -0
  6. package/dist/client/assets/{vendor-markdown-DUXj0nma.js → vendor-markdown-BDlxJt__.js} +2 -2
  7. package/dist/client/assets/{vendor-markdown-DUXj0nma.js.map → vendor-markdown-BDlxJt__.js.map} +1 -1
  8. package/dist/client/assets/vendor-prism-CNIrsK0M.js +4 -0
  9. package/dist/client/assets/{vendor-prism-tzddbd4Y.js.map → vendor-prism-CNIrsK0M.js.map} +1 -1
  10. package/dist/client/index.html +5 -5
  11. package/dist/server/archive-retention.test.d.ts +2 -0
  12. package/dist/server/archive-retention.test.d.ts.map +1 -0
  13. package/dist/server/archive-retention.test.js +63 -0
  14. package/dist/server/archive-retention.test.js.map +1 -0
  15. package/dist/server/contexts/web-ui.md +12 -3
  16. package/dist/server/event-stream.d.ts.map +1 -1
  17. package/dist/server/event-stream.js +14 -0
  18. package/dist/server/event-stream.js.map +1 -1
  19. package/dist/server/index.d.ts.map +1 -1
  20. package/dist/server/index.js +88 -0
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/processes/envelope.d.ts +5 -0
  23. package/dist/server/processes/envelope.d.ts.map +1 -0
  24. package/dist/server/processes/envelope.js +29 -0
  25. package/dist/server/processes/envelope.js.map +1 -0
  26. package/dist/server/processes/log-store.d.ts +24 -0
  27. package/dist/server/processes/log-store.d.ts.map +1 -0
  28. package/dist/server/processes/log-store.js +86 -0
  29. package/dist/server/processes/log-store.js.map +1 -0
  30. package/dist/server/processes/manager.d.ts +56 -0
  31. package/dist/server/processes/manager.d.ts.map +1 -0
  32. package/dist/server/processes/manager.js +343 -0
  33. package/dist/server/processes/manager.js.map +1 -0
  34. package/dist/server/processes/processes.test.d.ts +2 -0
  35. package/dist/server/processes/processes.test.d.ts.map +1 -0
  36. package/dist/server/processes/processes.test.js +85 -0
  37. package/dist/server/processes/processes.test.js.map +1 -0
  38. package/dist/server/processes/prompt-strings.d.ts +7 -0
  39. package/dist/server/processes/prompt-strings.d.ts.map +1 -0
  40. package/dist/server/processes/prompt-strings.js +28 -0
  41. package/dist/server/processes/prompt-strings.js.map +1 -0
  42. package/dist/server/processes/tool.d.ts +3 -0
  43. package/dist/server/processes/tool.d.ts.map +1 -0
  44. package/dist/server/processes/tool.js +160 -0
  45. package/dist/server/processes/tool.js.map +1 -0
  46. package/dist/server/processes/types.d.ts +125 -0
  47. package/dist/server/processes/types.d.ts.map +1 -0
  48. package/dist/server/processes/types.js +13 -0
  49. package/dist/server/processes/types.js.map +1 -0
  50. package/dist/server/processes/watches.d.ts +13 -0
  51. package/dist/server/processes/watches.d.ts.map +1 -0
  52. package/dist/server/processes/watches.js +55 -0
  53. package/dist/server/processes/watches.js.map +1 -0
  54. package/dist/server/routes/config.js +2 -2
  55. package/dist/server/routes/config.js.map +1 -1
  56. package/dist/server/routes/files-batch-delete.test.d.ts +2 -0
  57. package/dist/server/routes/files-batch-delete.test.d.ts.map +1 -0
  58. package/dist/server/routes/files-batch-delete.test.js +165 -0
  59. package/dist/server/routes/files-batch-delete.test.js.map +1 -0
  60. package/dist/server/routes/files.d.ts.map +1 -1
  61. package/dist/server/routes/files.js +99 -0
  62. package/dist/server/routes/files.js.map +1 -1
  63. package/dist/server/routes/processes.d.ts +3 -0
  64. package/dist/server/routes/processes.d.ts.map +1 -0
  65. package/dist/server/routes/processes.js +63 -0
  66. package/dist/server/routes/processes.js.map +1 -0
  67. package/dist/server/routes/sessions.d.ts.map +1 -1
  68. package/dist/server/routes/sessions.js +30 -1
  69. package/dist/server/routes/sessions.js.map +1 -1
  70. package/dist/server/session-store.d.ts +15 -1
  71. package/dist/server/session-store.d.ts.map +1 -1
  72. package/dist/server/session-store.js +99 -4
  73. package/dist/server/session-store.js.map +1 -1
  74. package/dist/server/ui-settings-store.d.ts +3 -0
  75. package/dist/server/ui-settings-store.d.ts.map +1 -1
  76. package/dist/server/ui-settings-store.js +11 -1
  77. package/dist/server/ui-settings-store.js.map +1 -1
  78. package/package.json +1 -1
  79. package/dist/client/assets/index-B959AkDe.css +0 -1
  80. package/dist/client/assets/index-BH5vWV2p.js +0 -192
  81. package/dist/client/assets/index-BH5vWV2p.js.map +0 -1
  82. package/dist/client/assets/vendor-icons-xTgSApeH.js +0 -2
  83. package/dist/client/assets/vendor-icons-xTgSApeH.js.map +0 -1
  84. package/dist/client/assets/vendor-prism-tzddbd4Y.js +0 -4
@@ -0,0 +1,343 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomBytes } from "node:crypto";
3
+ import { join } from "node:path";
4
+ import { config } from "../config.js";
5
+ import { LogChannel, processLogDir } from "./log-store.js";
6
+ import { buildMatchEvent, compileWatches, evaluateWatches } from "./watches.js";
7
+ import { LIVE_STATUSES, } from "./types.js";
8
+ const GRACE_MS = 5_000;
9
+ const SIGKILL_TIMEOUT_MS = 2_000;
10
+ function sanitizeEnvironment(extra = {}) {
11
+ const env = { ...process.env, ...extra };
12
+ // Clean sensitive server credentials from child process environment
13
+ delete env.API_KEY;
14
+ delete env.UI_PASSWORD;
15
+ delete env.JWT_SECRET;
16
+ return env;
17
+ }
18
+ export class ProcessManager {
19
+ bySession = new Map();
20
+ listeners = new Set();
21
+ subscribe(fn) {
22
+ this.listeners.add(fn);
23
+ return () => {
24
+ this.listeners.delete(fn);
25
+ };
26
+ }
27
+ notify(event) {
28
+ for (const fn of this.listeners) {
29
+ try {
30
+ fn(event);
31
+ }
32
+ catch {
33
+ // Listener errors must not crash manager
34
+ }
35
+ }
36
+ }
37
+ getOrCreateSession(sessionId) {
38
+ let s = this.bySession.get(sessionId);
39
+ if (s === undefined) {
40
+ s = { sessionId, processes: new Map() };
41
+ this.bySession.set(sessionId, s);
42
+ }
43
+ return s;
44
+ }
45
+ /**
46
+ * Spawn a new background process bound to a session.
47
+ */
48
+ start(sessionId, name, command, cwd, opts = {}) {
49
+ const session = this.getOrCreateSession(sessionId);
50
+ const id = randomBytes(4).toString("hex");
51
+ const logDir = processLogDir(config.forgeDataDir, sessionId, id);
52
+ const stdoutFile = join(logDir, "stdout.log");
53
+ const stderrFile = join(logDir, "stderr.log");
54
+ // Spawn under `/bin/sh -c` with detached: true so kill(-pid) kills the whole process group
55
+ const child = spawn("/bin/sh", ["-c", command], {
56
+ cwd,
57
+ env: sanitizeEnvironment(opts.toolEnv),
58
+ stdio: ["pipe", "pipe", "pipe"],
59
+ detached: true,
60
+ });
61
+ const info = {
62
+ id,
63
+ name,
64
+ pid: child.pid ?? -1,
65
+ command,
66
+ cwd,
67
+ startTime: Date.now(),
68
+ endTime: null,
69
+ status: "running",
70
+ exitCode: null,
71
+ success: null,
72
+ stdoutFile,
73
+ stderrFile,
74
+ alertOnSuccess: opts.alertOnSuccess === true,
75
+ alertOnFailure: opts.alertOnFailure !== false, // default true
76
+ alertOnKill: opts.alertOnKill === true,
77
+ };
78
+ const managed = {
79
+ info,
80
+ child,
81
+ stdout: new LogChannel(stdoutFile),
82
+ stderr: new LogChannel(stderrFile),
83
+ watches: compileWatches(opts.logWatches),
84
+ killSent: null,
85
+ killTimer: null,
86
+ };
87
+ session.processes.set(id, managed);
88
+ const wireUp = (source) => {
89
+ const stream = source === "stdout" ? child.stdout : child.stderr;
90
+ const channel = source === "stdout" ? managed.stdout : managed.stderr;
91
+ stream.on("data", (chunk) => {
92
+ channel.append(chunk, (line) => {
93
+ const hits = evaluateWatches(managed.watches, source, line);
94
+ for (const w of hits) {
95
+ this.notify({
96
+ type: "process_watch_matched",
97
+ sessionId,
98
+ match: buildMatchEvent(w, id, name, command, source, line),
99
+ });
100
+ }
101
+ });
102
+ this.notify({ type: "process_output_changed", sessionId, id });
103
+ });
104
+ };
105
+ wireUp("stdout");
106
+ wireUp("stderr");
107
+ child.on("error", (err) => {
108
+ const text = `[spawn error] ${err.message}\n`;
109
+ managed.stderr.append(Buffer.from(text, "utf8"));
110
+ info.endTime = Date.now();
111
+ info.exitCode = -1;
112
+ info.success = false;
113
+ info.status = "exited";
114
+ this.notify({ type: "process_ended", sessionId, info });
115
+ this.notify({ type: "processes_changed", sessionId });
116
+ if (info.alertOnFailure) {
117
+ this.notify({
118
+ type: "process_alert",
119
+ sessionId,
120
+ info,
121
+ reason: "failure",
122
+ });
123
+ }
124
+ void this.finalize(managed);
125
+ });
126
+ child.on("close", (code, signal) => {
127
+ info.endTime = Date.now();
128
+ info.exitCode = typeof code === "number" ? code : null;
129
+ const killedByUs = managed.killSent !== null;
130
+ const killedExternally = !killedByUs && signal !== null;
131
+ const wasKilled = killedByUs || killedExternally;
132
+ info.status = wasKilled ? "killed" : "exited";
133
+ info.success = info.exitCode === 0 && !wasKilled;
134
+ if (managed.killTimer !== null) {
135
+ clearTimeout(managed.killTimer);
136
+ managed.killTimer = null;
137
+ }
138
+ this.notify({ type: "process_ended", sessionId, info });
139
+ this.notify({ type: "processes_changed", sessionId });
140
+ // Determine alert notifications
141
+ if (info.success && info.alertOnSuccess) {
142
+ this.notify({
143
+ type: "process_alert",
144
+ sessionId,
145
+ info,
146
+ reason: "success",
147
+ });
148
+ }
149
+ else if (!info.success && !wasKilled && info.alertOnFailure) {
150
+ this.notify({
151
+ type: "process_alert",
152
+ sessionId,
153
+ info,
154
+ reason: "failure",
155
+ });
156
+ }
157
+ else if (killedExternally && info.alertOnKill) {
158
+ this.notify({
159
+ type: "process_alert",
160
+ sessionId,
161
+ info,
162
+ reason: "killed",
163
+ });
164
+ }
165
+ void this.finalize(managed);
166
+ });
167
+ this.notify({ type: "process_started", sessionId, info });
168
+ this.notify({ type: "processes_changed", sessionId });
169
+ return info;
170
+ }
171
+ async finalize(managed) {
172
+ try {
173
+ await Promise.all([managed.stdout.close(), managed.stderr.close()]);
174
+ }
175
+ catch {
176
+ // best-effort
177
+ }
178
+ }
179
+ /**
180
+ * List all processes for a session.
181
+ */
182
+ list(sessionId) {
183
+ const session = this.bySession.get(sessionId);
184
+ if (!session)
185
+ return [];
186
+ return Array.from(session.processes.values())
187
+ .map((m) => ({ ...m.info }))
188
+ .sort((a, b) => b.startTime - a.startTime);
189
+ }
190
+ /**
191
+ * Get a single process info by ID.
192
+ */
193
+ get(sessionId, id) {
194
+ return this.bySession.get(sessionId)?.processes.get(id)?.info;
195
+ }
196
+ /**
197
+ * Get recent stdout/stderr output lines for a process.
198
+ */
199
+ getOutput(sessionId, id, lineCount = 200) {
200
+ const managed = this.bySession.get(sessionId)?.processes.get(id);
201
+ if (!managed)
202
+ return undefined;
203
+ return {
204
+ stdout: managed.stdout.tail(lineCount),
205
+ stderr: managed.stderr.tail(lineCount),
206
+ status: managed.info.status,
207
+ };
208
+ }
209
+ /**
210
+ * Get on-disk log file paths for a process.
211
+ */
212
+ getLogFiles(sessionId, id) {
213
+ const managed = this.bySession.get(sessionId)?.processes.get(id);
214
+ if (!managed)
215
+ return undefined;
216
+ return {
217
+ stdoutFile: managed.info.stdoutFile,
218
+ stderrFile: managed.info.stderrFile,
219
+ };
220
+ }
221
+ /**
222
+ * Terminate a process: SIGTERM -> wait GRACE_MS -> SIGKILL.
223
+ */
224
+ async kill(sessionId, id) {
225
+ const managed = this.bySession.get(sessionId)?.processes.get(id);
226
+ if (!managed)
227
+ return { ok: false, info: undefined, reason: "not_found" };
228
+ if (!LIVE_STATUSES.has(managed.info.status)) {
229
+ return { ok: true, info: managed.info };
230
+ }
231
+ managed.info.status = "terminating";
232
+ managed.killSent = "SIGTERM";
233
+ this.notify({ type: "processes_changed", sessionId });
234
+ const sendSignal = (sig) => {
235
+ const pid = managed.child.pid;
236
+ if (pid === undefined)
237
+ return;
238
+ try {
239
+ // Signal the whole process group (detached process)
240
+ process.kill(-pid, sig);
241
+ }
242
+ catch {
243
+ try {
244
+ managed.child.kill(sig);
245
+ }
246
+ catch {
247
+ // already exited
248
+ }
249
+ }
250
+ };
251
+ sendSignal("SIGTERM");
252
+ return new Promise((resolve) => {
253
+ let resolved = false;
254
+ const finish = (result) => {
255
+ if (resolved)
256
+ return;
257
+ resolved = true;
258
+ if (managed.killTimer !== null) {
259
+ clearTimeout(managed.killTimer);
260
+ managed.killTimer = null;
261
+ }
262
+ resolve(result);
263
+ };
264
+ managed.child.once("close", () => {
265
+ finish({ ok: true, info: managed.info });
266
+ });
267
+ managed.killTimer = setTimeout(() => {
268
+ if (!LIVE_STATUSES.has(managed.info.status))
269
+ return;
270
+ managed.info.status = "terminate_timeout";
271
+ managed.killSent = "SIGKILL";
272
+ this.notify({ type: "processes_changed", sessionId });
273
+ sendSignal("SIGKILL");
274
+ managed.killTimer = setTimeout(() => {
275
+ finish({ ok: false, info: managed.info, reason: "timeout" });
276
+ }, SIGKILL_TIMEOUT_MS);
277
+ }, GRACE_MS);
278
+ });
279
+ }
280
+ /**
281
+ * Write to process stdin.
282
+ */
283
+ write(sessionId, id, input, end = false) {
284
+ const managed = this.bySession.get(sessionId)?.processes.get(id);
285
+ if (!managed)
286
+ return { ok: false, reason: "not_found" };
287
+ if (!LIVE_STATUSES.has(managed.info.status)) {
288
+ return { ok: false, reason: "process_exited" };
289
+ }
290
+ const stdin = managed.child.stdin;
291
+ if (!stdin || stdin.destroyed || stdin.writableEnded) {
292
+ return { ok: false, reason: "stdin_closed" };
293
+ }
294
+ try {
295
+ stdin.write(input);
296
+ if (end)
297
+ stdin.end();
298
+ return { ok: true };
299
+ }
300
+ catch {
301
+ return { ok: false, reason: "write_error" };
302
+ }
303
+ }
304
+ /**
305
+ * Remove finished / exited / killed processes from the session state.
306
+ */
307
+ clearFinished(sessionId) {
308
+ const session = this.bySession.get(sessionId);
309
+ if (!session)
310
+ return 0;
311
+ let cleared = 0;
312
+ for (const [id, proc] of session.processes.entries()) {
313
+ if (!LIVE_STATUSES.has(proc.info.status)) {
314
+ session.processes.delete(id);
315
+ cleared++;
316
+ }
317
+ }
318
+ if (cleared > 0) {
319
+ this.notify({ type: "processes_changed", sessionId });
320
+ }
321
+ return cleared;
322
+ }
323
+ /**
324
+ * Kill all processes and clean up when a session is disposed.
325
+ */
326
+ async disposeSession(sessionId) {
327
+ const session = this.bySession.get(sessionId);
328
+ if (!session)
329
+ return;
330
+ const liveProcesses = Array.from(session.processes.values()).filter((p) => LIVE_STATUSES.has(p.info.status));
331
+ await Promise.all(liveProcesses.map(async (proc) => {
332
+ try {
333
+ await this.kill(sessionId, proc.info.id);
334
+ }
335
+ catch {
336
+ // best-effort cleanup
337
+ }
338
+ }));
339
+ this.bySession.delete(sessionId);
340
+ }
341
+ }
342
+ export const processManager = new ProcessManager();
343
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/processes/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=processes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processes.test.d.ts","sourceRoot":"","sources":["../../src/processes/processes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect, afterEach } from "vitest";
2
+ import { processManager } from "./manager.js";
3
+ import { createProcessTool } from "./tool.js";
4
+ const TEST_SESSION = "test-session-" + Date.now();
5
+ describe("Background Process Manager", () => {
6
+ afterEach(async () => {
7
+ await processManager.disposeSession(TEST_SESSION);
8
+ });
9
+ it("starts, lists, and kills a process", async () => {
10
+ const info = processManager.start(TEST_SESSION, "test-echo", "node -e 'setInterval(() => console.log(\"hello\"), 100)'", process.cwd());
11
+ expect(info.id).toBeDefined();
12
+ expect(info.status).toBe("running");
13
+ expect(info.pid).toBeGreaterThan(0);
14
+ const list = processManager.list(TEST_SESSION);
15
+ expect(list.length).toBe(1);
16
+ expect(list[0].id).toBe(info.id);
17
+ // Wait a brief moment for output
18
+ await new Promise((r) => setTimeout(r, 250));
19
+ const out = processManager.getOutput(TEST_SESSION, info.id);
20
+ expect(out).toBeDefined();
21
+ expect(out?.stdout.some((line) => line.includes("hello"))).toBe(true);
22
+ const killRes = await processManager.kill(TEST_SESSION, info.id);
23
+ expect(killRes.ok).toBe(true);
24
+ // After kill, status should update to killed or exited
25
+ const updated = processManager.get(TEST_SESSION, info.id);
26
+ expect(["killed", "exited"]).toContain(updated?.status);
27
+ });
28
+ it("writes to stdin and receives response", async () => {
29
+ const info = processManager.start(TEST_SESSION, "test-stdin", "node -e 'process.stdin.on(\"data\", d => console.log(\"echo:\" + d.toString().trim()))'", process.cwd());
30
+ await new Promise((r) => setTimeout(r, 100));
31
+ const writeRes = processManager.write(TEST_SESSION, info.id, "pi-kot\n");
32
+ expect(writeRes.ok).toBe(true);
33
+ await new Promise((r) => setTimeout(r, 200));
34
+ const out = processManager.getOutput(TEST_SESSION, info.id);
35
+ expect(out?.stdout.some((line) => line.includes("echo:pi-kot"))).toBe(true);
36
+ await processManager.kill(TEST_SESSION, info.id);
37
+ });
38
+ it("triggers logWatches regex matches", async () => {
39
+ const matchedLines = [];
40
+ const unsubscribe = processManager.subscribe((ev) => {
41
+ if (ev.type === "process_watch_matched") {
42
+ matchedLines.push(ev.match.line);
43
+ }
44
+ });
45
+ const info = processManager.start(TEST_SESSION, "test-watch", "node -e 'console.log(\"READY: server started\"); setInterval(() => {}, 100)'", process.cwd(), {
46
+ logWatches: [{ pattern: "READY: .*" }],
47
+ });
48
+ await new Promise((r) => setTimeout(r, 300));
49
+ expect(matchedLines.length).toBeGreaterThanOrEqual(1);
50
+ expect(matchedLines[0]).toContain("READY: server started");
51
+ unsubscribe();
52
+ await processManager.kill(TEST_SESSION, info.id);
53
+ });
54
+ it("clears finished processes", async () => {
55
+ const info = processManager.start(TEST_SESSION, "quick-exit", "node -e 'process.exit(0)'", process.cwd());
56
+ await new Promise((r) => setTimeout(r, 200));
57
+ const cleared = processManager.clearFinished(TEST_SESSION);
58
+ expect(cleared).toBe(1);
59
+ const list = processManager.list(TEST_SESSION);
60
+ expect(list.length).toBe(0);
61
+ });
62
+ it("executes through createProcessTool wrapper", async () => {
63
+ const tool = createProcessTool(TEST_SESSION, process.cwd());
64
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+ const execTool = tool.execute;
66
+ const startRes = await execTool("call-1", {
67
+ action: "start",
68
+ name: "tool-test",
69
+ command: "node -e 'console.log(\"from-tool\"); setInterval(() => {}, 100)'",
70
+ });
71
+ expect(startRes.details.success).toBe(true);
72
+ const procId = startRes.details.process.id;
73
+ await new Promise((r) => setTimeout(r, 200));
74
+ const listRes = await execTool("call-2", { action: "list" });
75
+ expect(listRes.details.success).toBe(true);
76
+ expect(listRes.details.processes.length).toBe(1);
77
+ const outRes = await execTool("call-3", { action: "output", id: procId });
78
+ expect(outRes.details.success).toBe(true);
79
+ const firstContent = outRes.content[0];
80
+ expect(firstContent.text).toContain("from-tool");
81
+ const killRes = await execTool("call-4", { action: "kill", id: procId });
82
+ expect(killRes.details.success).toBe(true);
83
+ });
84
+ });
85
+ //# sourceMappingURL=processes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processes.test.js","sourceRoot":"","sources":["../../src/processes/processes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Prompt snippets and guidelines for the background process tool.
3
+ */
4
+ export declare const PROMPT_SNIPPET = "Manage background processes without blocking the conversation";
5
+ export declare const PROMPT_GUIDELINES: string[];
6
+ export declare const TOOL_DESCRIPTION = "Manage background processes. Actions:\n- start: Run command in background (requires 'name' and 'command')\n - alertOnSuccess (default: false): Show an informational notification on clean completion; does not wake the agent\n - alertOnFailure (default: true): Get a turn to react when process crashes/fails\n - alertOnKill (default: false): Get a turn to react if killed by external signal (killing via tool never triggers a turn)\n - logWatches (optional): Runtime output watches that trigger immediate alerts while running\n - pattern: regex string to match per output line\n - stream: stdout | stderr | both (default both)\n - repeat: false by default (single-fire). Set true for repeat alerts\n- list: Show all managed processes with their IDs and names\n- output: Get recent stdout/stderr (requires 'id')\n- logs: Get log file paths to inspect with read tool (requires 'id')\n- kill: Terminate a process (requires 'id')\n- clear: Remove all finished processes from the list\n- write: Write to process stdin (requires 'id' and 'input', optional 'end' to close stdin)\n\nImportant: Use bash when you need a command's result before continuing in the current turn. Use process for asynchronous/background work only. You DON'T need to poll or wait for processes. Do not repeatedly call list/output after start just to check whether the process has completed. Start processes and continue other work.";
7
+ //# sourceMappingURL=prompt-strings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-strings.d.ts","sourceRoot":"","sources":["../../src/processes/prompt-strings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc,kEAAkE,CAAC;AAE9F,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAKrC,CAAC;AAEF,eAAO,MAAM,gBAAgB,w4CAgByS,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Prompt snippets and guidelines for the background process tool.
3
+ */
4
+ export const PROMPT_SNIPPET = "Manage background processes without blocking the conversation";
5
+ export const PROMPT_GUIDELINES = [
6
+ "Use the process tool for long-running commands such as dev servers, test watchers, build watchers, and log tails instead of bash.",
7
+ "Avoid shell background patterns such as &, nohup, disown, or setsid when the process tool fits.",
8
+ "After starting a process, continue other work instead of waiting for it. Do not repeatedly call list/output just to see whether it has finished.",
9
+ "Use bash instead when you need a command's result before continuing. Use process notify flags/logWatches only for asynchronous follow-up, especially failures or specific output patterns.",
10
+ ];
11
+ export const TOOL_DESCRIPTION = `Manage background processes. Actions:
12
+ - start: Run command in background (requires 'name' and 'command')
13
+ - alertOnSuccess (default: false): Show an informational notification on clean completion; does not wake the agent
14
+ - alertOnFailure (default: true): Get a turn to react when process crashes/fails
15
+ - alertOnKill (default: false): Get a turn to react if killed by external signal (killing via tool never triggers a turn)
16
+ - logWatches (optional): Runtime output watches that trigger immediate alerts while running
17
+ - pattern: regex string to match per output line
18
+ - stream: stdout | stderr | both (default both)
19
+ - repeat: false by default (single-fire). Set true for repeat alerts
20
+ - list: Show all managed processes with their IDs and names
21
+ - output: Get recent stdout/stderr (requires 'id')
22
+ - logs: Get log file paths to inspect with read tool (requires 'id')
23
+ - kill: Terminate a process (requires 'id')
24
+ - clear: Remove all finished processes from the list
25
+ - write: Write to process stdin (requires 'id' and 'input', optional 'end' to close stdin)
26
+
27
+ Important: Use bash when you need a command's result before continuing in the current turn. Use process for asynchronous/background work only. You DON'T need to poll or wait for processes. Do not repeatedly call list/output after start just to check whether the process has completed. Start processes and continue other work.`;
28
+ //# sourceMappingURL=prompt-strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-strings.js","sourceRoot":"","sources":["../../src/processes/prompt-strings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,+DAA+D,CAAC;AAE9F,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC,mIAAmI;IACnI,iGAAiG;IACjG,kJAAkJ;IAClJ,4LAA4L;CAC7L,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;sUAgBsS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
2
+ export declare function createProcessTool(sessionId: string, workspacePath: string): ToolDefinition;
3
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/processes/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAyFtE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,cAAc,CAsH1F"}