diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py
index 2a210434949b..8e061f831b8e 100644
--- a/agent/prompt_builder.py
+++ b/agent/prompt_builder.py
@@ -350,7 +350,13 @@ def _strip_yaml_frontmatter(content: str) -> str:
),
"cli": (
"You are a CLI AI Agent. Try not to use markdown but simple text "
- "renderable inside a terminal."
+ "renderable inside a terminal. "
+ "File delivery: there is no attachment channel — the user reads your "
+ "response directly in their terminal. Do NOT emit MEDIA:/path tags "
+ "(those are only intercepted on messaging platforms like Telegram, "
+ "Discord, Slack, etc.; on the CLI they render as literal text). "
+ "When referring to a file you created or changed, just state its "
+ "absolute path in plain text; the user can open it from there."
),
"sms": (
"You are communicating via SMS. Keep responses concise and use plain text "
diff --git a/hermes_cli/model_normalize.py b/hermes_cli/model_normalize.py
index 76dace065a3a..b1781162c5d5 100644
--- a/hermes_cli/model_normalize.py
+++ b/hermes_cli/model_normalize.py
@@ -408,6 +408,23 @@ def normalize_model_for_provider(model_input: str, target_provider: str) -> str:
return bare
return _normalize_for_deepseek(bare)
+ # --- Kimi / Moonshot: map auto-discovered short IDs (k2p6) to API-accepted
+ # canonical names (kimi-k2.6). The /models endpoint returns internal
+ # short forms that fail at request time without this repair (issue #13758).
+ if provider in {"kimi-coding", "kimi-coding-cn", "moonshot"}:
+ bare = _strip_matching_provider_prefix(name, provider)
+ if "/" in bare:
+ bare = bare.split("/", 1)[1]
+ # k2p6 -> kimi-k2.6, k2p5 -> kimi-k2.5, etc.
+ _kimi_short_map = {
+ "k2p6": "kimi-k2.6",
+ "k2p5": "kimi-k2.5",
+ "k2p8": "kimi-k2.8",
+ }
+ if bare.lower() in _kimi_short_map:
+ return _kimi_short_map[bare.lower()]
+ return bare
+
# --- Direct providers: repair matching provider prefixes only ---
if provider in _MATCHING_PREFIX_STRIP_PROVIDERS:
return _strip_matching_provider_prefix(name, provider)
diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py
index 36b3c7f3f395..521e891e7e03 100644
--- a/hermes_cli/tools_config.py
+++ b/hermes_cli/tools_config.py
@@ -80,12 +80,20 @@ def _get_effective_configurable_toolsets():
Plugin toolsets are appended at the end so they appear after the
built-in toolsets in the TUI checklist.
+ Duplicate keys (plugin toolsets whose key already exists in
+ CONFIGURABLE_TOOLSETS) are skipped so the built-in row is kept —
+ plugin-added tools are extensions of that toolset, not a second
+ top-level row (issue #13640).
"""
result = list(CONFIGURABLE_TOOLSETS)
+ built_in_keys = {ts_key for ts_key, _, _ in CONFIGURABLE_TOOLSETS}
try:
from hermes_cli.plugins import discover_plugins, get_plugin_toolsets
discover_plugins() # idempotent — ensures plugins are loaded
- result.extend(get_plugin_toolsets())
+ plugin_toolsets = get_plugin_toolsets()
+ # Skip plugin toolsets whose key already exists in built-ins
+ plugin_toolsets = [(k, l, d) for k, l, d in plugin_toolsets if k not in built_in_keys]
+ result.extend(plugin_toolsets)
except Exception:
pass
return result
diff --git a/tests/agent/test_prompt_builder.py b/tests/agent/test_prompt_builder.py
index 0962060313bb..11712b95192d 100644
--- a/tests/agent/test_prompt_builder.py
+++ b/tests/agent/test_prompt_builder.py
@@ -789,6 +789,24 @@ def test_platform_hints_known_platforms(self):
assert "cron" in PLATFORM_HINTS
assert "cli" in PLATFORM_HINTS
+ def test_cli_hint_does_not_suggest_media_tags(self):
+ # Regression: MEDIA:/path tags are intercepted only by messaging
+ # gateway platforms. On the CLI they render as literal text and
+ # confuse users. The CLI hint must steer the agent away from them.
+ cli_hint = PLATFORM_HINTS["cli"]
+ assert "MEDIA:" in cli_hint, (
+ "CLI hint should mention MEDIA: in order to tell the agent "
+ "NOT to use it (negative guidance)."
+ )
+ # Must contain explicit "don't" language near the MEDIA reference.
+ assert any(
+ marker in cli_hint.lower()
+ for marker in ("do not emit media", "not intercepted", "do not", "don't")
+ ), "CLI hint should explicitly discourage MEDIA: tags."
+ # Messaging hints should still advertise MEDIA: positively (sanity
+ # check that this test is calibrated correctly).
+ assert "include MEDIA:" in PLATFORM_HINTS["telegram"]
+
# =========================================================================
# Environment hints
diff --git a/ui-tui/src/components/appChrome.tsx b/ui-tui/src/components/appChrome.tsx
index 28f7b324e2f9..f7d2aee19832 100644
--- a/ui-tui/src/components/appChrome.tsx
+++ b/ui-tui/src/components/appChrome.tsx
@@ -131,7 +131,10 @@ export function StatusRule({
) : (
{status}
)}
- │ {model}
+ │
+
+ {model}
+
{ctxLabel ? │ {ctxLabel} : null}
{bar ? (