diff --git a/docs/tools/exec.md b/docs/tools/exec.md index 201bebc4815..70770af9f6f 100644 --- a/docs/tools/exec.md +++ b/docs/tools/exec.md @@ -20,7 +20,7 @@ Background sessions are scoped per agent; `process` only sees sessions from the - `yieldMs` (default 10000): auto-background after delay - `background` (bool): background immediately - `timeout` (seconds, default 1800): kill on expiry -- `pty` (bool): run in a pseudo-terminal when available (TTY-only CLIs, coding agents, terminal UIs). Use for CLIs that only print when stdout is a TTY (e.g. gog / Google Workspace CLI). +- `pty` (bool): run in a pseudo-terminal when available (TTY-only CLIs, coding agents, terminal UIs) - `host` (`sandbox | gateway | node`): where to execute - `security` (`deny | allowlist | full`): enforcement mode for `gateway`/`node` - `ask` (`off | on-miss | always`): approval prompts for `gateway`/`node` @@ -42,19 +42,6 @@ Notes: the gateway host (no container) and **does not require approvals**. To require approvals, run with `host=gateway` and configure exec approvals (or enable sandboxing). -### TTY-only CLIs (e.g. gog) - -Some CLIs write to stdout only when it is a TTY. In non-interactive contexts (exec tool, scripts, CI) -they exit with code 0 but produce no output. Examples: **gog** (Google Workspace CLI), and other -tools that use `isatty(stdout)` to decide whether to print. For these, set **`pty: true`** so the -command runs in a pseudo-terminal and output is captured. - -Example: - -```json -{ "tool": "exec", "command": "gog --version", "pty": true } -``` - ## Config - `tools.exec.notifyOnExit` (default: true): when true, backgrounded exec sessions enqueue a system event and request a heartbeat on exit. diff --git a/src/agents/bash-tools.exec-runtime.ts b/src/agents/bash-tools.exec-runtime.ts index c659b4402fd..48a169343c9 100644 --- a/src/agents/bash-tools.exec-runtime.ts +++ b/src/agents/bash-tools.exec-runtime.ts @@ -1,16 +1,16 @@ -import path from "node:path"; import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import { Type } from "@sinclair/typebox"; +import path from "node:path"; import type { ExecAsk, ExecHost, ExecSecurity } from "../infra/exec-approvals.js"; -import { requestHeartbeatNow } from "../infra/heartbeat-wake.js"; -import { mergePathPrepend } from "../infra/path-prepend.js"; -import { enqueueSystemEvent } from "../infra/system-events.js"; import type { ProcessSession } from "./bash-process-registry.js"; import type { ExecToolDetails } from "./bash-tools.exec.js"; import type { BashSandboxConfig } from "./bash-tools.shared.js"; +import { requestHeartbeatNow } from "../infra/heartbeat-wake.js"; +import { mergePathPrepend } from "../infra/path-prepend.js"; +import { enqueueSystemEvent } from "../infra/system-events.js"; export { applyPathPrepend, normalizePathPrepend } from "../infra/path-prepend.js"; -import { logWarn } from "../logger.js"; import type { ManagedRun } from "../process/supervisor/index.js"; +import { logWarn } from "../logger.js"; import { getProcessSupervisor } from "../process/supervisor/index.js"; import { addSession, @@ -116,7 +116,7 @@ export const execSchema = Type.Object({ pty: Type.Optional( Type.Boolean({ description: - "Run in a pseudo-terminal (PTY) when available (TTY-required CLIs e.g. gog, coding agents)", + "Run in a pseudo-terminal (PTY) when available (TTY-required CLIs, coding agents)", }), ), elevated: Type.Optional( diff --git a/src/agents/bash-tools.exec.ts b/src/agents/bash-tools.exec.ts index f3cd7464785..e0fba6ea2b6 100644 --- a/src/agents/bash-tools.exec.ts +++ b/src/agents/bash-tools.exec.ts @@ -1,7 +1,8 @@ +import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; import crypto from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; -import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; +import type { BashSandboxConfig } from "./bash-tools.shared.js"; import { type ExecAsk, type ExecHost, @@ -50,7 +51,6 @@ import { type ExecProcessHandle, validateHostEnv, } from "./bash-tools.exec-runtime.js"; -import type { BashSandboxConfig } from "./bash-tools.shared.js"; import { buildSandboxEnv, clampWithDefault, @@ -242,7 +242,7 @@ export function createExecTool( name: "exec", label: "exec", description: - "Execute shell commands with background continuation. Use yieldMs/background to continue later via process tool. Use pty=true for TTY-required commands (e.g. gog, terminal UIs, coding agents).", + "Execute shell commands with background continuation. Use yieldMs/background to continue later via process tool. Use pty=true for TTY-required commands (terminal UIs, coding agents).", parameters: execSchema, execute: async (_toolCallId, args, signal, onUpdate) => { const params = args as {