fix(honcho): don't let auto-generated session titles override sessionStrategy
Auto-generated display titles (LLM or derived) were passed to Honcho's resolve_session_name() as authoritative, so a titled per-repo, per-directory, or global session silently remapped onto a second Honcho session named after the generated title. Only explicit /title commands (user provenance) should act as an intentional session-name override. Thread session_title_source from the session DB through agent_init into the Honcho provider, and skip title-based remapping when the source is 'derived' or 'llm'. Missing provenance keeps the legacy explicit-title behavior for callers that predate source threading. Gateway per-chat keys and per-session identity safeguards are unchanged. Adds regressions for titled per-repo, per-directory, and global sessions at both the resolver and provider level. Fixes #24740 (cherry picked from commit e7ba26ee15821baa382a397ce9ce9cd57a260188)
This commit is contained in:
@@ -273,15 +273,21 @@ The Honcho session name determines which conversation bucket memory lands in. Re
|
||||
|
||||
| Priority | Source | Example session name |
|
||||
|----------|--------|---------------------|
|
||||
| 1 | Manual map (`sessions` config) | `"myproject-main"` |
|
||||
| 2 | `/title` command (mid-session rename) | `"refactor-auth"` |
|
||||
| 3 | Gateway session key (Telegram, Discord, etc.) | `"agent-main-telegram-dm-8439114563"` |
|
||||
| 4 | `per-session` strategy | Hermes session ID (`20260415_a3f2b1`) |
|
||||
| 1 | Gateway session key (Telegram, Discord, etc.) | `"agent-main-telegram-dm-8439114563"` |
|
||||
| 2 | `per-session` strategy | Hermes session ID (`20260415_a3f2b1`) |
|
||||
| 3 | Manual map (`sessions` config) | `"myproject-main"` |
|
||||
| 4 | Explicit `/title` command (non-automatic title) | `"refactor-auth"` |
|
||||
| 5 | `per-repo` strategy | Git root directory name (`hermes-agent`) |
|
||||
| 6 | `per-directory` strategy | Current directory basename (`src`) |
|
||||
| 7 | `global` strategy | Workspace name (`hermes`) |
|
||||
| 6 | `per-directory` strategy | Directory basename (`my-project`) |
|
||||
| 7 | `global` strategy | Workspace name |
|
||||
|
||||
Gateway platforms always resolve via priority 3 (per-chat isolation) regardless of `sessionStrategy`. The strategy setting only affects CLI sessions.
|
||||
Messaging gateway platforms always resolve via priority 1 (per-chat isolation) regardless of `sessionStrategy`. The strategy setting controls non-gateway sessions such as CLI and Desktop.
|
||||
|
||||
Directory strategies and manual mappings use the logical session workspace, not the backend process's launch directory. Desktop/TUI and ACP pass the workspace during agent construction; deferred Desktop/TUI builds use the same session cwd. With no non-empty construction cwd, Honcho uses the runtime resolver: session cwd context, scoped `terminal.cwd`, then the launch directory. No process-wide `chdir` is needed.
|
||||
|
||||
Automatically generated Hermes titles (`derived` or `llm`) are display metadata and do not override `sessionStrategy`. An explicit user title remains an intentional session-name override for non-gateway, non-`per-session` sessions.
|
||||
|
||||
Sessions created before title provenance was recorded retain legacy behavior: because an old automatic title cannot be distinguished from an old user title, a title with no source is treated as an explicit override.
|
||||
|
||||
If `sessionPeerPrefix` is `true`, the user peer name is prepended: `alice-hermes-agent`.
|
||||
|
||||
@@ -293,7 +299,7 @@ In bot mode another Hermes profile can DM this agent. The relay marks that turn
|
||||
|
||||
#### What each strategy produces
|
||||
|
||||
- **`per-directory`** — basename of `$PWD`. Opening hermes in `~/code/myapp` and `~/code/other` gives two separate sessions. Same directory = same session across runs.
|
||||
- **`per-directory`** — basename of the logical session working directory. Opening Hermes in `~/code/myapp` and `~/code/other` gives two separate sessions. Same directory = same session across runs.
|
||||
- **`per-repo`** — git root directory name. All subdirectories within a repo share one session. Falls back to `per-directory` if not inside a git repo.
|
||||
- **`per-session`** — Hermes session ID (timestamp + hex). Every `hermes` invocation starts a fresh Honcho session. Falls back to `per-directory` if no session ID is available.
|
||||
- **`global`** — workspace name. One session for everything. Memory accumulates across all directories and runs.
|
||||
|
||||
@@ -277,6 +277,7 @@ class HonchoMemoryProvider(DialecticMixin, MemoryProvider):
|
||||
"""Resolve the Honcho session key without touching the network."""
|
||||
return cfg.resolve_session_name(
|
||||
session_title=kwargs.get("session_title"), session_id=session_id,
|
||||
session_title_source=kwargs.get("session_title_source"),
|
||||
gateway_session_key=kwargs.get("gateway_session_key"),
|
||||
) or session_id or "hermes-default"
|
||||
|
||||
|
||||
@@ -488,6 +488,7 @@ class HonchoClientConfig:
|
||||
def resolve_session_name(
|
||||
self, cwd: str | None = None, session_title: str | None = None,
|
||||
session_id: str | None = None, gateway_session_key: str | None = None,
|
||||
session_title_source: str | None = None,
|
||||
) -> str | None:
|
||||
"""Resolve the Honcho session name; with ``session_ai_peer_prefix`` the result is prefixed
|
||||
``{ai_peer}-`` on every path, including the AI-peer-agnostic gateway session key."""
|
||||
@@ -523,7 +524,9 @@ class HonchoClientConfig:
|
||||
manual = self.sessions.get(cwd)
|
||||
if manual:
|
||||
return manual
|
||||
if session_title and _slug(session_title):
|
||||
# Absent provenance retains the legacy explicit-title override. Generated
|
||||
# display titles must not change a strategy-selected memory identity.
|
||||
if session_title and session_title_source not in {"derived", "llm"} and _slug(session_title):
|
||||
return self._with_peer_prefix(_slug(session_title))
|
||||
if self.session_strategy == "per-repo":
|
||||
return self._with_peer_prefix(self._git_repo_name(cwd) or Path(cwd).name)
|
||||
|
||||
Reference in New Issue
Block a user