All process management now goes through active_tools:
- TUI reads metadata (name, elapsed time)
- Ctrl+K aborts handles (KillOnDrop sends SIGTERM)
- Running count from active_tools.len()
No more separate PID tracking, register/unregister, or
ProcessInfo. One data structure for everything.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
tokio::spawn abort drops the future but leaves child processes
running as orphans. KillOnDrop sends SIGTERM to the process
group on drop, ensuring cleanup. Defused via mem::forget on
normal completion.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
One data structure for all in-flight tool calls — metadata for
TUI display + JoinHandle for result collection and cancellation.
Agent spawns tool calls via tokio::spawn, pushes to shared
Arc<Mutex<Vec<ActiveToolCall>>>. TUI reads metadata, can abort().
No separate inflight/background collections.
Non-background: awaited after stream ends.
Background: persists, drained at next turn start.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Move active tool tracking from TUI message-passing to shared
Arc<RwLock> state. Agent pushes on dispatch, removes on
apply_tool_result. TUI reads during render. Background tasks
show as active until drained at next turn start.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
When </tool_call> is detected in the content stream, parse and
dispatch immediately via FuturesOrdered. Tool calls execute
concurrently while the stream continues. Results collected in
order after the stream ends.
Structured API path (ToolCallDelta) unchanged — still uses
post-stream parallel dispatch.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
All tools go through tools::dispatch() — no more separate
dispatch path for memory tools in the runner. The only
remaining special case is tagging memory_render results as
ConversationEntry::Memory for context deduplication, which
is a result-handling concern, not dispatch.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
channel-test was a debug tool, mcp-schema was superseded by
consciousness-mcp, cmd_mcp_schema in cli/misc.rs was the old
poc-memory subcommand.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
query_one_daemon returns Option — None means connection failed,
Some(vec![]) means connected but no channels yet. Fixes telegram
showing as disconnected when it's running but has no messages.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Track outgoing messages separately (own counter) so they appear
in the log but don't inflate unread counts. Reset on recv.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
mcp-schema is Claude Code glue — extract from poc-memory
subcommand to src/claude/mcp-schema.rs standalone binary.
Update Python MCP bridge to call the new binary.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
consciousness binary subscribes to all channel daemons on startup.
Notifications forwarded via NotifyForwarder callback through mpsc.
Pending notifications stored for thalamus agent consumption.
Channel list refreshed automatically when notifications arrive.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Move ChannelLog to src/thalamus/channel_log.rs — shared by all
channel daemon implementations. Each channel/PM gets its own
log with consumed/unread tracking.
IRC daemon: channels tracked via BTreeMap<String, ChannelLog>.
list() returns all channels (joined + PMs) with per-channel
unread counts. Sent messages stored in logs too.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
fetch_all_channels() connects to each daemon socket and calls
list() via capnp RPC. Runs on a dedicated thread (capnp uses Rc).
Results sent back via mpsc channel, TUI reads cached state.
Fetched at startup and when switching to F5 thalamus screen.
Also calls ensure_running() to restart dead daemons.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
The consciousness binary now has its own idle state machine,
fed directly by TUI events:
- Key press → user_activity()
- Turn complete → response_activity()
- Render tick → decay_ewma(), snapshot to TUI
F5 thalamus screen shows presence/activity from the in-process
state instead of shelling out to poc-daemon status. No tmux
pane scraping, no socket RPC — the binary IS the presence.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
thalamus/idle.rs: pure state machine — activity tracking, EWMA,
timers, sleep/quiet/dream state, notifications. No tmux, no
Claude Code dependencies.
claude/idle.rs: wraps thalamus state via Deref, adds claude_pane
tracking, tmux prompt injection, dream nudges, context building.
The Claude-specific tick() loop stays here.
The consciousness binary can now use thalamus::idle::State directly,
fed by TUI key events instead of tmux pane scraping.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Separates the Claude-specific daemon (idle timer, tmux pane detection,
prompt injection, RPC server, session hooks) from the universal
infrastructure (channels, supervisor, notify, daemon protocol).
thalamus/ now contains only substrate-independent code: the channel
client/supervisor, notification system, daemon_capnp protocol, and
shared helpers (now(), home()).
claude/ contains: idle.rs, tmux.rs, context.rs, rpc.rs, config.rs,
hook.rs (moved from subconscious/), plus the daemon CLI and server
startup code from thalamus/mod.rs.
All re-exports preserved for backward compatibility.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Channel status is cached on App and refreshed when switching
to F5, not polled every render frame. Shows connected/disconnected
status and unread count per channel daemon.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
Only redraw when something actually changed. The 50ms render
interval still ticks (for process count updates) but no longer
triggers draws. Dirty is set by key events, mouse events,
resize, UI messages, turn completions, and DMN ticks.
Saves bandwidth over SSH and reduces CPU usage when idle.
Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
- Add Thalamus variant to Screen enum (F5)
- Fix HashMap iteration ordering causing flickering in F4/F5
screens by using BTreeMap in supervisor and sorting plan_counts
- Update screen legend: F1=interact F2=conscious F3=subconscious
F4=unconscious F5=thalamus
- Add dirty bit field to App (prep for event-driven rendering)
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Move thalamus/ (poc-daemon) source files into src/thalamus/ as a
module of the main crate. The daemon entry point becomes a library
function thalamus::run() with a thin poc-daemon binary for backward
compatibility.
- Copy thalamus source into src/thalamus/, fix crate:: -> super::
- Copy daemon.capnp into schema/, add to build.rs
- Re-export daemon_capnp at crate root (capnp codegen requires it)
- Add thalamus dependencies (capnp-rpc, tokio-util, toml, rustls, etc.)
- Keep thalamus/ subcrate for comparison
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
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>
Replace prompt_logprobs-based scoring with the new vLLM /v1/score
endpoint. Much simpler: one API call per memory drop, returns
per-message total_logprob directly. No chunking needed, no OOM risk
— the endpoint only computes logits for scored tokens.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
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>
Single reqwest::Client shared across all prompt_logprobs calls
instead of creating a new one per call. Keeps HTTP connections
alive for faster sequential requests.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
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>
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>
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>
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>
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>
Split conversation into ~50K token chunks (configurable via
scoring_chunk_tokens in config) for prompt_logprobs calls.
Each chunk ends at an assistant message boundary. Avoids the
~40GB logprobs tensor allocation that OOM'd on full contexts.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
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>
/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>
score_memories() drops each memory from the context one at a time,
runs prompt_logprobs against the full conversation, and builds a
divergence matrix: memories × responses.
Row sums = memory importance (for graph weight updates)
Column sums = response memory-dependence (training candidates)
Uses vLLM's prompt_logprobs to check "would the model have said
this without this memory?" — one forward pass per memory, all
responses scored at once. ~3s per memory on B200.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Delete subconscious/transcript.rs (94 lines), is_segment_mined,
mark_segment_mined — all orphaned by the extraction pipeline removal.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Delete enrich.rs (conversation extraction), select_conversation_fragments,
mark_observation_done, format_segment, and the {{conversations}} placeholder.
Transcript processing is handled by observe/journal agents now.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Session mining, stale session detection, is_file_open /proc scan,
segment extraction, and fact mining are all replaced by the
observe/journal agents. Remove the entire session-watcher thread,
find_stale_sessions(), is_file_open(), MIN_SESSION_BYTES, and
SESSION_STALE_SECS. -329 lines.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
The install_hook() function is about hook infrastructure setup, not daemon
runtime. Move it to hook.rs where it belongs alongside the hook execution
logic.
- Move install_hook() from daemon.rs to hook.rs
- Update caller in daemon.rs to use crate::subconscious:🪝:install_hook()
- Update caller in cli/admin.rs to use crate::subconscious:🪝:install_hook()
This improves module boundaries: daemon.rs now only contains daemon runtime
and admin commands, while hook.rs contains all hook-related functionality.
prompts_dir now defaults to ~/.consciousness/prompts instead of
hardcoded repo path. Function pointer cast goes through *const ()
to silence the compiler warning.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Four expect("HOME not set") calls in config.rs and one unwrap()
in admin.rs would panic if HOME wasn't set. Use dirs::home_dir()
consistently for portability.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>