Skip to content

fix(integrations): map Pi JSON dispatch to --mode json - #5043

Open
RaycarlLei wants to merge 1 commit into
github:mainfrom
RaycarlLei:fix/pi-dispatch-mode-json
Open

RaycarlLei wants to merge 1 commit into
github:mainfrom
RaycarlLei:fix/pi-dispatch-mode-json

Conversation

@RaycarlLei

Copy link
Copy Markdown
Contributor

Description

PiIntegration does not override build_exec_args(), so it inherits MarkdownIntegration.build_exec_args() (base.py#L1139-L1158), which appends --output-format json when output_json is true.

Pi has no --output-format option. It selects JSONL events with --mode json, and --mode accepts only text, json and rpc (packages/coding-agent/src/cli/args.ts#L96-L110, documented in docs/cli.md#L43-L48). Any other long option is kept as a possible extension flag (args.ts#L249-L262). Once extensions are loaded, a flag that no extension registers becomes an Unknown option error (core/agent-session-services.ts#L99-L125), and pi exits 1 (main.ts#L916-L925) before it sends the prompt. 71023ae is the v1.3.0 tag, published as @earendil-works/pi-coding-agent@1.3.0, the current npm latest. This reproduces without a provider account. With HOME and PI_CODING_AGENT_DIR pointing at empty directories (not logged in) and PI_OFFLINE=1 PI_SKIP_VERSION_CHECK=1 PI_TELEMETRY=0:

$ pi --version
1.3.0
$ pi -p x --output-format json
Error: Unknown option: --output-format
$ echo $?
1
$ pi -p x --mode json
{"type":"session","version":3,"id":"01a15c0d-ddf6-7299-9d2f-cb8c4e2c9555","timestamp":"2026-10-21T01:22:55.094Z","cwd":"<empty dir>"}
No API key found for the selected model.

Use /login to log into a provider via OAuth or API key. See:
  <pi package>/docs/providers.md
  <pi package>/docs/models.md

The --mode json run gets past option parsing and writes its first JSONL record to stdout. It then exits 1 only because that empty agent directory has no credentials.

The same failure through Spec Kit on main (505781d), with pi 1.3.0 on PATH:

$ .venv/bin/python -c "from specify_cli.integrations.pi import PiIntegration as P; r = P().dispatch_command('speckit.plan', 'x', stream=False); print(r['exit_code'], r['stderr'].strip())"
1 Error: Unknown option: --output-format

Reachability. The built-in workflow steps do not hit this. The command step either streams, where output_json is left as None and resolves to not stream, i.e. False (base.py#L462-L463), or captures with an explicit output_json=False (step/command/__init__.py#L313-L319). The prompt step passes output_json=False (step/prompt/__init__.py#L248-L253). It is reached through the public dispatch_command(..., stream=False) when output_json is left unset (it then resolves to True), through direct build_exec_args() calls (default output_json=True), and by extensions or other callers of those APIs.

Fix. Override build_exec_args() in PiIntegration so structured output requests --mode json, the flag the OMP integration already passes (omp/__init__.py#L29-L53). The rest matches the base implementation: the requires_cli guard, -p <prompt>, SPECKIT_INTEGRATION_PI_EXTRA_ARGS before --model, and --model, which Pi accepts (args.ts#L117-L118). Unlike OMP, the prompt can stay right after -p: Pi's -p takes the next argument as the message when it does not start with - or @ (args.ts#L177-L183), and Spec Kit's dispatch prompts start with /. The change stays inside the Pi integration package, its test file, and its agent page docs/integrations/pi.md, which named --output-format json.

Part of #2416, which lists Pi's inherited pi -p "prompt" --model X --output-format json argv as unverified. Same shape as the Kimi Code fix in #5031.

Testing

  • Tested locally with uv run specify --help

  • Ran existing tests with uv sync && uv run pytest: run as .venv/bin/python -m pytest, results below

  • Tested with a sample project (if applicable): see the first bullet below

  • Sample project: specify init proj --integration pi --script sh --non-interactive, then dispatch_command('speckit.plan', 'x', stream=False) against pi 1.3.0. No provider account was used: PI_CODING_AGENT_DIR points at a models.json for a local OpenAI-compatible stub model, and its settings.json sets defaultProjectTrust: "always" so Pi loads the project's .pi/prompts. On main it exits 1 with the error above. On this branch it exits 0 and stdout holds 15 JSONL events, from session to agent_settled; the user message in them is the rendered speckit.plan template with x as its arguments. Without that trust setting (Pi's default is ask), a non-interactive run skips the project's prompt templates and the model receives the literal /speckit.plan x; that is independent of this argv fix and not changed here.

  • tests/integrations/test_integration_pi.py gets four argv tests: text mode, --mode json, --model, and SPECKIT_INTEGRATION_PI_EXTRA_ARGS. Run against main, the --mode json and extra-args cases fail with '--output-format' != '--mode'. All four pass on this branch.

  • .venv/bin/python -m pytest tests/integrations tests/workflows tests/test_agent_config_consistency.py -q: 3620 passed, 8 skipped.

  • uvx ruff@0.15.0 check src tests: all checks passed.

  • Full suite, .venv/bin/python -m pytest tests -q (macOS, Python 3.14.3): 12517 passed, 376 skipped, 15 failed. All 15 are in 6 files this PR does not touch, and running those files on unmodified main on the same machine fails the same 15 test IDs. 11 are composed-template cases in test_*_python_parity.py, whose bash variant runs python3 from PATH, and that interpreter has no PyYAML on this machine; they pass with the venv's python3 first on PATH. The other 4 are in test_workflow_step_submission.py, where the fake curl gets a #!<sys.executable> shebang and the interpreter path on this machine contains a space.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Claude Code opened this PR on behalf of @RaycarlLei. Claude Code (model: Claude Opus 5.5, reasoning effort xhigh, autonomous agent mode with tool approvals bypassed) reproduced the bug against pi 1.3.0, read the Pi source for the accepted --mode values and its unknown-option handling, wrote the override, the four tests and the docs/integrations/pi.md update, ran the checks above, wrote this description, and pushed the branch. A read-only Claude Code subagent on the same model cross-checked the description's claims and the diff, and its corrections were applied before posting. @RaycarlLei reviewed the diff and a draft of this description and approved posting, but did not re-run the tests or edit the text. The commit carries Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous).

🤖 Generated with Claude Code

PiIntegration inherited MarkdownIntegration.build_exec_args(), which
appends --output-format json when output_json is true. Pi has no
--output-format option: its parser keeps unknown long flags for
extensions, and when no extension registers the flag, pi reports
"Unknown option: --output-format" and exits 1 before the prompt is
sent. This is reachable through dispatch_command(stream=False) when
output_json is left unset (it then resolves to True), and through
direct build_exec_args() calls.

Override build_exec_args() to request --mode json, the flag Pi uses for
JSONL events and the one the OMP integration already passes. The base
requires_cli guard and argument order (EXTRA_ARGS before --model) are
unchanged. docs/integrations/pi.md named the old flag and now names
--mode json.

Assisted-by: Claude Code (model: Claude Opus 5.5, autonomous)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RaycarlLei
RaycarlLei requested a review from mnriem as a code owner October 21, 2026 01:56
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Oct 21, 2026

This branch has not been deployed

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

Labels

triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants