You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Security
/ws filesystem sidecar is now sandboxed to work_dir — previously any connected WebSocket client could read/write/delete arbitrary directories by choosing its own root in watch, bypassing the agent's sandbox. All fs operations now validate against work_dir using the same path validator (with symlink canonicalization) as the built-in file tools.
Subagents (delegate_task) no longer bypass session/request_permission. Subagents previously ran with a hardcoded always-allow gate — an unconditional permission bypass in interactive ACP sessions. They now inherit the parent turn's real permission gate and cancellation token.
"Allow Always" on a shell command no longer approves every future shell command. Remembered decisions were keyed by tool name only, so approving git status once silently pre-approved any later execute_command, including destructive ones. Shell approvals are now scoped by the command's program name.
Changed (WS protocol)
watch no longer sets the fs validation root — it only enables fs_event notifications; the watched directory must be within work_dir.
fs operations no longer require a prior watch — they work immediately, validated against work_dir.
fs error messages now return the validator's descriptive message instead of a generic one.
Added
Tool-call permission requests via session/request_permission, with remembered Allow/Reject Always decisions.
TUI permission prompts — the terminal UI now asks before running any tool call (execute_command included) instead of auto-allowing.
SessionHandle::permission_gate / .client_io — embedders can supply a custom permission gate and client-side file I/O per session.
SessionHandle::cancel() — cancel an in-flight turn from the library facade.
OpenheimBuilder::tool(...) — register custom in-process tools when embedding openheim as a library.
session/cancel actually cancels a running turn — prompt turns now run in a spawned task with cancellation checked between iterations and before tool calls.
Client-side filesystem delegation — read_file/write_file delegate to the ACP client's fs/* methods when advertised.
GET /acp WebSocket endpoint — bare ACP JSON-RPC endpoint alongside /ws.
Image content in prompts — vision support for Anthropic, OpenAI, and Gemini; ResourceLink blocks become text hints; Audio/embedded Resource now error clearly instead of being dropped.
New public APIs: StreamEvent::MessageAppended, HistoryManager::append_message, AppConfig::resolve_provider_default.
Fixed
openheim run could hang or falsely deny every tool call due to a response-routing bug in the ACP dispatch handler.
Anthropic extended thinking was effectively broken end-to-end (wrong beta-header gating + budget_tokens 400s on current-gen models) — switched to adaptive thinking.
Thinking blocks were never replayed back to Anthropic, breaking the required tool-call round trip.
session/cancel no longer waits out an in-flight LLM request.
Exhausting max_iterations was misreported to ACP clients as a normal EndTurn.
Overlapping session/prompt calls on the same session could race and corrupt history/cancellation state.
Non-streaming Anthropic calls (subagents) never got extended thinking.
GET /api/sessions/{id} could 404 for the wrong reason.
TUI discarded the real startup error, flattening typed errors into opaque strings.
openheim init shipped stale default models, drifted from the programmatic defaults.
session/load restored sessions with an unvalidated, hand-assembled provider config.
GET /api/sessions endpoints did blocking file I/O on the async runtime.
History durability — a crash mid-turn no longer loses the whole turn; a crash mid-save can no longer corrupt previously-saved conversations (append-only .jsonl log + atomic writes).
Breaking changes (library)
SandboxedExecutor::new takes an additional client_io: Arc<dyn ClientIo> argument.
run_agent_with_history / run_agent_streaming_with_history take a &TurnContext.
TurnContext moved from core::agent to core::turn.
tools::ToolExecutor::execute gained a turn: &TurnContext<'_> parameter; DelegateTool no longer implements ToolHandler.
acp::AgentState::new takes an additional custom_tools argument.
StreamEvent::ToolCall/ToolResult gained an id field.
core::models::Message redesigned around content blocks (Vec<ContentBlock> replaces the flat fields); ChatRequest/ChatResponse/ToolCall/FunctionCall removed from core::models.