fix(codex-local): raise default output-inactivity timeout to 30m (#9699)
## Thinking Path > - Paperclip is the open source control plane for managing AI-agent companies. > - Agent adapters are responsible for launching, observing, and terminating provider processes safely. > - The local Codex adapter uses an output-inactivity monitor to stop genuinely hung child processes. > - The existing seven-minute default also stopped legitimate long-running tasks that emitted no output while tests or remote checks were still running. > - Explicit per-agent timeout overrides already provide configuration flexibility, so the smallest safe correction is to increase only the default window. > - This pull request raises the default to 30 minutes, retains the existing termination behavior, and adds a regression assertion for the new value. > - The benefit is fewer unnecessary Codex restarts while still bounding genuinely silent processes well below the platform safety limit. ## Linked Issues or Issue Description **Pre-submission checklist** - Searched open and closed GitHub issues and pull requests; no duplicate fix exists. The original inactivity monitor was introduced in #5017. - Reproduces on the current `master` implementation. - The termination originates in Paperclip's Codex adapter inactivity monitor rather than the model provider or local configuration. **What happened?** Long-running `codex_local` tasks were terminated after seven minutes without stdout or stderr, even when the child process was still performing legitimate work such as a quiet test suite or waiting for remote checks. **Expected behavior** The default inactivity window should tolerate common long-running quiet tasks while continuing to terminate processes that remain silent for an extended period. **Steps to reproduce** 1. Start a `codex_local` run with the default `outputInactivityTimeoutMs` configuration. 2. Have the child process perform legitimate work without emitting stdout or stderr for more than seven minutes. 3. Observe the adapter terminate the process at the old default threshold. **Version / deployment** Current `master`, built from source in local/self-hosted deployments, using the Codex adapter. This behavior is not database- or access-context-specific. ## What Changed - Raise `DEFAULT_CODEX_OUTPUT_INACTIVITY_TIMEOUT_MS` from seven minutes to 30 minutes. - Update the adapter configuration documentation to state the new default. - Add a focused regression assertion that pins the default to 30 minutes. ## Verification - `pnpm vitest run packages/adapters/codex-local/src/server/output-inactivity-monitor.test.ts` — 15 tests passed. - `pnpm --filter @paperclipai/adapter-codex-local typecheck` — passed. ## Risks - Low risk: only the fallback default changes; explicit positive timeout values and `null` disablement retain their existing behavior. - A genuinely silent Codex process now remains alive up to 23 minutes longer before the same SIGTERM/SIGKILL cleanup path runs. - No schema, API, migration, UI, or workflow changes are included. > This is a focused bug fix and does not overlap with planned core feature work in `ROADMAP.md`. ## Model Used - Anthropic Claude Fable 5 via the `claude_local` adapter produced the initial investigation and implementation with repository/tool access. - OpenAI Codex via the Codex CLI prepared the PR, added the focused regression assertion, and ran verification; the runtime did not expose a more specific model ID or context-window value. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [ ] I have used a public-friendly branch name without internal tracker identifiers (execution-workspace exception: this branch is runtime-managed and cannot be renamed) - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge The source branch is execution-workspace managed and cannot be renamed during this run; the PR title and body intentionally contain no internal tracker references. Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
6ec059ab4e
commit
9a92124c63
|
|
@ -95,7 +95,7 @@ Core fields:
|
|||
Operational fields:
|
||||
- timeoutSec (number, optional): run timeout in seconds
|
||||
- graceSec (number, optional): SIGTERM grace period in seconds
|
||||
- outputInactivityTimeoutMs (number | null, optional): inactivity monitor around the codex child. Resets whenever the child emits stdout or stderr bytes, including non-JSON progress from long-running verification commands. Defaults to 7 * 60_000 ms when unset or non-positive. Set to \`null\` to disable the monitor entirely (only do this for known-slow tasks; the platform-level 1h silent-run safety net still applies). On fire, the adapter sends SIGTERM to the process group, waits 5s, then SIGKILL, and surfaces the run as failed with errorMessage "monitor: no codex output for {N}m {S}s".
|
||||
- outputInactivityTimeoutMs (number | null, optional): inactivity monitor around the codex child. Resets whenever the child emits stdout or stderr bytes, including non-JSON progress from long-running verification commands. Defaults to 30 * 60_000 ms when unset or non-positive. Set to \`null\` to disable the monitor entirely (only do this for known-slow tasks; the platform-level 1h silent-run safety net still applies). On fire, the adapter sends SIGTERM to the process group, waits 5s, then SIGKILL, and surfaces the run as failed with errorMessage "monitor: no codex output for {N}m {S}s".
|
||||
- agentCommand (string, optional): ACP server command override used only when engine="acp"; defaults to the package-local codex-acp binary
|
||||
- mode (string, optional): ACP session mode when engine="acp"; persistent or oneshot
|
||||
- nonInteractivePermissions (string, optional): ACP non-interactive permission fallback when engine="acp"; deny or fail
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ class FakeClock {
|
|||
}
|
||||
|
||||
describe("resolveCodexInactivityTimeout", () => {
|
||||
it("defaults to 30 minutes", () => {
|
||||
expect(DEFAULT_CODEX_OUTPUT_INACTIVITY_TIMEOUT_MS).toBe(30 * 60 * 1000);
|
||||
});
|
||||
|
||||
it("uses default when value is unset", () => {
|
||||
expect(resolveCodexInactivityTimeout(undefined)).toEqual({
|
||||
mode: "default",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { parseJson } from "@paperclipai/adapter-utils/server-utils";
|
||||
|
||||
export const DEFAULT_CODEX_OUTPUT_INACTIVITY_TIMEOUT_MS = 7 * 60 * 1000;
|
||||
export const DEFAULT_CODEX_OUTPUT_INACTIVITY_TIMEOUT_MS = 30 * 60 * 1000;
|
||||
export const CODEX_OUTPUT_INACTIVITY_MONITOR_SIGTERM_GRACE_MS = 5_000;
|
||||
|
||||
export type CodexOutputInactivityMonitorResolution =
|
||||
|
|
@ -13,9 +13,9 @@ export type CodexOutputInactivityMonitorResolution =
|
|||
* Resolve the inactivity monitor timeout from raw adapter config.
|
||||
*
|
||||
* - `null` → disabled (explicit escape hatch).
|
||||
* - missing/`undefined` → default 7m.
|
||||
* - missing/`undefined` → default 30m.
|
||||
* - number > 0 → configured value.
|
||||
* - number ≤ 0 → default 7m (and a `non_positive` note for logging).
|
||||
* - number ≤ 0 → default 30m (and a `non_positive` note for logging).
|
||||
*/
|
||||
export function resolveCodexInactivityTimeout(rawValue: unknown): CodexOutputInactivityMonitorResolution {
|
||||
if (rawValue === null) return { mode: "disabled", reason: "explicit_null" };
|
||||
|
|
|
|||
Loading…
Reference in New Issue