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>
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>
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.
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.
- 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
/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.
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>
- Submit routes to Inject when a turn is already running, keeping the
routing decision in core rather than the frontend or 9p layer
- Inject no longer cancels the current action; the pending prompt is
stored and consumed at the next tool result boundary (success or
failure), matching goq interrupt semantics
- If an inject is already pending, fall back to the FIFO so nothing is
lost; /irw (interrupt-rewrite) explicitly overwrites the pending inject
- PopInject is now called after every tool result, not just the last one
- Injected prompts are echoed to the chat via the running turn's output
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The newline event is emitted via handler() directly, not through
loopcfg.Output, so the Output-based newline case never fired.
Commit replyBuf to s.reply alongside the state="idle" transition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontends no longer need to shadow these in their own structs; they can
read authoritative values directly through the Core interface.
State and reply tracking moves into agentCore: state transitions on
call/tool events, reply resets and accumulates per-turn in Submit's
Output func. This also fixes a bug where reply accumulated across all
queue-drained turns instead of reflecting only the most recent one.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Submit now emits Event{Role:"user"} before each turn so queued prompts
appear in the chat log via the normal event path, not just direct
appendChat calls from the 9p prompt handler
- Strengthen system prompt rule against using execute_code/echo as a
communication mechanism
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>
Remove MaxSteps limit and associated stalled event emission.
The agent will now run indefinitely until completion or interruption,
eliminating the annoying 'agent stalled' messages.
- 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>
Call() blocks on sc.Scan() waiting for a response that spec-compliant
servers must not send. Add Notify() for fire-and-forget messages and
use it for notifications/initialized.
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>