- 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.
- sandbox: remove dead code (DefaultConfig, Load/Save, LayeredConfig, Merge,
Version, SystemDefaults, validateName, ConfigPath, OpenSandbox); unexport
internal symbols; LoadSandbox now takes io.Reader; loadSandboxConfig owns
file opening; 83% package coverage via new sandbox_test.go
- backend: add BaseURL field to AnthropicBackend for testability; new
backend_test.go runs checkContract against all five implementations
(Ollama, OpenAI, Copilot, Anthropic, CodeWhisperer) via httptest servers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows wrapper scripts in ~/.config/ollie/scripts/x/ to shadow system
binaries transparently without modifying the user's shell environment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the elevation package and Elevator interface entirely. The
execute server now invokes x/elevate directly, with detection reduced
to a stat check. Decl() loses the elevator parameter.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove session-scoped env injection from frontend (s/{id}/env, -e/-env flags) — superseded
by per-invocation superpowers run-session in the elevator. Keep agentCore env map and
OLLIE_SESSION_ID propagation via pushSessionEnv.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New pkg/env package owns EnsureDefaults, Set, Get, All, Format
- BuildAgentEnv reverted to 3-arg signature (no initialEnv)
- agentCore.setEnv removed; pushSessionEnv handles OLLIE_SESSION_ID only
- execute.Server.SetEnv no longer calls os.Setenv (session-scoped only)
- !cmd handler sets OLLIE_SESSION_ID explicitly in subprocess env
- mcp/transport: seed cmd.Env from os.Environ() so MCP servers inherit PATH etc.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all hard-coded ~/.config/ollie and ~/.local/share/ollie paths
with a new paths package that reads OLLIE_CFG_PATH and OLLIE_DATA_PATH,
falling back to the previous defaults when unset.
- execute_code now takes steps:[{code,language}|{tool,args}] instead of
a single code/language pair. Single-step calls return raw output;
multi-step calls run in parallel and return results under === step N ===
headers in submission order.
- execute_pipe stages may now include {parallel:[...]} to fan out
concurrently within a pipeline. Parallel outputs are concatenated in
submission order and fed as stdin to the next stage.
- Stage execution is now Go-level (stdin chaining) rather than a single
bash pipeline string, enabling parallel stages and tool/code mixing.
- CodeStep and resolveCodeStep are the shared primitives for both
execute_code and execute_pipe parallel stages.
- executeWithStdin added to Server for stdin chaining between stages.
- Tool steps use shebang detection; language field applies only to
inline code steps (default: bash).
- ListTools schemas and descriptions updated throughout.
ToolsPath() fell back to ~/.config/ollie/tools when OLLIE_TOOLS_PATH
was unset, ignoring the 9P mount entirely. Add /home/lkn/mnt/ollie/t as the
preferred fallback so execute_tool finds tools on the mounted
filesystem regardless of cwd.
- extractMCPResult: parse isError from MCP response so tool failures
are returned as Go errors and marked isErr=true in the loop
- CallTool: emit isError:true content block instead of bare {"error":...}
so the model sees tool failures as error results, not success
- SetEnv: call os.Setenv so OLLIE_SESSION_ID/OLLIE are in the process
env and inherited by sandboxed subprocesses
- NewAgentCore: inject session env into execute server at creation time,
not only on rename, so tools have OLLIE_SESSION_ID from the first call
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
detectLanguage only checked filepath.Base(fields[0]), which returns
"env" for #!/usr/bin/env python3. Every such script was run as bash,
producing syntax errors. Now checks fields[1] when fields[0] is "env".
Also add OLLIE_MEMORY_PATH to default env passthrough.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove pkg/tools/file and pkg/tools/reasoning. Both are now implemented
as execute_tool scripts in ollie/t/ with feature parity:
- file_read, file_write, file_edit, file_grep, file_glob
- reasoning_think
isread guard delegated to /tmp/ollie/$OLLIE_SESSION_ID/<hash> markers.
SetSessionID renames the tmpdir on session rename.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace {{.Tools}} injection with ollie/t/idx (generated at session
start by rebuildToolsIdx); prompt now instructs grep-based discovery
- Replace {{.Skills}} injection with ollie/sk/idx (rebuildSkillsIdx);
same grep pattern
- Add {{.SessionID}} to system prompt identity line
- Expand filesystem section: full ollie/s/ layout, all session files,
ctl commands, s/idx cooperation pattern
- Fix execute_tool description: use ollie/t instead of physical ToolsPath()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
awk/sed/jq: exec.Command directly with program as arg — no shell, no escaping.
ed/expect/bc: exec.Command with cmd.Stdin — program piped without escaping.
execute_tool with file args: language switches to "bash" after injectArgs
since the resulting snippet is already a bash command.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jq: filter as positional arg, file args appended, pipeline-safe.
expect: pipes script via printf '%s' $'...' | expect -.
bc: pipes via printf '%s' $'...' | bc -ql (quiet + math library).
All three use ANSI-C quoting consistently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sed: sed -e $'...' inline, file args appended, pipeline-safe.
ed: pipes script via printf '%s' $'...' | ed -s [file].
detectLanguage now parses shebang command basename rather than
using strings.Contains, fixing potential false matches.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses gawk -e $'...' (ANSI-C quoting) consistently across Execute() and
pipelines. injectArgs for awk produces a bash snippet with file args
after --. No BEGIN block hacks needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delegate memory and task to MCP servers (denote-mcp, 9beads-mcp or
equivalents). When no MCP server provides these tools, the model
degrades gracefully — files in ollie/m and ollie/pl remain accessible
via file_* and execute_code. reasoning_think and file_* stay built-in.
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>
file_read, file_write, file_edit, file_grep, and file_glob now check
paths against the sandbox config before operating. Same policy that
landrun enforces on execute_code, applied at the application level.
- Add sandbox.LoadMerged: loads base config + named layer, graceful
fallback if layer missing. Replaces duplicated logic in execute.
- Add sandbox.CheckPath: resolves symlinks, expands templates, checks
path against allowed entries (RO/ROX for read, RW/RWX for write).
- file.Server.checkAccess wires the check into every file dispatch.
Strip flatfs-specific lifecycle instructions (filenames, sed, mv)
from the reasoning_plan tool description. The abstract tool now
describes only generic state transitions; concrete backends supply
their own instructions via CreatePlan response messages.
- OLLIE_TOOLS_PATH now takes first entry if colon-separated
- Default changed from ~/.local/share/ollie/tools to ~/.config/ollie/tools
- Update README accordingly
loadEnvFile now strips " # ..." suffixes from values so inline comments
in ~/.config/ollie/env don't leak into environment variables. Also add
kiro to the supported-backends error message and fix two raw-string
backtick escaping errors in tool descriptions.
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>
- Detect language from shebang (bash default, python3 if shebang contains "python")
- Inject args language-appropriately: set -- for bash, sys.argv for Python
- Add python3 to executor language switch
- Handle Python steps in execute_pipe using bash $'...' embedding
- Update execute_tool description to mention supported languages
- Add Tools section to SYSTEM_PROMPT.md pointing to $OLLIE_9MOUNT/t/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The line-range patching interface was fragile (models drift on line
numbers), and both tools were redundant with execute_code + standard
shell utilities (cat, grep, sed, ed, ssam). Drop the file server
entirely; update agent configs, system prompt, and documentation.
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 is now a function (func(workdir string) func() tools.Server)
rather than a var, making workdir an explicit dependency rather than
an implicit os.Getwd() call. execute.Server stores the workdir and
sets cmd.Dir accordingly; falls back to os.Getwd() if empty.
AgentCoreConfig gains WorkDir string, threaded into BuildAgentEnv and
the system prompt. The /agent switch uses s.workdir so the correct
directory is preserved across agent switches.
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>