docs: rebalance prose cleanup and add trimming skill
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* `LocalBashExecutor`: the local-subprocess implementation of the `@deepseek-ai/dsh-bash`
|
||||
* executor seam.
|
||||
* Local-subprocess implementation of the bash seam. Each call runs in its own
|
||||
* process group, background tasks are tracked, and disposal kills and awaits
|
||||
* them. Execution policy belongs in `tools/pre-execute` or a sandboxing
|
||||
* executor, not this local process layer.
|
||||
* @module @deepseek-ai/dsh-bash-local
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Process plumbing for the local bash executor: spawn, output collection with tail-keep +
|
||||
* spill-to-disk truncation, and process-group kill with SIGTERM→SIGKILL escalation.
|
||||
* Process plumbing for the local bash executor: detached process-group spawn,
|
||||
* tail-keep output with spill files, and SIGTERM→SIGKILL escalation. This layer
|
||||
* reacts to an abort signal; the executor owns deadlines and classifies causes.
|
||||
* @module dsh-bash-local/run
|
||||
*/
|
||||
|
||||
@@ -33,8 +34,8 @@ export const ENV_OVERRIDES = {
|
||||
export const SENSITIVE_ENV_PATTERN = /KEY|SECRET|TOKEN/i
|
||||
|
||||
/**
|
||||
* `process.env` minus credential-shaped vars, plus the model-friendly overrides, plus any
|
||||
* caller-supplied `extra` entries.
|
||||
* Build a child environment by scrubbing credential-shaped ambient variables,
|
||||
* applying model-friendly overrides, then merging trusted caller entries last.
|
||||
*
|
||||
* @param extra - caller-supplied entries merged last; an explicit entry wins even against the scrub and the overrides.
|
||||
* @returns the environment to hand to `spawn` for the child process.
|
||||
@@ -236,8 +237,8 @@ export class OutputCollector {
|
||||
try {
|
||||
closeSync(this.spillFd)
|
||||
} catch {
|
||||
// close can surface delayed writeback failures (for example EIO/ENOSPC) after writeSync
|
||||
// appeared to succeed.
|
||||
// A delayed writeback failure makes the spill unreliable; keep finalize
|
||||
// total but stop advertising that file.
|
||||
this.spillFile = undefined
|
||||
}
|
||||
this.spillFd = undefined
|
||||
@@ -247,9 +248,9 @@ export class OutputCollector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send `sig` to the process GROUP led by `pid` (requires the child to have been spawned with
|
||||
* `detached: true`).
|
||||
*
|
||||
* Send `sig` to a detached process group. Never throws: delivery races process
|
||||
* exit and may run in a timer callback, so failures are contained and a
|
||||
* non-positive pid is a no-op.
|
||||
* @param pid - the group leader's pid; non-positive means the spawn failed and the call is a no-op.
|
||||
* @param sig - the signal to deliver to the whole group.
|
||||
*/
|
||||
|
||||
@@ -337,7 +337,7 @@ describe('LocalBashExecutor background tasks', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('review fixes: lifecycle hardening', () => {
|
||||
describe('executor cancellation, callback, and disposal contracts', () => {
|
||||
it('start honors a pre-aborted or later-aborted AbortSignal', async () => {
|
||||
const { bash } = await setup()
|
||||
const controller = new AbortController()
|
||||
|
||||
@@ -189,8 +189,8 @@ describe('stdin and extra env (set by in-process plugins)', () => {
|
||||
})
|
||||
|
||||
it('gives fd 0 the exact pre-seam type: /dev/null when no stdin, a pipe when supplied', async () => {
|
||||
// The no-stdin path must stay observationally identical to the pre-seam `ignore` default: a
|
||||
// command that probes stdin's file type sees a char device (/dev/null).
|
||||
// With no bytes, fd 0 remains the pre-seam `ignore` default (/dev/null, a character device).
|
||||
// Supplied bytes use Node's spawn pipe, which is an AF_UNIX socket rather than a FIFO.
|
||||
const none = await runBash(spec('test -c /dev/stdin && echo char || echo other')).done
|
||||
expect(none.stdout.text).toBe('char\n')
|
||||
const piped = await runBash(spec('test -S /dev/stdin && echo socket || echo other', { stdin: 'x' })).done
|
||||
@@ -215,8 +215,8 @@ describe('stdin and extra env (set by in-process plugins)', () => {
|
||||
})
|
||||
|
||||
it('does not crash or reject when the child ignores a large stdin (EPIPE)', async () => {
|
||||
// The child exits immediately without reading; closing our end of a stdin pipe still
|
||||
// holding ~1MiB triggers EPIPE on the write.
|
||||
// The child exits without reading, so closing a stdin pipe holding ~1 MiB triggers EPIPE.
|
||||
// The handler swallows that write error and `done` reports the child's real exit.
|
||||
const big = 'x'.repeat(1024 * 1024)
|
||||
const result = await runBash(spec('exit 7', { stdin: big })).done
|
||||
expect(result.exitCode).toBe(7)
|
||||
@@ -355,7 +355,7 @@ describe('abort edge cases', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('review fixes: env scrubbing and spill hardening', () => {
|
||||
describe('environment and spill-file hardening', () => {
|
||||
it('scrubs credential-shaped env vars from child processes', async () => {
|
||||
process.env.DSH_TEST_API_KEY = 'super-secret'
|
||||
process.env.DSH_TEST_TOKEN = 'also-secret'
|
||||
|
||||
Reference in New Issue
Block a user