Commit graph

47 commits

Author SHA1 Message Date
Kent Overstreet
14dd8d22af Rename agent/ to user/ and poc-agent binary to consciousness
Mechanical rename: src/agent/ -> src/user/, all crate::agent:: ->
crate::user:: references updated. Binary poc-agent renamed to
consciousness with CLI name and user-facing strings updated.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-03 17:25:59 -04:00
Kent Overstreet
249726599b read_tail 64MB — just read the whole log
Images in the jsonl eat most of the byte budget. 64MB covers
any realistic conversation log; compact() trims to fit.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 23:13:28 -04:00
Kent Overstreet
31302961e2 estimate prompt tokens on restore so status bar isn't 0K
After restore_from_log + compact, set last_prompt_tokens from
the budget's used() count instead of waiting for the first API call.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 23:07:42 -04:00
Kent Overstreet
41b3f50c91 keep 2 most recent images, age out the rest
age_out_images now keeps 1 existing image + 1 about to be added
= 2 live images for motion/comparison. Previously aged all to 1.
Reduces image bloat in conversation log and context.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 23:06:08 -04:00
Kent Overstreet
3f3db9ce26 increase log read_tail from 2MB to 8MB
Large tool results (memory renders, bash output) consume most of
the 2MB budget — only 37 entries loaded from a 527-line log.
8MB captures ~300 entries, giving compact() enough conversation
to work with.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 23:02:43 -04:00
Kent Overstreet
736307b4c2 add debug logging to compact and restore_from_log
Logs entry counts before/after compaction (memory vs conversation),
budget breakdown, and restore load counts. Helps diagnose context
utilization issues.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:58:25 -04:00
Kent Overstreet
d921e76f82 increase context budget: 80% window, 15% journal, no double reserve
Context was too aggressively trimmed — 80% free after compaction.
Budget was 60% of window minus 25% reserve = only 45% usable.

Now: 80% of window for total budget (20% output reserve built in),
no extra reserve subtraction. Journal budget 5% → 15% to carry
more context across compactions.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:53:54 -04:00
Kent Overstreet
78abf90461 fix scoring: HTTP error checking, context refresh, chunk logging
Check HTTP status from logprobs API (was silently ignoring 500s).
Call publish_context_state() after storing scores so F10 screen
updates. Add chunk size logging for OOM debugging.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:47:44 -04:00
Kent Overstreet
19205b9bae show scoring progress and per-response memory attribution
Status bar shows "scoring 3/7..." during scoring. Debug pane logs
per-memory importance and top-5 response breakdowns. F10 context
screen shows which memories were important for each assistant
response as drilldown children (← memory_key (score)).

Added important_memories_for_entry() to look up the matrix by
conversation entry index.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:27:43 -04:00
Kent Overstreet
c01d4a5b08 wire up /score command and debug screen for memory importance
/score snapshots the context and client, releases the agent lock,
runs scoring in background. Only one score task at a time
(scoring_in_flight flag). Results stored on Agent and shown on
the F10 context debug screen with importance scores per memory.

ApiClient derives Clone. ContextState derives Clone.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 22:21:31 -04:00
Kent Overstreet
33e45f6ce8 replace hardcoded personal names with config values
User and assistant names now come from config.user_name and
config.assistant_name throughout: system prompt, DMN prompts,
debug screen, and all agent files. Agent templates use
{user_name} and {assistant_name} placeholders.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 19:45:35 -04:00
Kent Overstreet
13d9cc962e abort orphaned stream tasks on drop, reduce timeout to 60s
Spawned streaming tasks were never cancelled when a turn ended or
retried, leaving zombie tasks blocked on dead vLLM connections.
AbortOnDrop wrapper aborts the task when it goes out of scope.

Chunk timeout reduced from 120s to 60s.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 18:41:02 -04:00
Kent Overstreet
35f231233f clear activity indicator on error paths
"thinking..." was getting stuck in the status bar when a turn
ended with a stream error, context overflow, or model error —
only the success path cleared it. Now all error returns clear
the activity indicator.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 17:53:51 -04:00
Kent Overstreet
af3929cc65 simplify compaction: Agent owns config, compact() reloads everything
Agent stores AppConfig and prompt_file, so compact() reloads
identity internally — callers no longer pass system_prompt and
personality. restore_from_log() loads entries and calls compact().

Remove soft compaction threshold and pre-compaction nudge (journal
agent handles this). Remove /compact and /context commands (F10
debug screen replaces both). Inline do_compact, emergency_compact,
trim_and_reload into compact(). Rename model_context_window to
context_window, drop unused model parameter.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 16:08:41 -04:00
Kent Overstreet
d419587c1b WIP: trim_entries dedup, context_window rename, compact simplification
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:58:03 -04:00
Kent Overstreet
809679b6ce delete dead flat-file journal tool and ephemeral stripping
Journal entries are written to the memory graph via journal_new/
journal_update, not appended to a flat file. Remove thought/journal.rs
(67 lines), strip_ephemeral_tool_calls (55 lines), default_journal_path,
and all wiring. -141 lines.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:35:56 -04:00
Kent Overstreet
aceaf0410e delete dead flat-file journal code from thought/context.rs
Journal entries are loaded from the memory graph store, not from the
flat journal file. Remove build_context_window, plan_context,
render_journal_text, assemble_context, truncate_at_section,
find_journal_cutoff, parse_journal*, ContextPlan, and stale TODOs.
Keep JournalEntry, default_journal_path (write path), and the live
context management functions. -363 lines.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:31:12 -04:00
Kent Overstreet
214806cb90 move context functions from agent/context.rs to thought/context.rs
trim_conversation moved to thought/context.rs where model_context_window,
msg_token_count, is_context_overflow, is_stream_error already lived.
Delete the duplicate agent/context.rs (94 lines).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:28:00 -04:00
Kent Overstreet
01bfbc0dad move journal types from agent/journal.rs to thought/context.rs
JournalEntry, parse_journal, parse_journal_text, parse_header_timestamp,
and default_journal_path consolidated into thought/context.rs. Delete
the duplicate agent/journal.rs (235 lines). Update all references.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:25:07 -04:00
Kent Overstreet
64dbcbf061 unify memory tracking: entries are the single source of truth
Memory tool results (memory_render) are now pushed as
ConversationEntry::Memory with the node key, instead of plain
Messages. Remove loaded_nodes from ContextState — the debug
screen reads memory info from Memory entries in the conversation.

Surfaced memories from surface-observe are pushed as separate
Memory entries, reflections as separate system-reminder messages.
User input is no longer polluted with hook output.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 14:56:02 -04:00
Kent Overstreet
a21cf31ad2 unify conversation persistence to append-only jsonl
Log ConversationEntry (with Memory/Message typing) instead of
raw Message. restore_from_log reads typed entries directly,
preserving Memory vs Message distinction across restarts.

Remove current.json snapshot and save_session — the append-only
log is the single source of truth. Remove dead read_all and
message_count methods. Add push_entry for logging typed entries.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 14:31:19 -04:00
Kent Overstreet
e9e47eb798 Replace build_context_window with trim_conversation
build_context_window loaded journal from a stale flat file and
assembled the full context. Now journal comes from the memory graph
and context is assembled on the fly. All that's needed is trimming
the conversation to fit the budget.

trim_conversation accounts for identity, journal, and reserve
tokens, then drops oldest conversation messages until it fits.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 03:35:28 -04:00
Kent Overstreet
87add36cdd Fix: don't overwrite journal during restore/compaction
The restore and compaction paths called build_context_window which
reads from the stale flat journal file, overwriting the journal we
loaded from the memory graph. Preserve the graph-loaded journal
across these operations.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 03:33:04 -04:00
Kent Overstreet
b9e3568385 ConversationEntry enum: typed memory vs conversation messages
Replace untyped message list with ConversationEntry enum:
- Message(Message) — regular conversation turn
- Memory { key, message } — memory content with preserved message
  for KV cache round-tripping

Budget counts memory vs conversation by matching on enum variant.
Debug screen labels memory entries with [memory: key]. No heuristic
tool-name scanning.

Custom serde: Memory serializes with a memory_key field alongside
the message fields, deserializes by checking for the field.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 03:26:00 -04:00
Kent Overstreet
eb4dae04cb Compute ContextBudget on demand from typed sources
Remove cached context_budget field and measure_budget(). Budget
is computed on demand via budget() which calls
ContextState::budget(). Each bucket counted from its typed source.
Memory split from conversation by identifying memory tool calls.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 03:07:45 -04:00
Kent Overstreet
acdfbeeac3 Align debug screen and budget with conversation-only messages
context.messages is conversation-only now — remove conv_start
scanning. Memory counted from loaded_nodes (same as debug screen).
No subtraction heuristics.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:56:28 -04:00
Kent Overstreet
5e781e9ae4 Fix budget counting: remove stale refresh_context_message
refresh_context_message was injecting personality into conversation
messages (assuming fixed positions that no longer exist). Replaced
with refresh_context_state which just re-measures and publishes.

conv_tokens now subtracts mem_tokens since memory tool results are
in the conversation message list.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:52:59 -04:00
Kent Overstreet
a0aacfc552 Move conversation messages into ContextState
ContextState now owns everything in the context window:
system_prompt, personality, journal, working_stack, loaded_nodes,
and conversation messages. No duplication — each piece exists once
in its typed form.

assemble_api_messages() renders the full message list on the fly
from typed sources. measure_budget() counts each bucket from its
source directly. push_context() removed — identity/journal are
never pushed as messages.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:47:32 -04:00
Kent Overstreet
4580f5dade measure_budget: count from typed sources, not message scanning
Identity tokens from system_prompt + personality vec. Journal
from journal entries vec. Memory from loaded_nodes. Conversation
is the remainder. No string prefix matching.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:32:26 -04:00
Kent Overstreet
4bdc7ae112 Journal budget: count from structured data, not string matching
Count journal tokens directly from Vec<JournalEntry> instead of
scanning message text for prefix strings. Type system, not string
typing.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:29:48 -04:00
Kent Overstreet
5526a26d4c Journal: store as structured Vec<JournalEntry>, not String
Keep journal entries as structured data in ContextState. Render
to text only when building the context message. Debug screen reads
the structured entries directly — no parsing ## headers back out.

Compaction paths temporarily parse the string from build_context_window
back to entries (to be cleaned up when compaction is reworked).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:21:45 -04:00
Kent Overstreet
42f1e888c4 Journal: flat 5% context window budget, skip plan_context
Render journal entries directly with ## headers instead of going
through the plan_context/render_journal_text pipeline. 5% of
model context window (~6500 tokens for Qwen 128K). Simpler and
predictable.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 02:00:14 -04:00
Kent Overstreet
7776d87d53 Journal: walk backwards with token budget, not load-all
Iterate journal entries backwards from the conversation cutoff,
accumulating within ~10K token budget (~8% of context window).
Stops when budget is full, keeps at least one entry. Much more
efficient than loading all entries and trimming.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 01:50:36 -04:00
Kent Overstreet
e4285ba75f Load journal from memory graph, not flat file
Replace flat-file journal parser with direct store query for
EpisodicSession nodes. Filter journal entries to only those older
than the oldest conversation message (plus one overlap entry to
avoid gaps). Falls back to 20 recent entries when no conversation
exists yet.

Fixes: poc-agent context window showing 0 journal entries.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 01:48:16 -04:00
Kent Overstreet
c814ed1345 Split hook.rs: core orchestration -> subconscious.rs
subconscious::subconscious — AgentCycleState, AgentInfo, AgentSnapshot,
  SavedAgentState, format_agent_output, cycle methods. Core agent
  lifecycle independent of Claude Code.

subconscious::hook — Claude Code hook: context loading, chunking,
  seen-set management, run_agent_cycles (serialized state entry point).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 01:37:51 -04:00
Kent Overstreet
9ac50bd999 Track agent child processes, reap on completion
spawn_agent returns Child handle + log_path. AgentCycleState stores
the Child, polls with try_wait() on each trigger to detect completion.
No more filesystem scanning to track agent lifecycle.

AgentSnapshot (Clone) sent to TUI for display. AgentInfo holds the
Child handle and stays in the state.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 01:20:03 -04:00
Kent Overstreet
1c190a3925 Wire AgentCycleState through runner and TUI
Runner owns AgentCycleState, calls trigger() on each user message
instead of the old run_hook() JSON round-trip. Sends AgentUpdate
messages to TUI after each cycle.

TUI F2 screen reads agent state from messages instead of scanning
the filesystem on every frame. HookSession::from_fields() lets
poc-agent construct sessions without JSON serialization.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 00:52:57 -04:00
Kent Overstreet
a0245c1279 Refactor hook: split agent orchestration from formatting
- Remove POC_AGENT early return (was from old claude -p era)
- Split hook into run_agent_cycles() -> AgentCycleOutput (returns
  memory keys + reflection) and format_agent_output() (renders for
  Claude Code injection). poc-agent can call run_agent_cycles
  directly and handle output its own way.
- Fix UTF-8 panic in runner.rs display_buf slicing (floor_char_boundary)
- Add priority debug label to API requests
- Wire up F2 agents screen: live pid status, output files, hook log
  tail, arrow key navigation, Enter for log detail view

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 00:32:23 -04:00
Kent Overstreet
c72eb4d528 vLLM priority scheduling for agents
Thread request priority through the API call chain to vLLM's
priority scheduler. Lower value = higher priority, with preemption.

Priority is set per-agent in the .agent header:
- interactive (runner): 0 (default, highest)
- surface-observe: 1 (near-realtime, watches conversation)
- all other agents: 10 (batch, default if not specified)

Requires vLLM started with --scheduling-policy priority.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-01 23:21:39 -04:00
ProofOfConcept
13453606ae refactor: runner owns stream routing, suppress tool call XML from display
Split the streaming pipeline: API backends yield StreamEvents through
a channel, the runner reads them and routes to the appropriate UI pane.

- Add StreamEvent enum (Content, Reasoning, ToolCallDelta, etc.)
- API start_stream() spawns backend as a task, returns event receiver
- Runner loops over events, sends content to conversation pane but
  suppresses <tool_call> XML with a buffered tail for partial tags
- OpenAI backend refactored to stream_events() — no more UI coupling
- Anthropic backend gets a wrapper that synthesizes events from the
  existing stream() (TODO: native event streaming)
- chat_completion_stream() kept for subconscious agents, reimplemented
  on top of the event stream
- Usage derives Clone

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-29 21:22:42 -04:00
ProofOfConcept
2a64d8e11f move leaked tool call recovery into build_response_message
Tool call parsing was only in runner.rs, so subconscious agents
(poc-memory agent run) never recovered leaked tool calls from
models that emit <tool_call> as content text (e.g. Qwen via Crane).

Move the recovery into build_response_message where both code paths
share it. Leaked tool calls are promoted to structured tool_calls
and the content is cleaned, so all consumers see them uniformly.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-29 20:57:59 -04:00
ProofOfConcept
c5efc6e650 budget: identity = system prompt + personality, memory = loaded nodes
Personality is identity, not memory. Memory is nodes loaded during
the session via tool calls — things I've actively looked at.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 02:28:44 -04:00
ProofOfConcept
79672cbe53 budget: count personality + loaded nodes as memory tokens
mem% was always 0 because memory_tokens was hardcoded to 0. Now
counts personality context + loaded nodes from memory tool calls.
Also calls measure_budget + publish_context_state after memory tool
dispatch so the debug screen updates immediately.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 02:27:25 -04:00
ProofOfConcept
10932cb67e hippocampus: move MemoryNode + store ops to where they belong
MemoryNode moved from agent/memory.rs to hippocampus/memory.rs — it's
a view over hippocampus data, not agent-specific.

Store operations (set_weight, set_link_strength, add_link) moved into
store/ops.rs. CLI code (cli/graph.rs, cli/node.rs) and agent tools
both call the same store methods now. render_node() delegates to
MemoryNode::from_store().render() — 3 lines instead of 40.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 01:55:21 -04:00
ProofOfConcept
4b97bb2f2e runner: context-aware memory tracking
Memory tools now dispatch through a special path in the runner (like
working_stack) instead of the generic tools::dispatch. This gives them
&mut self access to track loaded nodes:

- memory_render/memory_links: loads MemoryNode, registers in
  context.loaded_nodes (replace if already tracked)
- memory_write: refreshes existing tracked node if present
- All other memory tools: dispatch directly, no tracking needed

The debug screen (context_state_summary) now shows a "Memory nodes"
section listing all loaded nodes with version, weight, and link count.

This is the agent knowing what it's holding — the foundation for
intelligent refresh and eviction.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 01:48:15 -04:00
ProofOfConcept
1399bb3a5e runner: call memory_search directly instead of spawning poc-hook
The agent was shelling out to poc-hook which shells out to memory-search.
Now that everything is one crate, just call the library function. Removes
subprocess overhead on every user message.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 01:32:54 -04:00
ProofOfConcept
998b71e52c flatten: move poc-memory contents to workspace root
No more subcrate nesting — src/, agents/, schema/, defaults/, build.rs
all live at the workspace root. poc-daemon remains as the only workspace
member. Crate name (poc-memory) and all imports unchanged.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-03-25 00:54:12 -04:00
Renamed from poc-memory/src/agent/runner.rs (Browse further)