Skip to content

Add AgentWatch tool handling for Codex long-running jobs#1088

Open
AliAlharmoodi wants to merge 2 commits intopingdotgg:mainfrom
AliAlharmoodi:Code/agentwatch-core
Open

Add AgentWatch tool handling for Codex long-running jobs#1088
AliAlharmoodi wants to merge 2 commits intopingdotgg:mainfrom
AliAlharmoodi:Code/agentwatch-core

Conversation

@AliAlharmoodi
Copy link

@AliAlharmoodi AliAlharmoodi commented Mar 14, 2026

Summary

  • add a small server-side AgentWatch runtime for monitored long-running shell jobs
  • route Codex item/tool/call requests for agentwatch.start|status|poll|tail through CodexAppServerManager
  • add focused regression tests for the AgentWatch runtime and tool-call routing

Why

This is a small reliability-oriented slice that lets Codex hand off long-running commands to a monitored background job instead of keeping everything tied to a single turn.

Scope

This PR intentionally avoids the later UI and orchestration follow-up work. It only adds the core runtime and Codex server plumbing.

Validation

  • bun fmt
  • bun lint
  • bun typecheck

Note

Add AgentWatch tool handling for Codex long-running jobs

  • Introduces AgentWatch, a job supervisor that starts detached shell commands via bash -lc, tracks liveness and output staleness, and captures exit codes by appending a sentinel marker to the job's log file.
  • Exposes agentwatch.start, agentwatch.status, agentwatch.poll, and agentwatch.tail tools via a handleToolCall interface.
  • Integrates AgentWatch into CodexAppServerManager, routing item/tool/call JSON-RPC requests to agentWatch.handleToolCall and disposing the instance on stopAll().
  • Behavioral Change: handleServerRequest now handles a new item/tool/call method, returning -32602 for missing tool name and -32000 for tool invocation failures.
📊 Macroscope summarized 664fb01. 4 files reviewed, 4 issues evaluated, 0 issues filtered, 2 comments posted

🗂️ Filtered Issues

@coderabbitai
Copy link

coderabbitai bot commented Mar 14, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6cdb4791-bc75-4dc9-ade6-f824196ba71c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.

Change the reviews.profile setting to assertive to make CodeRabbit's nitpick more issues in your PRs.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 14, 2026
});
}

if (request.method === "item/tool/call") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical src/codexAppServerManager.ts:1222

item/tool/call requests with non-agentwatch. tool names are routed to this.agentWatch.handleToolCall(), which throws Unsupported tool: ${toolName} and returns a JSON-RPC error to the client. This breaks all non-agentwatch tool calls instead of letting them fall through to the existing handling logic. Consider checking toolName.startsWith("agentwatch.") before routing to the agentWatch handler.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/server/src/codexAppServerManager.ts around line 1222:

`item/tool/call` requests with non-`agentwatch.` tool names are routed to `this.agentWatch.handleToolCall()`, which throws `Unsupported tool: ${toolName}` and returns a JSON-RPC error to the client. This breaks all non-agentwatch tool calls instead of letting them fall through to the existing handling logic. Consider checking `toolName.startsWith("agentwatch.")` before routing to the agentWatch handler.

Evidence trail:
apps/server/src/codexAppServerManager.ts lines 1222-1256 at REVIEWED_COMMIT: Shows `item/tool/call` handler routing ALL tool calls to `this.agentWatch.handleToolCall(toolName, rawArgs)` without checking if toolName starts with "agentwatch."

apps/server/src/agentWatch.ts lines 283-321 at REVIEWED_COMMIT: Shows `handleToolCall` only handles `agentwatch.start`, `agentwatch.status`, `agentwatch.poll`, `agentwatch.tail` - all other tool names cause `throw new Error(\`Unsupported tool: ${toolName}\`);`

Comment on lines +56 to +63
function isProcessAlive(pid: number): boolean {
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High src/agentWatch.ts:56

When job.pid is -1 (set on line 149 when child.pid is undefined after spawn), calling process.kill(-1, 0) does not check if a specific process is alive. On POSIX systems, kill(-1, sig) broadcasts the signal to all processes the caller can signal, so isProcessAlive(-1) returns true even though no actual job process exists. The function should return false when pid <= 0.

+function isProcessAlive(pid: number): boolean {
+  if (pid <= 0) {
+    return false;
+  }
+  try {
+    process.kill(pid, 0);
+    return true;
+  } catch {
+    return false;
+  }
+}
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/server/src/agentWatch.ts around lines 56-63:

When `job.pid` is `-1` (set on line 149 when `child.pid` is undefined after spawn), calling `process.kill(-1, 0)` does not check if a specific process is alive. On POSIX systems, `kill(-1, sig)` broadcasts the signal to all processes the caller can signal, so `isProcessAlive(-1)` returns `true` even though no actual job process exists. The function should return `false` when `pid <= 0`.

Evidence trail:
1. `apps/server/src/agentWatch.ts` lines 56-62: `isProcessAlive` function uses `process.kill(pid, 0)`
2. `apps/server/src/agentWatch.ts` line 149: `pid: child.pid ?? -1` sets pid to -1 if child.pid is undefined
3. `apps/server/src/agentWatch.ts` line 221: `if (!isProcessAlive(job.pid))` uses the function to detect finished jobs
4. Node.js documentation (https://nodejs.org/docs/latest-v22.x/api/process.html): `process.kill()` follows OS semantics, so `kill(-1, sig)` on POSIX sends to all processes caller can signal
5. POSIX `kill(2)` specification: pid=-1 means 'all processes for which the calling process has permission to send signals'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant