Commit Graph

646 Commits

Author SHA1 Message Date
Levi Neely 5582f3c8de add shared logger package; replace ad-hoc debug logging
New ollie/pkg/log with per-component log levels:
  OLLIE_LOG=debug        (global default, fallback: warn)
  OLLIE_CORE_LOG=debug   (component override)
  OLLIE_9P_LOG=info      (component override)

info/debug → stdout, warn/error → stderr.
2026-04-15 10:24:25 +02:00
Levi Neely 313a5d85fe add debug logging to all core agent methods
Gated behind OLLIE_CORE_DEBUG=1. Logs tagged with "core:" prefix
to distinguish from 9p server logs.
2026-04-15 10:13:32 +02:00
Levi Neely 655b9e7060 fix: surface tool script errors to model; inject session env at startup
- 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>
2026-04-14 22:49:00 +02:00
Levi Neely 64d3915593 docs: note olliesrv calls Close() on kill and shutdown
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:52:43 +02:00
Levi Neely 82ceaebbe6 agent: add OllieMountPath to system prompt template data
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:41:27 +02:00
Levi Neely 74a6715cd7 docs: session lifecycle, Close(), tmpdir
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:40:11 +02:00
Levi Neely ee82ac7181 agent: run ! shell commands in session cwd
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:35:13 +02:00
Levi Neely 8b3b6bd281 agent: add Core.Close() to manage session tmpdir lifecycle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:29:50 +02:00
Levi Neely c03f9386c1 agent: create /tmp/ollie/{session-id} on session start
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:27:35 +02:00
Levi Neely 72f7a95329 agent: add /sp command to display rendered system prompt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:18:43 +02:00
Levi Neely fd2a534943 agent: add SystemPrompt() to Core interface
Returns the fully rendered system prompt for the session, so
the 9P server can expose it via s/{id}/systemprompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:16:58 +02:00
Levi Neely fe00c607a1 agent: load system prompt from ordered p/ parts, not a single file
systemPrompt() now reads all *.md files from DefaultPromptsDir() in
lexical order (00_base.md, 01_foo.md, ...), applies template rendering
to each, and concatenates them with --- separators.

Removes hardcoded eager-loading of skills (reasoning, memory, task,
edit-text) and the skills package dependency. Those now live as numbered
prompt parts alongside the base prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 19:15:17 +02:00
Levi Neely 0762a37d1c eager-load edit-text skill; document eager-loading rationale
Skills are loaded into the system prompt from the first turn as an
alternative to encoding guidance in MCP schemas.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 17:58:13 +02:00
Levi Neely 13590a84e7 implement TrustedTools: explicit trust replaces implicit allow-all
- 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>
2026-04-14 17:52:37 +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 da6e8d46c4 eager-load task skill into system prompt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 17:30:55 +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 37bb6aa6c2 agent: read eager-loaded skills from physical path, not 9P mount
Reading from the 9P mount during session creation deadlocked the
server. Use skills.Read() to access the physical files directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 15:55:06 +02:00
Levi Neely aff2bbc65f agent: embed reasoning and memory skills into system prompt at render time
Read ollie/sk/reasoning.md and ollie/sk/memory.md from the 9P mount
and append them to the rendered system prompt. Removes dependency on
the model following a startup instruction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 15:52:19 +02:00
Levi Neely abe8ab76cc tools: replace file and reasoning built-ins with shell scripts
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>
2026-04-14 15:26:12 +02:00
Levi Neely 9ba68ff35e agent: remove rebuildToolsIdx and rebuildSkillsIdx
Both idx files are now served as live synthetic files by the 9P server.
No physical files are written to disk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 14:47:30 +02:00
Levi Neely 87f056e221 prompt: idx-based tool/skill discovery; session self-awareness
- 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>
2026-04-14 14:27:39 +02:00
Levi Neely 5d86326edf execute: language-specific dangerous patterns; skip domain-specific tools
universalPatterns: mkfs, dd if=/dev/, sudo/su, /etc/shadow|sudoers
bashPatterns: rm -rf flag syntax, fork bomb, redirects, eval "...$"
pythonPatterns: shutil.rmtree, os.system/subprocess with rm -rf, os.remove on sys paths
perlPatterns: system/exec/backtick with rm -rf, unlink glob on sys paths
luaPatterns: os.execute/io.popen with rm -rf, os.remove on sys paths
Domain-specific tools (awk, sed, jq, ed, bc, expect) skip validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:36:18 +02:00
Levi Neely 109622ded1 execute: remove bash wrappers; use direct invocation and stdin piping
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>
2026-04-14 13:32:25 +02:00
Levi Neely cdbf3096be execute: add lua support via lua -e; arg table injection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:28:16 +02:00
Levi Neely b65fc0fdf7 execute: add jq, expect, bc support
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>
2026-04-14 13:25:43 +02:00
Levi Neely 9ec58b0ae8 execute: add sed and ed support; refactor detectLanguage to use shebang basename
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>
2026-04-14 13:18:08 +02:00
Levi Neely 2ecdcc26c8 execute: add awk support via gawk -e; file args passed after --
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>
2026-04-14 13:15:27 +02:00
Levi Neely 3f0a77619b execute: add perl support (shebang detection, @ARGV injection, pipe support)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:07:03 +02:00
Levi Neely e5e94e57fe agent: inject shell tool descriptions into system prompt at build time
toolsSummary() scans OLLIE_TOOLS_PATH for # description: and # Args:
headers and injects the result as {{.Tools}} in the system prompt —
same effect as MCP schema injection but for shell/python tools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 13:00:03 +02:00
Levi Neely a81826b909 readme: move env config docs to top-level readme
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:48:01 +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 ac77e11afa remove built-in memory and task tool servers
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>
2026-04-14 08:37:26 +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 ae3fc3be78 refactor: split memory and task out of reasoning into own packages
- 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>
2026-04-14 08:14:41 +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 809ad3472d rename workdir to cwd
Go API: WorkDir→CWD, SetWorkDir→SetCWD, WorkDirSetter→CWDSetter.
Unexported: workdir→cwd in fields, params, locals.
Docs: README.md updated.
2026-04-13 18:03:20 +02:00
Levi Neely a035913514 fix: only use json wire field for JSON objects in tool results
Bare JSON scalars (0, true, null, "string") and arrays pass
json.Valid() but the Kiro API rejects them in the json field with
ValidationException. Once such a tool result is in session history,
every subsequent request fails, making the session unrecoverable.

Restrict the json path to content starting with '{' so only actual
JSON objects are sent that way; everything else uses the text field.
2026-04-13 16:21:45 +02:00
Levi Neely bebe3014fc rename workdir to cwd
Rename the user-facing 9P file and session key from "workdir" to
"cwd" for consistency with the /cwd command.
2026-04-13 15:51:48 +02:00
Levi Neely 2273f0e867 agent: drop empty input in Submit 2026-04-13 15:46:25 +02:00
Levi Neely aa32d17e81 backend: add Backends() listing supported backend names 2026-04-13 14:45:14 +02:00
Levi Neely 269c3eacd5 agent: add SetSessionID for session rename support
- Add SetSessionID to Core interface and agentCore implementation
- Renames persisted .json and .compaction.jsonl files on disk
- Propagates OLLIE_SESSION_ID env var to execute server
- Add /kill and /rn to /help output
2026-04-13 14:25:47 +02:00
Levi Neely dace96ce5b core: guard /model writes while agent is running 2026-04-13 13:34:13 +02:00
Levi Neely adb4b3c46f core: guard state-mutating commands while agent is running
/backend, /agent, /compact, and /clear now return an error if
the agent loop is active. These commands replace pointers or
mutate session state that the running loop holds by copy or
reference, leading to silent failures or races.
2026-04-13 13:29:46 +02:00
Levi Neely 46cd8e9a66 reasoning_plan: make tool description backend-agnostic
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.
2026-04-13 13:05:04 +02:00
Levi Neely d705eb520e plan prompt: document __todo/__wip/__done lifecycle and listing patterns 2026-04-13 12:01:36 +02:00