Conversation
Enables the OpenCode agent to handle permission_asked NDJSON events
emitted by OpenCode in --format json mode and relay permission
verification cards to messaging platforms via the cc-connect engine.
Changes:
- Pass prompt as positional argument instead of stdin, keeping stdin
open via io.Pipe for permission reply writes
- Add permission_asked event handler that emits EventPermissionRequest
with tool name and input summary
- Implement RespondPermission() to write JSON reply back to OpenCode
stdin, mapping engine behavior ("allow"/"deny") to OpenCode reply
format ("once"/"reject")
- Add stdin io.WriteCloser field to session struct
Fixes: chenhg5#1420
…nal arg The prior commit changed buildRunArgs to pass the prompt as a trailing positional argument (keeping stdin free for permission replies instead of piping). Update the test expectation to match.
…show the command The engine renders permission card content from Event.ToolInput; the reasonix adapter only set Content (approval subject), leaving the card's command field empty even though approval still executed. Mirror the opencode permission bridge which populates ToolInput.
…ction
- reasonixSession.SetLiveMode: /mode yolo|auto|force now POSTs
/auto-approve-tools {"on":true} to reasonix serve so it stops
emitting approval_request cards; default/plan disables it. Implements
core.LiveModeSwitcher so the engine's applyLiveModeChange works.
- Agent.StartSession applies the persisted mode to serve on session start.
- PlatformPromptInjector + SystemPromptSupporter: inject core.AgentSystemPrompt
(cc-connect send/cron/timer instructions) into every submitted turn,
since serve keeps its own workspace context and never reads cc-connect's
memory files. Fixes the model not knowing how to send images/files/voice.
- Tests: SetLiveMode posts auto-approve, platform prompt prepended.
…e command The engine renders tool-call cards from Event.ToolInput; the reasonix adapter only set Content on tool_dispatch, so executed commands appeared blank in yolo/auto mode (ask mode was unaffected because the permission card path already used ToolInput). Mirror the approval_request fix.
reasonix serve emits tool_dispatch args as JSON (e.g. bash
{"command":"ls -la"}); the adapter passed it through verbatim, so
Feishu/Telegram cards showed raw JSON. Add humanizeToolArgs which
extracts the actual command for bash, a description/path for other
tools, and falls back to compact key=value. Also applies defensively
to approval_request subject. Unit tests cover all formats.
1 task
Contributor
Author
AvailableModels only read enabledModels from settings.json, which is empty by default. /model in Feishu then renders an empty select with only the current model, making model switching impossible. Fall back to pi's own model catalog (~/.pi/agent/models-store.json), which pi maintains as providers are added, when enabledModels is not configured.
The pi permission-gate extension runs inside the pi CLI and has no way to learn cc-connect's permission mode. When a user switches to yolo (auto-approve) mode in Feishu, the engine restarts the session, but the new pi process is still spawned without any mode hint, so the extension keeps emitting permission cards. Inject CC_PERMISSION_MODE=<mode> into the spawned pi process environment in StartSession. The extension reads it and auto-approves all tool calls in yolo mode. Mode switches already recreate the session (pi does not implement LiveModeSwitcher), so the new process picks up the new value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related contributions to permission handling and the Reasonix agent:
opencode: bridge
permission_askedevents for verification cards — OpenCode's--format jsonmode emitspermission_askedNDJSON events, but cc-connect had no handler andRespondPermissionwas a no-op, so tool calls were silently auto-rejected with no user notification. Fixes [Bug] 使用 Opencode 无法发送验证卡片 #1420.reasonix: permission cards, live mode switching, context injection, readable tool args — fixes and enhancements for the Reasonix agent adapter so it works well with cc-connect's interactive permission cards and platform tooling.
Part 1 — opencode permission bridge (
agent/opencode/session.go)How permission bridging works
permission_askedJSON event → cc-connect converts toEventPermissionRequestRespondPermissionwrites JSON reply to stdinChanges
strings.NewReader(prompt)withio.Pipe()— prompt goes as positional arg, stdin stays open for permission repliespermission_askedhandler: Parses the permission event and emitsEventPermissionRequestwith tool name and input summaryRespondPermission: Maps engine behavior ("allow"/"deny") to OpenCode reply format ("once"/"reject"), writes JSON line to stdinPart 2 — reasonix agent fixes (
agent/reasonix/)approval_request→ permission card shows the commandThe engine renders permission cards from
Event.ToolInput, but the reasonix adapter only setContent, so the command field was blank even though approval still executed. Now bothContentandToolInputcarry the approval subject.Live mode switching (
/mode yolo|default|plan)reasonixSession implements
core.LiveModeSwitcher:/mode yolo(and aliasesauto/force) POSTs/auto-approve-tools {"on": true}to reasonix serve so it stops emittingapproval_requestevents;default/plandisables it. The configured mode is also applied when a session starts. Without this, switching to fully-automatic mode in chat had no effect and permission cards kept appearing.cc-connect capabilities prompt injection
reasonix serve is a separate process with its own workspace context; it never reads cc-connect's memory files. The adapter now implements
PlatformPromptInjector+SystemPromptSupporterand prependscore.AgentSystemPrompt()(cc-connect send / cron / timer usage) to every submitted turn, so the model knows how to send images/files/voice back through cc-connect.Human-readable tool args on cards
reasonix serve emits
tool_dispatchargs as JSON (e.g.{"command":"ls -la"}); the adapter passed it through verbatim, so Feishu/Telegram cards showed raw JSON.humanizeToolArgsnow extracts the actual command for bash, a description/path for other tools, and falls back to compactkey=value. Also applied defensively toapproval_requestsubjects.Dependencies
permission_askedevents: feat: emit permission_asked events in --format json mode for headless integrations anomalyco/opencode#39447serve_url.Testing
go test ./agent/reasonix/— all pass (new tests:SetLiveModeauto-approve, platform prompt prepended to submit,humanizeToolArgsformats, ToolInput carried on approval_request and tool_dispatch)go test ./agent/opencode/— all pass