Commit graph

16 commits

Author SHA1 Message Date
Kent Overstreet
d4331e80f5 user: share candidate-browser helpers between F6/F7
F6 (learn) and F7 (compare) were duplicating the candidate-screen
skeleton: outer magenta-bordered block with screen legend + title,
settings row / content / help vertical split, 40/60 list/detail
horizontal split, j/k/↑/↓ nav with bounds clamping.

Factor out three helpers in user/widgets.rs:

  candidate_frame(frame, area, title) -> (settings, content, help)
  list_detail_split(content) -> (list, detail)
  handle_list_nav(events, list_state, count, on_other)

Callers provide screen-specific content — settings line, empty state,
per-candidate list item, detail pane, help line, extra key bindings —
and the helpers absorb the common framing.

Net change is small in lines (-13 src) but removes the
copy-paste-and-tweak trap: F8/F9/whatever-next-screen now starts from
these three calls instead of a copy of learn.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-17 16:22:30 -04:00
Kent Overstreet
4603947506 Display memory scores in status column
Move score display from name (via label()) to status column for cleaner
layout. Score now appears right of tokens for all memory nodes.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-15 06:08:27 -04:00
ProofOfConcept
e17118e4c9 Convert SectionTree and all remaining callers to ScrollPane
SectionTree.scroll is now a ScrollPaneState. All callers of
render_scrollable replaced with ScrollPane::render_stateful_widget.

Deleted render_scrollable and its imports — no hand-rolled scroll
rendering remains outside of scroll_pane.rs.

Co-Authored-By: Kent Overstreet <kent.overstreet@gmail.com>
2026-04-11 01:42:49 -04:00
ProofOfConcept
2230fdf3c1 user: remove dead scroll state from thalamus and unconscious screens
Both had scroll: u16 fields that were never connected to any key
handling or rendering. The unconscious screen renders fixed-size
graph health gauges; thalamus builds a paragraph but never scrolled
it. Neither needs scroll state.

Co-Authored-By: Kent Overstreet <kent.overstreet@gmail.com>
2026-04-11 01:35:15 -04:00
ProofOfConcept
b116b3536e Widen name column on F2 conscious screen
Memory node keys were running into the token count column. Bump the
name column from 40 to 70 characters.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-09 21:13:56 -04:00
Kent Overstreet
1b6664ee1c Fix: skip empty CoT nodes, expand AST children in conscious screen, timestamps
Parser skips Thinking nodes that are just whitespace. Conscious screen
now shows assistant children (Content, Thinking, ToolCall) as nested
tree items via recursive node_to_view. Nodes get timestamped in
push_node and on assistant branch creation.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 17:18:48 -04:00
Kent Overstreet
bf3e2a9b73 WIP: Rename context_new → context, delete old files, fix UI layer
Renamed context_new.rs to context.rs, deleted context_old.rs,
types.rs, openai.rs, parsing.rs. Updated all imports. Rewrote
user/context.rs and user/widgets.rs for new types. Stubbed
working_stack tool. Killed tokenize_conv_entry.

Remaining: mind/mod.rs, mind/dmn.rs, learn.rs, chat.rs,
subconscious.rs, oneshot.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 15:20:26 -04:00
Kent Overstreet
5e4067c04f Replace token counting with token generation via HuggingFace tokenizer
Add agent/tokenizer.rs with global Qwen 3.5 tokenizer that generates
actual token IDs including chat template wrapping. ContextEntry now
stores token_ids: Vec<u32> instead of tokens: usize — the count is
derived from the length.

ContextEntry::new() tokenizes automatically via the global tokenizer.
ContextSection::push_entry() takes a raw ConversationEntry and
tokenizes it. set_message() re-tokenizes without needing an external
tokenizer parameter.

Token IDs include the full chat template: <|im_start|>role\ncontent
<|im_end|>\n — so concatenating token_ids across entries produces a
ready-to-send prompt for vLLM's /v1/completions endpoint.

The old tiktoken CoreBPE is now unused on Agent (will be removed in
a followup). Token counts are now exact for Qwen 3.5 instead of the
~85-90% approximation from cl100k_base.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:20:03 -04:00
Kent Overstreet
e0ee441aec Add ConversationEntry::Thinking — 0 tokens, not sent to API
Thinking/reasoning content is now a first-class entry type:
- Serialized as {"thinking": "..."} in conversation log
- 0 tokens for budgeting (doesn't count against context window)
- Filtered from assemble_api_messages (not sent back to model)
- Displayed in UI with "thinking: ..." label and expandable content

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:46:06 -04:00
Kent Overstreet
c7c69a8f06 Add status column to context tree with tab-stop alignment
SectionView gains a status field for extra info displayed after the
token count column. Memory nodes section shows "N scored, M unscored"
in the status column instead of burying it in the title.

Renderer uses fixed-width columns (40 name, 16 tokens, status) for
consistent alignment across sections.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:13:27 -04:00
Kent Overstreet
07b400c95c Restore context tree display with SectionView UI type
Introduced SectionView {name, tokens, content, children} as a
UI-only tree node, separate from the data ContextSection. The widget
SectionTree renders SectionView with the old recursive expand/collapse
behavior — children for sub-sections, content for text expansion.

section_to_view() converts data sections to UI views, using
ConversationEntry::label() for names and content_text() for
expandable content.

read_context_views() builds the same tree the old context_state_summary
did: System, Identity, Journal, Memory nodes (scored/unscored counts,
expandable to show content), Conversation entries.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:06:10 -04:00
Kent Overstreet
a20f3e3642 Restore entry labels in context tree: role, tool calls, memory keys
ConversationEntry::label() provides descriptive labels matching the
old entry_sections format:
- "Kent: what about..." / "Aria: [tool_call: memory_search, ...]"
- "mem: [memory: key-name score:0.73]"
- "dmn: [heartbeat]" / "system: [system prompt]"

Uses config names (assistant_name, user_name) not generic "asst"/"user".
Widget renderer uses label() instead of raw content preview.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 21:04:41 -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
578be807e7 Add expand/collapse all, per-pane key legends
SectionTree:
- 'e': expand all nodes
- 'c': collapse all nodes
- Home/End already wired from previous commit

Key legend shown at bottom border of each focused pane:
- Tree panes: nav, expand/collapse, expand/collapse all, paging
- Agent list: select, tab
- History: scroll, paging

Legend only appears on the focused pane to avoid clutter.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:09:04 -04:00
Kent Overstreet
19bb6d02e3 Fix scroll: PgUp/PgDn move cursor in place, add Scrollbar widget
SectionTree.handle_nav() now takes viewport height:
- PgUp/PgDn move both cursor and viewport by one page, keeping the
  cursor at the same screen position
- Home/End jump to first/last item
- scroll_to_selected() uses actual viewport height instead of
  hardcoded 30

Added render_scrollable() in widgets.rs: renders a Paragraph with a
vertical Scrollbar when content exceeds the viewport. Used by the
conscious and subconscious screens.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:07:00 -04:00
Kent Overstreet
818cdcc4e5 Three-pane subconscious debug screen with shared widgets
New layout for F3 screen:
- Top-left: agent list using ratatui List widget with ListState
- Middle-left: expandable agent state (persistent across runs)
- Bottom-left: memory store activity by provenance, walked keys
- Right: context tree from fork point, reusing SectionTree

Tab/Shift-Tab cycles focus clockwise between panes; focused pane
gets white border. Each pane handles its own input when focused.

Extracted user/widgets.rs:
- SectionTree (moved from mod.rs): expand/collapse tree for ContextSection
- pane_block_focused(): standard bordered block with focus indicator
- format_age()/format_ts_age(): shared duration formatting

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:03:14 -04:00