Commit Graph

259 Commits

Author SHA1 Message Date
ollie f08e0abdf0 core: support dynamic tool registration 2026-07-28 14:13:08 +02:00
ollie 3fb5528c97 flushSave persists backend and model 2026-07-27 20:07:17 +02:00
ollie dfc387d7b8 sanitize invalid ToolCall.Arguments before save; atomic write 2026-07-27 20:01:31 +02:00
ollie 08c9b3dc76 fix unused desc variable in ReactTo 2026-07-27 19:55:11 +02:00
ollie 52849794e8 stop emitting reaction events to chat log; badges handle display 2026-07-27 19:54:39 +02:00
ollie 05524b8aa7 add Reactions() method to Core interface 2026-07-27 19:47:16 +02:00
ollie af9a22b1db response IDs and structured reactions with exact targeting 2026-07-27 19:12:12 +02:00
ollie c656846cce categorize emoji reactions as positive/negative/confused with tracked counters 2026-07-27 18:30:01 +02:00
Levi Neely 96a140a83c add React() for emoji reactions on assistant messages
New method on the Core interface that appends a lightweight user
message to session history without triggering a model turn. The
agent sees the reaction as context on its next turn.

Used by the 9P react file: echo emoji > s/{id}/react
2026-07-27 15:19:33 +02:00
Levi Neely 273a31c5f1 emit post-stream suffixes to chat output
When tool results are streamed, suffixes appended after execution
(truncation hints, user-interruptions, PostTool context) were only
written to the stored message history but never emitted to the chat
stream. This meant they never appeared in D-Bus signals or the chat
file.

Accumulate suffixes explicitly and emit them as a final event when
streaming was active, guaranteeing they appear at the end of the
tool output in all output paths.
2026-07-27 13:07:41 +02:00
Levi Neely 75f11a7dc9 enforce 128KB tool result ceiling unconditionally
The tool result truncation had two bypasses:

1. Error results were exempt (!isErr condition) — a command returning
   output in its error message could flood the context with megabytes
   of untruncated data.

2. The streaming callback emitted chunks to the event handler (and
   thus D-Bus signals) with no size check, flooding the bus even
   when the final stored result would be truncated.

Fix:
- Remove the configurable ToolResultMaxBytes field; use the constant
  defaultToolResultMaxBytes (128KB) unconditionally for all results
  regardless of success/error status.
- Cap the streaming callback at 128KB so chunks stop being emitted
  once the ceiling is reached.
- Cap output embedded in execute server error messages to 8KB as
  defense in depth.
2026-07-27 13:02:45 +02:00
ollie d903980256 persist usage/cost data across session restarts 2026-07-26 19:01:19 +02:00
ollie 95557b35ab persist active sessions under active directory 2026-07-26 12:10:11 +02:00
ollie 88ca0c1842 agent: inject baseLayers (system prompt, operational model, env) into /agent reload path
The operational model was only rendered for new sessions, not for
restored sessions or /agent reloads. Store baseLayers on the agent
struct and pass them through on rebuild.

Also fix pre-existing test failures caused by DiscoverTools reading
from the live OLLIE_TOOLS_PATH during tests.
2026-07-21 14:40:24 +02:00
ollie 8ff14935b7 fix: exclude discovered tools from backend tool definitions
DiscoverTools() results have no InputSchema and are invoked via
call_tool, not directly. Sending them to Bedrock as tool definitions
caused ValidationException (inputSchema.json.type must be object).

Now only built-in executors (execute_code, call_tool, pipe) with proper
schemas are registered as backend tools. Discovered scripts remain in
allToolInfos for the preamble surface listing only.
2026-07-21 13:47:30 +02:00
ollie 3c2bf3eb40 tools: two-tier discovery (surface listing + on-demand prompt)
BuildRuntime now appends a compact surface listing (name + one-liner)
to the preamble instead of full tool prompts. Full prompts are
available on-demand via ToolPrompt(name) for the /net/dns pattern.

- DiscoverTools: extracts short description from first content line
- BuildRuntime: appends "# Available Tools" with name + description
- ToolPrompt(name): returns full ollie:prompt for a specific tool
2026-07-21 13:36:16 +02:00
ollie 41eedb0c27 tools: discover prompts from ollie:prompt script headers
- Add Prompt field to tools.ToolInfo
- Add ExtractPrompt parser for ollie:prompt...ollie:end blocks
- Add DiscoverTools to scan tool scripts directory
- BuildRuntime appends discovered tool prompts to preamble

Tool scripts can now embed their usage documentation directly in
the script header. This replaces the separate tools-*.md prompt
files and ensures documentation stays co-located with implementation.
2026-07-21 13:18:38 +02:00
ollie f5298306b1 agent: layered preamble scaffolding
BuildRuntime now accepts optional baseLayers (variadic strings) that
are prepended to the agent-resolved preamble. This enables the server
to compose: system_prompt + operational_model + environment + agent_prompts.

- config.Config: add SystemPrompt field (path override)
- AgentCoreConfig: add OperationalModel and SystemPrompt fields
- BuildRuntime: prepend baseLayers before agent prompt content
- Remove debug fprintf statements from prompt resolution
2026-07-21 12:53:51 +02:00
ollie c2688a1d3d agent: cross-turn tool result cache
Move the read-safe tool result cache from a per-turn local variable
to the agent struct, persisting it across turns. This eliminates
redundant calls to file_read, lsp_*, and memory_recall when the
underlying data has not changed.

The cache is invalidated (cleared entirely) when file_write or
file_edit executes, ensuring stale results are never returned
after mutations.
2026-07-21 12:04:35 +02:00
ollie bd3b46bbed agent: debounce session persistence
saveSession() now sets a dirty flag and starts a 2-second timer
instead of immediately serializing and writing the full message
history. For a 50-step turn, this reduces 50 JSON marshals + disk
writes down to ~25 (one every 2s) plus a guaranteed flush at
turn end and on close.

flushSave() is called:
- At end of turn (after setState idle)
- On interrupt
- On Close()
- When the 2s timer fires (if still dirty)
2026-07-21 12:00:30 +02:00
Levi Neely 05e43b9a7c agent: resolve prompt from file paths and OLLIE_PROMPTS_PATH 2026-07-20 13:37:09 +02:00
ollie 663311daa0 remote: persist Remote field in session save/restore 2026-07-19 21:53:01 +02:00
ollie 9c1dd58474 streaming: tool output streams into [tool:] block, no new roles 2026-07-19 21:36:55 +02:00
ollie 805933453f streaming: tool output streams into tool block directly 2026-07-19 21:25:42 +02:00
ollie 5fc7bd816e streaming: emit partial tool output via context callback 2026-07-19 21:06:13 +02:00
ollie d501b47bf7 prompt: store PromptEnvExtra on agent for /agent reloads
Added PromptEnvExtra to AgentCoreConfig and agent struct. The /agent
command now uses stored PRIME_* vars instead of recomputing locally.
This ensures remote sessions get the correct remote host info on
every prompt rebuild.
2026-07-19 20:37:37 +02:00
ollie 95d9e9fd85 prompt: unified PromptEnv for local and remote sessions
Added PromptEnv(cwd) helper that returns PRIME_CWD, PRIME_PLATFORM,
PRIME_IS_GIT_REPO. All callers of BuildRuntime now pass these.
prime script is now a pure template renderer with no detection logic.
Removed ad-hoc PRIME_CWD injection from prompt_resolver.
2026-07-19 20:26:52 +02:00
ollie a53d5b9618 remote: fetch host_info, inject PWD for remote prompt resolution
prompt_resolver: when cmd.Dir cannot be set (remote CWD does not exist
locally), inject PWD=cwd into subprocess env so envsubst in prime sees
the correct working directory.

remote.Server: fetch host_info RPC after connect, expose HostInfo struct
with platform, arch, is_git_repo for the session to pass to prompts.
2026-07-19 20:17:32 +02:00
ollie 414220c2e5 fix: pass PWD and OLLIE_UNAME to BuildRuntime in /agent command
The /agent command rebuilds the runtime but only passed OLLIE_SESSION_ID.
For remote sessions where cmd.Dir falls through, the prompt scripts need
PWD explicitly set to the session CWD for envsubst in prime.
2026-07-19 20:05:22 +02:00
ollie 160e285e68 fix: prompt resolution for remote sessions + vet context leaks
prompt_resolver: guard cmd.Dir with stat check so remote CWDs that
do not exist locally do not cause prompt commands to fail with ENOENT.

server.go: add cancel on all early-return paths to fix go vet
cancel-not-used-on-all-paths warnings.
2026-07-19 19:43:12 +02:00
ollie 64ab94f121 hooks: skip non-existent CWD for remote sessions
If the session CWD does not exist locally (remote execution), do not
set cmd.Dir. This prevents fork/exec failures when the CWD only
exists on the remote host.
2026-07-19 19:18:28 +02:00
ollie 6f35059d83 agent/hooks: add run/fail summary to HookResult
Track Total, Succeeded, Failed counts and FailedCmds in HookResult.
Add Summary() method producing "(N of X hooks run) (K of X failed: cmd)".
Emit hook summary as info event at all lifecycle hook call sites and
on preTool/postTool failure.
2026-07-19 10:25:09 +02:00
Levi Neely f8ed2189f1 agent: inject detached process output on exit
When a detached process exits, its output (last 2KB of ring buffer)
is queued as a prompt wrapped in <detached-process-result> tags.
The agent sees it on its next turn (or immediately if idle via Queue).

- InjectSystemEvent(content) added to Core interface
- SetOnExit(fn) added to execute.Server for external hook wiring
2026-07-17 22:07:26 +02:00
Levi Neely 5df603a9e3 agent: expose detach methods on Core interface
Adds Detach, ListDetached, SignalDetached, GetDetachedOutput,
DismissDetached to the Core interface. Implemented on agent struct
via interface type assertions to the execute server.

Also adds ListDetachedRaw() to execute.Server for cross-package
consumption without import cycles.
2026-07-17 16:49:29 +02:00
ollie 451dc96d47 agent: add SaveSession to Core interface for external persistence
- Add Backend/Model fields to PersistedSession for full restore metadata
- Add saveToFull() that includes backend/model in persisted state
- Add exported LoadPersistedSession(path) helper
- Add SaveSession(path) to Core interface, implemented on agent struct
- Existing saveTo() preserved as backward-compatible wrapper
2026-07-14 20:41:38 +02:00
ollie a50149d075 fix: send profileArn for social accounts, improve error messages
- Remove IsSocial guard from sqliteKiroAuth.ProfileARN(); the Kiro API
  now requires profileArn on all requests including personal accounts
- Add OLLIE_KIRO_PROFILE_ARN env var for static token auth
- Add repeated error detection (3x identical error triggers corrective nudge)
- Include expected format in tool dispatch error messages
2026-07-11 16:08:44 +02:00
Levi Neely fd20070294 refactor: remove 9P mount logic from core execute server
Moved all 9P FUSE mount code from core to 9p module using lifecycle hooks.

Changes:
- Removed 9P-specific fields (mountProc, mountPath, mountEnabled) from execute.Server
- Removed WithMount(), MountPath(), startMount(), remountIfStale() functions
- Added lifecycle hooks: OnPreDispatch, OnClose, OnEnvSet with corresponding options
- Updated SetEnv(), Close(), and Dispatch() to call hooks instead of hardcoded mount logic
- Fixed tool descriptions to use $OLLIE_TOOLS_PATH instead of 9P-specific $OLLIE/s/$SID/t paths
- Removed unused execute import from agent/commands.go

The core execute server is now harness-agnostic.
2026-07-08 15:55:10 +02:00
ollie f05b736af9 agent: update preamble when cwd changes
SetCWD now replaces old cwd references in the system prompt,
matching the pattern used by SetSessionID. Without this, the
model continued to see the original cwd in its environment
section after a directory change.
2026-07-07 12:20:48 +02:00
ollie 331edc332d fix test 2026-07-01 21:22:16 +02:00
ollie 8e7dd60a8b agent: remove $OLLIE mount dependency from core
- Add ListHandlers map to AgentCoreConfig/agent struct; /skills and /tools
  dispatch through it instead of reading local paths directly
- Add ReadPlanStep to AgentCoreConfig; wired by 9p/ directly from sess.plan
- Export NextUncheckedStep([]byte) as pure helper
- Fix prependOlliePath to use OLLIE_CFG_PATH/scripts/x/ instead of $OLLIE/x/
- Add OLLIE_CFG_PATH to EnsureDefaults and managed env var list
2026-06-16 12:30:36 +02:00
Levi Neely 1dbc75cecc agent: replace cold truncation with real LLM summarization
- store all tool results verbatim at update time
- stripColdResults now calls LLM to summarize, skips hot tail
- stripCold interface takes ctx+backend
- remove stripColdResults from RestoreSession
2026-06-01 09:45:27 +02:00
ollie c529ebf41a updates 2026-06-01 08:05:38 +02:00
ollie cb1551fe67 fix compaction model to deepseek-v4-flash; accept error stop reason in loop 2026-05-30 10:46:12 +02:00
ollie bc7a536ced fix: round-trip reasoning_content for DeepSeek thinking models
DeepSeek requires reasoning_content to be echoed back on assistant
messages. Store reasoning from stream events on Message and serialize
it as reasoning_content in the OpenAI wire format.
2026-05-28 19:04:03 +02:00
ollie 10cbded305 token efficiency: fix tier classification, expand cold tier, add usage log and compaction model override
- Fix dead-code bug: ClassifyTier now parses inner tool names from
  call_tool/pipe arguments via ResultTierArgs
- Add file_grep, file_glob, lsp_symbols, lsp_completion, lsp_diagnostics,
  reasoning_think to cold tier
- Add append-only JSONL usage log (~/.local/share/ollie/usage.jsonl)
- Add compaction model override: config > OLLIE_COMPACTION_MODEL env >
  per-backend default (haiku/gpt-4o-mini/flash)
- Expose CompactionModel on Core interface
2026-05-28 18:44:30 +02:00
Levi Neely 2b914ce150 codewhisperer: image content block support in user messages and tool results 2026-05-25 23:14:40 +02:00
ollie 02df4b8dd5 agent: plumb image ContentBlocks from tool results through to backend messages
toolExecutor now returns (string, []ContentBlock, error).
extractToolResult parses image blocks from structured tool output.
Session.update populates ContentBlocks on tool messages.
file_read detects PNG/JPEG/GIF/WEBP and returns base64-encoded image blocks.
2026-05-25 18:02:21 +02:00
Levi Neely 19877f0a06 agent/loop: send full compacted history instead of recent-only tail
After compaction, the loop was discarding cold+warm zones and only
sending the last 8 messages to the backend. This caused the agent to
lose context after manual or auto compaction.

Remove the recentHistory path entirely: state.history() already
returns the compacted (small) history post-compact. The TaskState
render block remains as additional steering injected after the system
prompt.

Removed: StepContext struct, recentHistory from state interface and
Session.
2026-05-23 13:16:41 +02:00
Levi Neely 9d6800a51c agent: parse text-based tool calls instead of failing
Models that don't support native function calling emit tool calls as
plain text. Instead of treating this as ToolUnsupportedError, parse the
text and execute the tool calls normally.

Handles both direct JSON and shorthand (key=value) formats with relaxed
JSON support (unquoted keys).
2026-05-23 11:46:49 +02:00
Levi Neely 47f8eed119 agent: remove unsandboxed ! shell escape
The ! prefix allowed arbitrary command execution without sandbox
protection. Since agents share the same Submit path as users, this
was a sandbox bypass vector. Remove it entirely; users who need
shell access can use execute_code (sandboxed) or run commands
directly in their terminal.
2026-05-21 15:18:02 +02:00