Repository navigation
feat(opencode): add a setting that turns prompt-time recall off - #2455
Conversation
POWERCONTEXT_OPENCODE_PROMPT_RECALL (default true) lets the OpenCode plugin leave prompt-time context to the PowerContext gateway. Behind the gateway, Core's before_send check rejects any prepared-context block the gateway did not inject, so the plugin's synthetic context part made every turn fail. With the setting false, chat.message sends no prepare request and the messages transform adds no context. Prompt capture keeps its own setting; with both off, the plugin sends no request for a prompt. Part of oceanbase#2250.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
hidb4ai
left a comment
There was a problem hiding this comment.
Reviewed at 0c9b1a6. No blocking issues found: disabling prompt recall leaves capture independently controlled, and the default behavior is preserved. No new database tables or callable public APIs; the new configuration flag and gateway Scope/Responses-route constraints are documented.
Plugin tests, type checking, bundle reproducibility, and focused Python checks passed. Independent full OpenCode/gateway acceptance remains unverified: the local OpenCode probe timed out during dependency initialization before plugin activation.
Bring in the two commits that landed since the previous merge: the website SEO and Markdown export changes (oceanbase#2454) and the OpenCode setting that turns prompt-time recall off (oceanbase#2455). The merge is textually clean. Neither commit touches `src/`, so nothing needed to follow the access-control, scheduler, or helper moves. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Which issue or RFC does this PR close?
Part of #2250 (step 5 of the plan, starting with OpenCode). Gateway design: RFC #2199. The Codex setting is #2453.
Rationale for this change
When OpenCode's model traffic goes through the gateway, the gateway prepares and injects prepared context for each turn. Core's
before_sendcheck (_require_bound_markersinsrc/powercontext/builtin/runtime/context_check.py) rejects anyBEGIN_POWERCONTEXT_PREPARED_CONTEXT_V1orBEGIN_POWERCONTEXT_PREPARED_TEXT_V1block that the gateway did not declare. On each turn the OpenCode plugin'schat.messagehook calls prepare, andexperimental.chat.messages.transformappends a synthetic text part with the prepared content to the current user message. With the plugin installed, every turn through the gateway fails:context-binding-required;gate_paused;The gateway already recognizes OpenCode's
x-opencode-session-id(gateway/README.md), so OpenCode through the gateway is an intended setup. As for Codex, only the host's configuration knows where its model requests go, so the signal is a plugin setting.What changes are included in this PR?
integrations/opencode/plugins/powercontext/src/config.ts: new fieldpromptRecall, read fromPOWERCONTEXT_OPENCODE_PROMPT_RECALL, defaulttrue, next tocapturePrompts. It accepts the same boolean spellings as the other flags.integrations/opencode/plugins/powercontext/src/index.ts(prepareTurn):promptRecallfalse, the plugin skips the/v1/context/preparecall. No content is cached for the turn, so the messages transform adds no synthetic part.capturePrompts, and it still resolves the Session Scope it needs.prepareTurnreturns before resolving the Scope, so the plugin sends no request for the prompt.context_prepareentry. With both off, it also no longer writes thecapture_content_sourcecapture_disabledentry that capture-off alone still writes.session.createdandsession.updated.pc_*tools.GUIDANCEsystem text, which contains no marker.PC_GATEWAY_DEFAULT_SCOPEis that same Scope.lib/index.js,lib/tui.jsandlib/tui.d.tsare rebuilt;make opencode-testconfirms the committed bundle is current.docs/en/docs/integrations/opencode.mdanddocs/zh/docs/integrations/opencode.md:POWERCONTEXT_OPENCODE_CAPTURE_PROMPTS=falseandPC_GATEWAY_SEDIMENT=on, and names the Scope difference below.@ai-sdk/openai(the Responses route), because streamed Chat Completions turns don't complete through the gateway (below).tests/plugin.spec.ts: with recall off, the plugin resolves the Scope and captures, sends no prepare, and the transform adds nothing; with recall and capture both off, it makes nofetchcall and adds nothing.tests/config.spec.ts: the default istrue;falseturns recall off without changing capture; an invalid value is rejected.What changes once the gateway owns prompt-time context
This comes from the gateway, not from this PR, and the docs state it:
PC_GATEWAY_DEFAULT_SCOPE, not in the Scope the plugin resolves for the Session or workspace. The first gateway follow-up in feat(integrations): keep host plugins thin and make them work behind the gateway #2250 covers this.Gateway observations from the run
These belong with the gateway follow-ups in #2250 and don't block this setting.
/gateway/v1/chat/completionsthe gateway forwardsstream: trueupstream and hands the SSE tobefore_release. Core's check accepts onlyapplication/jsoncarriers there, so the release is withheld ascarrier_unsupportedand the gateway answers 409. Withoutallow_streaming=trueon the target,before_sendwithholdsstreaming_unsupportedfirst. This happens with or without the plugin. On/gateway/v1/responsesthe gateway sends a non-streaming upstream request and replays SSE, so the runs below use the Responses route (@ai-sdk/openai).empty. So the rejected requests carry only the plugin's block, as in thePC_GATEWAY_INJECTION=offrow of feat(integrations): keep host plugins thin and make them work behind the gateway #2250.x-opencode-session-id. The gateway prepares and injects for it and, with sediment on, captures it as its owngw-turnSource: two messages produced three gateway Sources.Are there any user-facing changes?
Yes, opt-in only:
POWERCONTEXT_OPENCODE_PROMPT_RECALL, defaulttrue.false, the OpenCode plugin sends no preparation request and injects no prepared context.How was this change tested?
make opencode-test: install, 110 tests, typecheck, build, andgit diff --exit-codeonlib/: passed.make check: passed (prek hooks, ruff, ty, manifest tests).uv run pytest tests/test_opencode_cli.py tests/test_opencode_installation.py tests/test_full_capability_docs.py tests/test_docs_remote_access_contract.py "tests/test_integration_guidance_evaluation.py::test_native_adapter_handoff_uses_real_request_mapping_and_response_envelopes[opencode]" tests/e2e/test_opencode_plugin_host.py: passed. The e2e host test skipped because OpenCode is not onPATH.make unit-test: 7766 passed, 365 skipped, 13 failed. None of the failing tests touch the OpenCode plugin; feat(codex): add a setting that turns prompt-time recall off #2453 reported the same failures on macOS:tests/test_source_management.py, which read/proc/<pid>/stat, a Linux-only path;tests/test_ci_installation_roles.py, which install wheels into fresh environments.Real host: OpenCode 1.19.5 (npm
opencode-ai, macOS arm64), unmodified.lib/index.jscopied toconfig/opencode/plugins/.@opencode-ai/pluginwas resolved offline from the plugin's own lock file.upstream/master63e9665, then from this branch, with enforced auth and enforcing context protection.PC_GATEWAY_CORE_UDS), with injection at its default. Thegateway/tree is unchanged since 9c8f061.max_output_tokensfrom the model'slimit.output, so no shim was needed.opencode run --format json, thenopencode run --continue).PREPARED_CONTEXT_V1partPREPARED_TEXT_V1blockcontext-binding-required. The gateway answers 503gate_paused; OpenCode retries six times per message, and the turn fails.PROMPT_RECALL=false,CAPTURE_PROMPTS=falsePC_GATEWAY_SEDIMENT=onbefore_sendandbefore_releaseallowgw-turn-*, plus one for the first title requestPROMPT_RECALL=false, capture defaultopencode-user-prompt:*before_sendcheck of the completed runs, the gateway declared one prepared context, and the carrier held exactly that block.opencode run; the TUI was not exercised. The payloads were real OpenCode requests; the upstream was recorded, not a provider.AI usage statement
This PR was prepared with Claude Code (Claude Opus 5.5). It made the change, the tests and the docs, ran the checks, and ran the real OpenCode host behind the gateway. I reviewed the change and the results.