Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
735 commits
Select commit Hold shift + click to select a range
b1d420e
fix(kanban): avoid fragile failure-column renames
helix4u May 6, 2026
a2ff193
chore: follow-up cleanup for Kanban migration fix
kshitijk4poor May 6, 2026
a345f7b
Merge pull request #19908 from NousResearch/typecheck
ethernet8023 May 6, 2026
946ef0e
fix(tui): bound virtual history offset searches
asheriif May 5, 2026
f4031df
ci(docker): don't cancel overlapping builds, guard :latest
ethernet8023 May 6, 2026
d514dd4
docs(tool-gateway): rewrite as pitch-first marketing page (#20827)
teknium1 May 6, 2026
33bf5f6
fix(auth): fall back to global-root auth.json for providers missing i…
teknium1 May 6, 2026
b71f80e
feat(gateway): per-platform gateway_restart_notification flag
guillaumemeyer May 6, 2026
7df6115
feat(gateway): also gate pre-restart "Gateway restarting" notification
guillaumemeyer May 6, 2026
d8b85bf
chore: add guillaumemeyer to AUTHOR_MAP
teknium1 May 6, 2026
5044e1c
fix(cli): submit LF enter in thin PTYs (#20896)
OutThisLife May 6, 2026
da60198
fix(tui): refresh virtual offsets after row resize (#20898)
OutThisLife May 6, 2026
f1a8e99
fix(tui): honor skin highlight colors (#20895)
OutThisLife May 6, 2026
53a0249
Merge pull request #20890 from NousResearch/fix/docker-push
ethernet8023 May 6, 2026
5ccab51
fix(tui): steady transcript scrollbar (#20917)
OutThisLife May 6, 2026
04cf478
fix(tui): restore voice push-to-talk parity (#20897)
OutThisLife May 6, 2026
3cdbf33
fix(gateway): don't dead-end setup wizard when only system-scope unit…
teknium1 May 6, 2026
65c762b
fix(tui): preserve session when switching personality
austinpickett May 6, 2026
d797755
fix(gateway): wait for systemd restart readiness
helix4u May 6, 2026
5a3cadf
fix(discord): narrow rate-limit catch and move sync state under gateway/
teknium1 May 7, 2026
45cbf93
docs(kanban): fix orchestrator skill setup instructions (#20958)
helix4u May 7, 2026
49c3c2e
docs(kanban): fix worker skill setup instructions too (#20960)
teknium1 May 7, 2026
51f9953
feat(profiles): --no-skills flag for empty profile creation (#20986)
teknium1 May 7, 2026
bd0c54d
fix: route Telegram image documents through photo handling
mrcoferland May 2, 2026
e7eb07c
chore: AUTHOR_MAP entry for mrcoferland
teknium1 May 7, 2026
033e533
test(docker): align Dockerfile contract tests with simplified TUI flow
Sanjays2402 May 2, 2026
595bcc8
test(update): patch isatty on real streams to fix xdist-flaky --yes t…
Sanjays2402 May 2, 2026
a5c9c83
fix(web): force light color-scheme on docs iframe
counterposition May 4, 2026
7d36e83
fix(security): close TOCTOU window when saving MCP OAuth credentials
Gutslabs May 7, 2026
aa56903
chore(release): add Gutslabs to AUTHOR_MAP for PR #21148 salvage
teknium1 May 7, 2026
1f27ca6
test(update): teach restart-mocks about the post-update survivor sweep
Sanjays2402 May 2, 2026
11b9b14
fix(image-routing): expose attached image paths in native multimodal …
briandevans May 3, 2026
fce58cb
feat(optional-skills): port Anthropic financial-services skills as op…
teknium1 May 7, 2026
d4de7d4
test(skills): cover additional rescan paths in skill_commands cache (…
Tranquil-Flow May 3, 2026
7c0766e
fix(gateway): translate inbound document host paths to container path…
ambition0802 May 2, 2026
bf843ad
feat(gateway): opt-in cleanup of temporary progress bubbles (#21186)
teknium1 May 7, 2026
40b51c9
fix(kanban): heartbeat tool extends claim TTL, not just last_heartbea…
stephen0110 May 7, 2026
63bd690
chore(release): map stephen0110 noreply email
teknium1 May 7, 2026
06f2435
fix(kanban): stop reclaimed workers before retry
LeonSGP43 May 7, 2026
b49a3f8
fix(kanban): reap completed worker children in dispatch_once
sonic-netizen May 7, 2026
595e906
chore(release): map sonic-netizen noreply email
teknium1 May 7, 2026
411cfa2
fix: auto-block repeated kanban retries
mwnickerson May 6, 2026
233bfd3
chore(release): map mwnickerson noreply email
teknium1 May 7, 2026
fad684b
feat(gateway): auto-resume interrupted sessions after restart
kyan12 May 6, 2026
961a353
fix(gateway): preserve resume marker on interrupted restart
kyan12 May 6, 2026
38b1c7d
refactor(gateway): simplify auto-resume + extend to crash recovery
teknium1 May 7, 2026
a84e56d
fix(auth): sync shared Nous refresh tokens
quocanh261997 May 5, 2026
429e785
refactor(auth): dedupe file-lock helper; document Nous lock order
teknium1 May 7, 2026
8a96fa4
fix(gateway): avoid duplicated responses history
thelumiereguy May 2, 2026
73d6371
chore: add AUTHOR_MAP entries for thelumiereguy and counterposition
teknium1 May 7, 2026
6e8f1e0
fix(gateway): use monotonic deadlines in QR onboarding flows
Zyproth May 5, 2026
2e00bca
fix(oauth,gateway): monotonic deadlines for polling/timeout loops
teknium1 May 7, 2026
3a0d52d
fix(weixin): replace all aiohttp ClientTimeout with asyncio.wait_for()
May 3, 2026
ecaafe5
test(weixin): update timeout assertion for asyncio.wait_for migration
teknium1 May 7, 2026
d856f45
chore: AUTHOR_MAP entry for chenlinfeng@ruije / @noOne-list
teknium1 May 7, 2026
fb1ce79
feat(security): enable secret redaction by default (#17691, #20785) (…
teknium1 May 7, 2026
8b32a9d
feat: add Discord message deletion action
May 3, 2026
991df4e
chore: AUTHOR_MAP entry for @likejudy
teknium1 May 7, 2026
042eb93
fix(security): close TOCTOU window in hermes_cli/auth.py credential w…
teknium1 May 7, 2026
6969203
fix(delegate): correct ACP docs — Claude Code CLI has no --acp flag
liuhao1024 May 3, 2026
5bf12eb
fix: exclude hidden and archive dirs from _find_skill rglob
Kailigithub May 3, 2026
176b935
fix(gateway): preserve thread routing from cached live session sources
Zyproth May 5, 2026
333598c
fix(gateway): cap cached session sources with LRU eviction
teknium1 May 7, 2026
4f364c4
fix(mcp): give 'mcp add --command' a distinct argparse dest
discodirector May 4, 2026
f0dd5b9
chore: add discodirector email to AUTHOR_MAP
teknium1 May 7, 2026
8d363f8
fix(bedrock): preserve reasoningContent across converse normalization
molvikar May 5, 2026
d34f03c
feat(gateway): support [[as_document]] directive for skill media routing
leon7609 May 3, 2026
e82f3b0
test: update send_message_tool mocks for force_document kwarg
teknium1 May 7, 2026
4e27e4e
chore: AUTHOR_MAP entry for @leon7609
teknium1 May 7, 2026
abe5a3c
fix(model_switch): live model discovery for custom_providers in /mode…
0oAstro May 3, 2026
7137ccc
fix(memory): support OpenViking local resource uploads
ggnnggez Apr 15, 2026
187951e
test(memory): harden OpenViking local upload coverage
ehz0ah May 4, 2026
2b6345c
fix(memory): harden OpenViking local path uploads
ehz0ah May 4, 2026
aa9a209
chore(release): add AUTHOR_MAP entries for ggnnggez and ehz0ah
teknium1 May 7, 2026
699c770
docs(readme): drop misleading RL install-extras claim, defer to CONTR…
deep-name May 3, 2026
fdb9e0f
fix(kanban): auto-block workers that exit without completing (#20894)…
teknium1 May 7, 2026
a0758cd
fix(dashboard): stabilize embedded chat resume and scrollback
nouseman666 May 3, 2026
8aceef5
fix(dashboard): let embedded chat use a single scroll system
nouseman666 May 3, 2026
7cbef2b
fix(dashboard): route browser wheel into inner TUI scrolling
nouseman666 May 3, 2026
eef2335
chore: AUTHOR_MAP entry for @nouseman666
teknium1 May 7, 2026
6d9b306
fix(cli): honor positive tool preview length
GinWU05 May 3, 2026
3c8154e
chore: AUTHOR_MAP entry for @GinWU05
teknium1 May 7, 2026
e38ea38
fix(credential_pool): resolve key mix-up when custom providers share …
May 3, 2026
103e119
feat(cli): show context compression count in status bar
TruaShamu May 1, 2026
f5a232a
refactor: replace 'cmp' text with 🗜️ emoji in status bar
TruaShamu May 2, 2026
3a82172
feat(tui): surface compression count in Ink status bar
teknium1 May 7, 2026
bda7b24
chore(release): map altriatree@gmail.com -> @TruaShamu
teknium1 May 7, 2026
6b9f714
fix(curator): make manual runs synchronous
LeonSGP43 May 6, 2026
6b3a9b4
docs(curator): update CLI docs for synchronous-by-default manual run
teknium1 May 7, 2026
d8d57fb
fix(install): remove uv exclude-newer cutoff
LeonSGP43 May 4, 2026
43a6645
docs: clarify API server tool execution locality
pingchesu May 3, 2026
36ad973
fix(kanban): treat dashboard event-stream cancellation as normal shut…
SandroHub013 May 6, 2026
a5f116f
chore(release): map SandroHub013 email
teknium1 May 7, 2026
fe4748e
test(kanban): regression for CancelledError swallow in stream_events
teknium1 May 7, 2026
61d9e33
fix(model_tools): log plugin hook exceptions instead of silently swal…
sprmn24 May 4, 2026
3c439ec
feat(gateway): add `hermes gateway list` to show all profiles' gatewa…
cixuuz May 3, 2026
c4a7992
fix(mcp-oauth): persist OAuth server metadata across process restarts…
teknium1 May 7, 2026
12289c2
feat: add SSE transport support for MCP client
andrewhosf May 3, 2026
0214858
fix(browser): enforce cloud-metadata SSRF floor in hybrid routing (#1…
teknium1 May 7, 2026
0d3593e
fix: WhatsApp bridge process leak and disable config asymmetry
liuhao1024 May 3, 2026
647f95b
docs(contributing): align tool discovery and test runner with AGENTS.md
xxxigm May 6, 2026
b9f1ac8
fix(kanban): make dashboard board pin authoritative over server curre…
teknium1 May 7, 2026
e9685a5
fix: avoid unsupported anthropic context beta by default
abhinav11082001-stack May 3, 2026
b12a5a7
Follow latest child session on dashboard resume
CCClelo May 3, 2026
6e250a5
fix(openviking): add Bearer auth header and omit empty/legacy tenant …
teknium1 May 7, 2026
c3be6ec
feat: add transform_llm_output plugin hook
JezzaHehn May 6, 2026
47bf5d7
test+docs: cover transform_llm_output hook + release author map
teknium1 May 7, 2026
ae1f058
feat(curator): add `hermes curator list-archived` command (#21236)
teknium1 May 7, 2026
5b24c0f
fix: require memory schema fields by action
altmazza0-star May 3, 2026
2c14d3b
fix(tui): refresh scroll height at cached bottom
counterposition May 6, 2026
8308d18
fix(gateway): preserve max turns after env reload
altmazza0-star May 3, 2026
ef1e565
fix(discord): scope DISCORD_ALLOWED_ROLES to originating guild (CVSS …
0xyg3n Apr 18, 2026
5c045b8
fix(discord): extend role-scope fix to slash surface + fixture update
teknium1 May 7, 2026
80717a1
fix(discord): route DM role-auth opt-in through config.yaml (not env …
teknium1 May 7, 2026
e735089
fix(agent): avoid persisting empty-response recovery scaffolding
wxst May 3, 2026
2021c18
fix(agent): drop terminal empty-response sentinels
wxst May 3, 2026
8dcdc3c
fix(auth): keep Spotify logout from resetting model config
LeonSGP43 May 3, 2026
6e46f99
fix(tui): surface backend error as visible text when final_response i…
teknium1 May 7, 2026
14f3882
fix(models): prefer image modalities for vision routing
LeonSGP43 May 3, 2026
5ead126
fix(doctor): retry DashScope China endpoint
LeonSGP43 May 3, 2026
5cf7032
fix(image-routing): sniff magic bytes for image MIME, ignore misleadi…
shashwatgokhe May 3, 2026
afbcca0
chore: AUTHOR_MAP entry for @shashwatgokhe
teknium1 May 7, 2026
84287b0
fix(docker): refuse root gateway runs in official image
LeonSGP43 May 3, 2026
9442a8f
fix(update): migrate config in non-interactive updates
stevenchouai May 3, 2026
8cef149
chore: AUTHOR_MAP entry for @stevenchouai
teknium1 May 7, 2026
31f2289
fix(matrix): defer reaction cleanup redactions
LeonSGP43 May 3, 2026
a494a61
fix(tui): avoid main-screen scrollback reset loops
LeonSGP43 May 3, 2026
7244a1f
fix(weixin): wrap long copy-unfriendly lines
LeonSGP43 May 3, 2026
c2d6b38
fix(windows): terminal drain and cwd path conversion for native Windows
alanxchen85 May 3, 2026
d12be46
fix(skills): lock usage telemetry updates
LeonSGP43 May 3, 2026
f648c2e
fix: use max_completion_tokens for GitHub Copilot
stormhierta May 3, 2026
4876959
fix(auth): shorten credential 401 cooldown
LeonSGP43 May 3, 2026
2f2f654
fix: add dashboard to CLI help epilogue and Docker CI smoke test
luoyuctl May 3, 2026
498c014
fix(docker): chown runtime node_modules trees to hermes user (#18800)
nudiltoys-cmyk May 3, 2026
b93c9f6
feat(kanban): convert inline-create title input to multiline textarea
JezzaHehn May 7, 2026
fa58274
fix(kanban): restore Enter=submit, Shift+Enter=newline in inline-crea…
teknium1 May 7, 2026
6ea4a6a
fix(vision): Z.AI vision model compatibility — endpoint routing and m…
agilejava May 3, 2026
fd13b7d
chore: AUTHOR_MAP entry for @agilejava
teknium1 May 7, 2026
5533ad7
fix(auxiliary): enforce Codex Responses stream timeout
acc001k May 7, 2026
cfe019c
chore: AUTHOR_MAP entry for @acc001k
teknium1 May 7, 2026
b739fcd
fix(security): require explicit allowlist or TEAMS_ALLOW_ALL_USERS op…
memosr May 3, 2026
a9c7bda
feat(image-gen): honor image_gen.model from config.yaml in plugin dis…
kowenhao May 3, 2026
fcd619c
chore: AUTHOR_MAP entry for @kowenhaoai
teknium1 May 7, 2026
98ca069
fix(gateway): log agent task failures instead of silently losing usag…
wabrent May 7, 2026
b7a97cd
chore: AUTHOR_MAP entry for wabrent
teknium1 May 7, 2026
9575bce
fix(mcp): clear stale thread interrupt before MCP discovery
AJV20 Apr 15, 2026
46d1fc1
chore(release): add AJV20 to AUTHOR_MAP for PR #10287 salvage
teknium1 May 7, 2026
5909526
fix(security): support SRI integrity verification for dashboard plugi…
memosr May 3, 2026
926402d
fix(gateway): surface bootstrap failures to stderr instead of silentl…
wabrent May 7, 2026
4d32f40
fix(gateway): include exception detail in bootstrap warning output
teknium1 May 7, 2026
a9ebee5
Fix WhatsApp long message splitting
hedirman May 3, 2026
25187ca
chore: AUTHOR_MAP entry for @hedirman
teknium1 May 7, 2026
80548f9
fix(mcp): report configured timeout in MCP call errors
masonjames Apr 15, 2026
8aa3040
chore(release): add masonjames to AUTHOR_MAP for PR #10439 salvage
teknium1 May 7, 2026
f7b71aa
fix: use configured model for gateway auth fallback
LucianoSP May 3, 2026
755b74f
chore: AUTHOR_MAP entry for @LucianoSP
teknium1 May 7, 2026
5d90611
fix(gateway): log platform status write failures instead of silently …
wabrent May 7, 2026
0efc547
fix(gateway): consolidate runtime-status writes + rate-limit failure …
teknium1 May 7, 2026
4d48075
fix(gateway): honor configured goal turn budget
paul-tian May 3, 2026
33563df
chore: AUTHOR_MAP entry for @paul-tian
teknium1 May 7, 2026
8ad117a
fix(models): add alibaba-coding-plan to _PROVIDER_MODELS curated list
TakeshiSawaguchi May 4, 2026
a1f85ef
fix(mcp): retry stale pipe transport failures
May 4, 2026
f481395
chore(release): add subtract0 to AUTHOR_MAP for PR #19935 salvage
teknium1 May 7, 2026
f9b4b8a
fix(mcp): include exception type in error messages when str(exc) is e…
liuhao1024 May 3, 2026
2c19212
feat(models): add paid tencent/hy3-preview route on OpenRouter (#21077)
Contentment003111 May 7, 2026
edbbc96
fix(cli): replace get_event_loop() with get_running_loop() to silence…
oluwadareab12 May 4, 2026
30c9990
chore: correct AUTHOR_MAP for oluwadareab12 (was mismapped to bennytimz)
teknium1 May 7, 2026
ec9d0e2
fix(tui): render structured content on resume
glesperance May 4, 2026
6769060
chore: AUTHOR_MAP entry for @glesperance
teknium1 May 7, 2026
52e2777
feat(dashboard): support serving under URL prefix via X-Forwarded-Prefix
cmcgrabby-hue May 4, 2026
a78e622
fix(agent): honor configured model max tokens
LeonSGP43 May 4, 2026
e795b7e
fix(delegate): expand composite toolsets before intersection in deleg…
luyao618 May 4, 2026
fc88eec
fix(compressor): soften summary prompt for content filters
LeonSGP43 May 4, 2026
76d2dcd
fix(kanban): make code/pre styling theme-immune across all themes (#2…
teknium1 May 7, 2026
6a4ecc0
fix(whatsapp): reject strangers by default, never respond in self-cha…
teknium1 May 7, 2026
cd3ef68
feat(slack): add allowed_channels whitelist config
CashWilliams Apr 10, 2026
f5c9bb5
chore(release): add CashWilliams to AUTHOR_MAP
teknium1 May 7, 2026
69d025e
feat(gateway): add allowed_{chats,channels,rooms} whitelist to Telegr…
teknium1 May 7, 2026
3924cb4
fix: strip Codex-hostile top-level schema combinators
hrkzogw May 7, 2026
5a3e5b2
fix(memory): remove dead allOf schema block at the source
teknium1 May 7, 2026
e0a2b08
fix(mcp): re-raise CancelledError explicitly in MCPServerTask.run (#2…
teknium1 May 7, 2026
12a0f59
fix(dashboard): finish resumeId -> resumeParam rename in ChatPage (#2…
teknium1 May 7, 2026
d5fcc83
fix(tests): avoid asyncio DeprecationWarning in event loop fixture on…
xxxigm May 7, 2026
4ee6c33
chore(release): map tuancanhnguyen706@gmail.com → xxxigm
teknium1 May 7, 2026
dd2dc2b
fix(mcp): forward OAuth auth and bump sse_read_timeout on SSE transpo…
teknium1 May 7, 2026
c8e3e39
fix(mcp): surface image tool results as MEDIA tags instead of droppin…
teknium1 May 7, 2026
af9336d
feat(gateway): generic plugin hooks for env enablement + cron delivery
teknium1 May 7, 2026
44cd79e
feat(plugins/google_chat): Google Chat platform adapter as a bundled …
donramon77 May 7, 2026
be87a96
refactor(plugins/platforms): migrate IRC + Teams to new env_enablemen…
teknium1 May 7, 2026
43cf72a
chore(release): map donramon77 to AUTHOR_MAP for PR #18425 salvage
teknium1 May 7, 2026
62c2f5d
fix(mcp): coerce numeric tool args defensively
qWaitCrypto May 7, 2026
1baab87
chore(release): add qWaitCrypto to AUTHOR_MAP for PR #21055 salvage
teknium1 May 7, 2026
145e8ec
fix(pairing): enforce lockout on approve_code, not just generate_code…
teknium1 May 7, 2026
ff09853
docs(readme): prefer .venv to match AGENTS.md and scripts/run_tests.s…
xxxigm May 7, 2026
ac51c4c
feat(kanban): per-task max_retries override (#20263 follow-up, supers…
teknium1 May 7, 2026
9feaeb6
feat(qqbot): add chunked upload with structured error types
WideLee May 7, 2026
de584cd
feat(qqbot): add inline-keyboard approvals and update prompts
WideLee May 7, 2026
5b121c6
feat(qqbot): process attachments in quoted (reply) messages
WideLee May 7, 2026
5c08b85
docs(platforms): document env_enablement_fn + cron_deliver_env_var ho…
teknium1 May 7, 2026
fb4f953
fix: block INSECURE_NO_AUTH on non-localhost webhook bindings
0z1-ghb May 7, 2026
898b6d7
fix(webhook): widen INSECURE_NO_AUTH loopback check + tests + docs
teknium1 May 7, 2026
74c9c0e
fix(mcp): gate utility stubs on server-advertised capabilities (#21347)
teknium1 May 7, 2026
f4de381
test(kanban): cover dashboard select filter wiring
maciekczech May 4, 2026
162ad3d
fix(kanban): filter dashboard board by selected tenant
maciekczech May 4, 2026
bbff2f6
chore(release): map maciekczech noreply email
teknium1 May 7, 2026
a1fe5f4
fix(cron): scan assembled prompt including skill content (#3968) (#21…
teknium1 May 7, 2026
4de3ef3
feat(qqbot): wire native tool-approval UX via inline keyboards
WideLee May 7, 2026
0491834
fix(cron): initialize MCP servers before constructing the cron AIAgen…
teknium1 May 7, 2026
1d2029b
fix(update): reset-failed before every fallback restart so the gatewa…
teknium1 May 7, 2026
812ce0b
fix(run_agent): break permanent empty-response loop from orphan tool-…
teknium1 May 7, 2026
2564132
fix(telegram): preserve thread_id=1 for forum General typing indicato…
teknium1 May 7, 2026
498bfc7
chore: release v0.13.0 (2026.5.7) (#21406)
teknium1 May 7, 2026
733e297
fix(acp): inline file attachment resources
HenkDz May 7, 2026
7e2af0c
feat(acp): pass image file attachments through as image_url parts
teknium1 May 7, 2026
cdc0a47
test(hermes_constants): cover parse_reasoning_effort()
xxxigm May 7, 2026
04193cf
feat(web): add Brave Search (free tier) and DDGS search providers
Abd0r May 7, 2026
54c0b10
fix(update): add heartbeat during dependency install
adybag14-cyber May 7, 2026
da18fd0
fix: strengthen termux install network prerequisites
adybag14-cyber May 7, 2026
dc5ef1a
fix: add termux-all install profile and safe fallbacks
adybag14-cyber May 7, 2026
732a6c4
feat: add termux doctor fallback guidance for blocked extras
adybag14-cyber May 7, 2026
24d48ff
feat(kanban): add `specify` — auxiliary LLM fleshes out triage tasks …
teknium1 May 7, 2026
9076a2e
fix(agent): keep Nous GPT-5 fallback on chat completions
voteblake May 4, 2026
2214ab1
chore: fix AUTHOR_MAP for johnsonblake1@gmail.com → voteblake
teknium1 May 7, 2026
cff821e
docs: register triage_specifier in the aux-models enumerations (#21494)
teknium1 May 7, 2026
d87c7b9
fix(analytics): prevent silent token loss and add Claude 4.5–4.7 pric…
austinpickett May 7, 2026
292f468
fix(mcp): unwrap platforms key in channels_list
teknium1 May 7, 2026
c80fa72
fix(installer): set UV_NO_CONFIG=1 to avoid permission denied under s…
hllqkb May 7, 2026
7f369bf
chore(release): add hllqkb to AUTHOR_MAP for PR #21288 salvage
teknium1 May 7, 2026
b0393af
Merge pull request #20805 from NousResearch/austin-feat-sessions-skil…
austinpickett May 7, 2026
7f92e55
Merge pull request #20942 from NousResearch/austin/fix/personality
austinpickett May 7, 2026
901eccc
Merge origin/main and resolve conflict in nix/tui.nix
Copilot May 7, 2026
7d66d30
feat(kanban): add tooltips and docs link across dashboard (#21541)
teknium1 May 7, 2026
03ddff8
fix(gateway): defer goal status notices until after response delivery
May 3, 2026
307c85e
fix(goals): auto-pause when judge model returns unparseable output
teknium1 May 8, 2026
34f7297
Serialize Hermes config access
BennetYrWang Apr 26, 2026
1bdacb6
chore(release): add BennetYrWang to AUTHOR_MAP
teknium1 May 8, 2026
faa13e4
docs(web): fix SearXNG env configuration
helix4u May 8, 2026
7338e5d
fix(model-switch): prevent stale Ollama credentials after provider sw…
kshitijk4poor May 8, 2026
5d1bdf1
Add AUTHOR_MAP entry for Isaac Huang
isaachuangGMICLOUD May 6, 2026
81928f0
refactor(gmi): move User-Agent to profile.default_headers
kshitijk4poor May 8, 2026
486b14b
feat(cron): routing intent — deliver=all fans out to every connected …
teknium1 May 8, 2026
b32461f
fix(auth): send Nous refresh token via header
shannonsands May 8, 2026
80775d7
test(auth): assert Nous refresh rotation payload
shannonsands May 8, 2026
5fa493a
fix(google-workspace): detect disabled_client in --check and add --ch…
ygd58 May 4, 2026
617ac05
fix: correct docstring syntax error in check_auth_live
ygd58 May 4, 2026
83c23e8
fix(google-workspace): cleanup for --check-live salvage
teknium1 May 8, 2026
7190e20
fix: include terminal backend in quick setup wizard (#21842)
alt-glitch May 8, 2026
42f9234
feat(tui): segment turns with rule above non-first user msgs; trim ti…
OutThisLife May 8, 2026
a313186
Merge pull request #19830 from NousResearch/austin/fix/pluralization
austinpickett May 8, 2026
3ce3a89
chore: sync with upstream main (2026-05-08)
May 8, 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
36 changes: 36 additions & 0 deletions agent/auxiliary_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,20 @@ def _to_async_client(sync_client, model: str, is_vision: bool = False):
)
elif base_url_host_matches(sync_base_url, "api.kimi.com"):
async_kwargs["default_headers"] = {"User-Agent": "claude-code/0.1.0"}
else:
# Fall back to profile.default_headers for providers that declare
# client-level headers on their ProviderProfile (e.g. attribution
# User-Agent strings). Provider is inferred from the hostname.
try:
from agent.model_metadata import _infer_provider_from_url
from providers import get_provider_profile as _gpf_async
_inferred = _infer_provider_from_url(sync_base_url)
if _inferred:
_ph_async = _gpf_async(_inferred)
if _ph_async and _ph_async.default_headers:
async_kwargs["default_headers"] = dict(_ph_async.default_headers)
except Exception:
pass
return AsyncOpenAI(**async_kwargs), model


Expand Down Expand Up @@ -2368,6 +2382,16 @@ def _wrap_if_needed(client_obj, final_model_str: str, base_url_str: str = "",
extra["default_headers"] = copilot_request_headers(
is_agent_turn=True, is_vision=is_vision
)
else:
# Fall back to profile.default_headers for providers that
# declare client-level attribution headers on their profile.
try:
from providers import get_provider_profile as _gpf_custom
_ph_custom = _gpf_custom(provider)
if _ph_custom and _ph_custom.default_headers:
extra["default_headers"] = dict(_ph_custom.default_headers)
except Exception:
pass
client = OpenAI(api_key=custom_key, base_url=_clean_base, **extra)
client = _wrap_if_needed(client, final_model, custom_base, custom_key)
return (_to_async_client(client, final_model, is_vision=is_vision) if async_mode
Expand Down Expand Up @@ -2556,6 +2580,18 @@ def _wrap_if_needed(client_obj, final_model_str: str, base_url_str: str = "",
headers.update(copilot_request_headers(
is_agent_turn=True, is_vision=is_vision
))
else:
# Fall back to profile.default_headers for providers that declare
# client-level attribution headers on their profile (e.g. GMI
# User-Agent for traffic identification, Vercel AI Gateway
# Referer/Title for analytics).
try:
from providers import get_provider_profile as _gpf_main
_ph_main = _gpf_main(provider)
if _ph_main and _ph_main.default_headers:
headers.update(_ph_main.default_headers)
except Exception:
pass
client = OpenAI(api_key=api_key, base_url=base_url,
**({"default_headers": headers} if headers else {}))

Expand Down
173 changes: 159 additions & 14 deletions agent/usage_pricing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import re
from dataclasses import dataclass
from datetime import datetime, timezone
from decimal import Decimal
Expand Down Expand Up @@ -82,6 +83,121 @@ class CostResult:
# Official docs snapshot entries. Models whose published pricing and cache
# semantics are stable enough to encode exactly.
_OFFICIAL_DOCS_PRICING: Dict[tuple[str, str], PricingEntry] = {
# ── Anthropic Claude 4.7 ─────────────────────────────────────────────
# Opus 4.5/4.6/4.7 share $5/$25 pricing (new tokenizer, up to 35% more
# tokens for the same text).
# Source: https://platform.claude.com/docs/en/about-claude/pricing
(
"anthropic",
"claude-opus-4-7",
): PricingEntry(
input_cost_per_million=Decimal("5.00"),
output_cost_per_million=Decimal("25.00"),
cache_read_cost_per_million=Decimal("0.50"),
cache_write_cost_per_million=Decimal("6.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-opus-4-7-20250507",
): PricingEntry(
input_cost_per_million=Decimal("5.00"),
output_cost_per_million=Decimal("25.00"),
cache_read_cost_per_million=Decimal("0.50"),
cache_write_cost_per_million=Decimal("6.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
# ── Anthropic Claude 4.6 ─────────────────────────────────────────────
(
"anthropic",
"claude-opus-4-6",
): PricingEntry(
input_cost_per_million=Decimal("5.00"),
output_cost_per_million=Decimal("25.00"),
cache_read_cost_per_million=Decimal("0.50"),
cache_write_cost_per_million=Decimal("6.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-opus-4-6-20250414",
): PricingEntry(
input_cost_per_million=Decimal("5.00"),
output_cost_per_million=Decimal("25.00"),
cache_read_cost_per_million=Decimal("0.50"),
cache_write_cost_per_million=Decimal("6.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-sonnet-4-6",
): PricingEntry(
input_cost_per_million=Decimal("3.00"),
output_cost_per_million=Decimal("15.00"),
cache_read_cost_per_million=Decimal("0.30"),
cache_write_cost_per_million=Decimal("3.75"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-sonnet-4-6-20250414",
): PricingEntry(
input_cost_per_million=Decimal("3.00"),
output_cost_per_million=Decimal("15.00"),
cache_read_cost_per_million=Decimal("0.30"),
cache_write_cost_per_million=Decimal("3.75"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
# ── Anthropic Claude 4.5 ─────────────────────────────────────────────
(
"anthropic",
"claude-opus-4-5",
): PricingEntry(
input_cost_per_million=Decimal("5.00"),
output_cost_per_million=Decimal("25.00"),
cache_read_cost_per_million=Decimal("0.50"),
cache_write_cost_per_million=Decimal("6.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-sonnet-4-5",
): PricingEntry(
input_cost_per_million=Decimal("3.00"),
output_cost_per_million=Decimal("15.00"),
cache_read_cost_per_million=Decimal("0.30"),
cache_write_cost_per_million=Decimal("3.75"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
"claude-haiku-4-5",
): PricingEntry(
input_cost_per_million=Decimal("1.00"),
output_cost_per_million=Decimal("5.00"),
cache_read_cost_per_million=Decimal("0.10"),
cache_write_cost_per_million=Decimal("1.25"),
source="official_docs_snapshot",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
# ── Anthropic Claude 4 / 4.1 ─────────────────────────────────────────
(
"anthropic",
"claude-opus-4-20250514",
Expand All @@ -91,8 +207,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("1.50"),
cache_write_cost_per_million=Decimal("18.75"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-prompt-caching-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
Expand All @@ -103,8 +219,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("0.30"),
cache_write_cost_per_million=Decimal("3.75"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-prompt-caching-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
# OpenAI
(
Expand Down Expand Up @@ -184,7 +300,7 @@ class CostResult:
source_url="https://openai.com/api/pricing/",
pricing_version="openai-pricing-2026-03-16",
),
# Anthropic older models (pre-4.6 generation)
# ── Anthropic older models (pre-4.5 generation) ────────────────────────
(
"anthropic",
"claude-3-5-sonnet-20241022",
Expand All @@ -194,8 +310,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("0.30"),
cache_write_cost_per_million=Decimal("3.75"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-pricing-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
Expand All @@ -206,8 +322,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("0.08"),
cache_write_cost_per_million=Decimal("1.00"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-pricing-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
Expand All @@ -218,8 +334,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("1.50"),
cache_write_cost_per_million=Decimal("18.75"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-pricing-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
(
"anthropic",
Expand All @@ -230,8 +346,8 @@ class CostResult:
cache_read_cost_per_million=Decimal("0.03"),
cache_write_cost_per_million=Decimal("0.30"),
source="official_docs_snapshot",
source_url="https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching",
pricing_version="anthropic-pricing-2026-03-16",
source_url="https://platform.claude.com/docs/en/about-claude/pricing",
pricing_version="anthropic-pricing-2026-05",
),
# DeepSeek
(
Expand Down Expand Up @@ -426,8 +542,37 @@ def resolve_billing_route(
return BillingRoute(provider=provider_name or "unknown", model=model.split("/")[-1] if model else "", base_url=base_url or "", billing_mode="unknown")


def _normalize_anthropic_model_name(model: str) -> str:
"""Normalize Anthropic model name variants to canonical form.

Handles:
- Dot notation: claude-opus-4.7 → claude-opus-4-7
- Short aliases: claude-opus-4.7 → claude-opus-4-7
- Strips anthropic/ prefix if present
"""
name = model.lower().strip()
if name.startswith("anthropic/"):
name = name[len("anthropic/"):]
# Normalize dots to dashes in version numbers (e.g. 4.7 → 4-7, 4.6 → 4-6)
# But preserve the rest of the name structure
name = re.sub(r"(\d+)\.(\d+)", r"\1-\2", name)
return name


def _lookup_official_docs_pricing(route: BillingRoute) -> Optional[PricingEntry]:
return _OFFICIAL_DOCS_PRICING.get((route.provider, route.model.lower()))
model = route.model.lower()
# Direct lookup first
entry = _OFFICIAL_DOCS_PRICING.get((route.provider, model))
if entry:
return entry
# Try normalized name for Anthropic (handles dot-notation like opus-4.7)
if route.provider == "anthropic":
normalized = _normalize_anthropic_model_name(model)
if normalized != model:
entry = _OFFICIAL_DOCS_PRICING.get((route.provider, normalized))
if entry:
return entry
return None


def _openrouter_pricing_entry(route: BillingRoute) -> Optional[PricingEntry]:
Expand Down
23 changes: 18 additions & 5 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5804,12 +5804,15 @@ def _apply_model_switch_result(self, result, persist_global: bool) -> None:
self.model = result.new_model
self.provider = result.target_provider
self.requested_provider = result.target_provider
# Always overwrite explicit overrides so stale credentials from the
# previous provider (e.g. Ollama api_key/base_url) don't leak into
# the new provider's credential resolution on the next turn.
self._explicit_api_key = result.api_key
self._explicit_base_url = result.base_url
if result.api_key:
self.api_key = result.api_key
self._explicit_api_key = result.api_key
if result.base_url:
self.base_url = result.base_url
self._explicit_base_url = result.base_url
if result.api_mode:
self.api_mode = result.api_mode

Expand Down Expand Up @@ -6027,12 +6030,15 @@ def _handle_model_switch(self, cmd_original: str):
self.model = result.new_model
self.provider = result.target_provider
self.requested_provider = result.target_provider
# Always overwrite explicit overrides so stale credentials from the
# previous provider (e.g. Ollama api_key/base_url) don't leak into
# the new provider's credential resolution on the next turn.
self._explicit_api_key = result.api_key
self._explicit_base_url = result.base_url
if result.api_key:
self.api_key = result.api_key
self._explicit_api_key = result.api_key
if result.base_url:
self.base_url = result.base_url
self._explicit_base_url = result.base_url
if result.api_mode:
self.api_mode = result.api_mode

Expand Down Expand Up @@ -7991,6 +7997,7 @@ def _show_usage(self):
output_tokens = getattr(agent, "session_output_tokens", 0) or 0
cache_read_tokens = getattr(agent, "session_cache_read_tokens", 0) or 0
cache_write_tokens = getattr(agent, "session_cache_write_tokens", 0) or 0
reasoning_tokens = getattr(agent, "session_reasoning_tokens", 0) or 0
prompt = agent.session_prompt_tokens
completion = agent.session_completion_tokens
total = agent.session_total_tokens
Expand Down Expand Up @@ -8022,6 +8029,8 @@ def _show_usage(self):
print(f" Cache read tokens: {cache_read_tokens:>10,}")
print(f" Cache write tokens: {cache_write_tokens:>10,}")
print(f" Output tokens: {output_tokens:>10,}")
if reasoning_tokens:
print(f" ↳ Reasoning (subset): {reasoning_tokens:>10,}")
print(f" Prompt tokens (total): {prompt:>10,}")
print(f" Completion tokens: {completion:>10,}")
print(f" Total tokens: {total:>10,}")
Expand Down Expand Up @@ -10440,7 +10449,11 @@ def handle_enter(event):

# --- /model picker modal ---
if self._model_picker_state:
self._handle_model_picker_selection()
try:
self._handle_model_picker_selection()
except Exception as _exc:
_cprint(f" ✗ Model selection failed: {_exc}")
self._close_model_picker()
event.app.current_buffer.reset()
event.app.invalidate()
return
Expand Down
Loading
Loading