Commit Graph

27 Commits

Author SHA1 Message Date
ollie 36d3021aae sandbox: require landrun, fail hard if unavailable
WrapCommand now returns an error instead of silently falling back to
unsandboxed execution when landrun is not in PATH. execute_code
propagates this as a hard failure.
2026-05-03 22:10:02 +02:00
Levi Neely 7884921dd0 fix TestWrapCommand flake when superpowerd is running 2026-04-22 08:59:54 +02:00
Levi Neely 694530a321 sandbox: 100% test coverage
- Test all expandPath branches (HOME, XDG_*, OLLIE_CFG/DATA_PATH)
- Test checkPath symlink resolution and ROX read/write
- Test LoadSandbox reader error
- Test WrapCommand: landrun unavailable, ROX/RWX entries, sort tiebreaker, superpowerd wrapping
- Test isSuperpowerdRunning: all socket dir paths, successful connection
- Make isAvailableFn/isSuperpowerdRunningFn overridable for testing
2026-04-21 21:49:22 +02:00
Levi Neely 46272f22a6 test: sandbox coverage + backend contract tests
- 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>
2026-04-21 13:00:06 +02:00
Levi Neely 95fdc90c18 sandbox: allow write access to OLLIE_TMP_PATH
Add {OLLIE_TMP_PATH} to DefaultConfig filesystem RW list so landrun
permits writes to the tmp directory. Also mkdir the path at session
init so the pathExists check in WrapCommand doesn't skip it.
2026-04-17 16:09:44 +02:00
Levi Neely 2703e754b8 propagate OLLIE_TMP_PATH to sandbox
Add OLLIE_TMP_PATH to DefaultConfig env list and inject it via SetEnv
in NewAgentCore and SetSessionID, matching the pattern used for OLLIE
and OLLIE_SESSION_ID.
2026-04-17 16:07:33 +02:00
Levi Neely 92034b5342 add OLLIE_CFG_PATH and OLLIE_DATA_PATH env vars
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.
2026-04-17 15:31:19 +02:00
Levi Neely e0a0dba76a rename OLLIE_9MOUNT to OLLIE; remove redundant sandbox RWX entry 2026-04-17 14:54:40 +02:00
Levi Neely d8421f2c24 rename OLLIE_9MOUNT → OLLIE; always inject OLLIE into execute env
$OLLIE is the ollie root (FUSE mount). Renaming makes it shorter and
cleaner for use in sandboxed code. SetSessionID now resolves and
injects OLLIE into the execute server env so it is always available
regardless of whether the parent process has it set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 17:39:31 +02:00
Levi Neely 4e230d6f0c fix execute_tool: detect language for #!/usr/bin/env shebangs
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>
2026-04-14 17:29:19 +02:00
Levi Neely 81dfbd4fab sandbox: use OLLIE_9MOUNT for RWX path with ~/mnt/ollie fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:28:43 +02:00
Levi Neely 64ae30a16d sandbox: move ~/.config/ollie to RWX, keep ~/mnt/ollie RWX
Physical ollie paths need RWX so tools can read/write/execute
both through the 9P mount and directly to the backing store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:15:46 +02:00
Levi Neely 2afdc12711 sandbox: add ~/mnt/ollie as RWX path
Allows tools to read/write/execute through the 9P mount.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:11:19 +02:00
Levi Neely 6cdfa2d42a sandbox: pass OLLIE_MEMORY_PATH through to tool environment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:05:26 +02:00
Levi Neely 1b98305d92 sandbox: remove OLLIE_*_PATH from built-in defaults
OLLIE_MEMORY_PATH and OLLIE_PLAN_PATH are user-configured paths that
belong in sandbox yaml overlays, not hardcoded into the built-in
defaults. Remove them from DefaultConfig() and SystemDefaults() env
lists, and remove the hardcoded XDG_DATA_HOME/ollie/memory rw path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:41:40 +02:00
Levi Neely bb66b526ba sandbox: allow OLLIE_MEMORY_PATH and default memory dir
Add OLLIE_MEMORY_PATH to the env allowlist and both the env-var path and
the XDG default (~/.local/share/ollie/memory) to the RW filesystem list,
so file_* tools can read and write memory files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:24:05 +02:00
Levi Neely 2d122c70dd gate file tools with sandbox path checks
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.
2026-04-13 18:37:17 +02:00
Levi Neely 47133b1ccd flat planning repo built-in 2026-04-13 11:41:01 +02:00
Levi Neely c7d2684cfc sandbox: copy from anvillm, break dependency
Vendor anvillm/pkg/sandbox into internal/sandbox, updating config
paths from ~/.config/anvillm to ~/.config/ollie. Remove anvillm
from go.mod.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:19:46 +02:00
Levi Neely 97b85e5163 refactor: promote backend/config to pkg/, extract TUI to ollie-tui
Move internal/backend and internal/config to pkg/ so external consumers
can import them. Remove cmd/ollie and internal/tui — they now live in
the separate ollie-tui repo which imports ollie as a library.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:05:35 +02:00
Levi Neely a3e1a078c4 refactor: move mcp/tools/execute to pkg/ for external consumability
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>
2026-04-09 21:59:01 +02:00
Levi Neely ce329bfcc7 backend: internalize model state; remove model param from ChatStream
Each backend now owns its active model via Model()/SetModel(). ChatStream
no longer takes a model string — callers use SetModel to configure it.
AgentCoreConfig.ModelName sets the backend model at construction time via
SetModel, then the field can be dropped from the live agentCore struct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:42:30 +02:00
Levi Neely f280ef17db Make pkg/agent internals private; move app-level utils to cmd/ollie
Everything not part of the agent<->frontend contract is now unexported:
- contextConfig/Builder/Stats, loopConfig, toolExecutor, confirmFn,
  run, state, toolResult — internal loop/session machinery
- buildFirstPrompt, systemPrompt, builtinTools — impl details
- agentCore struct (NewAgentCore returns Core)
- Session methods (saveTo, history, rollback, compact, etc.)
- AgentEnv internal fields (mcpExec, exec, confirm, tools, etc.)

App-level utilities moved from pkg/agent to cmd/ollie:
- resolveBackendName, defaultModelForBackend, newSessionID,
  agentConfigPath

RestoreSession now takes int (ctxOverhead) directly, eliminating
the need for contextConfig to be public.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:31:02 +02:00
Levi Neely c8d2a7a907 Merge agentcore into agent; decouple pkg/core from internal/agent
AgentCore (the Core interface impl) belongs in internal/agent alongside
the loop, session, and state it orchestrates — not in a separate one-file
package.

To break the resulting import cycle (agent → pkg/core → agent), define
Event and EventHandler natively in pkg/core instead of aliasing from
internal/agent. The agent loop now imports pkg/core for these types.
Usage token tracking is internal to the loop and no longer emitted as
an event (no consumer used it).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:13:00 +02:00
Levi Neely c31436c8bf Move hook mechanism to pkg/core
Hooks are a generic lifecycle concept — not specific to any frontend.
core.Hooks, core.HookAgentSpawn/UserPromptSubmit/Stop constants, and
Hooks.Run() now live in pkg/core and are usable by any implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:06:43 +02:00
Levi Neely dffce36dd4 Move signal handling from internal/tui to pkg/core
WatchSignals and CtrlCExitWindow are generic — any frontend can use them.
Removing them from the TUI package keeps tui focused on terminal I/O only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:03:46 +02:00
Levi Neely c5b16e739e Restructure: pkg/core interface, internal/ packages, cmd/ollie TUI entry point
- pkg/core: public Core interface (Submit/Prompt/Interrupt) + Event/EventHandler types
- internal/agentcore: AgentCore implementation of Core (session, tools, commands)
- internal/tui: TUI package (readline loop, splitInput, signals, bracketed paste)
- internal/agent,backend,config,exec,mcp,tools: moved from root to internal/
- cmd/ollie: minimal main() that wires agentcore + tui together (~130 lines)
- mkfile: update build target to ./cmd/ollie

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:00:04 +02:00