Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1170 commits
Select commit Hold shift + click to select a range
5a00211
chore: add Qwinty to AUTHOR_MAP
teknium1 May 9, 2026
3170c8d
fix(browser_tool): do not cache transient None cloud provider resolution
wesleysimplicio May 9, 2026
48bf0ea
fix(browser_tool): fall through to autodetect on config read failure
wesleysimplicio May 9, 2026
3fd4ccb
fix(email): send IMAP ID extension to support 163/NetEase mailbox
wesleysimplicio May 9, 2026
a671d8a
fix(email): use real hermes version in IMAP ID command
wesleysimplicio May 9, 2026
98e94be
fix(deps): declare youtube-transcript-api in pyproject.toml [youtube]…
wesleysimplicio May 9, 2026
68854cd
fix(agent): extract thinking from content-list blocks for DeepSeek V4…
wesleysimplicio May 9, 2026
7869838
fix(kanban): make _migrate_add_optional_columns idempotent on concurr…
wesleysimplicio May 9, 2026
1dd0790
fix(doctor): skip pluggable provider profiles when a dedicated check …
wesleysimplicio May 9, 2026
6e848f6
fix(doctor): normalize provider name and aliases before dedicated-ski…
wesleysimplicio May 9, 2026
fe61d95
fix(completion): use valid zsh _arguments exclusion-group syntax
Sanjays2402 May 9, 2026
1c9ffb1
fix(model-metadata): align hy3-preview static fallback + delete chang…
teknium1 May 9, 2026
ca13993
fix(delegate): add explicit do-not-use guidance to acp_command/acp_ar…
wesleysimplicio May 9, 2026
236f3b0
feat(gateway): add Telegram notification mode to suppress intermediat…
CalmProton May 9, 2026
b4d3092
chore: add CalmProton to AUTHOR_MAP
teknium1 May 9, 2026
448c11f
fix(telegram): default notifications to 'important' (silence intermed…
teknium1 May 9, 2026
1508dcb
fix(gateway): adopt unit's HERMES_HOME for --system CLI ops
mbac May 9, 2026
5e2eba8
chore: add mbac to AUTHOR_MAP
teknium1 May 9, 2026
883e11f
fix(openrouter): add x-grok-conv-id header for Grok models to improve…
Ninso112 May 9, 2026
bfc84bd
chore: add Ninso112 to AUTHOR_MAP
teknium1 May 9, 2026
9c26297
fix(gateway): preserve Ctrl+C for Windows foreground runs
helix4u May 9, 2026
840ebe0
fix: make session search initialize session db
HenkDz May 3, 2026
550f6e2
perf(teams): defer httpx import to first webhook call (#22831)
teknium1 May 9, 2026
b349ae1
fix(acp): honor task cwd for foreground terminal commands
HenkDz May 1, 2026
c7f0aab
feat(openrouter): wire Pareto Code router with min_coding_score knob …
teknium1 May 9, 2026
70bfd42
fix(gateway): preserve reasoning_content, codex_message_items, finish…
teknium1 May 9, 2026
0bcc327
docs(openrouter): document auxiliary.<task>.extra_body for OR routing…
teknium1 May 9, 2026
fef1a41
docs: round 2 audit — messaging, developer-guide, guides, integration…
teknium1 May 9, 2026
c1cc3d4
perf(image_gen): defer fal_client import to first generation request …
teknium1 May 10, 2026
1321bcf
fix(gateway): finalize final stream edit on done
kidonng May 9, 2026
af9df46
chore: add kidonng to AUTHOR_MAP
teknium1 May 9, 2026
0c5c4d1
fix(skills-hub): cover remaining SSRF fetch paths after #10029
heathley May 9, 2026
35f773c
fix(context_compressor): treat streaming premature-close as transient…
wesleysimplicio May 9, 2026
058c508
fix(session): route OR-combined short CJK tokens to LIKE fallback (#2…
wesleysimplicio May 9, 2026
2245879
fix(checkpoint): guard _touch_project against non-dict project metadata
wesleysimplicio May 9, 2026
3863d6d
fix(update): prebuild psutil on Termux Android via Linux path shim
adybag14-cyber May 9, 2026
6d5d467
fix(update): use termux-all uv fallback path on Termux
adybag14-cyber May 9, 2026
c179bda
fix(install): also patch psutil on Termux fresh-install path
teknium1 May 10, 2026
53ec328
fix(process_registry): kill orphaned Popen on post-spawn setup failure
wesleysimplicio May 9, 2026
116a144
fix(terminal): bridge docker_env config to TERMINAL_DOCKER_ENV
wesleysimplicio May 9, 2026
246c676
fix(gateway): degrade gracefully when all platform adapters are missing
wesleysimplicio May 9, 2026
6ddc48b
fix(fallback): resolve api_key_env in fallback chain entries (carve-o…
wesleysimplicio May 9, 2026
4f8d8ad
fix(error_classifier): classify generic-typed timeout messages as tra…
wesleysimplicio May 9, 2026
2ffef15
fix(test_gateway): stop run_gateway() tests from rewriting the dev's …
teknium1 May 10, 2026
6bf7ac3
fix(gateway): detect gateway process via /proc in Docker without procps
wesleysimplicio May 9, 2026
4ca7c21
test(gateway): stub /proc unavailability in find_gateway_pids fallbac…
teknium1 May 9, 2026
1fb9f7c
fix(gateway): pass max_total_size_mb and max_file_size_mb to Checkpoi…
DanielLSM May 9, 2026
f93b8c2
chore: add DanielLSM to AUTHOR_MAP
teknium1 May 9, 2026
4fdaf0b
fix: use credential_pool for custom endpoint model listing probes
v1b3coder May 9, 2026
de54618
chore: add v1b3coder to AUTHOR_MAP
teknium1 May 9, 2026
85383c6
fix(cli): preserve config comments on setting writes
ming1523 May 9, 2026
da086a0
chore: add ming1523 to AUTHOR_MAP
teknium1 May 9, 2026
5971a4e
feat(docs): richer info panels on the Skills Hub for built-in + optio…
teknium1 May 10, 2026
b67ea7f
perf(cli): skip welcome banner on `chat -q` single-query mode (#22904)
teknium1 May 10, 2026
4375b82
feat(curator): show rename map in user-visible summary (#22910)
teknium1 May 10, 2026
ded194e
chore(skills): move heavy training skills + outlines to optional-skil…
teknium1 May 10, 2026
08ec602
fix(tool-result-storage): persist via stdin to bypass 128 KB exec-arg…
teknium1 May 10, 2026
d04a0b8
docs(skills): clarify kanban fan-out decomposition
eloklam May 10, 2026
eb3db23
chore: AUTHOR_MAP entry for eloklam (#22898)
teknium1 May 10, 2026
8954537
fix(kanban): request default board explicitly (#21819)
Tranquil-Flow May 8, 2026
dd49d50
test(kanban): assert re-block notification is delivered after unblock…
jackey8616 May 9, 2026
a403665
fix(kanban): remove blocked kind from unsub
jackey8616 May 9, 2026
998676d
chore(test): comment of test case rewrite to english
jackey8616 May 9, 2026
e622504
docs(user-stories): add 18 verified social entries (99 → 117) (#22920)
teknium1 May 10, 2026
3800972
feat(vision): vision_analyze returns pixels to vision-capable models,…
teknium1 May 10, 2026
68e4464
fix(stream-retry): collapse two-line drop status, name provider, and …
teknium1 May 10, 2026
6f2d605
fix(kanban): drop redundant init_db() in gateway watchers (#21378)
li0near May 10, 2026
e2ce89a
chore: AUTHOR_MAP entry for li0near gmail (#21378)
teknium1 May 10, 2026
3d2bfc5
chore(models): refresh OpenRouter + Nous fallback lists (#23001)
teknium1 May 10, 2026
d1fc748
fix(kanban): /kanban slash command emits argparse garbage instead of …
tymrtn May 8, 2026
5a70d9b
chore: AUTHOR_MAP entry for tymrtn (#21794)
teknium1 May 10, 2026
126cbff
feat(stream-retry): add upstream + timing diagnostics to drop log (#2…
teknium1 May 10, 2026
e5af1dd
fix(review): tell background reviewer not to capture transient env fa…
teknium1 May 10, 2026
dcc8de8
feat(codex): add gpt-5.3-codex-spark model
nederev May 1, 2026
2a6f3de
fix(model-metadata): restore gpt-5.3-codex-spark fallback context
nederev May 1, 2026
c6dc295
fix(model-metadata): set codex-spark fallback context to 128k
nederev May 1, 2026
9457644
fix: surface Codex CLI-only models
askclaw-vesper May 4, 2026
6b5e011
chore: add codex-spark salvage contributors to AUTHOR_MAP
kshitijk4poor May 10, 2026
9ee9a42
docs(codex-spark): document ChatGPT Pro entitlement gating
kshitijk4poor May 10, 2026
826e717
test(codex-spark): add live-API regression and make picker test deter…
kshitijk4poor May 10, 2026
44cdf55
fix(codex-spark): defensive 128k entry in DEFAULT_CONTEXT_LENGTHS + c…
kshitijk4poor May 10, 2026
236cbe1
feat(kanban): add orchestrator board tools
kallidean May 6, 2026
26bf45f
fix(kanban): parse include_archived explicitly
kallidean May 6, 2026
50d2814
fix(kanban): parse triage flag explicitly
kallidean May 6, 2026
2704e7b
fix(kanban): restrict board routing tools to orchestrators
teknium1 May 10, 2026
ce374bc
chore: AUTHOR_MAP entry for kallidean (#20568)
teknium1 May 10, 2026
3d4297a
docs(user-stories): add 4 entries from @emmagine79 thread (#23204)
teknium1 May 10, 2026
9cdcf31
docs(web-search): explain auxiliary-model summarization for web_extra…
teknium1 May 10, 2026
50f9fee
feat(gateway): add LINE Messaging API platform plugin (#23197)
teknium1 May 10, 2026
7312f7f
feat(curator): hint at `hermes curator pin` in the rename block (#23212)
teknium1 May 10, 2026
ec9329e
fix(security): require dashboard auth for plugin API routes
liuhao1024 May 4, 2026
ae4b09c
test(security): broaden plugin API auth coverage + correct stale docs…
teknium1 May 10, 2026
5aa755e
feat(plugins): run any LLM call from inside a plugin via ctx.llm (#23…
teknium1 May 10, 2026
d3db672
fix(kanban): use sys.executable -m hermes for dispatcher spawn
wali-reheman May 10, 2026
62b1c74
fix(kanban): correct dispatcher spawn module name + PATH-first lookup
teknium1 May 10, 2026
c391684
feat(i18n): localize all gateway commands + web dashboard, add 8 new …
teknium1 May 10, 2026
061a183
fix(kanban): guard task_age against corrupt created_at values like '%s'
baocin May 6, 2026
40a4bfa
test(kanban): cover task_age safe-int guards + AUTHOR_MAP entry
teknium1 May 10, 2026
b308dd7
fix(kanban): preserve assignee casing in dashboard
princepal9120 May 7, 2026
08c5b35
test(kanban-dashboard): pin assignee-casing static-asset regressions …
teknium1 May 10, 2026
d4b26df
perf(browser): route browser_console eval through supervisor's persis…
teknium1 May 10, 2026
0e0ddaa
fix(kanban-dashboard): tone down completed-run metadata panel (#19548)
Tranquil-Flow May 10, 2026
a91e5a8
feat(kanban-dashboard): native <details> collapse + skip empty metadata
teknium1 May 10, 2026
673418d
fix(kanban): reject toolset names in task skills
LeonSGP43 May 10, 2026
1f5983c
feat(kanban): aggregate all toolset-name typos in skills before raising
teknium1 May 10, 2026
cede612
feat(gateway): shutdown forensics — non-blocking diag, per-phase timi…
teknium1 May 10, 2026
845be25
fix(kanban): cap dispatch by running workers
guglielmofonda May 7, 2026
3fbbf58
docs(kanban): document max_spawn as live concurrency cap (not per-tic…
teknium1 May 10, 2026
d62808c
chore: AUTHOR_MAP entry for guglielmofonda (#21505)
teknium1 May 10, 2026
5942093
fix(xai): drop models being retired May 15, 2026 from pickers (#23291)
teknium1 May 10, 2026
a282434
feat(gateway): per-platform admin/user split for slash commands (salv…
teknium1 May 10, 2026
6e5c49b
refactor(kanban-orchestrator): drop hardcoded specialist roster, add …
teknium1 May 10, 2026
878611a
feat(session): add /handoff command for cross-platform session transfer
kshitijk4poor May 9, 2026
00ce5f0
feat(session): make /handoff actually transfer the session live
teknium1 May 10, 2026
4d9dcbc
fix(windows): unbreak install + update on Windows (#23394)
teknium1 May 10, 2026
373c4d6
docs(sessions): document /handoff cross-platform session transfer (#2…
teknium1 May 10, 2026
861ce7c
fix: dedupe kanban notifier delivery claims
quocanh261997 May 9, 2026
9c68d12
test(kanban): cover send-exception rewind + drop noisy success log to…
teknium1 May 10, 2026
6062c24
ci: skip lint comment on fork PRs
quocanh261997 May 9, 2026
cdb6e5e
test(conftest): block tests from killing the live hermes-gateway (#23…
teknium1 May 10, 2026
4eb8479
fix(gateway): delete partial message after fallback send on flood con…
HuangYuChuh Apr 29, 2026
ec1fad3
fix(gateway): align fallback delete with sibling style + add regressi…
teknium1 May 10, 2026
04e1816
chore: AUTHOR_MAP entry for HuangYuChuh
teknium1 May 10, 2026
a96dd54
fix: deduplicate kanban notifications for blocked/gave_up states
jelrod27 May 7, 2026
787e3c3
test(kanban): cover redeliver-on-cycle + flip stale unsub-on-abnormal…
teknium1 May 10, 2026
b38b100
chore: AUTHOR_MAP entry for jelrod27 (#21398)
teknium1 May 10, 2026
6636fec
fix(gateway): only mark final response sent when split-overflow chunk…
teknium1 May 10, 2026
ff14666
fix(gateway): stream consumer first message drops thread context
hrygo May 10, 2026
e164a9c
fix(stream-consumer): preserve thread routing on overflow first-send …
hotplex-ai May 9, 2026
f9e0d60
test(thread-routing): handle both lark-SDK-present and absent paths
teknium1 May 10, 2026
cc2a0c6
chore: AUTHOR_MAP entry for hrygo (黄飞虹)
teknium1 May 10, 2026
d6e1fad
fix(xai): omit reasoning.effort for grok models that reject it (#23435)
teknium1 May 10, 2026
3974a13
docs(user-stories): add 116 stories from the Hermes Discord archive (…
teknium1 May 10, 2026
88588b6
fix(kanban): extend stale claim instead of killing live worker
konsisumer May 10, 2026
59d3f24
chore: AUTHOR_MAP entry for konsisumer noreply (#23071)
teknium1 May 10, 2026
a2920b1
fix(tui): right-click copies selection, only pastes when no selection
wesleysimplicio May 9, 2026
2f00559
fix(telegram): pass source.thread_id explicitly on auto-reset notice …
keyuyuan May 10, 2026
62cfe79
fix(tools): clarify kanban_complete phantom-card retry guidance
konsisumer May 10, 2026
c5f1f86
fix(cli): drive _prompt_text_input directly when off main thread (#23…
teknium1 May 10, 2026
c0da5d0
fix: use UTF-16 length for Telegram stream consumer message splitting
freemanconsulting Apr 16, 2026
121bbe0
test(stream-consumer): add UTF-16 overflow regression tests for #11170
teknium1 May 10, 2026
c0bbdec
chore: AUTHOR_MAP entry for Freeman-Consulting
teknium1 May 10, 2026
404640a
feat(goals): /goal checklist + /subgoal user controls (#23456)
teknium1 May 10, 2026
737314f
fix(telegram): normalize dm threads and retry control sends
rahimsais May 10, 2026
666b751
chore: AUTHOR_MAP entry for rahimsais
teknium1 May 10, 2026
ae83a54
docs(kanban): worker lane contract page + review-required convention
teknium1 May 11, 2026
e5bce32
fix(auxiliary): evict cached client on timeout/connection error (#23482)
teknium1 May 11, 2026
771b8c4
test(conftest): plug every gateway-kill leak path (#23486)
teknium1 May 11, 2026
da2ed47
fix(achievements): inject Authorization header in plugin API calls
May 10, 2026
80bb5f2
fix(achievements): use canonical X-Hermes-Session-Token header
teknium1 May 11, 2026
4ed293b
feat(telegram): native draft streaming via sendMessageDraft (Bot API …
NivOO5 May 11, 2026
7f90141
test(telegram): native-draft transport coverage + docs
teknium1 May 11, 2026
9e005d6
chore: AUTHOR_MAP entry for NivOO5
teknium1 May 11, 2026
ba5640f
fix(gateway): route kanban notifications to creator profile
quocanh261997 May 11, 2026
68d081f
fix(kanban): keep '--created-by' default as 'user'
teknium1 May 11, 2026
4a080b1
fix(goals): forward standing /goal state on auto-compression session …
teknium1 May 11, 2026
a63a2b7
fix(goals): force judge to use tool calls instead of JSON-text replie…
teknium1 May 11, 2026
518d37f
feat(kanban): add reclaim_first support to bulk reassign endpoint
May 10, 2026
0ea234e
feat(kanban): dashboard batch QOL upgrade
May 10, 2026
98c499b
kanban dashboard: fix batch QOL oracle blockers
May 10, 2026
a88f201
kanban dashboard: multi-card drag visual feedback
May 10, 2026
6905383
kanban dashboard: remove redundant t.summary from search haystack
May 10, 2026
3df7e30
kanban dashboard: fix shift-click range selection, column select-all …
May 10, 2026
b60462a
test(kanban): remove stale t.summary assertion from search test
eloklam May 10, 2026
b8bf2f8
fix(kanban): merge dashboard batch QOL with i18n + collapse + assigne…
teknium1 May 11, 2026
bf5b8a7
chore(release): map @eloklam tailnet email
teknium1 May 11, 2026
3b122cc
feat(kanban): stranded_in_ready diagnostic for unclaimed tasks (#23578)
teknium1 May 11, 2026
bf1f409
fix(telegram): split-and-deliver oversized edits instead of silent tr…
May 11, 2026
82352e5
test(telegram): regression coverage for edit overflow split-and-deliver
teknium1 May 11, 2026
6c1af45
chore: AUTHOR_MAP entry for kjames2001 (James Huang)
teknium1 May 11, 2026
4c57a5b
feat(skills): add api-testing optional skill (#1800)
eren-karakus0 May 11, 2026
f6736ce
fix(security): sanitize env and redact output in quick commands + rem…
0xbyt4 Mar 17, 2026
28b4fe6
test: stabilize quick-command redaction test against xdist ordering
teknium1 May 11, 2026
f2e8ed2
Add unit tests for hyperliquid skill functionality
Hugo-SEQUIER Mar 18, 2026
1f89939
chore(skills/hyperliquid): tighten SKILL.md to modern format
teknium1 May 11, 2026
5f76787
chore(release): AUTHOR_MAP entry for Hugo-SEQUIER
teknium1 May 11, 2026
e3b88a8
rename(skills): api-testing -> rest-graphql-debug (#23589)
teknium1 May 11, 2026
ac95b8c
perf(gateway): tune Telegram cadence + adaptive fast-path for short r…
wilsen0 May 11, 2026
edb4a2b
test(telegram): cover env-clamped helper + adaptive text-batch tiers
teknium1 May 11, 2026
482d49c
chore: AUTHOR_MAP entry for wilsen0
teknium1 May 11, 2026
3af3c4e
fix(misc): three small defensive fixes from PR #1974
Gutslabs May 11, 2026
228a4d1
fix(config): warn loudly on YAML parse failure instead of silent defa…
teknium1 May 11, 2026
bf2cc8b
Merge pull request #20317 from NousResearch/meta/security-policy
jquesnelle May 11, 2026
896a7ce
feat: add stocks & finance skill (Yahoo Finance, no API key)
Mar 19, 2026
2ea957f
chore(skills/stocks): relocate to optional-skills/finance/stocks/
teknium1 May 11, 2026
9526040
chore(skills/stocks): tighten SKILL.md to modern format
teknium1 May 11, 2026
0458d99
chore(release): AUTHOR_MAP entry for Mibayy clawhub email
teknium1 May 11, 2026
ace1c4e
fix(discord): typing indicator task not cleaned up after API error
0xbyt4 Mar 22, 2026
228b7d2
fix(auxiliary): cache 402'd providers as unhealthy with TTL to stop p…
teknium1 May 11, 2026
ebf2ea5
feat(terminal,cli): docker_extra_args + display.timestamps
Mibayy May 11, 2026
d992fd9
feat(deps): add hindsight-client as optional dependency (#21818)
alt-glitch May 11, 2026
5606258
feat(nix): add extraDependencyGroups for sealed venv extras (#21817)
alt-glitch May 11, 2026
64145a1
fix(nix): replace chown -R with targeted find in container entrypoint…
alt-glitch May 11, 2026
f6d4f3c
fix(kanban): route gateway create auto-subscribe to explicit board
Frowtek May 10, 2026
2b3bf17
fix(kanban): call kanban_block on iteration-budget exhaustion to prev…
liuhao1024 May 10, 2026
641e40c
fix(kanban): restore HERMES_KANBAN_BOARD after scoped slash override
Sylw3ster May 10, 2026
5af315c
fix(kanban): inject HERMES_HOME into worker subprocess env
TurgutKural May 10, 2026
8ac998c
fix(send_message): allow kanban workers to call send_message
dmnkhorvath May 10, 2026
379e7dd
test(send_message): cover _check_send_message gating paths
dmnkhorvath May 10, 2026
27cfe72
fix(kanban): use localized column label in select-all aria label
smwbev May 11, 2026
a1854ac
fix(kanban): treat archived parent tasks as terminal for dependency r…
Ninso112 May 10, 2026
7087702
chore: add salvage contributors to AUTHOR_MAP
kshitijk4poor May 11, 2026
5712483
fix: guard resolve_profile_env against missing profile dirs
kshitijk4poor May 11, 2026
494824f
chore: remove unused sentinel in test_send_message_tool
kshitijk4poor May 11, 2026
9520a1c
fix(terminal): block sudo -S password guessing when SUDO_PASSWORD is …
May 9, 2026
976d8e2
fix(approval): catch sudo with stdin/askpass/shell privilege flags
fr33d3m0n May 7, 2026
1d4a499
chore: AUTHOR_MAP entries for sudo-hardening salvage contributors
kshitijk4poor May 11, 2026
3e7145e
revert: roll back /goal checklist + /subgoal feature stack (#23813)
teknium1 May 11, 2026
7026af4
fix(agent): catch ChatGPT-account Codex data-URL rejection so images …
teknium1 May 11, 2026
a479ec0
fix: make web UI build output decoding robust on Windows
VinceZcrikl May 11, 2026
88a2ce4
chore: AUTHOR_MAP entry for VinceZcrikl noreply (#23647)
teknium1 May 11, 2026
7085f4e
fix(dashboard): fallback to stale dist, retry build, add --skip-build…
ygd58 May 11, 2026
283381b
fix(dashboard): validate dist exists when --skip-build is set
teknium1 May 11, 2026
e155f2a
rebuild model catalog
rob-maron May 11, 2026
054f568
fix: use TUI modal for slash confirmations
zhengyn0001 May 11, 2026
cc9e788
fix(cli): defensive _slash_confirm_state access + AUTHOR_MAP
teknium1 May 11, 2026
8e2eb4b
fix(/model): surface Nous Portal models from remote catalog manifest …
teknium1 May 11, 2026
6578744
chore: ruff auto-fixes — collapsible-else-if, if-stmt-min-max, dict.f…
kshitijk4poor May 11, 2026
1d00716
fix(cli,tui): align CJK / wide-char markdown tables (#23863)
teknium1 May 11, 2026
111b859
fix(auxiliary): evict async wrappers on poisoned client (follow-up to…
wuli666 May 11, 2026
8c11710
chore(release): add AUTHOR_MAP entry for wuli666
teknium1 May 11, 2026
2ec8d2b
chore: ruff auto-fix PLR6201 — tuple → set in membership tests (#23937)
kshitijk4poor May 11, 2026
7b76366
feat(prompt-cache): cross-session 1h prefix cache for Claude on Anthr…
teknium1 May 11, 2026
ce0f529
chore: ruff auto-fix C401, C416, C408, PLR1722 (#23940)
kshitijk4poor May 11, 2026
2718834
feat: expose HERMES_SESSION_ID to agent tools via ContextVar + env (#…
alt-glitch May 11, 2026
3197b4d
Merge remote-tracking branch 'origin/main' into fix/bundle-size
ethernet8023 May 11, 2026
91eef62
fix: correct context-length resolution for kimi-k2.6 on Ollama Cloud …
kshitijk4poor May 11, 2026
e2b713c
fix(model-metadata): skip OpenRouter for known providers, add kimi/mo…
nicoechaniz May 11, 2026
9a63b5f
chore: add nicoechaniz to AUTHOR_MAP
kshitijk4poor May 11, 2026
c6ca116
refactor(tui): simplify TUI build logic, remove stale staleness checks
ethernet8023 May 11, 2026
75b428c
feat(ui-tui): resolve markdown links to readable page titles (#24013)
OutThisLife May 11, 2026
825bd50
Merge pull request #18036 from NousResearch/fix/bundle-size
ethernet8023 May 11, 2026
ea1d046
fix(cli): vertical fallback for markdown tables wider than terminal (…
teknium1 May 11, 2026
05bad7b
fix(dashboard): MiniMax 'Login' button launched Claude OAuth (#22832)
ahmedbadr3 May 9, 2026
97a0e69
chore(release): add AUTHOR_MAP entry for ahmedbadr3
teknium1 May 11, 2026
ced1990
feat(computer-use): refresh cua-driver on `hermes update` + add `inst…
teknium1 May 12, 2026
e855925
fix(nous): surface Portal-flagged free models in picker even when cur…
teknium1 May 12, 2026
3c23b15
fix(tui-clipboard): skip native safety net on OSC52-capable terminals…
benbarclay May 12, 2026
7993e03
fix(cache): route Nous Portal Qwen through Portal-Claude cache pathwa…
teknium1 May 12, 2026
528bba6
fix kimi
rob-maron May 12, 2026
057fc7b
fix guard
rob-maron May 12, 2026
f0c2964
remove comments
rob-maron May 12, 2026
32abe74
fix comment
rob-maron May 12, 2026
58e2109
fix(minimax): harden OAuth dashboard and runtime
austinpickett May 12, 2026
94d9db7
add client marker tag on aux inference requests
rewbs May 12, 2026
407683b
fix(docs): repair Voice & TTS provider table
May 12, 2026
99ad2d1
fix(deps): unbreak [all] install — drop mistralai while PyPI quaranti…
teknium1 May 12, 2026
c1eb2dc
feat(security): supply-chain advisory checker + lazy-install framewor…
teknium1 May 12, 2026
dd0923b
docs: remove public advisory page (handle community comms separately)…
teknium1 May 12, 2026
0a672f5
chore: sync with upstream main (2026-05-12)
bot-ted May 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
4 changes: 2 additions & 2 deletions acp_adapter/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,8 @@ def _build_patch_mode_content(patch_text: str) -> List[Any]:
old_chunks: list[str] = []
new_chunks: list[str] = []
for hunk in op.hunks:
old_lines = [line.content for line in hunk.lines if line.prefix in (" ", "-")]
new_lines = [line.content for line in hunk.lines if line.prefix in (" ", "+")]
old_lines = [line.content for line in hunk.lines if line.prefix in {" ", "-"}]
new_lines = [line.content for line in hunk.lines if line.prefix in {" ", "+"}]
if old_lines or new_lines:
old_chunks.append("\n".join(old_lines))
new_chunks.append("\n".join(new_lines))
Expand Down
2 changes: 1 addition & 1 deletion agent/account_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _title_case_slug(value: Optional[str]) -> Optional[str]:


def _parse_dt(value: Any) -> Optional[datetime]:
if value in (None, ""):
if value in {None, ""}:
return None
if isinstance(value, (int, float)):
return datetime.fromtimestamp(float(value), tz=timezone.utc)
Expand Down
24 changes: 20 additions & 4 deletions agent/anthropic_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ def _get_anthropic_sdk():
"""Return the ``anthropic`` SDK module, importing lazily. None if not installed."""
global _anthropic_sdk
if _anthropic_sdk is ...:
try:
from tools.lazy_deps import ensure as _lazy_ensure
_lazy_ensure("provider.anthropic", prompt=False)
except ImportError:
pass
except Exception:
# FeatureUnavailable — fall through to ImportError handling below
pass
try:
import anthropic as _sdk
_anthropic_sdk = _sdk
Expand Down Expand Up @@ -1289,13 +1297,21 @@ def convert_tools_to_anthropic(tools: List[Dict]) -> List[Dict]:
continue
if name:
seen_names.add(name)
result.append({
anthropic_tool: Dict[str, Any] = {
"name": name,
"description": fn.get("description", ""),
"input_schema": _normalize_tool_input_schema(
fn.get("parameters", {"type": "object", "properties": {}})
),
})
}
# Forward cache_control marker when present on the OpenAI-format
# tool dict (set by ``mark_tools_for_long_lived_cache``). Anthropic's
# tools array supports cache_control on the last tool to cache the
# entire schema cross-session.
cache_control = t.get("cache_control")
if isinstance(cache_control, dict):
anthropic_tool["cache_control"] = dict(cache_control)
result.append(anthropic_tool)
return result


Expand Down Expand Up @@ -1537,7 +1553,7 @@ def convert_messages_to_anthropic(
# downgraded to a spurious text block on the last assistant message.
reasoning_content = m.get("reasoning_content")
_already_has_thinking = any(
isinstance(b, dict) and b.get("type") in ("thinking", "redacted_thinking")
isinstance(b, dict) and b.get("type") in {"thinking", "redacted_thinking"}
for b in blocks
)
if isinstance(reasoning_content, str) and not _already_has_thinking:
Expand Down Expand Up @@ -1688,7 +1704,7 @@ def convert_messages_to_anthropic(
if isinstance(m["content"], list):
m["content"] = [
b for b in m["content"]
if not (isinstance(b, dict) and b.get("type") in ("thinking", "redacted_thinking"))
if not (isinstance(b, dict) and b.get("type") in {"thinking", "redacted_thinking"})
]
prev_blocks = fixed[-1]["content"]
curr_blocks = m["content"]
Expand Down
59 changes: 37 additions & 22 deletions agent/auxiliary_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def _normalize_aux_provider(provider: Optional[str]) -> str:
# Resolve to the user's actual main provider so named custom providers
# and non-aggregator providers (DeepSeek, Alibaba, etc.) work correctly.
main_prov = (_read_main_provider() or "").strip().lower()
if main_prov and main_prov not in ("auto", "main", ""):
if main_prov and main_prov not in {"auto", "main", ""}:
normalized = main_prov
else:
return "custom"
Expand Down Expand Up @@ -382,7 +382,7 @@ def build_or_headers(or_config: dict | None = None) -> dict:
# Nous Portal extra_body for product attribution.
# Callers should pass this as extra_body in chat.completions.create()
# when the auxiliary client is backed by Nous Portal.
NOUS_EXTRA_BODY = {"tags": ["product=hermes-agent"]}
NOUS_EXTRA_BODY = {"tags": ["product=hermes-agent", "client=aux"]}

# Set at resolve time — True if the auxiliary client points to Nous Portal
auxiliary_is_nous: bool = False
Expand Down Expand Up @@ -578,7 +578,7 @@ def _convert_content_for_responses(content: Any) -> Any:
if detail:
entry["detail"] = detail
converted.append(entry)
elif ptype in ("input_text", "input_image"):
elif ptype in {"input_text", "input_image"}:
# Already in Responses format — pass through
converted.append(part)
else:
Expand Down Expand Up @@ -798,7 +798,7 @@ def _item_get(obj: Any, key: str, default: Any = None) -> Any:
if item_type == "message":
for part in (_item_get(item, "content") or []):
ptype = _item_get(part, "type")
if ptype in ("output_text", "text"):
if ptype in {"output_text", "text"}:
text_parts.append(_item_get(part, "text", ""))
elif item_type == "function_call":
tool_calls_raw.append(SimpleNamespace(
Expand Down Expand Up @@ -900,6 +900,14 @@ def __init__(self, sync_wrapper: "CodexAuxiliaryClient"):
self.chat = _AsyncCodexChatShim(async_adapter)
self.api_key = sync_wrapper.api_key
self.base_url = sync_wrapper.base_url
# Mirror the sync wrapper's _real_client so cache eviction by leaf
# OpenAI client (e.g. _close_client_on_timeout in #23482) drops
# this async entry too. Without this, sync and async cache entries
# diverge on poisoning: the sync entry is evicted but the async
# entry keeps reusing the closed transport, failing every
# subsequent async aux call with 'Connection error' until the
# gateway restarts.
self._real_client = sync_wrapper._real_client


class _AnthropicCompletionsAdapter:
Expand Down Expand Up @@ -1035,6 +1043,9 @@ def __init__(self, sync_wrapper: "AnthropicAuxiliaryClient"):
self.chat = _AsyncAnthropicChatShim(async_adapter)
self.api_key = sync_wrapper.api_key
self.base_url = sync_wrapper.base_url
# See AsyncCodexAuxiliaryClient: mirror _real_client so cache
# eviction on a poisoned underlying client also drops this entry.
self._real_client = sync_wrapper._real_client


def _endpoint_speaks_anthropic_messages(base_url: str) -> bool:
Expand Down Expand Up @@ -1949,7 +1960,7 @@ def _is_payment_error(exc: Exception) -> bool:
err_lower = str(exc).lower()
# OpenRouter and other providers include "credits" or "afford" in 402 bodies,
# but sometimes wrap them in 429 or other codes.
if status in (402, 429, None):
if status in {402, 429, None}:
if any(kw in err_lower for kw in ("credits", "insufficient funds",
"can only afford", "billing",
"payment required")):
Expand Down Expand Up @@ -2108,9 +2119,13 @@ def _evict_cached_client_instance(target: Any) -> bool:
transport after a timeout, broken streaming session, etc.) so the next
auxiliary call rebuilds rather than reusing the dead instance.

Walks ``CodexAuxiliaryClient`` wrappers via their ``_real_client`` so a
timeout that closes the underlying ``OpenAI`` client also evicts the
Codex shim that exposed it.
Walks both sync and async wrappers (``CodexAuxiliaryClient``,
``AnthropicAuxiliaryClient``, ``AsyncCodexAuxiliaryClient``, etc.) via
their ``_real_client`` attribute so a timeout that closes the underlying
``OpenAI`` (or native provider) client evicts every cached shim that
exposed it. Async wrappers must mirror their sync sibling's
``_real_client`` for this to work — otherwise the sync entry is evicted
but the async entry survives and keeps reusing the dead transport.

Returns True when at least one entry was evicted.
"""
Expand Down Expand Up @@ -2142,7 +2157,7 @@ def _pool_cache_hint(
if normalized == "auto":
runtime = _normalize_main_runtime(main_runtime)
normalized = _normalize_aux_provider(runtime.get("provider") or _read_main_provider())
if normalized in ("", "auto", "custom"):
if normalized in {"", "auto", "custom"}:
return ""
entry = _peek_pool_entry(normalized)
if entry is None:
Expand All @@ -2164,7 +2179,7 @@ def _pool_error_context(exc: Exception) -> Dict[str, Any]:
def _recoverable_pool_provider(resolved_provider: str, client: Any) -> Optional[str]:
"""Infer which provider pool can recover the current auxiliary client."""
normalized = _normalize_aux_provider(resolved_provider)
if normalized not in ("", "auto", "custom"):
if normalized not in {"", "auto", "custom"}:
return normalized
base = str(getattr(client, "base_url", "") or "")
if base_url_host_matches(base, "chatgpt.com"):
Expand Down Expand Up @@ -2481,7 +2496,7 @@ def _resolve_auto(main_runtime: Optional[Dict[str, Any]] = None) -> Tuple[Option
main_provider = runtime_provider or _read_main_provider()
main_model = runtime_model or _read_main_model()
if (main_provider and main_model
and main_provider not in ("auto", "")):
and main_provider not in {"auto", ""}):
resolved_provider = main_provider
explicit_base_url = None
explicit_api_key = None
Expand Down Expand Up @@ -3142,7 +3157,7 @@ def _wrap_if_needed(client_obj, final_model_str: str, base_url_str: str = "",
return (_to_async_client(client, final_model, is_vision=is_vision) if async_mode
else (client, final_model))

elif pconfig.auth_type in ("oauth_device_code", "oauth_external"):
elif pconfig.auth_type in {"oauth_device_code", "oauth_external"}:
# OAuth providers — route through their specific try functions
if provider == "nous":
return resolve_provider_client("nous", model, async_mode)
Expand Down Expand Up @@ -3251,7 +3266,7 @@ def get_available_vision_backends() -> List[str]:
available: List[str] = []
# 1. Active provider — if the user configured a provider, try it first.
main_provider = _read_main_provider()
if main_provider and main_provider not in ("auto", ""):
if main_provider and main_provider not in {"auto", ""}:
if main_provider in _VISION_AUTO_PROVIDER_ORDER:
if _strict_vision_backend_available(main_provider):
available.append(main_provider)
Expand Down Expand Up @@ -3297,7 +3312,7 @@ def _finalize(resolved_provider: str, sync_client: Any, default_model: Optional[

if resolved_base_url:
provider_for_base_override = (
requested if requested and requested not in ("", "auto") else "custom"
requested if requested and requested not in {"", "auto"} else "custom"
)
client, final_model = resolve_provider_client(
provider_for_base_override,
Expand Down Expand Up @@ -3325,7 +3340,7 @@ def _finalize(resolved_provider: str, sync_client: Any, default_model: Optional[
# 4. Stop
main_provider = _read_main_provider()
main_model = _read_main_model()
if main_provider and main_provider not in ("auto", ""):
if main_provider and main_provider not in {"auto", ""}:
vision_model = _PROVIDER_VISION_MODELS.get(main_provider, main_model)
if main_provider == "nous":
sync_client, default_model = _resolve_strict_vision_backend(
Expand Down Expand Up @@ -4011,7 +4026,7 @@ def _build_call_kwargs(
# Provider-specific extra_body
merged_extra = dict(extra_body or {})
if provider == "nous" or auxiliary_is_nous:
merged_extra.setdefault("tags", []).extend(["product=hermes-agent"])
merged_extra.setdefault("tags", []).extend(NOUS_EXTRA_BODY["tags"])
if merged_extra:
kwargs["extra_body"] = merged_extra

Expand Down Expand Up @@ -4131,7 +4146,7 @@ def call_llm(
# credentials were found, fail fast instead of silently routing
# through OpenRouter (which causes confusing 404s).
_explicit = (resolved_provider or "").strip().lower()
if _explicit and _explicit not in ("auto", "openrouter", "custom"):
if _explicit and _explicit not in {"auto", "openrouter", "custom"}:
raise RuntimeError(
f"Provider '{_explicit}' is set in config.yaml but no API key "
f"was found. Set the {_explicit.upper()}_API_KEY environment "
Expand Down Expand Up @@ -4261,7 +4276,7 @@ def call_llm(

# ── Auth refresh retry ───────────────────────────────────────
if (_is_auth_error(first_err)
and resolved_provider not in ("auto", "", None)
and resolved_provider not in {"auto", "", None}
and not client_is_nous):
if _refresh_provider_credentials(resolved_provider):
logger.info(
Expand Down Expand Up @@ -4344,7 +4359,7 @@ def call_llm(
# Only try alternative providers when the user didn't explicitly
# configure this task's provider. Explicit provider = hard constraint;
# auto (the default) = best-effort fallback chain. (#7559)
is_auto = resolved_provider in ("auto", "", None)
is_auto = resolved_provider in {"auto", "", None}
if should_fallback and is_auto:
if _is_payment_error(first_err):
reason = "payment error"
Expand Down Expand Up @@ -4500,7 +4515,7 @@ async def async_call_llm(
)
if client is None:
_explicit = (resolved_provider or "").strip().lower()
if _explicit and _explicit not in ("auto", "openrouter", "custom"):
if _explicit and _explicit not in {"auto", "openrouter", "custom"}:
raise RuntimeError(
f"Provider '{_explicit}' is set in config.yaml but no API key "
f"was found. Set the {_explicit.upper()}_API_KEY environment "
Expand Down Expand Up @@ -4611,7 +4626,7 @@ async def async_call_llm(

# ── Auth refresh retry (mirrors sync call_llm) ───────────────
if (_is_auth_error(first_err)
and resolved_provider not in ("auto", "", None)
and resolved_provider not in {"auto", "", None}
and not client_is_nous):
if _refresh_provider_credentials(resolved_provider):
logger.info(
Expand Down Expand Up @@ -4673,7 +4688,7 @@ async def async_call_llm(
or _is_connection_error(first_err)
or _is_rate_limit_error(first_err)
)
is_auto = resolved_provider in ("auto", "", None)
is_auto = resolved_provider in {"auto", "", None}
if should_fallback and is_auto:
if _is_payment_error(first_err):
reason = "payment error"
Expand Down
17 changes: 8 additions & 9 deletions agent/context_compressor.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def _strip_image_parts_from_parts(parts: Any) -> Any:
out.append(part)
continue
ptype = part.get("type")
if ptype in ("image", "image_url", "input_image"):
if ptype in {"image", "image_url", "input_image"}:
had_image = True
out.append({"type": "text", "text": "[screenshot removed to save context]"})
else:
Expand Down Expand Up @@ -274,8 +274,8 @@ def _summarize_tool_result(tool_name: str, tool_args: str, tool_content: str) ->
mode = args.get("mode", "replace")
return f"[patch] {mode} in {path} ({content_len:,} chars result)"

if tool_name in ("browser_navigate", "browser_click", "browser_snapshot",
"browser_type", "browser_scroll", "browser_vision"):
if tool_name in {"browser_navigate", "browser_click", "browser_snapshot",
"browser_type", "browser_scroll", "browser_vision"}:
url = args.get("url", "")
ref = args.get("ref", "")
detail = f" {url}" if url else (f" ref={ref}" if ref else "")
Expand Down Expand Up @@ -304,7 +304,7 @@ def _summarize_tool_result(tool_name: str, tool_args: str, tool_content: str) ->
code_preview += "..."
return f"[execute_code] `{code_preview}` ({line_count} lines output)"

if tool_name in ("skill_view", "skills_list", "skill_manage"):
if tool_name in {"skill_view", "skills_list", "skill_manage"}:
name = args.get("name", "?")
return f"[{tool_name}] name={name} ({content_len:,} chars)"

Expand Down Expand Up @@ -979,13 +979,13 @@ def _generate_summary(self, turns_to_summarize: List[Dict[str, Any]], focus_topi
_status = getattr(e, "status_code", None) or getattr(getattr(e, "response", None), "status_code", None)
_err_str = str(e).lower()
_is_model_not_found = (
_status in (404, 503)
_status in {404, 503}
or "model_not_found" in _err_str
or "does not exist" in _err_str
or "no available channel" in _err_str
)
_is_timeout = (
_status in (408, 429, 502, 504)
_status in {408, 429, 502, 504}
or "timeout" in _err_str
)
# Non-JSON / malformed-body responses from misconfigured providers
Expand Down Expand Up @@ -1316,8 +1316,7 @@ def _find_tail_cut_by_tokens(

# Ensure we protect at least min_tail messages
fallback_cut = n - min_tail
if cut_idx > fallback_cut:
cut_idx = fallback_cut
cut_idx = min(cut_idx, fallback_cut)

# If the token budget would protect everything (small conversations),
# force a cut after the head so compression can still remove middle turns.
Expand Down Expand Up @@ -1480,7 +1479,7 @@ def compress(self, messages: List[Dict[str, Any]], current_tokens: int = None, f
first_tail_role = messages[compress_end].get("role", "user") if compress_end < n_messages else "user"
# Pick a role that avoids consecutive same-role with both neighbors.
# Priority: avoid colliding with head (already committed), then tail.
if last_head_role in ("assistant", "tool"):
if last_head_role in {"assistant", "tool"}:
summary_role = "user"
else:
summary_role = "assistant"
Expand Down
2 changes: 1 addition & 1 deletion agent/credential_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def to_dict(self) -> Dict[str, Any]:
}
result: Dict[str, Any] = {}
for field_def in fields(self):
if field_def.name in ("provider", "extra"):
if field_def.name in {"provider", "extra"}:
continue
value = getattr(self, field_def.name)
if value is not None or field_def.name in _ALWAYS_EMIT:
Expand Down
Loading
Loading