Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
74c214e
feat(honcho): async memory integration with prefetch pipeline and rec…
erosika Mar 9, 2026
b4af03a
fix(honcho): clarify API key signup instructions
erosika Mar 9, 2026
6782249
fix(honcho): rewrite tokens and peer CLI help for clarity
erosika Mar 9, 2026
c1228e9
refactor(honcho): rename recallMode "auto" to "hybrid"
erosika Mar 9, 2026
792be0e
feat(honcho): add honcho_conclude tool for writing facts back to memory
erosika Mar 9, 2026
0cb639d
refactor(honcho): rename query_user_context to honcho_context
erosika Mar 9, 2026
c047c03
feat(honcho): honcho_context can query any peer (user or ai)
erosika Mar 9, 2026
87cc528
fix(honcho): enforce local mode and cache-safe warmup
adavyas Mar 10, 2026
87349b9
fix(gateway): persist Honcho managers across session requests
adavyas Mar 10, 2026
960c152
docs(honcho): rewrite Honcho Memory docs as full feature documentation
erosika Mar 10, 2026
5489c66
docs(honcho): restore use cases, example queries, and configurability…
erosika Mar 10, 2026
c90ba02
refactor(honcho): write all host-scoped settings into hosts block
erosika Mar 10, 2026
4c54c27
Revert "refactor(honcho): write all host-scoped settings into hosts b…
erosika Mar 10, 2026
047b118
fix(honcho): resolve review blockers for merge
erosika Mar 11, 2026
a0b0dbe
Merge remote-tracking branch 'origin/main' into feat/honcho-async-memory
erosika Mar 11, 2026
d987ff5
fix: change session_strategy default from per-directory to per-session
erosika Mar 11, 2026
3c81353
fix(honcho): scope config writes to hosts.hermes, not root
erosika Mar 11, 2026
8cddcfa
docs(honcho): update config docs for host-scoped write convention
erosika Mar 11, 2026
2d35016
fix(honcho): harden tool gating and migration peer routing
erosika Mar 11, 2026
cd6e5e4
feat(honcho): show clickable session line on CLI startup
erosika Mar 12, 2026
f896bb5
fix(test): patch correct method in subagent interrupt test
erosika Mar 12, 2026
ae2a5e5
refactor(honcho): remove local memory mode
erosika Mar 12, 2026
0aed9bf
refactor(honcho): rename memory tools to Honcho tools, clarify recall…
erosika Mar 12, 2026
45d3e83
fix(honcho): normalize legacy recallMode values like 'auto' to 'hybrid'
erosika Mar 12, 2026
fefc709
merge: resolve conflict with main in subagent interrupt test
erosika Mar 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ Activate with `/skin cyberpunk` or `display.skin: cyberpunk` in config.yaml.
---

## Important Policies

### Prompt Caching Must Not Break

Hermes-Agent ensures caching remains valid throughout a conversation. **Do NOT implement changes that would:**
Expand Down
43 changes: 43 additions & 0 deletions agent/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,46 @@ def _wrap(line: str) -> str:

preview = build_tool_preview(tool_name, args) or ""
return _wrap(f"┊ ⚡ {tool_name[:9]:9} {_trunc(preview, 35)} {dur}")


# =========================================================================
# Honcho session line (one-liner with clickable OSC 8 hyperlink)
# =========================================================================

_DIM = "\033[2m"
_SKY_BLUE = "\033[38;5;117m"
_ANSI_RESET = "\033[0m"


def honcho_session_url(workspace: str, session_name: str) -> str:
"""Build a Honcho app URL for a session."""
from urllib.parse import quote
return (
f"https://app.honcho.dev/explore"
f"?workspace={quote(workspace, safe='')}"
f"&view=sessions"
f"&session={quote(session_name, safe='')}"
)


def _osc8_link(url: str, text: str) -> str:
"""OSC 8 terminal hyperlink (clickable in iTerm2, Ghostty, WezTerm, etc.)."""
return f"\033]8;;{url}\033\\{text}\033]8;;\033\\"


def honcho_session_line(workspace: str, session_name: str) -> str:
"""One-line session indicator: `Honcho session: <clickable name>`."""
url = honcho_session_url(workspace, session_name)
linked_name = _osc8_link(url, f"{_SKY_BLUE}{session_name}{_ANSI_RESET}")
return f"{_DIM}Honcho session:{_ANSI_RESET} {linked_name}"


def write_tty(text: str) -> None:
"""Write directly to /dev/tty, bypassing stdout capture."""
try:
fd = os.open("/dev/tty", os.O_WRONLY)
os.write(fd, text.encode("utf-8"))
os.close(fd)
except OSError:
sys.stdout.write(text)
sys.stdout.flush()
1 change: 1 addition & 0 deletions cli-config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ display:
# all: Running output updates + final message (default)
background_process_notifications: all


# Play terminal bell when agent finishes a response.
# Useful for long-running tasks — your terminal will ding when the agent is done.
# Works over SSH. Most terminals can be configured to flash the taskbar or play a sound.
Expand Down
53 changes: 50 additions & 3 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,7 @@ def _init_agent(self) -> bool:
session_db=self._session_db,
clarify_callback=self._clarify_callback,
reasoning_callback=self._on_reasoning if self.show_reasoning else None,
honcho_session_key=self.session_id,
honcho_session_key=None, # resolved by run_agent via config sessions map / title
fallback_model=self._fallback_model,
thinking_callback=self._on_thinking,
checkpoints_enabled=self.checkpoints_enabled,
Expand Down Expand Up @@ -2739,6 +2739,28 @@ def process_command(self, command: str) -> bool:
try:
if self._session_db.set_session_title(self.session_id, new_title):
_cprint(f" Session title set: {new_title}")
# Re-map Honcho session key to new title
if self.agent and getattr(self.agent, '_honcho', None):
try:
hcfg = self.agent._honcho_config
new_key = (
hcfg.resolve_session_name(
session_title=new_title,
session_id=self.agent.session_id,
)
if hcfg else new_title
)
if new_key and new_key != self.agent._honcho_session_key:
old_key = self.agent._honcho_session_key
self.agent._honcho.get_or_create(new_key)
self.agent._honcho_session_key = new_key
from tools.honcho_tools import set_session_context
set_session_context(self.agent._honcho, new_key)
from agent.display import honcho_session_line, write_tty
write_tty(honcho_session_line(hcfg.workspace_id, new_key) + "\n")
_cprint(f" Honcho session: {old_key} → {new_key}")
except Exception:
pass
else:
_cprint(" Session not found in database.")
except ValueError as e:
Expand Down Expand Up @@ -3207,6 +3229,12 @@ def _manual_compress(self):
f" ✅ Compressed: {original_count} → {new_count} messages "
f"(~{approx_tokens:,} → ~{new_tokens:,} tokens)"
)
# Flush Honcho async queue so queued messages land before context resets
if self.agent and getattr(self.agent, '_honcho', None):
try:
self.agent._honcho.flush_all()
except Exception:
pass
except Exception as e:
print(f" ❌ Compression failed: {e}")

Expand Down Expand Up @@ -3657,6 +3685,7 @@ def run_agent():
if response and pending_message:
response = response + "\n\n---\n_[Interrupted - processing new message]_"

response_previewed = result.get("response_previewed", False) if result else False
# Display reasoning (thinking) box if enabled and available
if self.show_reasoning and result:
reasoning = result.get("last_reasoning")
Expand All @@ -3675,7 +3704,7 @@ def run_agent():
display_reasoning = reasoning.strip()
_cprint(f"\n{r_top}\n{_DIM}{display_reasoning}{_RST}\n{r_bot}")

if response:
if response and not response_previewed:
# Use a Rich Panel for the response box — adapts to terminal
# width at render time instead of hard-coding border length.
try:
Expand All @@ -3696,7 +3725,7 @@ def run_agent():
box=rich_box.HORIZONTALS,
padding=(1, 2),
))

# Play terminal bell when agent finishes (if enabled).
# Works over SSH — the bell propagates to the user's terminal.
if self.bell_on_complete:
Expand Down Expand Up @@ -3754,6 +3783,18 @@ def run(self):
"""Run the interactive CLI loop with persistent input at bottom."""
self.show_banner()

# One-line Honcho session indicator (TTY-only, not captured by agent)
try:
from honcho_integration.client import HonchoClientConfig
from agent.display import honcho_session_line, write_tty
hcfg = HonchoClientConfig.from_global_config()
if hcfg.enabled:
sname = hcfg.resolve_session_name(session_id=self.session_id)
if sname:
write_tty(honcho_session_line(hcfg.workspace_id, sname) + "\n")
except Exception:
pass

# If resuming a session, load history and display it immediately
# so the user has context before typing their first message.
if self._resumed:
Expand Down Expand Up @@ -4663,6 +4704,12 @@ def process_loop():
# Unregister terminal_tool callbacks to avoid dangling references
set_sudo_password_callback(None)
set_approval_callback(None)
# Flush + shut down Honcho async writer (drains queue before exit)
if self.agent and getattr(self.agent, '_honcho', None):
try:
self.agent._honcho.shutdown()
except Exception:
pass
# Close session in SQLite
if hasattr(self, '_session_db') and self._session_db and self.agent:
try:
Expand Down
Loading
Loading