Skip to content

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

Description

@kiwihouling

Platform

Pi

context-mode version

1.0.169

Debug script output (REQUIRED)

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:

    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

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions