Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion acp_adapter/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ def _format_session_search_result(result: Optional[str]) -> Optional[str]:
return None
mode = data.get("mode") or "search"
query = data.get("query")
lines = ["Recent sessions" if mode == "recent" else f"Session search results" + (f" for `{query}`" if query else "")]
lines = ["Recent sessions" if mode == "recent" else "Session search results" + (f" for `{query}`" if query else "")]
if not results:
lines.append(str(data.get("message") or "No matching sessions found."))
return "\n".join(lines)
Expand Down
16 changes: 8 additions & 8 deletions agent/conversation_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,7 @@ def _perform_api_call(next_api_kwargs):
elif _resp_error_code == 504:
_failure_hint = f"upstream gateway timeout (504, {api_duration:.0f}s)"
elif _resp_error_code == 429:
_failure_hint = f"rate limited by upstream provider (429)"
_failure_hint = "rate limited by upstream provider (429)"
elif _resp_error_code in {500, 502}:
_failure_hint = f"upstream server error ({_resp_error_code}, {api_duration:.0f}s)"
elif _resp_error_code in {503, 529}:
Expand Down Expand Up @@ -2350,11 +2350,11 @@ def _perform_api_call(next_api_kwargs):
agent._unicode_sanitization_passes += 1
if _surrogates_found:
agent._buffer_vprint(
f"⚠️ Stripped invalid surrogate characters from messages. Retrying..."
"⚠️ Stripped invalid surrogate characters from messages. Retrying..."
)
else:
agent._buffer_vprint(
f"⚠️ Surrogate encoding error — retrying after full-payload sanitization..."
"⚠️ Surrogate encoding error — retrying after full-payload sanitization..."
)
continue
if _is_ascii_codec:
Expand Down Expand Up @@ -2761,7 +2761,7 @@ def _perform_api_call(next_api_kwargs):
):
_retry.copilot_auth_retry_attempted = True
if agent._try_refresh_copilot_client_credentials():
agent._buffer_vprint(f"🔐 Copilot credentials refreshed after 401. Retrying request...")
agent._buffer_vprint("🔐 Copilot credentials refreshed after 401. Retrying request...")
continue
if (
agent.api_mode == "anthropic_messages"
Expand Down Expand Up @@ -2984,10 +2984,10 @@ def _perform_api_call(next_api_kwargs):
)
if agent.providers_allowed:
agent._buffer_vprint(
f" Your provider_routing.only restriction is filtering out tool-capable providers."
" Your provider_routing.only restriction is filtering out tool-capable providers."
)
agent._buffer_vprint(
f" Try removing the restriction or adding providers that support tools for this model."
" Try removing the restriction or adding providers that support tools for this model."
)
agent._buffer_vprint(
f" Check which providers support tools: https://openrouter.ai/models/{_model}"
Expand Down Expand Up @@ -4314,7 +4314,7 @@ def _perform_api_call(next_api_kwargs):
if has_incomplete_scratchpad(assistant_message.content or ""):
agent._incomplete_scratchpad_retries += 1

agent._buffer_vprint(f"⚠️ Incomplete <REASONING_SCRATCHPAD> detected (opened but never closed)")
agent._buffer_vprint("⚠️ Incomplete <REASONING_SCRATCHPAD> detected (opened but never closed)")

if agent._incomplete_scratchpad_retries <= 2:
agent._buffer_vprint(f"🔄 Retrying API call ({agent._incomplete_scratchpad_retries}/2)...")
Expand Down Expand Up @@ -4549,7 +4549,7 @@ def _perform_api_call(next_api_kwargs):
else:
# Instead of returning partial, inject tool error results so the model can recover.
# Using tool results (not user messages) preserves role alternation.
agent._buffer_vprint(f"⚠️ Injecting recovery tool results for invalid JSON...")
agent._buffer_vprint("⚠️ Injecting recovery tool results for invalid JSON...")
agent._invalid_json_retries = 0 # Reset for next attempt

# Append the assistant message with its (broken) tool_calls
Expand Down
2 changes: 1 addition & 1 deletion agent/curator_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ def rollback(backup_id: Optional[str] = None) -> Tuple[bool, str, Optional[Path]
if target is None:
return (
False,
f"no matching backup found"
"no matching backup found"
+ (f" for id '{backup_id}'" if backup_id else "")
+ " (use `hermes curator rollback --list` to see available snapshots)",
None,
Expand Down
2 changes: 1 addition & 1 deletion agent/lsp/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async def read_message(reader: asyncio.StreamReader) -> Optional[dict]:
header_bytes += len(line)
if header_bytes > 8192:
raise LSPProtocolError(
f"LSP header block exceeded 8 KiB without terminator"
"LSP header block exceeded 8 KiB without terminator"
)
line = line[:-2] # strip CRLF
if not line:
Expand Down
2 changes: 1 addition & 1 deletion agent/pet/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ def _encode_iterm(frame, *, cell_cols: int | None = None, cell_rows: int | None
"""Encode one frame as an iTerm2 inline image (OSC 1337 File)."""
payload = base64.standard_b64encode(_png_bytes(frame)).decode("ascii")
size = len(payload)
args = [f"inline=1", f"size={size}", "preserveAspectRatio=1"]
args = ["inline=1", f"size={size}", "preserveAspectRatio=1"]
if cell_cols:
args.append(f"width={cell_cols}")
if cell_rows:
Expand Down
4 changes: 2 additions & 2 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10048,8 +10048,8 @@ def _billing_poll_charge(self, state, charge_id, amount):
_time.sleep(interval)

# Past the cap with no terminal state = timeout (not an error).
print(f" 🟡 Still processing after 5 minutes — this is a timeout, not a "
f"failure. Check /billing or the portal shortly.")
print(" 🟡 Still processing after 5 minutes — this is a timeout, not a "
"failure. Check /billing or the portal shortly.")
self._billing_portal_hint(state)

def _billing_render_charge_failed(self, state, reason):
Expand Down
2 changes: 1 addition & 1 deletion gateway/platforms/qqbot/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2677,7 +2677,7 @@ async def send_exec_approval(

req = ApprovalRequest(
session_key=session_key,
title=f"Execute this command?",
title="Execute this command?",
description=description,
command_preview=command,
timeout_sec=self._APPROVAL_TIMEOUT_SECONDS,
Expand Down
6 changes: 3 additions & 3 deletions hermes_cli/auth_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ def _interactive_auth() -> None:
if has_aws_credentials():
auth_source = resolve_aws_auth_env_var() or "unknown"
region = resolve_bedrock_region()
print(f"bedrock (AWS SDK credential chain):")
print("bedrock (AWS SDK credential chain):")
print(f" Auth: {auth_source}")
print(f" Region: {region}")
try:
Expand All @@ -546,7 +546,7 @@ def _interactive_auth() -> None:
arn = identity.get("Arn", "unknown")
print(f" Identity: {arn}")
except Exception:
print(f" Identity: (could not resolve — boto3 STS call failed)")
print(" Identity: (could not resolve — boto3 STS call failed)")
print()
except ImportError:
pass # boto3 or bedrock_adapter not available
Expand Down Expand Up @@ -574,7 +574,7 @@ def _interactive_auth() -> None:
str(_entra.get("scope") or "").strip()
or SCOPE_AI_AZURE_DEFAULT
)
print(f"azure-foundry (Microsoft Entra ID):")
print("azure-foundry (Microsoft Entra ID):")
print(f" Endpoint: {_base_url or '(not configured)'}")
print(f" Scope: {_scope}")
if not has_azure_identity_installed():
Expand Down
6 changes: 3 additions & 3 deletions hermes_cli/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ def run_backup(args) -> None:
print(f" {p}")

if skipped_dirs:
print(f"\n Excluded directories:")
print("\n Excluded directories:")
for d in sorted(skipped_dirs):
print(f" {d}/")

Expand Down Expand Up @@ -721,8 +721,8 @@ def run_import(args) -> None:
except ImportError:
# hermes_cli.profiles might not be available (fresh install)
if any(profiles_dir.iterdir()):
print(f"\n Profiles detected but aliases could not be created.")
print(f" Run: hermes profile list (after installing hermes)")
print("\n Profiles detected but aliases could not be created.")
print(" Run: hermes profile list (after installing hermes)")

# Guidance
print()
Expand Down
6 changes: 3 additions & 3 deletions hermes_cli/cli_commands_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def _handle_handoff_command(self, cmd_original: str) -> bool:
home = gw_config.get_home_channel(platform)
if not home or not home.chat_id:
_cprint(f" No home channel configured for {platform_name}.")
_cprint(f" Set one with /sethome on the destination chat first.")
_cprint(" Set one with /sethome on the destination chat first.")
return True

# Refuse mid-turn: an in-flight agent run would race with the
Expand Down Expand Up @@ -626,7 +626,7 @@ def _handle_handoff_command(self, cmd_original: str) -> bool:
return True

_cprint(f" Queued handoff of '{session_title}' → {platform_name} (home: {home.name}).")
_cprint(f" Waiting for the gateway to pick it up...")
_cprint(" Waiting for the gateway to pick it up...")

# Poll-block on terminal state. Tick every 0.5s; bail at ~60s.
import time as _time
Expand Down Expand Up @@ -1872,7 +1872,7 @@ def _handle_browser_command(self, cmd: str):
sys_name = _plat.system()
chrome_cmd = manual_chrome_debug_command(_port, sys_name)
if chrome_cmd:
print(f" Launch a Chromium-family browser manually:")
print(" Launch a Chromium-family browser manually:")
print(f" {chrome_cmd}")
else:
print(" No supported Chromium-family browser executable found in this environment")
Expand Down
10 changes: 5 additions & 5 deletions hermes_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5282,8 +5282,8 @@ def warn_deprecated_cwd_env_vars(config: Optional[Dict[str, Any]] = None) -> Non
hint_path = os.environ.get("HERMES_HOME", "~/.hermes")
lines.insert(0, "\033[33m⚠ Deprecated .env settings detected:\033[0m")
lines.append(
f" \033[2mMove to config.yaml instead: "
f"terminal:\\n cwd: /your/project/path\033[0m"
" \033[2mMove to config.yaml instead: "
"terminal:\\n cwd: /your/project/path\033[0m"
)
lines.append(
f" \033[2mThen remove the old entries from {hint_path}/.env\033[0m"
Expand Down Expand Up @@ -5516,7 +5516,7 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
config["stt"] = stt
_persist_migration(config)
if not quiet:
print(f" ✓ Migrated legacy stt.model to provider-specific config")
print(" ✓ Migrated legacy stt.model to provider-specific config")

# ── Version 14 → 15: add explicit gateway interim-message gate ──
if current_ver < 15:
Expand Down Expand Up @@ -7210,8 +7210,8 @@ def _check_non_ascii_credential(key: str, value: str) -> str:
f"\n"
+ "\n".join(f" {line}" for line in bad_chars[:5])
+ ("\n ... and more" if len(bad_chars) > 5 else "")
+ f"\n\n The non-ASCII characters have been stripped automatically.\n"
f" If authentication fails, re-copy the key from the provider's dashboard.\n",
+ "\n\n The non-ASCII characters have been stripped automatically.\n"
" If authentication fails, re-copy the key from the provider's dashboard.\n",
file=sys.stderr,
)
return sanitized
Expand Down
6 changes: 3 additions & 3 deletions hermes_cli/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ def run_debug_share(args):

# Print results
label_width = max(len(k) for k in result.urls)
print(f"\nDebug report uploaded:")
print("\nDebug report uploaded:")
for label, url in result.urls.items():
print(f" {label:<{label_width}} {url}")

Expand All @@ -874,9 +874,9 @@ def run_debug_share(args):
print(f"\n⏱ Pastes will auto-delete in {hours} hours.")

# Manual delete fallback
print(f"To delete now: hermes debug delete <url>")
print("To delete now: hermes debug delete <url>")

print(f"\nShare these links with the Hermes team for support.")
print("\nShare these links with the Hermes team for support.")


_NOUS_PRIVACY_NOTICE = """\
Expand Down
2 changes: 1 addition & 1 deletion hermes_cli/dingtalk_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def dingtalk_qr_auth() -> Optional[Tuple[str, str]]:
print()

if not render_qr_to_terminal(url):
print_warning(f" QR code render failed, please open the link below to authorize:")
print_warning(" QR code render failed, please open the link below to authorize:")

print()
print_info(f" Or open this link manually: {url}")
Expand Down
2 changes: 1 addition & 1 deletion hermes_cli/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -3169,7 +3169,7 @@ def _require_service_installed(action: str, system: bool = False) -> None:
unit_path = get_systemd_unit_path(system=system)
if not unit_path.exists():
scope_flag = " --system" if system else ""
print(f"✗ Gateway service is not installed")
print("✗ Gateway service is not installed")
print(f" Run: {'sudo ' if system else ''}hermes gateway install{scope_flag}")
sys.exit(1)

Expand Down
10 changes: 5 additions & 5 deletions hermes_cli/kanban_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,11 @@ def _rule_hallucinated_cards(task, events, runs, now, cfg) -> list[Diagnostic]:
severity="error",
title="Worker claimed cards that don't exist",
detail=(
f"The completing worker declared created_cards that either didn't "
f"exist or weren't created by its profile. The completion was "
f"blocked and the task stayed in its prior state. "
f"Usually means the worker hallucinated ids instead of capturing "
f"return values from kanban_create."
"The completing worker declared created_cards that either didn't "
"exist or weren't created by its profile. The completion was "
"blocked and the task stayed in its prior state. "
"Usually means the worker hallucinated ids instead of capturing "
"return values from kanban_create."
),
actions=actions,
first_seen_at=first,
Expand Down
2 changes: 1 addition & 1 deletion hermes_cli/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def tail_log(
log_path = get_hermes_home() / "logs" / filename
if not log_path.exists():
print(f"Log file not found: {log_path}")
print(f"(Logs are created when Hermes runs — try 'hermes chat' first)")
print("(Logs are created when Hermes runs — try 'hermes chat' first)")
sys.exit(1)

# Parse --since into a datetime cutoff
Expand Down
22 changes: 11 additions & 11 deletions hermes_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8716,8 +8716,8 @@ def _run_pre_update_backup(args) -> None:

print(f" Saved: {display_path} ({size_str}, {elapsed:.1f}s)")
print(f" Restore: hermes import {out_path}")
print(f" Disable: omit --backup (backups are off by default)")
print(f" set updates.pre_update_backup: false in config.yaml")
print(" Disable: omit --backup (backups are off by default)")
print(" set updates.pre_update_backup: false in config.yaml")
print()


Expand Down Expand Up @@ -9537,7 +9537,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
"✗ Authentication failed — check your git credentials or SSH key."
)
else:
print(f"✗ Failed to fetch updates from origin.")
print("✗ Failed to fetch updates from origin.")
if stderr:
print(f" {stderr.splitlines()[0]}")
sys.exit(1)
Expand Down Expand Up @@ -9801,7 +9801,7 @@ def _cmd_update_impl(args, gateway_mode: bool):
print(
f" ℹ️ Local changes preserved in stash (ref: {auto_stash_ref})"
)
print(f" Restore manually with: git stash apply")
print(" Restore manually with: git stash apply")
elif discard_local_changes:
# Non-interactive update + user opted into discarding local
# source edits (updates.non_interactive_local_changes:
Expand Down Expand Up @@ -11150,7 +11150,7 @@ def cmd_profile(args):
try:
set_active_profile(name)
if name == "default":
print(f"Switched to: default (~/.hermes)")
print("Switched to: default (~/.hermes)")
else:
print(f"Switched to: {name}")
except (ValueError, FileNotFoundError) as e:
Expand Down Expand Up @@ -11239,9 +11239,9 @@ def cmd_profile(args):
if not _is_wrapper_dir_in_path():
print(f"\n⚠ {_get_wrapper_dir()} is not in your PATH.")
print(
f" Add to your shell config (~/.bashrc or ~/.zshrc):"
" Add to your shell config (~/.bashrc or ~/.zshrc):"
)
print(f' export PATH="$HOME/.local/bin:$PATH"')
print(' export PATH="$HOME/.local/bin:$PATH"')

# Profile dir for display
try:
Expand All @@ -11250,7 +11250,7 @@ def cmd_profile(args):
profile_dir_display = str(profile_dir)

# Next steps
print(f"\nNext steps:")
print("\nNext steps:")
print(f" {name} setup Configure API keys and model")
print(f" {name} chat Start chatting")
print(f" {name} gateway start Start the messaging gateway")
Expand All @@ -11261,7 +11261,7 @@ def cmd_profile(args):
print(
f"\n ⚠ This profile has no API keys yet. Run '{name} setup' first,"
)
print(f" or it will inherit keys from your shell environment.")
print(" or it will inherit keys from your shell environment.")
print(f" Edit {profile_dir_display}/SOUL.md to customize personality")
print()

Expand Down Expand Up @@ -12559,7 +12559,7 @@ def cmd_memory(args):
)
return

print(f"\n This will permanently erase the following memory files:")
print("\n This will permanently erase the following memory files:")
for f, desc in existing:
path = mem_dir / f
size = path.stat().st_size
Expand All @@ -12580,7 +12580,7 @@ def cmd_memory(args):
print(f" ✓ Deleted {f} ({desc})")

print(
f"\n Memory reset complete. New sessions will start with a blank slate."
"\n Memory reset complete. New sessions will start with a blank slate."
)
print(f" Files were in: {display_hermes_home()}/memories/\n")
else:
Expand Down
Loading
Loading