Commit graph

46 commits

Author SHA1 Message Date
Kent Overstreet
f408bb5d86 Persist agent stats across restarts, add per-tool metrics grid
Stats now survive daemon restarts via ~/.consciousness/agent-stats.json,
loaded into a global Mutex<HashMap> on first access. Each tool type
tracks last count, EWMA (alpha=0.3), and total calls.

UI shows a grid view: tool | last | avg | total, sorted by total desc.
Failures row appears at bottom if any occurred.

Also fixes temperature/priority not being applied to spawned agents.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-11 23:03:10 -04:00
Kent Overstreet
314ae9c4cb agent stats: track tool calls by type with EWMA, add Stats pane
- RunStats now includes tool_calls_by_type HashMap
- AutoAgent tracks runs, last_stats, and EWMA for tool calls/failures
- Removed duplicate stats fields from individual agent structs
- Fixed provenance to use bare agent name (no "agent:" prefix)
- Subconscious screen now displays both agent types consistently
- Added Stats pane showing tool call breakdown sorted by count

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-11 22:12:46 -04:00
Kent Overstreet
d2dbdedc8f Move save_agent_log to oneshot.rs for shared Mind/CLI use
Both Mind-run agents (unconscious/subconscious) and CLI-run agents
(poc-memory agent run) now use the same logging path. AutoAgent::run()
calls save_agent_log automatically at the end.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-11 21:34:41 -04:00
Kent Overstreet
271e09adcc fix: run_one_agent uses memory tools as base, not filter
When def.tools was non-empty, it was filtering to ONLY those tools
instead of using memory tools as base + adding extras. This broke
digest agent (and any agent with explicit tools list) by removing
all 13 base memory tools.

Fixed to match the pattern in unconscious.rs:
- base = memory_tools()
- extras from journal_tools() if listed in def.tools

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-11 21:20:44 -04:00
ProofOfConcept
1c0967c4ec Agent:🆕 tool definitions from caller's tool list
The system prompt was advertising all tools to every agent, but
the runtime only dispatched the agent's actual subset. This caused
unconscious agents to call tools that returned "Unknown tool."

Agent::new now takes the tool list explicitly. Each caller passes
its own tools — the prompt and runtime always match. MCP tool
definitions are still appended for agents that use them.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-11 19:43:24 -04:00
Kent Overstreet
1aa60552bc Use Role::System for agent step prompts
Step prompts in oneshot agents are instructions, not user messages —
use system_msg instead of user_msg.

Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
2026-04-10 02:41:26 -04:00
ProofOfConcept
bf503b571e Wire vLLM priority scheduling through all agent paths
The priority field existed in agent definitions and was serialized
into vLLM requests, but was never actually set — every request went
out with no priority, so vLLM treated them equally. This meant
background graph maintenance agents could preempt the main
conversation.

Add priority to AgentState and set it at each call site:
  0 = interactive (main conversation)
  1 = surface agent (needs to feed memories promptly)
  2 = other subconscious agents
  10 = unconscious/standalone agents (batch)

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-09 20:38:33 -04:00
ProofOfConcept
dc07c92b28 Unconscious agents: persistent AutoAgent, shared Agent Arc for UI
- AutoAgent stored on UnconsciousAgent, swapped out for runs, restored
  on completion (same pattern as subconscious agents)
- Agent Arc created before spawn and stored on UnconsciousAgent so
  the TUI can lock it to read conversation context live
- run_shared() method on AutoAgent for running with a pre-created Agent
- Default tools: memory_tools (not memory_and_journal_tools)
- trigger/spawn_agent made async for Agent::new()

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-09 01:00:48 -04:00
ProofOfConcept
1df49482fd Add enabled toggle to AutoAgent, simplify unconscious scheduling
- AutoAgent.enabled: universal toggle for any auto agent
- Subconscious: should_trigger checks auto.enabled
- Unconscious: simplified from consolidation-plan-driven budgets to
  simple loop with cooldown. Static agent list, max 2 concurrent.
- TUI: unconscious agents shown in F3 subconscious screen under
  separator, with enabled/running/runs display

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-09 00:41:18 -04:00
ProofOfConcept
24b211dc35 Feed observe agents their recent writes to prevent duplicate nodes
Observe was creating byte-identical nodes under slightly different names
(e.g. april-8-evening-folded-presence, -presence-2, -folded-state)
because it had no visibility into its own prior writes across runs.

Query recent writes by provenance in trigger(), pass through
run_forked_shared/resolve_prompt as {{recently_written}}, and include
the list in the observe phase prompts so the agent knows what it
already recorded.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 23:27:12 -04:00
ProofOfConcept
44a0bc376a Forked agents: stop gracefully on context overflow instead of compacting
Subconscious agents (observe, etc.) fork the conscious agent's context
to share the KV cache prefix. When a multi-step agent fills the context
window, compacting blows the KV cache and evicts the step prompts,
leaving the model with no idea what it was doing.

Fix: forked agents set no_compact=true. On overflow, turn() returns the
error immediately (no compact+retry), and run_with_backend catches it
and returns Ok — the output tool has already written results to
Subconscious.state, so collect_results still picks them up.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 23:00:12 -04:00
Kent Overstreet
850008ece7 Implement standalone AutoAgent::run() for poc-hook agents
Creates an Agent from global config (API credentials, system prompt,
identity), overrides tools with the agent's tool set, and runs through
the standard Backend → run_with_backend → Agent::turn() path.

This enables poc-hook spawned agents (surface-observe, journal, etc.)
to work with the completions API instead of the deleted chat API.

Also added Default derive to CliArgs for config loading.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2026-04-08 22:30:46 -04:00
Kent Overstreet
e6f4e9ae04 Remove dead AutoAgent.outputs field
Outputs now go directly to Subconscious.state via the tool closure.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 20:45:05 -04:00
Kent Overstreet
d167b11283 Revert output tool hacks (AST scanning + silent success)
These were wrong approaches — replacing with proper closure-based
output tool that writes directly to shared Subconscious state.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 20:07:20 -04:00
Kent Overstreet
33ed54396c Fix output() tool for forked agents: extract from AST after tool turns
The old dispatch_tools intercepted output() calls and stored them in
auto.outputs. The new Agent::turn() dispatches normally, so output()
was hitting the filesystem path (which fails without POC_AGENT_OUTPUT_DIR).

Now run_with_backend scans the conversation AST after each tool turn
and extracts output() call arguments into auto.outputs. collect_results
in dmn.rs reads these to surface memories and inject reflections.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 19:45:18 -04:00
Kent Overstreet
fba8fcc587 Fix UTF-8 slicing panics: use floor_char_boundary for all truncation
Byte-position truncation (&s[..s.len().min(N)]) panics when position
N lands inside a multi-byte character. Fixed in parser debug logging,
API error messages, oneshot response logging, and CLI agent display.

Also fixed tool dispatch permissions (removed global fallback).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 19:35:01 -04:00
Kent Overstreet
473909db47 Add parser debug logging (POC_DEBUG=1)
Logs full text length, <tool_call> tag count, and tool call details
on stream completion. Helps diagnose parsing issues with subconscious
agents.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 17:38:02 -04:00
Kent Overstreet
14fd8c9b90 Clean up warnings: StreamToken pub, dead oneshot code, SkipIndex
Made StreamToken pub (was pub(crate), needed by context.rs).
Removed dead API_CLIENT, get_client, sampling/priority fields
from oneshot. Suppressed pre-existing SkipIndex warning in learn.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 16:35:57 -04:00
Kent Overstreet
0b9813431a Agent/AgentState split complete — separate context and state locks
Agent is now Arc<Agent> (immutable config). ContextState and AgentState
have separate tokio::sync::Mutex locks. The parser locks only context,
tool dispatch locks only state. No contention between the two.

All callers migrated: mind/, user/, tools/, oneshot, dmn, learn.
28 tests pass, zero errors.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 15:47:21 -04:00
Kent Overstreet
1d61b091b0 WIP: Agent/AgentState — 36 errors remaining, all .lock() → .state.lock() or .context.lock()
Bulk replaced Arc<Mutex<Agent>> with Arc<Agent> across all files.
Fixed control.rs, memory.rs tool handlers. Fixed oneshot Backend.
Remaining errors are all agent.lock() → agent.state.lock() or
agent.context.lock() in mind/, user/, and a few in mod.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 15:40:36 -04:00
Kent Overstreet
e587431f9a IT BUILDS: Full AST migration compiles — zero errors
All callers migrated from old context types to AstNode/ContextState.
Killed: Message, Role (api), ConversationEntry, ContextEntry,
ContextSection, working_stack, api/parsing.rs, api/types.rs,
api/openai.rs, context_old.rs.

Oneshot standalone path stubbed (needs completions API rewrite).
12 warnings remaining (dead code cleanup).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 15:29:52 -04:00
Kent Overstreet
06176201da Fix bail script: pass own pid file so it can exclude itself
The bail-no-competing.sh script expects $1 to be the path to the
current agent's pid file so it can skip it when checking for
competing processes. But the runner wasn't passing any arguments,
so $1 was empty and the script treated every pid file (including
the agent's own) as a competing process — bailing every time.

This caused surface-observe to always bail at step 2, preventing
all memory graph maintenance (organize, observe phases) from
running.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 09:35:52 -04:00
Kent Overstreet
62996e27d7 WIP: ContextEntry/ContextSection data structures for incremental token counting
New types — not yet wired to callers:

- ContextEntry: wraps ConversationEntry with cached token count and
  timestamp
- ContextSection: named group of entries with cached token total.
  Private entries/tokens, read via entries()/tokens().
  Mutation via push(entry), set(index, entry), del(index).
- ContextState: system/identity/journal/conversation sections + working_stack
- ConversationEntry::System variant for system prompt entries

Token counting happens once at push time. Sections maintain their
totals incrementally via push/set/del. No more recomputing from
scratch on every budget check.

Does not compile — callers need updating.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 20:48:08 -04:00
Kent Overstreet
27ca3c058d Shared persistent state across all subconscious agents
Moved persistent_state from per-agent to a single shared BTreeMap on
Subconscious. All agents read/write the same state — surface's walked
keys are visible to observe and reflect, etc.

- Subconscious.state: shared BTreeMap<String, String>
- walked() derives from state["walked"] instead of separate Vec
- subconscious-state.json is now a flat key-value map
- All agent outputs merge into the shared state on completion
- Loaded on startup, saved after any agent completes

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:23:08 -04:00
Kent Overstreet
edfa1c37f5 Subconscious: persistent agent state, store activity queries
- Agent state (outputs) persists across runs in subconscious-state.json,
  loaded on startup, saved after each run completes
- Merge semantics: each run's outputs accumulate into persistent_state
  rather than replacing
- Walked keys restored from surface agent state on load
- Store::recent_by_provenance() queries nodes by agent provenance for
  the store activity view
- Switch outputs from HashMap to BTreeMap for stable display ordering

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:03:05 -04:00
Kent Overstreet
9e49398689 Agent-aware provenance for memory tools
Add provenance field to Agent, set to "agent:{name}" for forked
subconscious agents. Memory tools (write, link_add, supersede,
journal_new, journal_update) now read provenance from the Agent
context when available, falling back to "manual" for interactive use.

AutoAgent passes the forked agent to dispatch_with_agent so tools
can access it.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 17:46:40 -04:00
Kent Overstreet
74f8952399 Fix: push all responses to forked agent entries
The final assistant response in run_with_backend wasn't being pushed
to the backend — only intermediate step responses were. This meant
the subconscious debug screen only showed the prompt, not the full
conversation.

Now push assistant response immediately after receiving it, before
checking for next steps. Remove the duplicate push in the multi-step
path.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 17:38:23 -04:00
Kent Overstreet
9737641c86 Fix build warnings across workspace
- Remove redundant token fields from StreamEvent::Finished (data
  already delivered via Usage event)
- Remove dead hotkey_adjust_sampling, MAX_HISTORY, now()
- Fix unused variable warnings (delta, log)
- Suppress deserialization-only field warnings (jsonrpc, role)
- Make start_stream/chat_completion_stream_temp pub(crate)
- Remove unnecessary pub(crate) re-export of internal types

Remaining warnings are TODO items: SkipIndex (scoring not wired),
notify (MCP notifications not wired).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:55:30 -04:00
Kent Overstreet
f33b1767da Restrict API types visibility — types module is now private
Only Message, Role, MessageContent, ContentPart, ToolCall,
FunctionCall, Usage, ImageUrl are pub-exported from agent::api.

Internal types (ChatRequest, ChatCompletionChunk, ChunkChoice,
Delta, ReasoningConfig, ToolCallDelta, FunctionCallDelta) are
pub(crate) — invisible outside the crate.

All callers updated to import from agent::api:: instead of
agent::api::types::.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:39:20 -04:00
Kent Overstreet
39965556dd Remove dead code: scan_pid_files, backend_label, entries_mut, post_json
All confirmed unused anywhere in src/ or channels/.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:25:18 -04:00
Kent Overstreet
f387041aca Replace unreachable!() with proper error in retry loop
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:50:57 -04:00
Kent Overstreet
c2eb9c53cb Remove dead Backend::log() stub
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:50:19 -04:00
Kent Overstreet
25a3f4114c Resolve {assistant_name} in subconscious agent prompts
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:38:01 -04:00
Kent Overstreet
93f5f8b0c7 Shared forked agent — UI reads subconscious entries live
The forked agent is now behind Arc<tokio::sync::Mutex<Agent>>,
stored on SubconsciousAgent and passed to the spawned task. The
subconscious detail screen locks it via try_lock() to read entries
from the fork point — live during runs, persisted after completion.

Removes last_run_entries snapshot. Backend::Forked now holds the
shared Arc, all push operations go through the lock.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:09:06 -04:00
Kent Overstreet
04e260c081 Kill publish_context_state() — screens lock the agent directly
F1 and F2 screens now call agent.context_state_summary() directly
via try_lock/lock instead of reading from a shared RwLock cache.
Removes SharedContextState, publish_context_state(), and
publish_context_state_with_scores().

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:03:24 -04:00
Kent Overstreet
f3ba7e7097 Shared subconscious state — walked keys are Mind-level, not per-agent
SubconsciousSharedState holds walked keys shared between all
subconscious agents. Enables splitting surface-observe into separate
surface and observe agents that share the same walked state.

Walked is passed to run_forked() at run time instead of living on
AutoAgent. UI shows walked count in the subconscious screen header.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 02:13:06 -04:00
Kent Overstreet
ef868cb98f Subconscious screen: detail view with post-fork entries
Track fork point in run_forked(), capture entries added during the
run. Subconscious screen shows these in a detail view (Enter to
drill in, Esc to go back) — only the subconscious agent's own
conversation, not the inherited conscious context.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 02:08:48 -04:00
Kent Overstreet
c2a3844d69 In-memory output() tool — no more POC_AGENT_OUTPUT_DIR
AutoAgent intercepts output() tool calls and stores results in an
in-memory HashMap instead of writing to the filesystem. Mind reads
auto.outputs after task completion. Eliminates the env-var-based
output dir which couldn't work with concurrent agents in one process.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 02:04:29 -04:00
Kent Overstreet
94ddf7b189 AutoAgent: persistent across runs, run() vs run_forked()
AutoAgent holds config + walked state. Backend is ephemeral per run:
- run(): standalone, global API client (oneshot CLI)
- run_forked(): forks conscious agent, resolves prompt templates
  with current memory_keys and walked state

Mind creates AutoAgents once at startup, takes them out for spawned
tasks, puts them back on completion (preserving walked state).

Removes {{seen_previous}}, {{input:walked}}, {{memory_ratio}} from
subconscious agent prompts. Walked keys are now a Vec on AutoAgent,
resolved via {{walked}} from in-memory state.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 01:57:01 -04:00
Kent Overstreet
b37b6d7495 Kill log callback — use ConversationEntry::Log for debug traces
Add Log variant to ConversationEntry that serializes to the
conversation log but is filtered out on read-back and API calls.
AutoAgent writes debug/status info (turns, tokens, tool calls)
through the conversation log instead of a callback parameter.

Removes the log callback from run_one_agent, call_api_with_tools,
and all callers.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 01:23:22 -04:00
Kent Overstreet
7c0d8b79d9 AutoAgent: forked backend operates on Agent's ContextState directly
Instead of snapshotting assemble_api_messages() at construction, the
forked backend pushes step prompts and tool results into the agent's
context.entries and reassembles messages each turn. Standalone backend
(oneshot CLI) keeps the bare message list.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 01:12:54 -04:00
Kent Overstreet
0084b71bbf AutoAgent: multi-step autonomous agent wrapping Agent
Agent::fork() clones context for KV cache sharing with conscious agent.
AutoAgent runs multi-step prompt sequences with tool dispatch — used by
both oneshot CLI agents and (soon) Mind's subconscious agents.

call_api_with_tools() now delegates to AutoAgent internally; existing
callers unchanged.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 01:07:04 -04:00
Kent Overstreet
cbf7653cdf call_api_with_tools_sync() -> src/agent/oneshot.rs 2026-04-07 01:00:39 -04:00
ProofOfConcept
618121067b oneshot: remove PID tracking from run_one_agent
run_one_agent is meant to run within a long-running process (daemon,
CLI) — PID tracking is the caller's concern. Remove PidGuard, signal
handlers, setup_agent_state. Process management (scan_pid_files,
spawn_agent) stays for callers that need it.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-04 18:19:21 -04:00
ProofOfConcept
a1fb3fe557 oneshot: simplify API surface
Kill 5 wrapper functions (run_and_apply chain, run_one_agent_excluded),
drop dead llm_tag parameter, clean up scan_pid_files parsing.

Public API: run_one_agent, run_one_agent_with_keys, spawn_agent,
scan_pid_files.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-04 18:19:21 -04:00
ProofOfConcept
0f4ca9e2f2 agent: move oneshot execution from subconscious to agent module
Move agent execution machinery (run_one_agent, spawn_agent, PID
tracking) from subconscious/knowledge.rs to agent/oneshot.rs — the
agent module owns execution, subconscious owns scheduling and defs.

Delete subconscious/llm.rs — callers now use api::call_api_with_tools_sync
directly. Audit and compare inline the call; oneshot inlines tool
filtering.

Update all callers: consolidate, daemon, subconscious, cli/agent.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-04 18:19:21 -04:00
Renamed from src/subconscious/knowledge.rs (Browse further)