@felan-ai/ext-background-bash 0.3.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.
@@ -0,0 +1,292 @@
1
+ import { createOutputLog, readLogTail } from './logs.js';
2
+ import { BackgroundBashJobStore, isTerminalStatus, } from './job-store.js';
3
+ const WAIT_POLL_MS = 500;
4
+ const PID_STARTUP_GRACE_MS = 5_000;
5
+ const encoder = new TextEncoder();
6
+ export class BackgroundBashManager {
7
+ runtime;
8
+ #store;
9
+ constructor(runtime) {
10
+ this.runtime = runtime;
11
+ this.#store = new BackgroundBashJobStore(runtime);
12
+ }
13
+ async start(command) {
14
+ let job = await this.#store.createJob(command);
15
+ await createOutputLog(this.runtime.storage, job.meta.logPath);
16
+ await this.runtime.storage.writeFile(job.meta.commandPath, encoder.encode(`${command}\n`));
17
+ await this.runtime.storage.writeFile(job.meta.runnerPath, encoder.encode(createRunnerScript(job)));
18
+ try {
19
+ const launch = await this.runtime.shell(createLaunchCommand(job.meta.runnerPath, job.meta.processToken), {
20
+ cwd: this.runtime.cwd,
21
+ timeout: 10_000,
22
+ });
23
+ if (launch.killed || launch.code !== 0) {
24
+ throw new Error(launch.stderr || launch.stdout || 'Background runner failed to launch');
25
+ }
26
+ const launchedProcess = parseLaunchResult(launch.stdout);
27
+ if (!launchedProcess)
28
+ throw new Error('Background runner did not report a process id');
29
+ job = await this.#store.updatePid(job.meta.id, launchedProcess.pid, launchedProcess.processGroupId) ?? job;
30
+ return job;
31
+ }
32
+ catch (error) {
33
+ await this.#store.markStatus(job.meta.id, {
34
+ status: 'failed',
35
+ exitCode: null,
36
+ signal: null,
37
+ error: errorMessage(error),
38
+ });
39
+ throw new Error(`Failed to start background bash process: ${errorMessage(error)}`, { cause: error });
40
+ }
41
+ }
42
+ async list(status = 'all') {
43
+ const jobs = await this.#store.listJobs('all');
44
+ const normalized = [];
45
+ for (const job of jobs)
46
+ normalized.push(await this.#normalizeJob(job));
47
+ return status === 'all'
48
+ ? normalized
49
+ : normalized.filter((job) => job.status.status === status);
50
+ }
51
+ async get(id) {
52
+ const job = await this.#store.readJob(id);
53
+ if (!job)
54
+ throw new Error(`Background Bash process not found: ${id}`);
55
+ return this.#normalizeJob(job);
56
+ }
57
+ async wait(id, timeoutSeconds, signal) {
58
+ const deadline = timeoutSeconds === undefined
59
+ ? undefined
60
+ : Date.now() + Math.max(0, timeoutSeconds) * 1_000;
61
+ while (true) {
62
+ const job = await this.get(id);
63
+ if (isTerminalStatus(job.status.status))
64
+ return { job, timedOut: false };
65
+ if (deadline !== undefined && Date.now() >= deadline)
66
+ return { job, timedOut: true };
67
+ const delay = deadline === undefined
68
+ ? WAIT_POLL_MS
69
+ : Math.max(0, Math.min(WAIT_POLL_MS, deadline - Date.now()));
70
+ await sleep(delay, signal);
71
+ }
72
+ }
73
+ async stop(id, signal = 'SIGTERM') {
74
+ const job = await this.get(id);
75
+ if (isTerminalStatus(job.status.status))
76
+ return job;
77
+ const pid = job.status.pid ?? job.meta.pid;
78
+ const inspected = pid ? await this.#inspectJobProcess(job, pid) : undefined;
79
+ if (!pid || !inspected) {
80
+ const unknown = await this.#store.markStatus(id, {
81
+ status: 'unknown',
82
+ ...(pid === undefined ? {} : { pid }),
83
+ exitCode: null,
84
+ signal: null,
85
+ error: pid ? 'Process is no longer alive.' : 'No process id was recorded.',
86
+ });
87
+ if (!unknown)
88
+ throw new Error(`Background Bash process not found: ${id}`);
89
+ return unknown;
90
+ }
91
+ let result = inspected?.processGroupId === pid
92
+ ? await this.#sendSignal(-inspected.processGroupId, signal)
93
+ : await this.#sendSignal(pid, signal);
94
+ if (result.code !== 0 && inspected?.processGroupId === pid) {
95
+ result = await this.#sendSignal(pid, signal);
96
+ }
97
+ if (result.code !== 0) {
98
+ throw new Error(result.stderr || `Unable to send ${signal} to Background Bash process ${id}`);
99
+ }
100
+ const killed = await this.#store.markStatus(id, {
101
+ status: 'killed',
102
+ pid,
103
+ exitCode: null,
104
+ signal,
105
+ });
106
+ if (!killed)
107
+ throw new Error(`Background Bash process not found: ${id}`);
108
+ return killed;
109
+ }
110
+ async tail(id, lines = 80) {
111
+ const job = await this.get(id);
112
+ return readLogTail(this.runtime.storage, job.meta.logPath, lines);
113
+ }
114
+ async #normalizeJob(job) {
115
+ if (job.status.status !== 'running')
116
+ return job;
117
+ const pid = job.status.pid ?? job.meta.pid;
118
+ const now = Date.now();
119
+ if (!pid && now - job.status.startedAt <= PID_STARTUP_GRACE_MS)
120
+ return job;
121
+ if (pid && await this.#isJobProcessAlive(job, pid))
122
+ return job;
123
+ return await this.#store.markStatus(job.meta.id, {
124
+ status: 'unknown',
125
+ ...(pid === undefined ? {} : { pid }),
126
+ exitCode: null,
127
+ signal: null,
128
+ error: pid
129
+ ? 'Process is no longer alive and no terminal status was written.'
130
+ : 'No process id was recorded and no terminal status was written.',
131
+ }) ?? job;
132
+ }
133
+ async #isJobProcessAlive(job, pid) {
134
+ return await this.#inspectJobProcess(job, pid) !== undefined;
135
+ }
136
+ async #inspectJobProcess(job, pid) {
137
+ const result = await this.runtime.exec('ps', ['-o', 'pgid=', '-o', 'command=', '-p', String(pid)], { cwd: this.runtime.cwd });
138
+ if (result.code !== 0)
139
+ return undefined;
140
+ const match = result.stdout.match(/^\s*(\d+)\s+([\s\S]+?)\s*$/u);
141
+ if (!match)
142
+ return undefined;
143
+ const processGroupId = Number(match[1]);
144
+ if (!Number.isSafeInteger(processGroupId) || processGroupId <= 0)
145
+ return undefined;
146
+ const command = match[2] ?? '';
147
+ if (job.meta.processToken) {
148
+ if (!command.includes(job.meta.runnerPath) || !command.includes(job.meta.processToken))
149
+ return undefined;
150
+ }
151
+ else if (!command.includes(job.meta.runnerPath)
152
+ && !(command.includes('PI_BG_INFO_PATH') && command.includes('PI_BG_COMMAND'))) {
153
+ return undefined;
154
+ }
155
+ return { processGroupId };
156
+ }
157
+ #sendSignal(pid, signal) {
158
+ return this.runtime.exec('kill', [`-${signal.slice(3)}`, String(pid)], { cwd: this.runtime.cwd });
159
+ }
160
+ }
161
+ function createLaunchCommand(runnerPath, processToken) {
162
+ const path = shellQuote(runnerPath);
163
+ const token = shellQuote(processToken);
164
+ return [
165
+ 'if command -v setsid >/dev/null 2>&1; then',
166
+ ` nohup setsid sh ${path} ${token} >/dev/null 2>&1 < /dev/null &`,
167
+ ' pid="$!"',
168
+ " printf 'group:%s:%s\\n' \"$pid\" \"$pid\"",
169
+ 'else',
170
+ ' set -m 2>/dev/null || true',
171
+ ` nohup sh ${path} ${token} >/dev/null 2>&1 < /dev/null &`,
172
+ ' pid="$!"',
173
+ " process_group=$(ps -o pgid= -p \"$pid\" 2>/dev/null | tr -d ' ')",
174
+ ' if [ "$process_group" = "$pid" ]; then',
175
+ " printf 'group:%s:%s\\n' \"$pid\" \"$process_group\"",
176
+ ' else',
177
+ ' kill "$pid" 2>/dev/null',
178
+ ' wait "$pid" 2>/dev/null',
179
+ " printf '%s\\n' 'Unable to create a detached process group' >&2",
180
+ ' exit 1',
181
+ ' fi',
182
+ 'fi',
183
+ ].join('\n');
184
+ }
185
+ function createRunnerScript(job) {
186
+ const id = shellQuote(job.meta.id);
187
+ const commandPath = shellQuote(job.meta.commandPath);
188
+ const completionPath = shellQuote(job.meta.completionPath);
189
+ const outputPath = shellQuote(job.meta.logPath);
190
+ return `#!/bin/sh
191
+ set +e
192
+ job_id=${id}
193
+ command_path=${commandPath}
194
+ completion_path=${completionPath}
195
+ output_path=${outputPath}
196
+ started_at=${job.meta.startedAt}
197
+ child_pid=
198
+
199
+ write_completion() {
200
+ status="$1"
201
+ exit_code="$2"
202
+ signal_name="$3"
203
+ completed_at=$(($(date +%s) * 1000))
204
+ if [ "$signal_name" = "null" ]; then
205
+ signal_json=null
206
+ else
207
+ signal_json="\\\"$signal_name\\\""
208
+ fi
209
+ tmp_path="$completion_path.$$.$completed_at.tmp"
210
+ cat > "$tmp_path" <<EOF
211
+ {
212
+ "id": "$job_id",
213
+ "status": "$status",
214
+ "startedAt": $started_at,
215
+ "updatedAt": $completed_at,
216
+ "pid": $$,
217
+ "exitCode": $exit_code,
218
+ "signal": $signal_json,
219
+ "completedAt": $completed_at
220
+ }
221
+ EOF
222
+ mv "$tmp_path" "$completion_path"
223
+ }
224
+
225
+ terminate() {
226
+ signal_name="$1"
227
+ short_signal=\${signal_name#SIG}
228
+ if [ -n "$child_pid" ]; then
229
+ kill -"$short_signal" "$child_pid" 2>/dev/null
230
+ wait "$child_pid" 2>/dev/null
231
+ fi
232
+ write_completion killed null "$signal_name"
233
+ exit 143
234
+ }
235
+
236
+ trap 'terminate SIGTERM' TERM
237
+ trap 'terminate SIGINT' INT
238
+ trap 'terminate SIGHUP' HUP
239
+
240
+ sh "$command_path" >> "$output_path" 2>&1 &
241
+ child_pid=$!
242
+ wait "$child_pid"
243
+ exit_code=$?
244
+ trap - TERM INT HUP
245
+
246
+ if [ ! -f "$completion_path" ]; then
247
+ if [ "$exit_code" -eq 0 ]; then
248
+ write_completion completed "$exit_code" null
249
+ else
250
+ write_completion failed "$exit_code" null
251
+ fi
252
+ fi
253
+ exit "$exit_code"
254
+ `;
255
+ }
256
+ function parseLaunchResult(output) {
257
+ const match = output.trim().match(/(?:^|\n)(?:group:(\d+):(\d+)|pid:(\d+))$/u);
258
+ if (!match)
259
+ return undefined;
260
+ const pid = Number(match[1] ?? match[3]);
261
+ if (!Number.isSafeInteger(pid) || pid <= 0)
262
+ return undefined;
263
+ const processGroupId = match[2] === undefined ? undefined : Number(match[2]);
264
+ if (processGroupId !== undefined && (!Number.isSafeInteger(processGroupId) || processGroupId <= 0)) {
265
+ return undefined;
266
+ }
267
+ return { pid, ...(processGroupId === undefined ? {} : { processGroupId }) };
268
+ }
269
+ function shellQuote(value) {
270
+ return `'${value.replaceAll("'", `'\\''`)}'`;
271
+ }
272
+ function sleep(ms, signal) {
273
+ return new Promise((resolve, reject) => {
274
+ if (signal?.aborted) {
275
+ reject(new Error('aborted'));
276
+ return;
277
+ }
278
+ const onAbort = () => {
279
+ clearTimeout(timeout);
280
+ reject(new Error('aborted'));
281
+ };
282
+ const timeout = setTimeout(() => {
283
+ signal?.removeEventListener('abort', onAbort);
284
+ resolve();
285
+ }, ms);
286
+ signal?.addEventListener('abort', onAbort, { once: true });
287
+ });
288
+ }
289
+ function errorMessage(error) {
290
+ return error instanceof Error ? error.message : String(error);
291
+ }
292
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ExtensionContext } from '@felan-ai/agent-core';
2
+ import type { BackgroundBashManager } from '../process-manager.js';
3
+ type Theme = ExtensionContext['ui']['theme'];
4
+ export declare class BackgroundBashOverlay {
5
+ private readonly manager;
6
+ private readonly theme;
7
+ private readonly done;
8
+ private readonly requestRender;
9
+ private jobs;
10
+ private selected;
11
+ private listScroll;
12
+ private logLines;
13
+ private logScroll;
14
+ private loading;
15
+ private message;
16
+ private view;
17
+ constructor(manager: BackgroundBashManager, theme: Theme, done: () => void, requestRender: () => void);
18
+ handleInput(data: string): void;
19
+ render(width: number): string[];
20
+ invalidate(): void;
21
+ private handleListInput;
22
+ private handleDetailInput;
23
+ private renderList;
24
+ private renderDetail;
25
+ private refresh;
26
+ private refreshDetail;
27
+ private refreshLog;
28
+ private selectListJob;
29
+ private openDetail;
30
+ private clampListScroll;
31
+ private scrollLog;
32
+ private scrollLogToBottom;
33
+ private clampLogScroll;
34
+ private stopSelected;
35
+ private killSelected;
36
+ private signalSelected;
37
+ }
38
+ export {};
39
+ //# sourceMappingURL=background-bash-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background-bash-overlay.d.ts","sourceRoot":"","sources":["../../src/ui/background-bash-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAQnE,KAAK,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;AAG7C,qBAAa,qBAAqB;IAW9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAbhC,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,IAAI,CAAuB;gBAGhB,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,IAAI,EAChB,aAAa,EAAE,MAAM,IAAI;IAK5C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAa/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAQ/B,UAAU,IAAI,IAAI;IAElB,OAAO,CAAC,eAAe;IA4CvB,OAAO,CAAC,iBAAiB;IA2CzB,OAAO,CAAC,UAAU;IAmClB,OAAO,CAAC,YAAY;YA4BN,OAAO;YAuBP,aAAa;YAKb,UAAU;IAoBxB,OAAO,CAAC,aAAa;YAOP,UAAU;IAMxB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,cAAc;YAOR,YAAY;YAIZ,YAAY;YAIZ,cAAc;CAsB7B"}