Tools annotated with "# ollie:parallel read" now run concurrently when
the LLM issues multiple such calls in a single round, without needing
an execute_code pipeline.
- tools.ParallelClassifier interface; execute.Server implements it via
IsParallelRead, which reads the tool script and checks the annotation
- BuildAgentEnv wires IsParallelRead → AgentEnv.classifyTool →
agentConfig.ClassifyTool (nil when execute server absent)
- loop.go: consecutive parallel-safe calls are fanned out with a
WaitGroup; results are collected in submission order; cancellation
fills remaining calls with interrupted results; serial tools and
batches of one skip the goroutine overhead
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add contract tests for tools.Server and tools.Dispatcher interfaces
(tools_test.go), covering all exported behavior including error paths.
pkg/tools coverage: 0% -> 100%.
- Add contract test for execute.Server (ListTools, CallTool), Decl
factory test, and executeElevated early-exit test. execute coverage:
68% -> 71%.
- Remove Close() from Server and Dispatcher interfaces and all
implementations/callers. These existed for MCP server cleanup which
has been removed.
- Add TrustedToolsSetter interface and SetTrustedTools to execute.Server
- Add allowed(): trusted tools return true; untrusted with no Confirm
return false (deny by default). Confirm returns true=allow, consistent
with allowed() semantics throughout.
- BuildAgentEnv wires cfg.TrustedTools into the execute server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- pkg/tools/memory: memory_remember + memory_recall with FlatDirBackend
baked in (no more injectable MemoryBackend abstraction)
- pkg/tools/task: task_plan + task_complete with file-based plan
persistence baked in (no more injectable PlanBackend abstraction)
- pkg/tools/reasoning: stripped to reasoning_think only
- pkg/tools/tools: remove PlanStep/PlanBackend/MemoryBackend interfaces
- pkg/agent: remove dispatchMemoryBackend, dispatchPlanBackend,
WithFallbackPlanBackend; BuildAgentEnv takes no options
Fixes infinite recursion crash: previously dispatchMemoryBackend routed
memory_recall back to the reasoning server that owned it, causing
unbounded mutual recursion and a goroutine stack overflow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces memory_remember and memory_recall built-in tools on the
reasoning server. A MemoryBackend interface allows swapping backends:
dispatchMemoryBackend routes through a registered MCP server (e.g.
denote-mcp) when available; FlatDirBackend writes dated markdown files
to ~/.local/share/ollie/memory/ as a zero-config fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PlanBackend.CreatePlan now returns an optional message alongside IDs.
When non-empty, the reasoning server uses it as the tool response
instead of the default plan summary — allowing queue backends to
instruct the agent to stop after planning rather than execute directly.
- tools.PlanBackend: CreatePlan returns ([]string, string, error)
- dispatchPlanBackend: returns "" (agent continues as before)
- reasoning/server: uses backend message when non-empty
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add WorkDirSetter interface to pkg/tools so servers can receive workdir updates
- Add SetWorkDir on execute.Server with RWMutex-guarded workdir field
- Add WorkDir()/SetWorkDir() to the Core interface and agentCore
- Store agentPrompt in AgentEnv/agentCore so system prompt can be rebuilt on workdir change
- Add /cwd [path] slash command (no args shows current dir, arg changes it)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add reasoning_plan built-in tool: decomposes goals into ordered steps
with dependency edges; persists to task backend when available, falls
back to in-context plan otherwise.
- Add PlanBackend/PlanBackendSetter interfaces and PlanStep type to
pkg/tools; add GetServer to Dispatcher.
- Add dispatchPlanBackend in pkg/agent: routes task_create calls through
the dispatcher to any registered task MCP server.
- BuildAgentEnv auto-wires the task backend to the reasoning server after
connecting MCP servers; re-wires on every /agent switch.
- Add ListServers() to Core interface: groups all registered tools by
server, returns formatted text.
- Add /mcp command to handleCommand(); update /help.
- Add doc/PLANNING.md and update ARCHITECTURE.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- execute.Decl and file.Decl: package-level func() tools.Server factories;
consumers reference them without calling directly
- tools.NewDispatcherFunc: builds a fresh Dispatcher per call by invoking
each registered Decl — used as AgentCoreConfig.NewDispatcher
- execute.Server: remove LogDir, WorkspaceBase, MaxOutputChars, and all
file-based logging (metrics.go deleted); New() takes no args
- Export AgentConfigPath, NewSessionID, DefaultAgentsDir, DefaultSessionsDir
from pkg/agent so frontends don't duplicate them
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add tools.Server interface; MCPExecutor now holds map[string]Server
- execute.Executor implements tools.Server (ListTools/CallTool/Close)
- Built-in tools register as "builtin" server in MCPExecutor
- Remove duplicate dispatch functions from core.go (moved to dispatch.go)
- Remove builtinTools() from core.go (now in dispatch.go)
- Remove invalidateCaches and trustedTools dead code
- All tool calls now route through one mcpExec.Execute() path
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
internal/mcp → pkg/mcp (MCP client, concrete)
internal/tools → pkg/tools (Executor interface + MCPExecutor)
internal/exec → pkg/tools/execute (builtin sandbox executor, split by tool)
Split exec.go into executor.go (sandbox runner), pipe.go (BuildPipeline/PipeStep),
tool.go (ReadTool), and code.go (execute_code is Executor.Execute with trusted=false).
All three packages are now importable by consumers outside this module.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>