docs(tool): documented bash timeout clamp

Documented the 1-3600 second bash timeout clamp in the schema, model-facing prompt, and tool docs, including the async timeout behavior.

Added coverage that the shipped schema and rendered prompt expose the contract.

Fixes #4408
This commit is contained in:
roboomp
2026-07-03 06:13:52 +00:00
parent d0c1890a6c
commit 712d4e423b
5 changed files with 30 additions and 6 deletions
+1 -1
View File
@@ -27,7 +27,7 @@
| `timeout` | `number` | No | Timeout in seconds. Default `300`; clamped to `1..3600` by `clampTimeout("bash", ...)`. |
| `cwd` | `string` | No | Working directory, resolved against `session.cwd` via `resolveToCwd`. Must exist and be a directory. |
| `pty` | `boolean` | No | Request PTY mode. Default `false`. PTY is used only when `pty: true`, `PI_NO_PTY !== "1"`, and the tool context has a UI. |
| `async` | `boolean` | No | Background execution request. Present only when `async.enabled` is true for the session. Returns immediately with a job id instead of waiting. |
| `async` | `boolean` | No | Background execution request. Present only when `async.enabled` is true for the session. Returns immediately with a job id instead of waiting; it does not extend the effective `timeout`, so jobs are still killed after the clamped `1..3600` second budget. |
## Outputs
The tool returns a single `text` content block plus optional `details`.
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Documented the bash tool timeout clamp in the model-facing schema and prompt so callers know `async` jobs remain capped at 3600 seconds ([#4408](https://github.com/can1357/oh-my-pi/issues/4408)).
## [16.3.4] - 2026-07-03
### Fixed
@@ -39,9 +39,9 @@ Anything below → `eval` cell, not bash:
{{#if asyncEnabled}}
# Timeout and async
- `timeout` (seconds) caps wall-clock duration; the process is killed on elapse.
- `async: true` defers only reporting — it does NOT extend the timeout; a daemon run with `async: true` is still killed when `timeout` elapses.
- Long-running daemons (dev servers, watchers): pass a large explicit `timeout`. The shell session persists across calls, so `cmd &` keeps running between bash calls.
- `timeout` is seconds, clamped to `1..3600`; the process is killed on elapse.
- `async: true` defers only reporting — it does NOT extend the timeout; a daemon with `async: true` is still killed at the clamped timeout.
- Need >3600s? Detach/manage lifecycle yourself (`cmd &`, supervisor, self-restarting script). The shell session persists across calls.
{{/if}}
{{#if autoBackgroundEnabled}}
+4 -2
View File
@@ -132,10 +132,12 @@ async function saveBashOriginalArtifact(session: ToolSession, originalText: stri
}
}
const BASH_TIMEOUT_DESCRIPTION = `timeout in seconds; clamped to ${TOOL_TIMEOUTS.bash.min}-${TOOL_TIMEOUTS.bash.max}`;
const bashSchemaBase = type({
command: type("string").describe("command to execute"),
"env?": type({ "[string]": "string" }).describe("extra env vars"),
"timeout?": type("number").describe("timeout in seconds"),
"timeout?": type("number").describe(BASH_TIMEOUT_DESCRIPTION),
"cwd?": type("string").describe("working directory"),
"pty?": type("boolean").describe("run in pty mode"),
});
@@ -143,7 +145,7 @@ const bashSchemaBase = type({
const bashSchemaWithAsync = type({
command: "string",
"env?": { "[string]": "string" },
"timeout?": "number",
"timeout?": type("number").describe(BASH_TIMEOUT_DESCRIPTION),
"cwd?": "string",
"pty?": "boolean",
"async?": type("boolean").describe("run in background"),
@@ -288,6 +288,24 @@ describe("tool schema validation (post-sanitization)", () => {
expect(description).toContain("pr://123");
});
it("bash schema and prompt advertise the timeout clamp", async () => {
const session = createTestSession();
session.settings.set("async.enabled", true);
const tools = await createTools(session);
const bashTool = tools.find(tool => tool.name === "bash");
if (!bashTool?.parameters) throw new Error("bash tool parameters missing");
const schema = toolWireSchema(bashTool) as {
properties?: { timeout?: { description?: string } };
};
const timeoutDescription = schema.properties?.timeout?.description ?? "";
expect(timeoutDescription).toContain("clamped");
expect(timeoutDescription).toContain("1-3600");
expect(bashTool.description).toContain("clamped to `1..3600`");
expect(bashTool.description).toContain("does NOT extend the timeout");
});
it("hidden tools also have valid sanitized schemas", async () => {
const session = createTestSession();