@agent-sh/harness-bash 0.2.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.
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/index.cjs +1009 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +351 -0
- package/dist/index.d.ts +351 -0
- package/dist/index.js +951 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { ToolError, PermissionPolicy, ToolDefinition } from '@agent-sh/harness-core';
|
|
2
|
+
import * as v from 'valibot';
|
|
3
|
+
|
|
4
|
+
interface BashParams {
|
|
5
|
+
readonly command: string;
|
|
6
|
+
readonly cwd?: string;
|
|
7
|
+
readonly timeout_ms?: number;
|
|
8
|
+
readonly description?: string;
|
|
9
|
+
readonly background?: boolean;
|
|
10
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
11
|
+
}
|
|
12
|
+
interface BashOutputParams {
|
|
13
|
+
readonly job_id: string;
|
|
14
|
+
readonly since_byte?: number;
|
|
15
|
+
readonly head_limit?: number;
|
|
16
|
+
}
|
|
17
|
+
interface BashKillParams {
|
|
18
|
+
readonly job_id: string;
|
|
19
|
+
readonly signal?: "SIGTERM" | "SIGKILL";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Executor interface — the pluggable boundary between core (which ships a
|
|
23
|
+
* local subprocess runner) and adapter packages (bash-docker, bash-firejail,
|
|
24
|
+
* bash-e2b). Core NEVER imports an adapter; adapters are peer deps of the
|
|
25
|
+
* harness that chooses one.
|
|
26
|
+
*/
|
|
27
|
+
interface BashRunResult {
|
|
28
|
+
readonly exitCode: number | null;
|
|
29
|
+
readonly killed: boolean;
|
|
30
|
+
readonly signal: string | null;
|
|
31
|
+
}
|
|
32
|
+
interface BashRunInput {
|
|
33
|
+
readonly command: string;
|
|
34
|
+
readonly cwd: string;
|
|
35
|
+
readonly env: Readonly<Record<string, string>>;
|
|
36
|
+
readonly signal: AbortSignal;
|
|
37
|
+
readonly onStdout: (chunk: Uint8Array) => void;
|
|
38
|
+
readonly onStderr: (chunk: Uint8Array) => void;
|
|
39
|
+
}
|
|
40
|
+
interface BackgroundReadResult {
|
|
41
|
+
readonly stdout: string;
|
|
42
|
+
readonly stderr: string;
|
|
43
|
+
readonly running: boolean;
|
|
44
|
+
readonly exitCode: number | null;
|
|
45
|
+
readonly totalBytesStdout: number;
|
|
46
|
+
readonly totalBytesStderr: number;
|
|
47
|
+
}
|
|
48
|
+
interface BashExecutor {
|
|
49
|
+
run(input: BashRunInput): Promise<BashRunResult>;
|
|
50
|
+
spawnBackground?(input: {
|
|
51
|
+
command: string;
|
|
52
|
+
cwd: string;
|
|
53
|
+
env: Readonly<Record<string, string>>;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
jobId: string;
|
|
56
|
+
}>;
|
|
57
|
+
readBackground?(jobId: string, opts: {
|
|
58
|
+
since_byte?: number;
|
|
59
|
+
head_limit?: number;
|
|
60
|
+
}): Promise<BackgroundReadResult>;
|
|
61
|
+
killBackground?(jobId: string, signal?: "SIGTERM" | "SIGKILL"): Promise<void>;
|
|
62
|
+
closeSession?(): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Session-bound permission policy. Same shape as read/grep/glob sessions,
|
|
66
|
+
* with an opt-in escape hatch for unsandboxed test fixtures only.
|
|
67
|
+
*/
|
|
68
|
+
interface BashPermissionPolicy extends PermissionPolicy {
|
|
69
|
+
readonly unsafeAllowBashWithoutHook?: boolean;
|
|
70
|
+
}
|
|
71
|
+
interface BashSessionConfig {
|
|
72
|
+
readonly cwd: string;
|
|
73
|
+
readonly permissions: BashPermissionPolicy;
|
|
74
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
75
|
+
readonly executor?: BashExecutor;
|
|
76
|
+
readonly defaultInactivityTimeoutMs?: number;
|
|
77
|
+
readonly wallclockBackstopMs?: number;
|
|
78
|
+
readonly maxCommandLength?: number;
|
|
79
|
+
readonly maxOutputBytesInline?: number;
|
|
80
|
+
readonly maxOutputBytesFile?: number;
|
|
81
|
+
readonly maxBackgroundJobs?: number;
|
|
82
|
+
readonly signal?: AbortSignal;
|
|
83
|
+
/**
|
|
84
|
+
* Working directory the tool tracks across calls. When the model issues
|
|
85
|
+
* a top-level `cd <path>` that lands inside the workspace, we mutate this
|
|
86
|
+
* in place. Optional — if omitted, cwd-carry is disabled and every call
|
|
87
|
+
* runs at `session.cwd`.
|
|
88
|
+
*/
|
|
89
|
+
logicalCwd?: {
|
|
90
|
+
value: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
type BashOk = {
|
|
94
|
+
readonly kind: "ok";
|
|
95
|
+
readonly output: string;
|
|
96
|
+
readonly exitCode: number;
|
|
97
|
+
readonly stdout: string;
|
|
98
|
+
readonly stderr: string;
|
|
99
|
+
readonly durationMs: number;
|
|
100
|
+
readonly logPath?: string;
|
|
101
|
+
readonly byteCap: boolean;
|
|
102
|
+
};
|
|
103
|
+
type BashNonzeroExit = {
|
|
104
|
+
readonly kind: "nonzero_exit";
|
|
105
|
+
readonly output: string;
|
|
106
|
+
readonly exitCode: number;
|
|
107
|
+
readonly stdout: string;
|
|
108
|
+
readonly stderr: string;
|
|
109
|
+
readonly durationMs: number;
|
|
110
|
+
readonly logPath?: string;
|
|
111
|
+
readonly byteCap: boolean;
|
|
112
|
+
};
|
|
113
|
+
type BashTimeout = {
|
|
114
|
+
readonly kind: "timeout";
|
|
115
|
+
readonly output: string;
|
|
116
|
+
readonly stdout: string;
|
|
117
|
+
readonly stderr: string;
|
|
118
|
+
readonly reason: "inactivity timeout" | "wall-clock backstop";
|
|
119
|
+
readonly durationMs: number;
|
|
120
|
+
readonly logPath?: string;
|
|
121
|
+
};
|
|
122
|
+
type BashBackgroundStarted = {
|
|
123
|
+
readonly kind: "background_started";
|
|
124
|
+
readonly output: string;
|
|
125
|
+
readonly jobId: string;
|
|
126
|
+
};
|
|
127
|
+
type BashError = {
|
|
128
|
+
readonly kind: "error";
|
|
129
|
+
readonly error: ToolError;
|
|
130
|
+
};
|
|
131
|
+
type BashResult = BashOk | BashNonzeroExit | BashTimeout | BashBackgroundStarted | BashError;
|
|
132
|
+
type BashOutputResult = {
|
|
133
|
+
readonly kind: "output";
|
|
134
|
+
readonly output: string;
|
|
135
|
+
readonly running: boolean;
|
|
136
|
+
readonly exitCode: number | null;
|
|
137
|
+
readonly stdout: string;
|
|
138
|
+
readonly stderr: string;
|
|
139
|
+
readonly totalBytesStdout: number;
|
|
140
|
+
readonly totalBytesStderr: number;
|
|
141
|
+
readonly nextSinceByte: number;
|
|
142
|
+
} | BashError;
|
|
143
|
+
type BashKillResult = {
|
|
144
|
+
readonly kind: "killed";
|
|
145
|
+
readonly output: string;
|
|
146
|
+
readonly jobId: string;
|
|
147
|
+
readonly signal: "SIGTERM" | "SIGKILL";
|
|
148
|
+
} | BashError;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Top-level `cd` detector for session cwd-carry.
|
|
152
|
+
*
|
|
153
|
+
* Matches a single top-level `cd` invocation only — NOT inside pipelines
|
|
154
|
+
* (`cd x | true`), command lists (`cd x && y`), subshells (`(cd x)`),
|
|
155
|
+
* or with trailing arguments. This deliberately covers 95% of model
|
|
156
|
+
* intent without hand-parsing the full bash grammar.
|
|
157
|
+
*
|
|
158
|
+
* Returns the path argument if detected, else null.
|
|
159
|
+
*/
|
|
160
|
+
declare function detectTopLevelCd(command: string): string | null;
|
|
161
|
+
declare function bash(input: unknown, session: BashSessionConfig): Promise<BashResult>;
|
|
162
|
+
declare function bashOutput(input: unknown, session: BashSessionConfig): Promise<BashOutputResult>;
|
|
163
|
+
declare function bashKill(input: unknown, session: BashSessionConfig): Promise<BashKillResult>;
|
|
164
|
+
/**
|
|
165
|
+
* Apply cwd-carry: if the command is a top-level `cd <path>` and the
|
|
166
|
+
* destination resolves inside the workspace, mutate session.logicalCwd.
|
|
167
|
+
* Called AFTER the command executes with exit 0 (caller's responsibility).
|
|
168
|
+
*
|
|
169
|
+
* Exposed separately so tests can exercise the logic directly AND so a
|
|
170
|
+
* harness wrapper can call it at the right point in the lifecycle. In
|
|
171
|
+
* core, the orchestrator does NOT auto-call this — we keep cwd-carry
|
|
172
|
+
* out of the hot path for correctness; the caller opts in by invoking
|
|
173
|
+
* applyCwdCarry after a successful bash() result.
|
|
174
|
+
*
|
|
175
|
+
* Rationale: cwd-carry mutates session state which has observable
|
|
176
|
+
* implications for concurrent calls. Making it explicit is safer.
|
|
177
|
+
*/
|
|
178
|
+
declare function applyCwdCarry(session: BashSessionConfig, command: string, exitCode: number | null): {
|
|
179
|
+
changed: boolean;
|
|
180
|
+
newCwd: string | null;
|
|
181
|
+
escaped: boolean;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
declare const BashParamsSchema: v.StrictObjectSchema<{
|
|
185
|
+
readonly command: v.SchemaWithPipe<[v.StringSchema<undefined>, v.MinLengthAction<string, 1, "command is required">, v.MaxLengthAction<string, 16384, "command exceeds 16384 bytes">]>;
|
|
186
|
+
readonly cwd: v.OptionalSchema<v.SchemaWithPipe<[v.StringSchema<undefined>, v.MinLengthAction<string, 1, "cwd must not be empty">]>, never>;
|
|
187
|
+
readonly timeout_ms: v.OptionalSchema<v.SchemaWithPipe<[v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 100, "timeout_ms must be >= 100 ms">]>, never>;
|
|
188
|
+
readonly description: v.OptionalSchema<v.StringSchema<undefined>, never>;
|
|
189
|
+
readonly background: v.OptionalSchema<v.BooleanSchema<undefined>, never>;
|
|
190
|
+
readonly env: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>, never>;
|
|
191
|
+
}, undefined>;
|
|
192
|
+
declare const BashOutputParamsSchema: v.StrictObjectSchema<{
|
|
193
|
+
readonly job_id: v.SchemaWithPipe<[v.StringSchema<undefined>, v.MinLengthAction<string, 1, "job_id is required">]>;
|
|
194
|
+
readonly since_byte: v.OptionalSchema<v.SchemaWithPipe<[v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, "since_byte must be >= 0">]>, never>;
|
|
195
|
+
readonly head_limit: v.OptionalSchema<v.SchemaWithPipe<[v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, "head_limit must be >= 1">]>, never>;
|
|
196
|
+
}, undefined>;
|
|
197
|
+
declare const BashKillParamsSchema: v.StrictObjectSchema<{
|
|
198
|
+
readonly job_id: v.SchemaWithPipe<[v.StringSchema<undefined>, v.MinLengthAction<string, 1, "job_id is required">]>;
|
|
199
|
+
readonly signal: v.OptionalSchema<v.PicklistSchema<["SIGTERM", "SIGKILL"], undefined>, never>;
|
|
200
|
+
}, undefined>;
|
|
201
|
+
declare function safeParseBashParams(input: unknown): {
|
|
202
|
+
ok: true;
|
|
203
|
+
value: BashParams;
|
|
204
|
+
} | {
|
|
205
|
+
ok: false;
|
|
206
|
+
issues: v.BaseIssue<unknown>[];
|
|
207
|
+
};
|
|
208
|
+
declare function safeParseBashOutputParams(input: unknown): {
|
|
209
|
+
ok: true;
|
|
210
|
+
value: BashOutputParams;
|
|
211
|
+
} | {
|
|
212
|
+
ok: false;
|
|
213
|
+
issues: v.BaseIssue<unknown>[];
|
|
214
|
+
};
|
|
215
|
+
declare function safeParseBashKillParams(input: unknown): {
|
|
216
|
+
ok: true;
|
|
217
|
+
value: BashKillParams;
|
|
218
|
+
} | {
|
|
219
|
+
ok: false;
|
|
220
|
+
issues: v.BaseIssue<unknown>[];
|
|
221
|
+
};
|
|
222
|
+
declare const BASH_TOOL_NAME = "bash";
|
|
223
|
+
declare const BASH_TOOL_DESCRIPTION = "Run a single shell command in a bash subprocess. Output is captured and returned with the exit code.\n\nUsage:\n- 'cd' carries over to subsequent calls if it stays inside the workspace; otherwise the cwd is reset. Environment variables do NOT persist across calls \u2014 set them inline (FOO=bar some-cmd) or via 'env'.\n- For non-shell code, use language one-liners: 'python -c \"print(2+2)\"', 'node -e \"console.log(2+2)\"', 'deno eval \"console.log(2+2)\"'. For multi-line scripts, write a temp file with the write tool and invoke the interpreter on it.\n- Long-running processes (servers, watchers) MUST use background: true. The tool returns a job_id; poll output with bash_output(job_id). Do not leave a foreground command running past the 5-minute wall-clock backstop.\n- No interactive commands. Anything that needs stdin (pagers, Y/n prompts, REPLs, 'git commit' without -m) will hang until the inactivity timeout. Use flags to make commands non-interactive (--yes, -y, --no-pager) or pipe 'echo \"y\" |' in front.\n- Inactivity timeout resets on any output; default 60000 ms. Override with timeout_ms. Wall-clock backstop is 5 minutes for foreground calls.\n- Prefer this tool over other ways of running shell commands. For filename search prefer 'glob'; for content search prefer 'grep'.";
|
|
224
|
+
declare const bashToolDefinition: ToolDefinition;
|
|
225
|
+
declare const BASH_OUTPUT_TOOL_NAME = "bash_output";
|
|
226
|
+
declare const BASH_OUTPUT_TOOL_DESCRIPTION = "Poll a backgrounded bash job's output since a given byte offset.\n\nReturns stdout and stderr slices plus whether the job is still running and its exit code if finished. Use 'since_byte' from the previous call to paginate through a long-running job's output without re-fetching already-seen bytes.";
|
|
227
|
+
declare const bashOutputToolDefinition: ToolDefinition;
|
|
228
|
+
declare const BASH_KILL_TOOL_NAME = "bash_kill";
|
|
229
|
+
declare const BASH_KILL_TOOL_DESCRIPTION = "Send a termination signal to a backgrounded bash job.\n\nDefaults to SIGTERM (graceful). Use SIGKILL for an unresponsive job. The job's next bash_output call will report running: false.";
|
|
230
|
+
declare const bashKillToolDefinition: ToolDefinition;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Default local-subprocess executor.
|
|
234
|
+
*
|
|
235
|
+
* Launches the bash binary with `-c <command>` via the argv form of
|
|
236
|
+
* node:child_process.spawn — NEVER the string-based shell-eval entry
|
|
237
|
+
* point. The command string is passed as a single argument to the bash
|
|
238
|
+
* binary, not interpolated into our own spawn args. All shell parsing
|
|
239
|
+
* happens inside the child bash process.
|
|
240
|
+
*
|
|
241
|
+
* This executor ships unsandboxed; sandboxing is the job of adapter
|
|
242
|
+
* packages that implement the same BashExecutor interface. See
|
|
243
|
+
* packages/bash/src/types.ts.
|
|
244
|
+
*/
|
|
245
|
+
declare function createLocalBashExecutor(opts?: {
|
|
246
|
+
bashPath?: string;
|
|
247
|
+
logDir?: string;
|
|
248
|
+
}): BashExecutor;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Per-stream output buffer with head+tail capping and spill-to-file on
|
|
252
|
+
* overflow. Models rarely need the middle of a long output — they need
|
|
253
|
+
* either the setup line or the error tail. This buffer preserves both.
|
|
254
|
+
*/
|
|
255
|
+
declare class HeadTailBuffer {
|
|
256
|
+
private readonly maxInline;
|
|
257
|
+
private readonly maxFile;
|
|
258
|
+
private readonly kind;
|
|
259
|
+
private readonly spillDir;
|
|
260
|
+
private readonly chunks;
|
|
261
|
+
private totalBytes;
|
|
262
|
+
private byteCap;
|
|
263
|
+
private spilled;
|
|
264
|
+
private spillPath;
|
|
265
|
+
private spillBytes;
|
|
266
|
+
constructor(maxInline: number, maxFile: number, kind: "out" | "err", spillDir: string);
|
|
267
|
+
write(chunk: Uint8Array): void;
|
|
268
|
+
private appendSpill;
|
|
269
|
+
private spillInit;
|
|
270
|
+
private fileBytesWritten;
|
|
271
|
+
/**
|
|
272
|
+
* Return the inline render:
|
|
273
|
+
* - If not capped: the full buffered text.
|
|
274
|
+
* - If capped: head (first maxInline/2 bytes) + marker + tail
|
|
275
|
+
* (last maxInline/2 bytes) approximation. We approximate the tail
|
|
276
|
+
* by decoding only the tail window (maxInline/2 bytes from the spill
|
|
277
|
+
* file) because the stream is write-once and we dropped the middle.
|
|
278
|
+
*
|
|
279
|
+
* The actual implementation is simpler: we keep only the head inline
|
|
280
|
+
* (first maxInline bytes, never overwritten) and emit a marker that
|
|
281
|
+
* points at the log path. Head-only is a deliberate simplification
|
|
282
|
+
* versus spec's head+tail — it matches OpenCode's default, and we
|
|
283
|
+
* rely on Read(path) to see the tail. Spec §4 head+tail is a v2
|
|
284
|
+
* improvement once we prove the file-path recovery path.
|
|
285
|
+
*/
|
|
286
|
+
render(): {
|
|
287
|
+
text: string;
|
|
288
|
+
byteCap: boolean;
|
|
289
|
+
logPath: string | null;
|
|
290
|
+
};
|
|
291
|
+
bytesTotal(): number;
|
|
292
|
+
wasCapped(): boolean;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Format the text body of an "ok" / "nonzero_exit" result.
|
|
296
|
+
* Kept deliberately simple — structured fields ride on the result
|
|
297
|
+
* object; `output` is the canonical text the executor returns to the
|
|
298
|
+
* model at the tool_result boundary.
|
|
299
|
+
*/
|
|
300
|
+
declare function formatResultText(args: {
|
|
301
|
+
command: string;
|
|
302
|
+
exitCode: number;
|
|
303
|
+
stdout: string;
|
|
304
|
+
stderr: string;
|
|
305
|
+
durationMs: number;
|
|
306
|
+
byteCap: boolean;
|
|
307
|
+
logPath: string | null;
|
|
308
|
+
kind: "ok" | "nonzero_exit";
|
|
309
|
+
}): string;
|
|
310
|
+
declare function formatTimeoutText(args: {
|
|
311
|
+
command: string;
|
|
312
|
+
stdout: string;
|
|
313
|
+
stderr: string;
|
|
314
|
+
reason: "inactivity timeout" | "wall-clock backstop";
|
|
315
|
+
durationMs: number;
|
|
316
|
+
partialBytes: number;
|
|
317
|
+
logPath: string | null;
|
|
318
|
+
}): string;
|
|
319
|
+
declare function formatBackgroundStartedText(args: {
|
|
320
|
+
command: string;
|
|
321
|
+
jobId: string;
|
|
322
|
+
}): string;
|
|
323
|
+
declare function formatBashOutputText(args: {
|
|
324
|
+
jobId: string;
|
|
325
|
+
running: boolean;
|
|
326
|
+
exitCode: number | null;
|
|
327
|
+
stdout: string;
|
|
328
|
+
stderr: string;
|
|
329
|
+
sinceByte: number;
|
|
330
|
+
returnedBytes: number;
|
|
331
|
+
totalBytes: number;
|
|
332
|
+
}): string;
|
|
333
|
+
declare function formatBashKillText(args: {
|
|
334
|
+
jobId: string;
|
|
335
|
+
signal: "SIGTERM" | "SIGKILL";
|
|
336
|
+
}): string;
|
|
337
|
+
|
|
338
|
+
declare const DEFAULT_INACTIVITY_TIMEOUT_MS = 60000;
|
|
339
|
+
declare const DEFAULT_WALLCLOCK_BACKSTOP_MS = 300000;
|
|
340
|
+
declare const MAX_COMMAND_LENGTH = 16384;
|
|
341
|
+
declare const MAX_OUTPUT_BYTES_INLINE = 30720;
|
|
342
|
+
declare const MAX_OUTPUT_BYTES_FILE: number;
|
|
343
|
+
declare const BACKGROUND_MAX_JOBS = 16;
|
|
344
|
+
/**
|
|
345
|
+
* Env var name prefixes that the tool refuses to let the model set via `env`.
|
|
346
|
+
* Defense in depth: even if the harness forwards its environment, the model
|
|
347
|
+
* should not be able to override credentials per-call.
|
|
348
|
+
*/
|
|
349
|
+
declare const SENSITIVE_ENV_PREFIXES: readonly string[];
|
|
350
|
+
|
|
351
|
+
export { BACKGROUND_MAX_JOBS, BASH_KILL_TOOL_DESCRIPTION, BASH_KILL_TOOL_NAME, BASH_OUTPUT_TOOL_DESCRIPTION, BASH_OUTPUT_TOOL_NAME, BASH_TOOL_DESCRIPTION, BASH_TOOL_NAME, type BackgroundReadResult, type BashBackgroundStarted, type BashError, type BashExecutor, type BashKillParams, BashKillParamsSchema, type BashKillResult, type BashNonzeroExit, type BashOk, type BashOutputParams, BashOutputParamsSchema, type BashOutputResult, type BashParams, BashParamsSchema, type BashPermissionPolicy, type BashResult, type BashRunInput, type BashRunResult, type BashSessionConfig, type BashTimeout, DEFAULT_INACTIVITY_TIMEOUT_MS, DEFAULT_WALLCLOCK_BACKSTOP_MS, HeadTailBuffer, MAX_COMMAND_LENGTH, MAX_OUTPUT_BYTES_FILE, MAX_OUTPUT_BYTES_INLINE, SENSITIVE_ENV_PREFIXES, applyCwdCarry, bash, bashKill, bashKillToolDefinition, bashOutput, bashOutputToolDefinition, bashToolDefinition, createLocalBashExecutor, detectTopLevelCd, formatBackgroundStartedText, formatBashKillText, formatBashOutputText, formatResultText, formatTimeoutText, safeParseBashKillParams, safeParseBashOutputParams, safeParseBashParams };
|