[Bug]: ctx_execute cannot be cancelled with Esc mid-run; no intermediate progress visible

Author: kiwihoulingCreated Sep 18, 2026Updated Sep 18, 2026
Labelsbug

Platform

Pi

context-mode version

1.0.169

Debug script output (REQUIRED)

json
Note: the pi installation path (`pi install npm:context-mode`, installs under `~/.pi/agent/npm/node_modules/context-mode/`) does not ship `scripts/ctx-debug.sh` — the `scripts/` directory only contains `postinstall.mjs` and `heal-*.mjs`. So I could not run the debug script from the installed package. Substituting the output of the built-in `ctx_doctor` tool:

context-mode doctor

[OK] Runtimes: 3/11 (27%) — javascript, shell, python
[WARN] Performance: NORMAL — install Bun for 3-5x speed boost
[OK] Storage sessions: C:\Users\...\pi\context-mode\sessions (default)
[OK] Storage content: C:\Users\...\pi\context-mode\content (default)
[OK] Storage stats: C:\Users\...\pi\context-mode\sessions (default)
[OK] Server test: PASS
[OK] FTS5 / SQLite: PASS — native module works
[OK] Hook support: Pi hooks are wired via the context-mode Pi extension (~/.pi/extensions/context-mode/), not via JSON-stdio.
[OK] Hook scripts: no direct .mjs script paths to verify
[OK] Version: v1.0.169

Exact prompt that triggered the bug (REQUIRED)

Run this with ctx_execute and do not pass a timeout parameter:

python -c "import time; time.sleep(120)"

While it runs, press Esc.

Full error output (REQUIRED)

There is no error output — which is part of the problem. Pressing Esc produces no error, no message, and no visible change in the transcript; the turn simply keeps waiting for the tool result. The only output the tool call ever produces is the timeout notice when the call finally gives up, e.g. (from a reproduction with an explicit `timeout: 3000`):


start

_(timed out after 3000ms — partial output shown above)_

Steps to reproduce (REQUIRED)

  1. Install: pi install npm:context-mode (pi 0.85.1, Windows 11; pi runs in Windows Terminal, its shell tool is Git Bash)
  2. Send the prompt above, or anything that makes the model call ctx_execute with a long-running command and no timeout parameter
  3. While the tool call is in flight, press Esc (pi's interrupt key, app.interrupt, bound to escape by default)
  4. Observe: nothing is cancelled. The turn keeps waiting for the tool result until the request times out (~60 s)
  5. Repeat with an explicit timeout: the call ends at the specified time and returns partial output — but Esc still cannot cancel it earlier
  6. Also observe: no stdout from the sandboxed process is visible while it runs; output only arrives after completion or timeout

Affects all tools registered through the pi bridge (ctx_execute, ctx_execute_file, ctx_batch_execute, …).

What have you tried to fix it?

Facts found while debugging (not proposing a design — the maintainer knows best which layer should own this):

  • pi's extension tool API calls every tool as execute(toolCallId, params, signal, onUpdate, ctx): signal is an AbortSignal that aborts when the user presses Esc, and onUpdate exists for partial-result/progress reporting. pi invokes tools through executePreparedToolCall(prepared, signal, emit), so both are provided at the call site.

  • In build/adapters/pi/mcp-bridge.js, tools are re-registered into pi as:

    javascript
    async execute(_toolCallId, params) {
        const result = await client.callTool(tool.name, params ?? {});
        ...
    }

    signal and onUpdate are not declared in the signature, and client.callTool(name, args) does not forward any abort or progress mechanism to the server process.

  • The bridge's JSON-RPC request() defaults to DEFAULT_REQUEST_TIMEOUT_MS = 60_000, with a comment: "Responsibility for bounding a tool call belongs to the executor layer (per-tool timeout / background mode / Pi-level cancel), not to the transport." That is where the fixed ~60 s wait comes from when no timeout is passed.

  • Server-side, the ctx_execute timeout parameter description says: "When omitted, no server-side timer fires — the MCP host's RPC timeout governs." In the pi bridge case that governing timeout is the bridge's 60 s default, and there is no path for pi's user-level cancel to reach it.

  • Daily-use workaround: always pass an explicit timeout, and for long tasks run with background: true and redirect output to a file that I poll separately. Both work, but Esc never cancels anything and no progress appears in pi itself.

Pre-submission checklist

  • I have run the debug script and pasted the output above
  • I am using the latest version of context-mode
  • I have searched existing issues for duplicates
  • I have included steps to reproduce the issue

Operating System

Windows (PowerShell)

JS Runtime

node v25.8.0