chore: sync with upstream main (2026-05-09)#25
Conversation
- Add hermes dashboard examples to the CLI help epilogue so users can discover the web UI command from 'hermes --help' output - Add an independent 'Test dashboard subcommand' CI step that verifies 'hermes dashboard --help' works in the Docker image, with its own mkdir/chown setup to remain independent of the prior smoke test step - Prevents regressions like NousResearch#9153 where the dashboard subcommand was present in source but missing from the published Docker image Closes NousResearch#9153
- Changed Input component to native textarea for task creation - Removed Enter-to-submit behavior (use Create button instead) - Added proper styling: border, padding, rounded corners, focus ring - 2-row default height with vertical resize and max-height cap - Escape still cancels the form
…te textarea The textarea conversion in the previous commit dropped Enter-to-submit entirely, requiring a mouse click on Create for every single-line task. Restore the common-case shortcut while preserving multiline entry: - Enter (no modifier) submits the form - Shift+Enter inserts a newline - Escape still cancels Matches the convention used by Slack, Discord, GitHub PR comment boxes.
…ax_tokens handling
Z.AI (智谱 GLM) vision models (glm-4v-flash, glm-4v-plus, etc.) have two
compatibility issues when used through the Anthropic-compatible endpoint:
1. **Error 1210 — max_tokens rejected on multimodal calls**: Z.AI rejects
the max_tokens parameter for vision model requests with error code 1210
("API 调用参数有误"). The error string does not contain "max_tokens",
so the existing unsupported-parameter retry logic never fires.
2. **Wrong endpoint inheritance**: When the main runtime provider uses Z.AI's
Anthropic-compatible endpoint (open.bigmodel.cn/api/anthropic), the vision
client inherits this endpoint. But Z.AI's Anthropic wire cannot properly
handle image content — models silently fail ("I can't see the image") or
reject max_tokens.
Changes:
- resolve_vision_provider_client(): force Z.AI vision to use OpenAI-compatible
endpoint (open.bigmodel.cn/api/paas/v4) instead of inheriting Anthropic wire
- _build_call_kwargs(): skip max_tokens for Z.AI vision models (4v/5v/-v suffix)
- _AnthropicCompletionsAdapter: support _skip_zai_max_tokens flag
- _to_openai_base_url(): rewrite Z.AI Anthropic URLs to OpenAI-compatible path
- call_llm() retry: detect Z.AI error 1210 and strip max_tokens before retry
## Summary - Forwards chat-completions `timeout` into the Codex Responses stream call. - Adds total elapsed-time enforcement while the Responses stream is still yielding events. - Closes the underlying client on timeout to unblock stalled streams, then raises `TimeoutError`. - Adds focused tests for timeout forwarding and total timeout enforcement. ## Why The Codex auxiliary adapter can be used by non-interactive auxiliary work such as context compression. If the stream keeps yielding progress-like events but never completes, SDK socket/read timeouts do not necessarily protect the full operation. This makes the CLI look stuck until the user force-interrupts the whole session. This is a refreshed upstream-ready version of the earlier fork fix around `d3f08e9a0` / PR #3. ## Verification - `python -m py_compile agent/auxiliary_client.py tests/agent/test_auxiliary_client.py` - `python -m pytest -o addopts='' tests/agent/test_auxiliary_client.py::TestCodexAuxiliaryAdapterTimeout -q` - `git diff --check`
…t-in for Teams approval buttons
…patch
Image generation plugins were dispatched without a model name, leaving
the plugin to pick its default. Users on OpenRouter, ComfyUI, or custom
backends had no way to select a specific model through config — they
had to fork the plugin or patch the tool.
Add _read_configured_image_model() that reads image_gen.model from the
active profile's config.yaml and forwards it into
_dispatch_to_plugin_provider(). When model is set, the plugin call
gains a 'model' kwarg; when unset, the plugin falls back to its own
default, so single-model users see no behavior change.
Example config:
image_gen:
provider: openrouter
model: flux-pro
Tests: all 170 image tool tests pass. The new code path is opt-in via
config and no existing test exercises it, so the change is strictly
additive.
Fixes NousResearch#9930 When an agent session is interrupted (Ctrl+C or gateway timeout), the current thread's interrupt flag is set in _interrupted_threads. asyncio executor threads are pooled and reused across sessions, so a thread that carried an interrupt flag from a prior session will immediately cancel any new asyncio work dispatched to it — including MCP server discovery. Fix: in register_mcp_servers(), temporarily clear the interrupt flag on the current thread before running _discover_all(), then restore it afterward in a finally block so the original interrupt state is not lost.
Follow-up to the salvaged warning. Without the exception string, operators see "config validation failed" with no hint why.
Track elapsed wall time in _run_on_mcp_loop, cancel the in-flight future when a timeout expires, and raise a descriptive TimeoutError that includes the elapsed and configured timeout. Add regression coverage for the new timeout diagnostics.
…logs Extracts the three try/write_runtime_status/except-log blocks into a shared _write_runtime_status_safe() helper. On failure, logs the first occurrence per (platform, context) at warning level and downgrades subsequent failures to debug — so a persistently broken status dir (permissions, ENOSPC) doesn't spam the log on every Telegram reconnect. Uses getattr for the _status_write_logged set so test harnesses that skip __init__ (object.__new__(Adapter)) don't break. Follow-up to the salvaged NousResearch#21158.
The alibaba-coding-plan provider (DashScope coding-intl endpoint) was defined in providers.py but missing from _PROVIDER_MODELS in models.py. This caused /model to show "0 models" for this provider even though credentials were configured and the provider was functional. Add the curated model list so the provider picker displays available models correctly.
…ousResearch#22248 (NousResearch#22416) When an auxiliary LLM provider (or an upstream proxy) returns a non-JSON body with `Content-Type: application/json` — e.g. an HTML 502 page from a misconfigured gateway — the OpenAI SDK's `response.json()` raises a raw `json.JSONDecodeError` (or wraps it in `APIResponseValidationError` whose message contains "expecting value"). Previously this fell through to the unknown-error branch and entered a 60s cooldown without retrying on the main model, dropping the middle conversation turns instead. This change folds JSON-decode detection into the existing fast-path fallback chain: detect by `isinstance(e, JSONDecodeError)` OR substring match for "expecting value", retry once on the main model, and use a shorter 30s cooldown when already on main (the body shape tends to flip back to valid quickly when the upstream proxy recovers). The three duplicated fallback bodies (model-not-found, unknown-error, JSON-decode) are consolidated into a single `_fallback_to_main_for_compression` helper that handles the shared bookkeeping (record aux-model failure for `/usage`-style callers, clear summary_model, clear cooldown). Also adds three unit tests covering: raw `JSONDecodeError` retries on main, substring-match for wrapped exceptions, and the 30s cooldown when already on main. Salvage of NousResearch#22248 by @0xharryriddle. Closes NousResearch#22244. Co-authored-by: Harry Riddle <ntconguit@gmail.com>
…/user are set OpenViking 0.3.x requires X-OpenViking-Account and X-OpenViking-User headers for ROOT API key requests to tenant-scoped APIs. Previously the `!="default"` guard skipped these headers when account/user were the literal string "default", causing INVALID_ARGUMENT errors. Remove the `!="default"` guard so headers are sent whenever account/user are truthy. Empty strings are still correctly skipped since `""` is falsy. Update tests to reflect the new behavior: - test_viking_client_headers_send_tenant_when_default: asserts "default" headers ARE present - test_viking_client_headers_send_tenant_when_empty_falls_back_to_default: asserts "default" headers ARE present from constructor fallback Based on NousResearch#21775 by @happy5318
…oups (NousResearch#22423) Telegram forum supergroups address the General topic as `message_thread_id="1"` on incoming updates, but the Bot API rejects sends with `message_thread_id=1` ("Message thread not found"). The gateway adapter has a `_message_thread_id_for_send` helper that maps "1" to None for that reason; the standalone `_send_telegram` helper used by the `send_message` tool never got the same mapping, so any `send_message` call to a Topics-enabled group's General topic (target shape `telegram:<chat_id>:1`) failed with "Message thread not found." Reuse the adapter's helper when available, with an explicit fallback to the same mapping for environments where the adapter import path fails (e.g. python-telegram-bot missing in this venv). Fixes NousResearch#22267
…search#22043) SQLite's WAL mode requires shared-memory (mmap) coordination and fcntl byte-range locks that don't reliably work on network filesystems. Upstream documents this explicitly: https://www.sqlite.org/wal.html#sometimes_queries_return_sqlite_busy_in_wal_mode On NFS / SMB / some FUSE mounts / WSL1, 'PRAGMA journal_mode=WAL' raises 'sqlite3.OperationalError: locking protocol' (SQLITE_PROTOCOL). Before this change, every feature backed by state.db or kanban.db broke silently: - /resume, /title, /history, /branch returned 'Session database not available.' with no cause - gateway logged the init failure at DEBUG (invisible in errors.log) - kanban dispatcher crashed every 60s, driving the known migration race (duplicate column name: consecutive_failures, NousResearch#21708 / NousResearch#21374) Changes: - hermes_state.apply_wal_with_fallback(): shared helper that tries WAL and falls back to DELETE on SQLITE_PROTOCOL-style errors with one WARNING explaining why - hermes_state.get_last_init_error() + format_session_db_unavailable(): capture the init failure cause and surface it in user-facing strings (with an NFS/SMB pointer for 'locking protocol') - hermes_cli/kanban_db.connect(): use the shared helper - gateway/run.py: bump SessionDB init failure log DEBUG -> WARNING (matches cli.py's existing correct behavior) - cli.py (4 sites) + gateway/run.py (5 sites): replace bare 'Session database not available.' with format_session_db_unavailable() Tests: 12 new tests in tests/test_hermes_state_wal_fallback.py + 1 new test in tests/hermes_cli/test_kanban_db.py. Existing suites (state, kanban, gateway, cli) remain green for all tests unrelated to pre-existing failures on main. Evidence: real-world user on NFSv3 mount (172.26.224.200:d2dfac12/home, local_lock=none) reporting 'Session database not available.' on /resume; 'locking protocol' appears in 4 distinct log entries across backup, kanban, TUI, and CLI paths in the same session. closes NousResearch#22032
Maps egitimviscara@gmail.com to GitHub login uzunkuyruk so that contributor_audit.py recognizes their authored commits in upcoming salvage PRs (e.g. NousResearch#21933 fix).
Recover delegate_task batch inputs when open-weight models emit tasks as a JSON-encoded array string, and return clear errors for malformed task lists. Co-authored-by: Cursor <cursoragent@cursor.com>
When _coerce_json fails to parse a string as JSON or parses to the wrong type, log a clear WARNING instead of silently returning the original value. When coerce_tool_args wraps a bare string into a single-element list AND the string looks like a JSON array (starts with '['), warn that the model likely emitted a JSON-encoded string instead of a native array. This improves diagnostics for the open-weight model output drift described in NousResearch#21933 (JSON-array-as-string), as well as any other tool whose array-typed argument arrives stringified through handle_function_call. Note: delegate_task does NOT go through coerce_tool_args (it is in _AGENT_LOOP_TOOLS and dispatched directly from run_agent.py with raw function_args from json.loads). The actual delegate_task fix for NousResearch#21933 is the previous commit. These logging changes apply to all other array-typed arguments coerced via the shared pipeline. Salvaged from PR NousResearch#22092.
WebUI sessions construct AIAgent(platform="webui") but PLATFORM_HINTS had no "webui" entry, so the agent received no platform hint at all. The WebUI frontend supports rich MEDIA:/absolute/path previews for images, audio, video, PDF, HTML, CSV, diffs, and Excalidraw, but without a hint the agent either ignores MEDIA: or falls back to Markdown image syntax which silently fails for local files. Add a webui hint that documents the MEDIA: render path and warns against  for local files. Fixes NousResearch#21883
`ToolCall.extra_content` was annotated `Optional[Dict[str, Any]]`,
but neither `Optional` nor `Dict` are imported at the top of
`agent/transports/types.py` — only `Any` is. The rest of the file
consistently uses PEP 604 / 585 syntax (e.g. `str | None`,
`dict[str, Any] | None`).
The file has `from __future__ import annotations`, so the missing
names don't crash class definition. But the annotation IS evaluated
when anything calls `typing.get_type_hints(ToolCall)` —
introspection raises `NameError: name 'Optional' is not defined`.
ruff catches it cleanly:
F821 Undefined name `Optional` agent/transports/types.py:65:32
F821 Undefined name `Dict` agent/transports/types.py:65:41
Switch the annotation to `dict[str, Any] | None` to match the
rest of the file's style. No new imports needed.
Verified:
- ruff F-checks now pass on the file
- `typing.get_type_hints(ToolCall)` succeeds where it raised before
- 166/166 tests in tests/agent/transports/ pass on Windows + Python 3.12
…r to prevent BOT filter bypass
Adds five regression tests for the Format 3 (Cloud Run relay) envelope
path:
- test_relay_flat_honors_declared_sender_type_bot: BOT sender_type
propagates to msg['sender']['type'].
- test_relay_flat_defaults_sender_type_human_when_absent: backward
compat \u2014 missing field still flows as HUMAN.
- test_relay_flat_coerces_unknown_sender_type_to_human: defensive
coercion \u2014 strip+upper normalizes whitespace/case, anything outside
{HUMAN, BOT} falls back to HUMAN.
- test_relay_flat_bot_sender_is_filtered_end_to_end: end-to-end
through _on_pubsub_message \u2014 a relay envelope with sender_type=BOT
is dropped by the BOT self-filter without dispatch.
- test_relay_flat_human_sender_dispatches: end-to-end negative
control \u2014 human relay envelopes still reach the agent loop.
Also clarifies the operator contract in the adapter comment: the
relay must forward upstream sender.type as envelope.sender_type,
otherwise bot replies forwarded as HUMAN cannot be distinguished
from genuine humans by this filter.
Comments are injected into the next worker's system prompt by
build_worker_context() as '**{author}** (timestamp): {body}'. The
previous code accepted args['author'] as a free-form override and
exposed it on KANBAN_COMMENT_SCHEMA, which let a worker:
1. Receive a prompt-injection in a malicious task body.
2. Call kanban_comment with author='hermes-system' (or any other
authoritative-looking name) on a sibling task.
3. The next worker assigned to that sibling task sees the forged
comment in its boot context as what reads like a system-authored
directive.
Always derive author from HERMES_PROFILE (the dispatcher already sets
this per worker at hermes_cli/kanban_db.py:3718), and remove the
'author' property from the tool schema so the LLM can't see the
override surface.
Cross-task commenting itself remains unrestricted (see NousResearch#19713) —
comments are the deliberate handoff channel between tasks; only the
author-override surface is closed.
Co-authored-by: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com>
- Renames test_comment_custom_author -> test_comment_ignores_caller_supplied_author and inverts its assertion: an args['author'] override is silently ignored; the author always comes from HERMES_PROFILE. - Adds test_comment_schema_omits_author_override to assert the 'author' property is gone from KANBAN_COMMENT_SCHEMA so the forgery surface stays closed if someone re-adds the schema field by accident. - Adds test_worker_can_comment_on_foreign_task to pin the NousResearch#19713 policy decision: cross-task commenting must remain unrestricted. Without this guard, a future change accidentally adding _enforce_worker_task_ownership to _handle_comment would close the documented handoff channel between tasks.
Maps zhekinmaksim@gmail.com to GitHub login Zhekinmaksim so contributor_audit.py recognizes their authored commit in the upcoming NousResearch#21930 salvage PR.
… contexts Follow-up to PR NousResearch#21293 (cli.py), which fixed the same anti-pattern. `asyncio.get_event_loop()` is documented as effectively "always returns the running loop when called from a coroutine" and emits DeprecationWarning/RuntimeWarning in some interpreter configurations. The Python docs explicitly recommend get_running_loop() inside coroutines. Replaces the remaining 9 call sites that are unconditionally inside async def bodies: - tools/browser_cdp_tool.py — _cdp_call() (4 sites): deadline + remaining computations inside the async websockets.connect context manager. - hermes_cli/web_server.py — get_status, _start_device_code_flow, submit_oauth_code (3 sites): all FastAPI async endpoints offloading blocking httpx / PKCE work to run_in_executor. - environments/agent_loop.py — HermesAgentLoop (1 site): tool dispatch inside the async rollout loop. - environments/benchmarks/terminalbench_2/terminalbench2_env.py — rollout_and_score_eval (1 site): test verification thread offload. All 9 sites are unconditionally inside async def bodies, so a running loop is guaranteed and no try/except RuntimeError fallback is needed (unlike the cli.py case in NousResearch#21293, which ran from a background thread). Behavior is identical on supported Python versions; aligns the codebase with the post-NousResearch#21293 idiom and avoids future warnings as the deprecation hardens. Salvaged from PR NousResearch#21930 by @Zhekinmaksim onto current main (the original branch was 109 commits behind and carried unintended stale-branch reverts of unrelated landed changes — _tail_lines encoding=utf-8 and the Windows PTY bridge guard). Only the 9 swaps from the PR's intended scope are applied here.
Maps obafemiferanmi1999@gmail.com (the commit-author email used on PR NousResearch#21473's branch) to GitHub login KvnGz (the PR/branch owner) so contributor_audit.py recognizes the authored commit in the upcoming salvage PR.
Three tests in tests/agent/test_auxiliary_config_bridge.py read
in-tree source files (gateway/run.py and cli.py) via
Path.read_text() with no encoding argument. The default falls
back to the system locale, which on Western Windows installs is
cp1252, and the read fails as soon as the source contains any
byte that isn't valid cp1252 (e.g. an em-dash in a comment):
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f
in position 41190: character maps to <undefined>
Linux CI doesn't catch this because the default Linux locale is
UTF-8. Windows contributors hit it on every run of the test suite.
Pin encoding="utf-8" on the three call sites that read repo
source files. This matches the existing precedent in
hermes_cli/doctor.py:363, where the same pattern (with an
explanatory comment) was applied to fix the .env read on
non-UTF-8 Windows locales.
Affected tests now pass on Windows + Python 3.12:
- TestGatewayBridgeCodeParity.test_gateway_has_auxiliary_bridge
- TestGatewayBridgeCodeParity.test_gateway_no_compression_env_bridge
- TestCLIDefaultsHaveAuxiliaryKeys.test_cli_defaults_can_merge_auxiliary
Plugin platforms (IRC, Teams, Google Chat) currently fail with `No live adapter for platform '<name>'` when a `deliver=<plugin>` cron job runs in a separate process from the gateway, even though the platforms are eligible cron targets via `cron_deliver_env_var` (added in NousResearch#21306). Built-in platforms (Telegram, Discord, Slack, etc.) use direct REST helpers in `tools/send_message_tool.py` so cron can deliver without holding the gateway in the same process; plugin platforms historically depended on `_gateway_runner_ref()` which returns `None` out of process. This change adds an optional `standalone_sender_fn` field to `PlatformEntry` so plugins can register an ephemeral send path that opens its own connection, sends, and closes without needing the live adapter. The dispatch site in `_send_via_adapter` falls through to the hook when the gateway runner is unavailable, with a descriptive error when neither path applies. The hook is optional, so existing plugins are unaffected. Reference migrations land in the same change for IRC, Teams, and Google Chat, exercising the hook across stdlib (asyncio + IRC protocol), Bot Framework OAuth client_credentials, and Google service-account flows respectively. Security hardening on the new code paths: * IRC: control-character stripping on chat_id and message body to block CRLF command injection; bounded nick-collision retries; JOIN before PRIVMSG so channels with the default `+n` mode accept the delivery. * Teams: TEAMS_SERVICE_URL validated against an allowlist of known Bot Framework hosts (`smba.trafficmanager.net`, `smba.infra.gov.teams.microsoft.us`) to block SSRF; chat_id and tenant_id constrained to the documented Bot Framework character set; per-request timeouts so a slow STS endpoint cannot starve the activity POST. * Google Chat: chat_id and thread_id validated against strict resource-name regexes; service-account refresh wrapped in `asyncio.wait_for` so a hung token endpoint cannot stall the scheduler. Test coverage: 20 new tests covering happy path, missing-config errors, network failure modes, and each defensive validation. Existing tests unchanged. `bash scripts/run_tests.sh tests/tools/test_send_message_tool.py tests/gateway/test_irc_adapter.py tests/gateway/test_teams.py tests/gateway/test_google_chat.py` reports 341 passed, 0 regressions. Documentation: new "Out-of-process cron delivery" section in website/docs/developer-guide/adding-platform-adapters.md and an entry in gateway/platforms/ADDING_A_PLATFORM.md naming the hook.
…lone-all When the source profile is the default (~/.hermes), shutil.copytree() was copying multi-GB infrastructure alongside the ~40 MB of actual profile data: hermes-agent/ (repo checkout + 3 GB venv), .worktrees/, profiles/ (sibling profiles — recursive!), bin/ (installed binaries), node_modules/ (hundreds of MB). Add _CLONE_ALL_DEFAULT_EXCLUDE_ROOT frozenset with these five entries and pass an ignore callback to copytree(). Exclusions are gated on the source actually being the default profile (is_default_source) so named-profile sources are never affected. Also exclude at any depth: __pycache__/, *.pyc, *.pyo, *.sock, *.tmp. Profile data (config.yaml, .env, auth.json, state.db, sessions/, skills/, logs/) is preserved intact — clone-all means 'complete snapshot minus infrastructure'. Mirrors the approach already used by _default_export_ignore() and _DEFAULT_EXPORT_EXCLUDE_ROOT (the export-side exclusion set which is broader because it produces a portable archive, not a live clone). Co-authored-by: MustafaKara7 <karamusti912@gmail.com> Co-authored-by: fahdad <30740087+fahdad@users.noreply.github.com> Fixes NousResearch#5022 Based on PRs NousResearch#5025, NousResearch#5026, and NousResearch#21728
…-scoped path check_for_updates() and _resolve_repo_dir() were preferring $HERMES_HOME/hermes-agent/ over Path(__file__).parent.parent.resolve() when looking for a .git checkout. For profiles created with --clone-all, $HERMES_HOME/hermes-agent/ points to a stale copy with a frozen HEAD, causing persistent "N commits behind" banners that never resolved. Flip the resolution order: prefer the running code's location first, fall back to $HERMES_HOME/hermes-agent/ only when the live checkout doesn't have a .git (system-wide pip installs, distro packages). The embedded-rev branch (HERMES_REVISION env var, set by nix builds) is unaffected — it uses git ls-remote against upstream, never reads the local checkout's HEAD. Based on PR NousResearch#21728 by @fahdad
Nikita Nosov (nik1t7n, PR NousResearch#22264) — first-time contributor email and noreply alias.
🚨 CRITICAL Supply Chain Risk DetectedThis PR contains a pattern that has been used in real supply chain attacks. A maintainer must review the flagged code carefully before merging. 🚨 CRITICAL: Install-hook file added or modifiedThese files can execute code during package installation or interpreter startup. Files: Scanner only fires on high-signal indicators: .pth files, base64+exec/eval combos, subprocess with encoded commands, or install-hook files. Low-signal warnings were removed intentionally — if you're seeing this comment, the finding is worth inspecting. |
🔎 Lint report:
|
| Rule | Count |
|---|---|
invalid-argument-type |
44 |
unresolved-import |
43 |
unresolved-attribute |
41 |
invalid-method-override |
26 |
invalid-assignment |
10 |
unsupported-operator |
5 |
unused-type-ignore-comment |
4 |
invalid-parameter-default |
1 |
invalid-type-form |
1 |
call-non-callable |
1 |
not-subscriptable |
1 |
First entries
tests/tools/test_computer_use.py:11: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
gateway/platforms/qqbot/adapter.py:2669: [invalid-method-override] invalid-method-override: Invalid override of method `send_document`: Definition is incompatible with `BasePlatformAdapter.send_document`
tests/test_lint_config.py:23: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/gateway/test_telegram_thread_fallback.py:390: [invalid-argument-type] invalid-argument-type: Argument to function `build_session_key` is incorrect: Expected `SessionSource`, found `SimpleNamespace`
plugins/platforms/teams/adapter.py:1044: [invalid-method-override] invalid-method-override: Invalid override of method `send_image_file`: Definition is incompatible with `BasePlatformAdapter.send_image_file`
scripts/keystroke_diagnostic.py:38: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.layout`
tests/cli/test_cli_shift_enter_newline.py:11: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.input.ansi_escape_sequences`
hermes_cli/uninstall.py:328: [unresolved-attribute] unresolved-attribute: Module `winreg` has no member `QueryValueEx`
run_agent.py:10730: [invalid-argument-type] invalid-argument-type: Method `__getitem__` of type `Overload[(key: SupportsIndex | slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> LiteralString, (key: SupportsIndex | slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> str]` cannot be called with key of type `Literal["content"]` on object of type `str`
hermes_cli/gateway.py:3027: [unresolved-attribute] unresolved-attribute: Module `ctypes` has no member `windll`
tests/gateway/test_telegram_thread_fallback.py:897: [invalid-method-override] invalid-method-override: Invalid override of method `send`: Definition is incompatible with `BasePlatformAdapter.send`
tests/cli/test_cli_shift_enter_newline.py:9: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/tools/test_file_tools.py:379: [invalid-argument-type] invalid-argument-type: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> str, (s: slice[SupportsIndex | None, SupportsIndex | None, SupportsIndex | None], /) -> list[str]]` cannot be called with key of type `Literal["new_string"]` on object of type `list[str]`
gateway/platforms/msgraph_webhook.py:15: [unresolved-import] unresolved-import: Cannot resolve imported module `aiohttp`
gateway/platforms/telegram.py:2244: [unresolved-attribute] unresolved-attribute: Attribute `PRIVATE` is not defined on `None` in union `Unknown | None`
gateway/platforms/signal.py:1329: [invalid-method-override] invalid-method-override: Invalid override of method `send_video`: Definition is incompatible with `BasePlatformAdapter.send_video`
gateway/platforms/wecom.py:1454: [invalid-method-override] invalid-method-override: Invalid override of method `send_video`: Definition is incompatible with `BasePlatformAdapter.send_video`
hermes_cli/uninstall.py:324: [unresolved-attribute] unresolved-attribute: Module `winreg` has no member `OpenKey`
tests/hermes_cli/test_profile_distribution.py:120: [unresolved-attribute] unresolved-attribute: Attribute `distribution_owned` is not defined on `None` in union `DistributionManifest | None`
tests/gateway/test_tts_media_routing.py:86: [unresolved-attribute] unresolved-attribute: Object of type `bound method _MediaRoutingAdapter.send_voice(chat_id: str, audio_path: str, caption: str | None = None, reply_to: str | None = None, metadata: dict[str, Any] | None = None, **kwargs) -> CoroutineType[Any, Any, SendResult]` has no attribute `assert_not_awaited`
hermes_cli/web_server.py:2990: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to `<class 'PtyBridge'>`
gateway/platforms/qqbot/adapter.py:2627: [invalid-method-override] invalid-method-override: Invalid override of method `send_image_file`: Definition is incompatible with `BasePlatformAdapter.send_image_file`
scripts/keystroke_diagnostic.py:39: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.layout.containers`
tests/hermes_cli/test_profile_distribution.py:155: [unresolved-attribute] unresolved-attribute: Attribute `env_requires` is not defined on `None` in union `DistributionManifest | None`
gateway/platforms/msgraph_webhook.py:136: [unresolved-attribute] unresolved-attribute: Attribute `Application` is not defined on `None` in union `Unknown | None`
... and 152 more
✅ Fixed issues (37):
| Rule | Count |
|---|---|
invalid-argument-type |
11 |
unresolved-attribute |
9 |
unresolved-import |
6 |
unsupported-operator |
4 |
invalid-assignment |
4 |
unresolved-reference |
2 |
no-matching-overload |
1 |
First entries
run_agent.py:6655: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
run_agent.py:6484: [invalid-argument-type] invalid-argument-type: Argument to function `_codex_cloudflare_headers` is incorrect: Expected `str`, found `Unknown | str | dict[str, str] | ... omitted 3 union elements`
tools/environments/base.py:107: [unresolved-attribute] unresolved-attribute: Attribute `close` is not defined on `None` in union `IO[Unknown] | None`
tests/run_agent/test_provider_attribution_headers.py:155: [unsupported-operator] unsupported-operator: Operator `not in` is not supported between objects of type `Literal["X-OpenRouter-Cache"]` and `Unknown | str | dict[str, str] | ... omitted 3 union elements`
plugins/platforms/google_chat/adapter.py:2945: [unresolved-import] unresolved-import: Module `hermes_cli.config` has no member `print_success`
tests/gateway/test_tts_media_routing.py:101: [unresolved-attribute] unresolved-attribute: Object of type `bound method _MediaRoutingAdapter.send_voice(chat_id: str, audio_path: str, caption: str | None = None, reply_to: str | None = None, **kwargs) -> CoroutineType[Any, Any, SendResult]` has no attribute `assert_awaited_once_with`
plugins/platforms/google_chat/adapter.py:2942: [unresolved-import] unresolved-import: Module `hermes_cli.config` has no member `prompt`
hermes_cli/main.py:5350: [unresolved-import] unresolved-import: Cannot resolve imported module `openai`
tests/gateway/test_tts_media_routing.py:86: [unresolved-attribute] unresolved-attribute: Object of type `bound method _MediaRoutingAdapter.send_voice(chat_id: str, audio_path: str, caption: str | None = None, reply_to: str | None = None, **kwargs) -> CoroutineType[Any, Any, SendResult]` has no attribute `assert_not_awaited`
run_agent.py:2187: [invalid-argument-type] invalid-argument-type: Argument to function `query_ollama_num_ctx` is incorrect: Expected `str`, found `(str & ~AlwaysFalsy) | (dict[str, str] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 4 union elements`
agent/transports/types.py:65: [unresolved-reference] unresolved-reference: Name `Optional` used when not defined
gateway/platforms/base.py:2793: [invalid-assignment] invalid-assignment: Invalid subscript assignment with key of type `Literal["stop_event"]` and value of type `Event` on object of type `dict[str, dict[str, str] | None]`
gateway/platforms/base.py:2797: [invalid-argument-type] invalid-argument-type: Argument to bound method `BasePlatformAdapter._keep_typing` is incorrect: Expected `int | float`, found `dict[str, str] | None`
tests/agent/test_codex_cloudflare_headers.py:163: [unresolved-attribute] unresolved-attribute: Attribute `get` is not defined on `str & ~AlwaysFalsy`, `int & ~AlwaysFalsy` in union `(Unknown & ~AlwaysFalsy) | (str & ~AlwaysFalsy) | (dict[str, str] & ~AlwaysFalsy) | ... omitted 3 union elements`
tests/agent/test_codex_cloudflare_headers.py:163: [unresolved-attribute] unresolved-attribute: Attribute `startswith` is not defined on `dict[str, str]` in union `Unknown | str | dict[str, str]`
tests/run_agent/test_concurrent_interrupt.py:192: [unsupported-operator] unsupported-operator: Operator `+=` is not supported between objects of type `None` and `Literal[1]`
tools/environments/base.py:106: [unresolved-attribute] unresolved-attribute: Attribute `write` is not defined on `None` in union `IO[Unknown] | None`
agent/anthropic_adapter.py:1537: [invalid-assignment] invalid-assignment: Invalid subscript assignment with key of type `Literal["cache_control"]` and value of type `dict[Unknown, Unknown]` on object of type `dict[str, str]`
gateway/platforms/telegram.py:1258: [invalid-argument-type] invalid-argument-type: Argument to constructor `int.__new__` is incorrect: Expected `str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc`, found `str | None`
plugins/platforms/google_chat/adapter.py:2944: [unresolved-import] unresolved-import: Module `hermes_cli.config` has no member `print_info`
tests/gateway/test_tts_media_routing.py:106: [unresolved-attribute] unresolved-attribute: Object of type `bound method _MediaRoutingAdapter.send_document(chat_id: str, file_path: str, caption: str | None = None, file_name: str | None = None, reply_to: str | None = None, **kwargs) -> CoroutineType[Any, Any, SendResult]` has no attribute `assert_not_awaited`
run_agent.py:2470: [invalid-argument-type] invalid-argument-type: Argument to function `get_model_context_length` is incorrect: Expected `str`, found `str | dict[str, str] | Any | ... omitted 3 union elements`
tests/gateway/test_tts_media_routing.py:81: [unresolved-attribute] unresolved-attribute: Object of type `bound method _MediaRoutingAdapter.send_document(chat_id: str, file_path: str, caption: str | None = None, file_name: str | None = None, reply_to: str | None = None, **kwargs) -> CoroutineType[Any, Any, SendResult]` has no attribute `assert_awaited_once_with`
run_agent.py:12545: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
gateway/platforms/base.py:2797: [invalid-argument-type] invalid-argument-type: Argument to bound method `BasePlatformAdapter._keep_typing` is incorrect: Expected `Event | None`, found `dict[str, str] | None`
... and 12 more
Unchanged: 3999 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
Daily sync with upstream. Auto-created by cron job.
Total commits: 865
Recent commits:
f6d45e5 chore: add nik1t7n to AUTHOR_MAP
1ac8deb feat(gateway): stream Telegram edits safely
cca2869 fix(banner): resolve update-check repo from running code, not profile-scoped path
f7e514d fix(profiles): exclude infrastructure artifacts when cloning with --clone-all
93e25ce feat(plugins): add standalone_sender_fn for out-of-process cron delivery
3801825 fix(tests): pin UTF-8 encoding when reading source files on Windows
5d2a75d chore(release): add KvnGz to AUTHOR_MAP (NousResearch#22458)
4a1840e fix(async): replace get_event_loop() with get_running_loop() in async contexts
b7d8e28 chore(release): add Zhekinmaksim to AUTHOR_MAP (NousResearch#22449)
7e578f0 feat(feishu): add native update prompt cards
e3ebaa1 test(kanban): cover kanban_comment author hardening + cross-task policy
9bbad3c fix(security): drop caller-controlled author override in kanban_comment
e3cd4e4 chore(release): add heathley email to AUTHOR_MAP for PR NousResearch#21911 salvage (NousResearch#22446)
8578f89 test(google-chat): cover relay-declared sender_type honoring
c386400 fix(security): honor relay-declared sender_type in Google Chat adapter to prevent BOT filter bypass
0f1d41a fix(transports): use PEP 604 annotation for ToolCall.extra_content
2c8c48f fix(webui): clarify MEDIA absolute-path hint
aad5490 fix(webui): add platform hint for MEDIA rendering
7330183 fix(model_tools): log warnings for failed JSON-array coercion
326ca75 fix(delegate): accept JSON string batch tasks
4632be1 chore(release): add uzunkuyruk to AUTHOR_MAP (NousResearch#22434)
2a7047c fix(sqlite): fall back to journal_mode=DELETE on NFS/SMB/FUSE (NousResearch#22043)
ae005ec fix(send_message): map Telegram General topic id to None for forum groups (NousResearch#22423)
8fb3e2d fix: always send tenant headers in OpenViking _headers() when account/user are set
c7e8add fix(context): handle JSON decode errors in compression — salvage of NousResearch#22248 (NousResearch#22416)
aef297a fix(telegram): skip send_chat_action for DM topic reply-fallback lanes
b323957 fix(telegram): preserve DM topic routing via reply fallback
28b5bd7 chore(release): add leehack to AUTHOR_MAP for PR NousResearch#22053 salvage (NousResearch#22409)
96dc272 fix(cron): use getJobState helper in handlePauseResume
e572737 Fix cron dashboard rendering for partial jobs
e407376 fix(cron): normalize partial job records
f2afa68 chore(release): add oferlaor to AUTHOR_MAP for PR NousResearch#22356 salvage
dbafa08 fix(cron): avoid delivery origin as sender identity
a7e7921 fix(tui): trim markdown wrap spaces (NousResearch#22062)
78b0008 fix(gateway): also catch restart TimeoutExpired; friendly message
dccf1fb fix(gateway): cap adapter disconnect during stop
524cbab chore(release): add dandacompany to AUTHOR_MAP for salvaged PR NousResearch#20503
24d3216 fix(slack): enable writable app home DMs in manifest
8e4f3ba test(patch-tool): collapse 9 schema-shape tests into 2 invariants
3adcc64 fix(patch-tool): advertise per-mode required params in schema descriptions
7c174e6 fix: harden termux update path with uv bootstrap and env guard
6f7b698 fix: keep tui /quit behavior aligned with cli exit flow
0ec052c perf(cli): cut ~19s from 'hermes' cold start (skills cache + lazy Feishu + no Nous HTTP) (NousResearch#22138)
d606df8 docs(cli): call out Ctrl+Enter for Windows Terminal users
f5b635f feat(cli): recognise Shift+Enter as a newline key
cacb984 fix(google-chat): repair setup prompt imports
d10d19e Merge pull request NousResearch#22080 from NousResearch/fix/faster-docker
d971b26 fix(update): bypass systemd RestartSec after graceful drain (NousResearch#22101)
5089596 perf(cli): skip eager plugin discovery on known built-in subcommands (NousResearch#22120)
7a4d5c1 docs(windows): label native Windows support as early beta (NousResearch#22115)
... and 815 more commits.