@deepseek-ai/dsh-bash-local 0.0.1-rc.1 → 0.0.1-rc.2

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/bash/bash-local/README.md
5
- README.md: cb8e7f0ae766d9b1c5f1678e77d35992085d3d52
6
- README.zh.md: 20af9c18998c6f3f0403c50f3a8ac599607dc094
5
+ README.md: 386ffc00466108ab14352b6d39d3a20da3321e1c
6
+ README.zh.md: 39d37bededa72ec96911bb1ce055ed105fdd7082
package/README.md CHANGED
@@ -23,9 +23,10 @@ The package root exports the default and named `LocalBashExecutor` plugin plus i
23
23
  ## Behavior
24
24
 
25
25
  - **Spawn per call, no shell state** — every call is a fresh non-login `bash -c` with no rc files.
26
+ - **The composition entry is a layer, not the last word** — when a settings provider is composed, this executor registers the capability's [`bash` namespace](../bash/README.md) with the entry above as its base, so a user section in `settings.yaml` layers over it and the next command runs with the new budgets. Values the schema cannot judge (positive and finite, the `graceMs` timer bound) are refused at the write, leaving the running executor on its last good section; without a provider, or after one detaches, the composition entry is what runs.
26
27
  - **Configured budgets over managed groups** — `resolve()` fills `workdir`/`timeoutMs`/`stdoutMaxBytes` from config, and every spawn hands the service explicit byte caps, spill cap, and `graceMs`. The grace must be positive, finite, and no greater than [`MAX_TIMER_DELAY_MS`](../../util/timeout/README.md), so Node can represent it with one timer. Process-group kills, post-exit pipe draining, tail retention, and bounded spill files are [`dsh-subprocess-local`](../../subprocess/subprocess-local/README.md) mechanics. A foreground `BashExecRequest.stdoutMaxBytes` can raise stdout's capture budget for one trusted caller; stderr and background runs still use `maxOutputBytes`.
27
28
  - **Timeout and cancel classification** — `run()` fuses its config-clamped timeout with the caller's signal through one deadline; only the executor's own timeout reports `timedOut`, an upstream cancel reports `aborted`, and a self-signaled command reports neither ([timeout-library Agent Note](../../../.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md)).
28
- - **Model-friendly terminal env** — `NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat` prevents pagers and ANSI color from garbling results. These values merge as ordinary env under the service's credential scrub and `DSH_*` channel rules; an explicit caller entry still wins. See the [stdin/env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) and [managed environment Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md).
29
+ - **Model-friendly terminal env** — `NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat` prevents pagers and ANSI color from garbling results. These values merge as ordinary env under the service's credential scrub and `DSH_*` channel rules; an explicit caller entry still wins. See the [stdin/env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-api.md) and [managed environment Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md).
29
30
  - **Background processes** — `start()` returns a live `BashProcess` handle immediately with no timeout, and `readOutput()` merges offset-based stdout/stderr reads into one consuming delta, placing stderr under a `[stderr]` marker when present. A running process belongs to the subprocess service, survives executor reloads, and is killed and joined on service disposal. Task ids, ownership, polling, and notices belong to the generic [`ctx.tasks` runtime](../../tasks/tasks/README.md), which the tool layer registers the handle with.
30
31
 
31
32
  ## Model Experience
package/README.zh.md CHANGED
@@ -23,9 +23,10 @@
23
23
  ## 行为
24
24
 
25
25
  - **每次调用都 spawn,不保留 shell 状态**:每次调用都启动新的非登录 `bash -c`,且不读取 rc 文件。
26
+ - **组装条目是一层,而不是最终值**:当组装中存在 settings 提供方时,本执行器以上面的条目为 base 注册该能力的 [`bash` 命名空间](../bash/README.md),因此 `settings.yaml` 中的用户段会叠加其上,下一条命令即按新预算运行。schema 无法判定的值(正有限、`graceMs` 的定时器上界)会在写入时被拒绝,运行中的执行器保持它最后一份可用的段;没有提供方、或提供方脱离之后,运行的就是组装条目。
26
27
  - **在受管进程组之上应用配置预算**:`resolve()` 从配置补全 `workdir`/`timeoutMs`/`stdoutMaxBytes`,每次 spawn 都向服务传入显式的字节上限、spill 上限与 `graceMs`。该宽限期须为正有限值,且不得大于 [`MAX_TIMER_DELAY_MS`](../../util/timeout/README.md),这样 Node 就能用一个定时器表示它。进程组终止、退出后管道排空、尾部保留与有界 spill 文件是 [`dsh-subprocess-local`](../../subprocess/subprocess-local/README.md) 的机制。前台 `BashExecRequest.stdoutMaxBytes` 可为某个受信任调用方提高单次 stdout 捕获预算;stderr 和后台运行仍使用 `maxOutputBytes`。
27
28
  - **超时与取消分类**:`run()` 通过同一个 deadline 把经配置钳位的超时与调用方的信号融合;只有执行器自身的超时报告 `timedOut`,上游取消报告 `aborted`,自身因信号终止的命令两者皆不报告(见[超时库 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md))。
28
- - **适合模型的终端环境**:`NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat` 防止分页器与 ANSI 颜色破坏结果。这些值作为普通 env 合并,遵循服务的凭据清除与 `DSH_*` 通道规则;调用方的显式条目依旧优先。详见 [stdin/env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) 与 [受管环境 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md)。
29
+ - **适合模型的终端环境**:`NO_COLOR=1 TERM=dumb PAGER=cat GIT_PAGER=cat` 防止分页器与 ANSI 颜色破坏结果。这些值作为普通 env 合并,遵循服务的凭据清除与 `DSH_*` 通道规则;调用方的显式条目依旧优先。详见 [stdin/env Agent Note](../../../.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-api.md) 与 [受管环境 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-agent-session-identity-and-log-location.md)。
29
30
  - **后台进程**:`start()` 会立即返回活动的 `BashProcess` 句柄且不应用超时;`readOutput()` 把基于偏移量的 stdout/stderr 读取合并为一条消费式增量,并在存在 stderr 时将其置于 `[stderr]` 标记下。运行中的进程属于 subprocess 服务,可在执行器重载后存活,并在服务 dispose 时被终止且等待退出。task id、所有权、轮询和通知属于通用 [`ctx.tasks` 运行时](../../tasks/tasks/README.md),工具层会在其中注册该句柄。
30
31
 
31
32
  ## 模型体验
package/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
- import { BashExecutor } from "@deepseek-ai/dsh-bash";
2
+ import { BASH_SETTINGS_NAMESPACE, BashExecutor } from "@deepseek-ai/dsh-bash";
3
+ import { installSettingsSection } from "@deepseek-ai/dsh-settings";
3
4
  import { MAX_TIMER_DELAY_MS, clampTimeout, deadline, timeoutOf } from "@deepseek-ai/dsh-timeout";
4
5
  //#region lib/types/index.js
5
6
  /**
@@ -100,6 +101,23 @@ function assertPositiveFinite(name, value) {
100
101
  if (!Number.isFinite(value) || value <= 0) throw new Error(`bash-local: ${name} must be a positive finite number`);
101
102
  }
102
103
  /**
104
+ * Reject a resolved section this executor could not run with. The schema
105
+ * expresses neither "positive and finite" nor the timer bound `graceMs` has to
106
+ * fit, so a stored value is refused where it is written instead of failing at
107
+ * the next command.
108
+ * @param config - the resolved section, schema-valid by construction.
109
+ * @throws Error naming the field that cannot be used.
110
+ */
111
+ function assertServiceableBashConfig(config) {
112
+ const resolved = config;
113
+ assertPositiveFinite("timeoutMs", resolved.timeoutMs);
114
+ assertPositiveFinite("maxTimeoutMs", resolved.maxTimeoutMs);
115
+ assertPositiveFinite("maxOutputBytes", resolved.maxOutputBytes);
116
+ assertPositiveFinite("maxSpillBytes", resolved.maxSpillBytes);
117
+ assertPositiveFinite("graceMs", resolved.graceMs);
118
+ if (resolved.graceMs > MAX_TIMER_DELAY_MS) throw new Error(`bash-local: graceMs must be no greater than ${MAX_TIMER_DELAY_MS}`);
119
+ }
120
+ /**
103
121
  * Local bash executor over `ctx.subprocess`. Bounded output, spill files, and
104
122
  * process-group SIGTERM→SIGKILL escalation are the subprocess service's
105
123
  * mechanics; this executor supplies their configured budgets per spawn, so a
@@ -116,17 +134,24 @@ var LocalBashExecutor = class LocalBashExecutor extends BashExecutor {
116
134
  maxSpillBytes: z.number().default(DEFAULT_MAX_SPILL_BYTES),
117
135
  graceMs: z.number().default(DEFAULT_GRACE_MS)
118
136
  });
137
+ /** The currently authoritative config: the settings section, or the composition entry. */
138
+ source;
119
139
  /** Validated config (schemastery applied the defaults before construction). */
120
- config;
140
+ get config() {
141
+ return this.source();
142
+ }
121
143
  constructor(ctx, config) {
122
144
  super(ctx);
123
- this.config = config;
124
- assertPositiveFinite("timeoutMs", this.config.timeoutMs);
125
- assertPositiveFinite("maxTimeoutMs", this.config.maxTimeoutMs);
126
- assertPositiveFinite("maxOutputBytes", this.config.maxOutputBytes);
127
- assertPositiveFinite("maxSpillBytes", this.config.maxSpillBytes);
128
- assertPositiveFinite("graceMs", this.config.graceMs);
129
- if (this.config.graceMs > MAX_TIMER_DELAY_MS) throw new Error(`bash-local: graceMs must be no greater than ${MAX_TIMER_DELAY_MS}`);
145
+ const entry = config;
146
+ assertServiceableBashConfig(entry);
147
+ this.source = () => entry;
148
+ installSettingsSection(ctx, BASH_SETTINGS_NAMESPACE, LocalBashExecutor.Config, entry, {
149
+ validate: assertServiceableBashConfig,
150
+ setSource: (current) => {
151
+ this.source = current;
152
+ },
153
+ onChange: () => {}
154
+ });
130
155
  }
131
156
  /**
132
157
  * Resolve a request into a fully-specified spec: fill `workdir` from
@@ -305,4 +330,4 @@ var LocalBashExecutor = class LocalBashExecutor extends BashExecutor {
305
330
  onProcessDone(_proc, _stderr, _spawnFailed, _spawnError) {}
306
331
  };
307
332
  //#endregion
308
- export { ENV_OVERRIDES, LocalBashExecutor, LocalBashExecutor as default };
333
+ export { ENV_OVERRIDES, LocalBashExecutor, LocalBashExecutor as default, assertServiceableBashConfig };
@@ -42,6 +42,15 @@ export interface Config {
42
42
  }
43
43
  /** The shape after schemastery applied the defaults (cwd has none). */
44
44
  type ResolvedConfig = Required<Omit<Config, 'cwd'>> & Pick<Config, 'cwd'>;
45
+ /**
46
+ * Reject a resolved section this executor could not run with. The schema
47
+ * expresses neither "positive and finite" nor the timer bound `graceMs` has to
48
+ * fit, so a stored value is refused where it is written instead of failing at
49
+ * the next command.
50
+ * @param config - the resolved section, schema-valid by construction.
51
+ * @throws Error naming the field that cannot be used.
52
+ */
53
+ export declare function assertServiceableBashConfig(config: Config): void;
45
54
  /**
46
55
  * Local bash executor over `ctx.subprocess`. Bounded output, spill files, and
47
56
  * process-group SIGTERM→SIGKILL escalation are the subprocess service's
@@ -52,8 +61,10 @@ type ResolvedConfig = Required<Omit<Config, 'cwd'>> & Pick<Config, 'cwd'>;
52
61
  export declare class LocalBashExecutor extends BashExecutor {
53
62
  static inject: string[];
54
63
  static Config: z<Config>;
64
+ /** The currently authoritative config: the settings section, or the composition entry. */
65
+ private source;
55
66
  /** Validated config (schemastery applied the defaults before construction). */
56
- readonly config: ResolvedConfig;
67
+ get config(): ResolvedConfig;
57
68
  constructor(ctx: Context, config: Config);
58
69
  /**
59
70
  * Resolve a request into a fully-specified spec: fill `workdir` from
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-bash-local",
3
3
  "description": "Local-subprocess implementation of the DeepSeek Harness bash executor seam",
4
- "version": "0.0.1-rc.1",
4
+ "version": "0.0.1-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },
@@ -32,21 +32,23 @@
32
32
  ],
33
33
  "license": "BSD-3-Clause",
34
34
  "peerDependencies": {
35
- "@deepseek-ai/dsh-bash": "^0.0.1-rc.1",
36
- "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
37
- "@deepseek-ai/dsh-subprocess": "^0.0.1-rc.1",
38
- "@deepseek-ai/dsh-timeout": "^0.0.1-rc.1",
39
- "@deepseek-ai/cordis": "^4.0.1-rc.1"
35
+ "@deepseek-ai/dsh-bash": "^0.0.1-rc.2",
36
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.2",
37
+ "@deepseek-ai/dsh-subprocess": "^0.0.1-rc.2",
38
+ "@deepseek-ai/dsh-timeout": "^0.0.1-rc.2",
39
+ "@deepseek-ai/cordis": "^4.0.1-rc.1",
40
+ "@deepseek-ai/dsh-settings": "^0.0.1-rc.2"
40
41
  },
41
42
  "dependencies": {
42
43
  "@deepseek-ai/schemastery": "^3.18.1-rc.1"
43
44
  },
44
45
  "devDependencies": {
45
- "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
46
- "@deepseek-ai/dsh-bash": "^0.0.1-rc.1",
47
- "@deepseek-ai/dsh-subprocess-local": "^0.0.1-rc.1",
48
- "@deepseek-ai/dsh-subprocess": "^0.0.1-rc.1",
49
- "@deepseek-ai/dsh-timeout": "^0.0.1-rc.1",
50
- "@deepseek-ai/cordis": "^4.0.1-rc.1"
46
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.2",
47
+ "@deepseek-ai/dsh-subprocess-local": "^0.0.1-rc.2",
48
+ "@deepseek-ai/dsh-timeout": "^0.0.1-rc.2",
49
+ "@deepseek-ai/dsh-subprocess": "^0.0.1-rc.2",
50
+ "@deepseek-ai/dsh-bash": "^0.0.1-rc.2",
51
+ "@deepseek-ai/cordis": "^4.0.1-rc.1",
52
+ "@deepseek-ai/dsh-settings": "^0.0.1-rc.2"
51
53
  }
52
54
  }