Hermes Agent Architecture Wiki
基于 Nous Research Hermes Agent 源码的深度架构文档。 所有页面均经过逐行源码验证,确保准确性与时效性。
目录结构
核心架构
- agent-loop-and-prompt-assembly: Agent 循环、系统提示构建、平台提示、执行指导
- tool-registry-architecture: 中央工具注册系统,声明式注册+集中调度
- model-tools-dispatch: 工具编排与调度,异步桥接+动态 schema 调整+参数类型强制
- toolsets-system: 工具分组系统、递归解析、20+ 平台工具集
- prompt-builder-architecture: 系统提示模块化组装,注入防护+技能缓存+模型特定指导
- auxiliary-client-architecture: 辅助 LLM 客户端路由器,多 provider 解析链+自动降级
- provider-transport-architecture: Provider Transport ABC,统一抽象 Anthropic/Chat Completions/Responses API/Bedrock 的数据路径
- provider-plugin-system: NEW v0.13.0 ProviderProfile ABC + 30 个插件化 provider
记忆与会话
- memory-system-architecture: 三层架构(MemoryStore/MemoryManager/MemoryProvider),冻结快照模式
- session-search-and-sessiondb: FTS5 搜索 + LLM 摘要的跨会话回忆,orphan 删除策略
- context-compressor-architecture: 自动上下文压缩 v3
- skills-and-memory-interaction: Skills 与 Memory 的互补关系和决策树
- skills-system-architecture: 渐进式披露架构 + Curator 后台维护(v0.13 新增 archive/prune/list-archived)
工具与能力
- browser-tool-architecture: 多后端浏览器自动化,accessibility tree+三层安全防护
- web-tools-architecture: 八大后端插件化搜索/提取(WebSearchProvider ABC + 注册表),LLM 智能内容压缩(web_crawl 工具于 2026-05-29 移除 #33824)
- code-execution-sandbox: execute_code 沙箱,7 工具限制+UDS/File RPC 两种通信模式
- voice-mode-architecture: Push-to-talk 语音交互,STT(5 Provider)+ TTS(10 内置 Provider,含 Piper 本地神经 TTS)
- context-references: @file/@folder/@diff/@url/@git 引用系统,安全沙箱+注入量限制
- fuzzy-matching-engine: 8 策略链模糊匹配,从精确到相似度匹配
- large-tool-result-handling: 三层溢出防护(工具内截断/单结果持久化/轮次聚合预算)
- lsp-integration: NEW v0.14 LSP 语义诊断集成,agent/lsp/ 11 modules + file-mutation footer 三层后写校验
- i18n-and-locales: NEW v0.13 i18n 薄切片本地化(仅 hermes 自身静态消息,不动 agent 输出)
性能与优化
- parallel-tool-execution: 智能并发安全检测
- prompt-caching-optimization: 冻结快照保护 prefix cache,75% 成本节省
- smart-model-routing: 智能模型路由
安全与可靠性
- security-defense-system: 多层防御 + Redaction 默认 ON + Discord guild-scoped + post-write delta lint(v0.13.0 安全 wave)+ Wave 4 Dashboard OAuth + security-guidance 插件(2026-05-27)
- dashboard-auth-oauth-gate: NEW 2026-05-27 Dashboard OAuth 鉴权闸门(可插拔 ABC + Nous Portal Provider + WS 单次性 ticket + Phase 0-7)
- interrupt-and-fault-tolerance: 中断传播、Fallback 模型链
- credential-pool-and-isolation: 多密钥自动轮换、Profile 隔离
- checkpoints-architecture: NEW v0.13.0 Checkpoint v2 共享 shadow git store
- tool-loop-guardrails: NEW v0.12.0 工具调用循环护栏,exact failure / same-tool failure / idempotent no-progress 三维检测
多 Agent
- multi-agent-architecture: 5 种运行时机制(delegate_task/MoA/Background Review/send_message/Kanban)
- kanban-multi-agent-board: 可持久化多 Agent 协作板(SQLite + WAL,心跳/熔断/幻觉拦截,跨 session/profile)
- goal-and-ralph-loop:
/goal+/subgoal持续推进系统(fail-open judge,回合预算,保 prompt cache) - configuration-and-profiles: 多 Profile 架构,完全隔离的 agent 实例(第二种多 Agent 方案)
平台与扩展
- cli-architecture: CLI 架构、斜杠命令、hermes dump/proxy/kanban/curator/migrate
- terminal-backends: 7 种终端后端(含 Vercel Sandbox)、统一 spawn-per-call 执行模型
- messaging-gateway-architecture: 22 平台统一网关(含 Teams/LINE/SimpleX Chat/Google Chat 等插件平台),PlatformRegistry、Session auto-resume、统一 allowlist
- hermes-proxy: OAuth → OpenAI-compatible 本地代理,让 Aider/Cline/Codex 复用 Nous/SuperGrok 订阅
- gateway-session-management: 网关会话管理,多平台会话隔离+PII 脱敏+重置策略
- hook-system-architecture: 双 Hook 系统(Gateway Hooks + Plugin System),register_command/dispatch_tool,Dashboard 插件
- mcp-and-plugins: MCP 集成、插件钩子系统、OAuth 支持
- skin-engine: YAML 驱动的皮肤/主题系统
- worktree-isolation: Git Worktree 并行隔离模式
- cron-scheduling: 内置调度器、自然语言调度、多平台投递、
no_agentwatchdog 模式 - trajectory-and-data-generation: 轨迹保存、批量运行器、RL 训练环境
更新日志(50 个,最新优先 — 完整列表见 index.md)
-
2026-06-21-update: 179 commits 单日同步(hermes-agent
5a53e0f0 → 87ab373,v0.17.0 维护未发新版;约 70 fix / 16 feat / 13 test / 6 chore / 16 docs + 23 merge;~26h 单日窗口;266 文件 +17145/−1079)— ⭐ Compression cluster 9 commit(14ef631agent/context_compressor.py:1935-1950 _effective_protect_first_n()衰减 +7ace96brotation 三状态修复(goal 经hermes_cli/goals.py:282 migrate_goal_to_sessionmove-not-copy + 子 create_session 失败回滚agent.session_id = old_session_id+:694-701 on_session_start(platform=)转发)+2f3177aagent/auxiliary_client.py:121 _aux_interrupt_protection = threading.local()+aux_interrupt_protection()ctx mgr 让 Codex aux 流尊重压缩摘要保护(#23975)+1f874dffallback 摘要 active_task 单点(#49307)+b6a4638空 content raise 不再静默替换为空摘要(#11978/#11914)+3509be7_MIN_CTX_TRIGGER_RATIO = 0.85+_compute_threshold_tokens()让 64K-ctx 模型在 ~54.4K 触发(#14690)+d0de460TUI/compress显示前后摘要(#46686)+04730f3新hermes_cli/context_switch_guard.pypreflight-compress 预警 +41e0c10重复压缩告警走_emit_status(#36908))— ⭐ Kanban cluster 8 commit + lifecycle hooks(d164ed04 reclaim RESET SQL 加AND claim_lock IS ?(#50366)+1f4c5ae_resolve_auto_decompose_settings每 tick 重读(#50358)+84ba83bbounded init lock 10s(#50353)+9630ec6_default_spawn env["TERMINAL_CWD"]=workspace(#50348)+e217fd4三新 plugin hookkanban_task_claimed/completed/blocked注册hermes_cli/plugins.py:192-194 VALID_HOOKS+_fire_kanban_lifecycle_hookwrite commit 后 best-effort(#50349)+e581740_dispatch_tick_lockboard-scoped 非阻塞 flock(#50331)+15cfc28无路径 worktree 锚board.default_workdir+d79f67f_ensure_git_worktree实物化 +_git_common_dir短路复用(worktree 现真有 linked worktree 在/.worktrees/上分支wt/))— ⭐ Security cluster 9 commit(ed96669tools/url_safety.py:285-287 + :359-365ip_str.split('%')[0]剥 IPv6 scope-ID + fail-closed +ed3d12aWebSocket 空 peer fail-closed 4 endpoint +5b45fb2kanban markdown HTML 白名单消毒plugins/kanban/dashboard/dist/index.js:337/:354/:368/:387+ae46699/87615f4restore_quick_snapshot 路径穿越(snapshot_id + snap_dir + manifest src/dst 全.relative_to()校验)+3b56d3akanban tool payload secret redact 经redact_sensitive_text(force=True)+a18bae6_SECRET_CONFIG_KEYSfrozenset +redact_config_value()递归 masker(#50245/#50313 config show/set api_key 屏蔽)+9078b4btools/file_tools.py:286 _is_blocked_device_pathnormpath + 20 symlink 跳 walk +def3f63_is_blocked_device(filepath, base_dir=)锚 task cwd +71274f2/16899ae_looks_like_read_file_line_numbered_content拒 read_file 行号显示文本经 write_file 回写)— ⭐ Gateway/API server cluster 13 commit(b5b8a4cfresh-final 尊重prefers_fresh_final_streaming适配器 decline +__dict__双查防 MagicMock(#47048)+4c206b9/79f29785 plugin adaptersys.path.insert(parents[3])修 cron 命名空间冲突(#49410)+03563dahygiene 硬上限 400→5000 默(#50194)+4c349e8hygiene 无法 rotate 时保留 transcript(#21301 P1)+8ac5e90_JSON_MEDIA_TOOL_PATH_FIELDS+_collect_history_media_paths()让 image_generate JSON-payload 路径入历史去重集(#46627)+c11c510busy 模式文本 follow-up 经_queue_or_replace_pending_eventFIFO 不再 newline-merge(#43066 sub-bug 2)+d19aabb_finalize_shutdown_agentsflush_session_messages经 idempotent identity-tracked(#13121)+93ea9b0入站媒体下载 128MiB cap(防 Discord Nitro 500MB OOM)+bb77a8b未映射 Windows gateway 经 detached watcher 重生(#50090/#50373)+7a131f7stateless HTTP pathsupports_async_delivery=False经 contextvar +notify_unsupported/sync fallback(#50319)+e499d69gateway.api_server.max_concurrent_runs统一并发 cap 跨 3 endpoint + OpenAI 风格 429 + Retry-After(#50007)+51a338a + 0ee7546 + b577f25 + 4d7bb38active_agents轮边界 publish +/api/status加gateway_busy/drainable+parse_active_agents三处统一)— ⭐ Telegram cluster 9 commit(6183e8cBot API 10.1 rich messages 默改 offhermes_cli/config.py:2161 "rich_messages": False+ adapter_coerce_bool_extra经platforms.telegram.extra.rich_messages: trueopt-in;CJK 不走 rich + 表格不强换行 + slash 富文本保留换行 + chunk 标记移出代码栅栏 + native rich echo reply 文本恢复 + 流式 final 经 editMessageText 重索引 + finalize 前暂停 typing + 最终回复后 typing indicator 不残留)— ⭐ Cron cluster 6 commit(07424datickerBaseException不死 + heartbeat-aware status +f1f36b3迁移期时区偏移修复防双触发 +65d7c7f action='run'立即执行 +4cc28aaTelegram DM-topic 经DeliveryRouter(#22773)+d548908直播适配器显式 confirmation 步骤(#38922/#47056/#43014)+73b9226 model.default解析 fail-fast)— Plugins/Session lifecycle 7 commit(9d883ac ctx.profile_namewrapget_active_profile_name()经 HERMES_HOME(#50346)+9f67ba1 finalize_turn三段 cleanup 各自 try/except +result["cleanup_errors"](#50009)+b17180d AIAgent.close()step 7session_db.end_session()+9e4fe32background review fork opt out +56255f8 _collect_delegate_child_ids()用父 id seed found 集合 +99233fa/c7e8854CLI/TUI force-quit/signal 持久化)— Misc(c0409a8 SendResult.error_kind7 类 typed(too_long/bad_format/forbidden/not_found/rate_limited/transient/unknown)+2609bcci18n Spanish 完整(README.es.md 220 / CONTRIBUTING.es.md 602 / SECURITY.es.md 322)+65a477fDesktop About 加 Update now(#50186)+8666fd7模型可见性跨 provider 保留 hide-all +5e3e89cHindsight 健康 grace 可配(#50341)+7bc6f18Hindsight root 跳 +472c068MCP "unknown method" ping keepalive(#50028)+ Photon 三修 +2f4f23fCodex app-server item/started → Telegram tool-progress 桥接(#38835)+e0498bdBedrock prompt-cache 计价 + 跨区域前缀剥除(#50307)+a4b1554/491579fWhatsApp JID 规范 + bridge dir HERMES_HOME mirror +4467c22chat-completions timestamp 剥 +ac83365Windows install 8.3 短 %TEMP% 展长 +6f5f58e/41ba90fpoll() 只读 + CLI drain dedup(#10156)+3e354b6Copilot headers 保留 +6984026browser SSRF 容器化 +8a506edcredential_pool env-seeded 非破坏 +587b5b9memory provider 外部 backup paths(#50325)+ 模型切换 3 修(#50375/#23767)+824c9d3 model.api_base→model.base_url别名(#50385)+a9c8025approval honor 中断(#8697)+ Email 配置硬化(#40715)+ 16+ docs commit + AUTHOR_MAP 10+ salvage)— 验证基线/tmp/hermes-agentclone @87ab373+ 4 个并行 research agent 实证(A: Security 9 commit / B: Kanban 8 + lifecycle hooks / C: Compression 9 + Gateway/API 13 / D: Telegram 9 + Cron 6 + Misc 30+) -
2026-06-20-update: 69 commits 单日同步(hermes-agent
01f581d8d → 5a53e0f0,v0.17.0 维护未发新版;约 34 fix / 8 feat / 6 chore / 5 test / 3 refactor / 3 docs / 1 style + 8 merge;~22h 单日窗口;250 文件 +12225/−3725)— ⭐ Compression in-place compaction 6 commit(compression.in_place:bool=Falseopt-in 保留单 session_id;新archive_and_compact软归档非破坏性(hermes_state.py:2700++:2734-2737 UPDATE messages SET active=0, compacted=1)+ 新compacted列 3 态语义(:570+:3489-3494文档 active=1/compacted=0=live, active=0/compacted=1=archive in search, active=0/compacted=0=rewind out search)+search_messagesWHERE 放宽(m.active=1 OR m.compacted=1)(:3528-3532主 FTS5 +:3611-3614trigram)+ 边界 hook 双模触发(agent/conversation_compression.py:625 _is_boundary = bool(_old_sid) or in_place)+ gateway auto-compress 强history_offset=0(gateway/run.py:15872-15874)+/compressslash gate 扩if rotated or _in_place:(gateway/slash_commands.py:2636-2659)+agent._last_compaction_in_place信号 + 解 PR body 列 14 个 rotation 引发 issue 集群 #33618/#14238/#33907/#36777/#45117/#42228/#48989)— ⭐ Background delegation fan-out PR #49734(单 commit 5 文件 +721/-333;dispatch_async_delegation_batch(tools/async_delegation.py:337)批量当单异步槽位;runner_execute_and_aggregate(tools/delegate_tool.py:2247)join 所有子;完成事件is_batch=True(:389)+ 单 consolidated 渲染_format_async_delegation(tools/process_registry.py:1549-1628header:1586TASK i/N:1614);模型级background入参作废由_dispatch_delegate_task(run_agent.py:5210-5222)顶层强制background = (not _is_subagent);3 并发限delegation.max_concurrent_children+max_async_children=3默 +max_spawn_depth;满槽拒绝退化 inline sync 非排队;a6f08ff0单行 docs 澄清 subagent 模型 config 级非 per-call)— ⭐ Blank Slate setup mode PR #36733(第三 setup 模式hermes_cli/setup.py:2853-2861(不新 subcommand)+ 235 行 wizard:3056-3134+agent.disabled_toolsets全减集到{file, terminal}(:3026)+platform_toolsets.cli=["file","terminal"](:3006)+ 全 opt-out web/browser/code/vision/memory/delegation/cronjob/skills/imagegen/kanban/plugins/mcp/gateway/compression/checkpoints/smart_model_routing/session_reset(_blank_slate_minimize_config:3031)+set_bundled_skills_opt_out(True)(:3117-3118)+_blank_slate_walkthrough:3137-3214逐节 opt-in + gating invarianttools_config.py:1528-1536 _get_platform_tools末尾减agent.disabled_toolsets)— ⭐ Gateway adapters → bundled plugins 9 个迁移(单 commit56001054(salvage PR #41284)124 文件 +3647/-2583;slack/dingtalk/whatsapp/matrix/feishu/telegram/wecom/email/sms 全从gateway/platforms/.py迁到plugins/platforms//{adapter,plugin.yaml,__init__}.py+ 旧路径全删无 stub;signal 不迁仍在gateway/platforms/signal.py1701 行;注册register(ctx)PluginContext →ctx.register_platform()→PlatformEntry→platform_registry.register();发现_scan_directorywalk 一级 +plugin.yamlmanifest;Matrix YAML 补 4 键allowed_users/ignore_user_patterns/process_notices/session_scope(plugins/platforms/matrix/adapter.py:4288 _apply_yaml_config:4297/:4312/:4317/:4319);~60 test 原地 retarget;单一新test_slack_plugin_setup.py;c3292794跟进补 2 漏字符串字面量)— Desktop 浮动 composer popout PR #49488(renderer-only 不开新 BrowserWindow 无 IPC channel;apps/desktop/src/store/composer-popout.tsnanostore + localStoragehermes.desktop.composerPopout.{enabled,position}+POPOUT_WIDTH_REM=19.5+apps/desktop/src/app/chat/composer/index.tsx:196 popoutAllowed=!isSecondaryWindow()二级窗强制 docked +apps/desktop/src/app/chat/composer/hooks/use-popout-drag.ts:93 useComposerPopoutGestures+ dock zone 4 常量DOCK_ZONE_BOTTOM_PX=72/CENTER_TOLERANCE_PX=150/VERTICAL_FALLOFF_PX=260/HORIZONTAL_FALLOFF_PX=220;无键盘快捷 —— 纯手势双击+拖拽切换)— Provider 失效转移 5 commit(5a53e0f0aux 摘要 401/403 abort(agent/context_compressor.py:771 _last_summary_auth_failure+:1593-1602 _is_auth_error+:2335不管 config flag abort)+f22dd8a7agent loop is_auth 真失败转 fallback(agent/conversation_loop.py:2842-2858+ 新 retry flagturn_retry_state.py:65 auth_failover_attempted: bool = False)+c884ff64rewrite_prompt_model_identity(agent/chat_completion_helpers.py:1045-1071)只改最后一次出现 +_sync_failover_system_message(agent/conversation_loop.py:469-492)8 站点接 +c253b073clear_model_endpoint_credentials中央 helper(hermes_cli/config.py:3934)+ 12 picker flow 接入 +95a3affcNous picker 重load_config()+37a4dd49heal poisonedinference_base_url经DEFAULT_NOUS_INFERENCE_URL(hermes_cli/auth.py:71)双站点)— Signal 加固 14 commit(_validate_send_result(gateway/platforms/signal.py:1020)解 results[] +SignalRateLimitError抛 + 新gateway/platforms/signal_format.py140 行共享 markdown→Signal UTF-16 偏移 textStyles + ADTS AAC 识别(:83 _guess_extensionlines 105-109if (data[1] & 0xF6) == 0xF0: return ".aac")+ ffmpeg remux to MP4(:141 _remux_aac_to_m4a)+ OrderedDict echo ring 50→512 + 5min TTL(:315-316)+_consume_sent_timestamp(:1110)替set.discard+ quote-cache_sent_message_timestamps OrderedDict[str, None]FIFO(:324+:809-820)+ reply-to-own 追踪_extract_quote_author/_quote_references_own_message(:773/:790)+MessageEvent加reply_to_author_id/name/is_own_message3 字段 + 群组自身 mention 全剥(:640-641)+ stop-typing RPC(:1517-1538)+ 新env_float(utils.py:326)+ 11 文件 22 处 env cast 替为env_int/env_float;PR #49260/#49530/#49558/#49563/#49583/#49678/#49680)— Teams 原生附件 PR #49308(_send_media_attachmentshared helper(plugins/platforms/teams/adapter.py:1192-1240)+send_video/send_voice/send_document+microsoft_teams.api.AttachmentSDK + URL ref / data URI 双路径,无显式 size cap)— Language-aware title generation PR #45296(auxiliary.title_generation.languageconfig +_TITLE_PROMPT/_TITLE_PROMPT_PINNED_LANGUAGE双模板(agent/title_generator.py:22-34)+ detection-by-instruction 无 code-level locale 检测)— Creative-ideation skill v2.1.0 PR #42402(22 新方法 + method-catalog/heuristics/anti-slop/exercises;28 文件 +2269/-190)— Dashboard 隐藏 sidecar 会话 PR #49269(HERMES_SESSION_SOURCEContextVar 多站点 +_session_source+source="tool"标记)— 内联键盘 model picker 默 persist PR #49176 salvage(gateway/slash_commands.py:1155 is_global=persist_global+:1219-1247config.yaml 写 + 扁平字符串 coerce 嵌套)— 终止 busy session internal-event 中断 PR #49738(gateway/run.py:4172-4184 if getattr(event, "internal", False): return False—— delegate_task background + notify_on_complete 不再中止活跃轮)— gateway resume restart loop 修(_strip_dangling_tool_call_tailgateway/run.py:940-980)— 工具 model whitelist 不剥prompt/image_urls+ slash exec dispatch payload TUI/Desktop 双修 + Raft check_fn 静默 + Desktop GPU 加速被禁横幅(IPChermes:get-remote-display-reason+ `` 5 语 i18n)+ 隐藏 link-title 窗口静音(setAudioMuted(true)防 YouTube watch 自播)+ 右侧栏 tooltip + memory shutdown hook warning + CLI agent ref publish 让on_session_end生效 + 5 条 AUTHOR_MAP salvage(IamSanchoPanza/hakanpak/lkz-de/rratmansky/w31rdm4ch1nZ)+ 3 stale comment 清(tools/memory_tool.py:20,141-144,197-200+tools/fuzzy_match.py:9+run_agent.py:1531) — 验证基线/tmp/hermes-agentclone @5a53e0f0+ 4 个并行 research agent 实证(A: Compression in-place + auth failover 11 commit / B: Blank Slate + delegation + composer popout + Teams + lang titles + Creative-ideation 8 commit / C: gateway adapter migration + Signal 16 commit / D: 23 个 misc commit + AUTHOR_MAP + 7 merges) -
2026-06-19-update: 181 commits 跨日同步 + ⭐ v0.16.0 → v0.17.0 release(hermes-agent
03d9a95 → 01f581d8d,v0.17.0 已发经2bd1977d8 chore: release v0.17.0 (2026.6.19)+866f1d65c (#49236)Desktop fallback;约 76 fix / 39 feat / 14 test / 14 chore / 10 refactor / 4 docs / 24 merge;~24h 主活跃窗口;282 文件 +20287/−1661)— ⭐ Gateway Multiplex Phase 0-4 主轴 9 commit(单 gateway 进程内多 profile 并发;gateway/config.py:553 multiplex_profiles:bool=Falseopt-in +gateway/session.py:616-651 _session_key_namespace(profile)/build_session_key(profile=)默 profile→"agent:main" 命名→"agent:" +:97-104 SessionSource.profile:Optional[str]=Nonewire 字段 +:813-831 SessionStore._resolve_profile_for_key(source)+gateway/platforms/webhook.py:199-202注册/p/{profile}/webhooks/{route_name}与默/webhooks/{route_name}双路由 +:60-65 _PROFILE_REJECTED哨兵 +:413-441 _resolve_request_profile()验证 → 404 +:693-696Source.profile stamping + 新agent/secret_scope.py 205 行Phase 2 fail-closed credential 隔离::35 _MULTIPLEX_ACTIVE:bool=False+:39-50 set_multiplex_active/is_multiplex_active+:55-56 _SECRET_SCOPE:ContextVar[Optional[Mapping]]+:60-66 class UnscopedSecretError(RuntimeError)+:69-80 set_secret_scope/reset_secret_scope/current_secret_scope+:97-113 _GLOBAL_ENV_EXACT=frozenset({PATH, HOME, ...})allowlist +:114-116 _GLOBAL_ENV_PREFIXES+:122-163 get_secret(name) -> Optional[str]multiplex active + 无 scope + 不 allowlist → raise;否则 os.environ.get +:166-209 load_env_file/build_profile_secret_scope+gateway/run.py:46-52 @contextmanager _profile_runtime_scope(profile_home)+:1269 class MultiplexConfigError(RuntimeError)+:1275-1283 _PORT_BINDING_PLATFORM_VALUES=frozenset({webhook, api_server, msgraph_webhook, feishu, wecom_callback, bluebubbles, sms})不可多路 +:2401 _profile_adapters:Dict[str, Dict[Platform, BasePlatformAdapter]]+:5367-5370set_multiplex_active()+:6726-6794 _start_secondary_profile_adapters()->intorchestrator + 凭据指纹 +:6796-6854 _start_one_profile_adapters()->int端口/凭据冲突检测 raise MultiplexConfigError +:6857-6864 _make_profile_message_handler()stamp source.profile +:6866-6879 _adapter_credential_fingerprint()salted hash +hermes_cli/runtime_provider.py所有 os.getenv 走 _getenv→get_secret +agent/credential_pool.pyenv fallback 经 get_secret +tools/mcp_tool.pyMCP config interpolation 用 get_secret +hermes_cli/gateway.py:3854-3933 _guard_named_profile_under_multiplexer(force=False)lifecycle guard 防 named profile 在 multiplex 已运行时单独启动 +gateway/status.py:578-603 write_runtime_status(served_profiles=)写 runtime_status.json + 新文档website/docs/user-guide/multi-profile-gateways.md 133 行opt-in/路由/凭据隔离/端口绑定限制/--force + 4 套测试 phase0_165行/phase1_73行/credential_isolation_88行/adapter_registry_136行/lifecycle_55行/secret_scope_130行)— ⭐ Cron Chronos NAS-mediated scale-to-zero provider 11 commit(新cron/scheduler_provider.py:27-178class CronScheduler(ABC)实验性 +name抽象 +is_available()invariant:不得网络 IO +start(stop_event, *, adapters, loop, interval)阻塞调度循环 +stop/on_jobs_changed/fire_due/reconcile五 hook +class InProcessCronSchedulername="builtin" 60s 阻塞 ticker +:114-151 resolve_cron_scheduler() -> CronScheduler读 cron.provider 失败 degrade builtin + 新plugins/cron/__init__.py 344 行discovery machinery +@register_cron_scheduler装饰器 +load_cron_scheduler(name)+gateway/run.py _start_cron_ticker()deprecated shim +_start_gateway_housekeeping()拆出 channel-dir/cache cleanup/paste sweep/curator +start_gateway()resolve_cron_scheduler().start()+hermes_cli/web_server.py _start_desktop_cron_ticker()同走 resolver +cron/scheduler.py抽run_one_jobshared helper +cron/jobs.py:1076-1090 _machine_id()HERMES_MACHINE_ID env 或 hostname:pid +:1093-1127 claim_job_for_fire(job_id, *, claim_ttl_seconds=300) -> bool多机 at-most-once CAS:missing/disabled/paused→False / fresh claim→False / stale claim→overwrite + True;赢时 stampfire_claim={at, by}推进 next_run_at +:979-981 mark_job_run()完成清 fire_claim + 新插件plugins/cron/chronos/__init__.py 241 行class ChronosCronScheduler(CronScheduler)+_armed:dictcache +name="chronos"+is_available()config check only 无网络 +_have_nous_token()/_get_client()/_callback_url()lazy +start()reconcile + RETURN(非阻塞,由 NAS webhook 推触发)+on_jobs_changed()→reconcile +fire_due()→ABC default (claim + run_one_job) + re-arm 下一次 +reconcile()→arm 缺失/改变 cancel orphan + 新_nas_client.py 123 行 class NasCronClientHTTP wrapper (provision/cancel/list) + 新verify.py 103 行 _FIRE_PURPOSE="cron_fire"+verify_nas_fire_token(*, token, expected_audience, jwks_or_key, issuer, leeway_seconds) -> Optional[Dict]仅 RS/ES family(symmetric 拒)+ 校验 aud/exp/nbf/iss/purpose + 失败 None 不抛 +get_fire_verifier() -> Callablepluggable indirection +gateway/platforms/api_server.py:3345-3402 _handle_cron_fire(request) -> web.ResponsePOST/api/cron/fireBearer + get_fire_verifier(cron.chronos) 401 on bad token / 400 on 缺 job_id / 202 + backgroundprovider.fire_due()+ dashboard 同 surface +cron/scheduler.py:961-1041 _run_job_script():1034 env=_sanitize_subprocess_env(os.environ)防 provider 凭据泄漏给用户脚本 +tools/environments/local.py:206 _sanitize_subprocess_env(base_env, extra_env) -> dictblocklists 复用 + 测试 scheduler_provider/claim_job_for_fire 84行/chronos_cron 203行/chronos_verify 182行(真 RS256 sign-verify)/cron_fire_webhook 152行 + 新 docsdocs/chronos-managed-cron-contract.md+bfb6e0bb3 docs(cron): CronScheduler provider + cron.provider key)— ⭐ MCP late-connecting tools snapshot 8 commit(修:MCP HTTP/SSE 异步 connect 期间 agent build snapshot 时它们尚未 list_tools → 工具不入 system prompt;本 series:tools/mcp_tool.py:4361-4480 refresh_agent_mcp_tools(agent, *, quiet_mode=False)每轮调用:snapshotregistry._generation(line 4424) 在 rebuild 前 → rebuild → atomic publish:published_gen_raw = getattr(agent, "_tool_snapshot_generation", -1)(4458) →if snapshot_generation < published_gen: return拒 stale (4460) →agent._tool_snapshot_generation = max(published_gen, snapshot_generation)(4479) +agent/turn_context.py:126-129 build_turn_context()廉价预检has_registered_mcp_tools()然后refresh_agent_mcp_tools(quiet_mode=True)+ 3 轮 adversarial review:round 1 cache parity/gates/races / round 2 stale-publish race/parity holes / round 3 generation capture adjacency(捕获从"rebuild 开始"挪到"rebuild 前最后一刻"缩 race 窗)+ revert ACP rebuild 改回原始路径 + harden generation guard +tools/mcp_tool.py:22 服务端 config 文档 keepalive_interval:10+:291 _DEFAULT_KEEPALIVE_INTERVAL=180+:292 _MIN_KEEPALIVE_INTERVAL=5+:1694-1696 keepalive_interval = max(_MIN_KEEPALIVE_INTERVAL, float(config.get("keepalive_interval", _DEFAULT_KEEPALIVE_INTERVAL)))让短 TTL HTTP/SSE MCP 不每 idle 周期 reconnect + 新:1235-1389 class ElicitationHandlerMCP 1.1+ 服务端主动 elicitation 协议::1258 _OUTER_TIMEOUT_GRACE_SECONDS=5+:1260 __init__(server_name, config, owner)+:1281 async __call__(context, params)+:1320 import request_elicitation_consent from tools.approval+:1342 captured = getattr(self.owner, "_pending_call_context", None)抓 contextvars +:1354 captured.copy().run(request_elicitation_consent, ...)gateway-aware approval routing 让 Telegram/Discord/Slack 等平台正确弹审批 UI)— ⭐ Managed scope 系统级 /etc/hermes 配置层 10 commit(新hermes_cli/managed_scope.py 215 行::33 _DEFAULT_MANAGED_DIR=Path("/etc/hermes")POSIX 默 +:56 $HERMES_MANAGED_DIRenv override 优先(IT/bootstrap)+:52-71 get_managed_dir() -> Optional[Path]三级回退(env override → /etc/hermes 非 pytest → None)+:74 _invalidate_managed_cache()测试 hook +:115-125 load_managed_config() -> dictLRU cached + fail-open(读不到/格式错→{})+:128-134 load_managed_env() -> Dict[str, str]同 fail-open +:137-177 apply_managed_overlay(config) -> dict深合并 + env expansion +:202-204 managed_config_keys() -> set扁平 dotted key 集 +:207-209 is_key_managed(dotted_key) -> bool+:212-214 is_env_managed(name) -> bool+hermes_cli/config.py:5673-5726user config 加载后调 apply_managed_overlay +:6119-6211写hermes config set/env set经 is_key_managed/is_env_managed 拒 managed 键 +:5840-5842 managed_keys = managed_scope.managed_config_keys()doctor 输出 + managed.env后置覆盖(管理员强制 override user)+ cli.py 内 fast-path 也接 overlay + standalone loaders 都补 + config→env 桥经 overlay + 新文档website/docs/admin/managed-scope.md含部署模式 + 路径权限 + 重启行为 + IT 工作流 +bf9a0481f测试 pin config/env load 行为 before managed scope 防 regression)— ⭐ Unified provider catalog 8 commit(新hermes_cli/provider_catalog.py:45-52 _ACCOUNTS_AUTH_TYPES=frozenset({...})+:56-68 @dataclass(frozen=True) class ProviderDescriptor字段slug/label/description/auth_type/tab("keys"|"accounts")/api_key_env_vars/base_url_env_var/signup_url/order+:71-73 tab_for_auth_type(auth_type) -> str+:83-165 provider_catalog() -> list[ProviderDescriptor]单源含 OpenAI/Anthropic/Bedrock/OpenRouter/xAI/Codex/Custom +:168-170 provider_catalog_by_slug() -> dict+hermes_cli/web_server.py:3971-4056 _catalog_provider_env_metadata()经 catalog 派生 Keys tab metadata +:4059-4100 get_env_vars(profile)/api/env挂 provider/provider_label hints → Desktop Keys tab 按 backend grouping +:5836-5881 _build_oauth_catalog()Accounts tab 经 catalogflow="external"含 catalog-only 未连 provider +:5884-5924 list_oauth_providers(profile)+ Desktopapps/desktop/src/app/settings/providers-settings.tsx:121 OAuthPicker()+apps/desktop/src/app/settings/keys-settings.tsx按 provider 分组 + API-keys 搜索框 + priority-sorted by ProviderDescriptor.order +apps/desktop/src/hermes.ts:361 getEnvVars()/.:408 listOAuthProviders()+ parity test 锁 GUI ⊇hermes modelprovider 集含 Bedrock + catalog-only OAuth status fallthrough)— Raft 新平台插件 3 commit(新plugins/platforms/raft/plugin.yamlname:raft-platform / label:Raft / kind:platform / version:1.0.0 / author:botiverse / kind:platform;requires_env:RAFT_PROFILE设置即 enable;adapter "external agent via wake-channel bridge",loopback HTTP 接 wake hints,不碰消息正文 / 投递游标 +plugins/platforms/raft/adapter.py 774 行::174 _make_activity_eventschemaraft-activity.v1+:260 class ActivityQueuebounded telemetry 队列 +:438 class RaftAdapterHTTP 服务器 +:768-774注册 7 activity hooks + bridge subprocessstdin=DEVNULL+ AUTHOR_MAP [email protected]→xxchan)— simplify-code skilldb744e7d1(skills/software-development/simplify-code/SKILL.md 212 行灵感来自 Claude Code/simplify;3 risk tierSAFE(auto-apply 无 semantics 改变)/CAREFUL(verify 后)/RISKY(flag only) + Chesterton's Fence lines 90-91 删前 git blame 查 fence 缘由 + AI slop 检测 (redundant comments / as any cast / 过度 null-check / unused param) + silent failure 检测 (空 catch / 错误抑制无日志 / Optional 默静默) + 3 并行 subagent reviewer reuse/quality/efficiency + 触发关键词simplify/review my code/clean up;不 auto-run)— html-artifact skill9362ce257 (#48899)加后立即 revert92451151cHEAD 上 ABSENT 三个 sub-skill sketch/architecture-diagram/concept-diagrams 仍独立 — Relay WS-only Phase 3 (#48294) + hosted gateway 实际 connect 修 (#48828) + self-provision 触发改 relay-config+NAS-token 非 is_managed() (#48724) + terminal 块禁内部 gateway lifecycle (#245b95b09)(d2c53ff55gateway/relay/adapter.py:85,89 set_inbound_handler/set_interrupt_inbound_handler全绑 WebSocketRelayTransport 删 signed-HTTP fallback;a64fc490fhosted gateway 真 connect inbound/outbound round-trip;2c6e266e8gateway/relay/__init__.py:207 self_provision_relay():219触发改 "relay_url 配 + NAS token + 无 secret 钉";245b95b09tools/terminal_tool.py:2068-2082gateway 进程内拒 hermes gateway start/stop/restart 防 agent 自杀)— image_generate 加 image-to-image / editingc02192ff6 (#48705)(agent/image_gen_provider.py +79ImageGenProviderABCgenerate()加 keyword-onlyimage_url + reference_image_urls+ 新方法capabilities()声明 modalities + max_reference_images(默 0 text-only 向后兼容)+success_response.modality+normalize_reference_images()+tools/image_generation_tool.py +426顶层 schema 暴露 + 动态 schema 反映当前模型 actual edit capability + 6 plugin 更新:openai +146 行 DALL-E edit endpoint / xai +104 行 grok image edit / krea +69 行 保 dict-shaped image_style_references verbatim 防 KeyError / fal +41 行 text-to-image delegation 时不传 None kwargs(保字节相同)/ openai-codex +28 行 text-only 友好错误消息 / 测试 image_to_image 349 行 + 文档 image-gen-provider-plugin/image-generation/tools-reference)— Desktop UX 18 commit(Cmd+K Restart gatewayapps/desktop/src/app/command-palette/index.tsx:368+apps/desktop/src/store/system-actions.ts:15 $gatewayRestartingjotai atom 状态栏 spinner + 重命名 Restart messaging→Restart gateway + 选 logs 可复制 + Restart action 在 messaging save/toggle toasts + Refresh Models cache bustapps/desktop/src/app/shell/model-menu-panel.tsx:119 refresh:true+ 通知 clickapps/desktop/src/lib/session-ids.ts:15resume stored session id + selectable slash/shell logspreview-console.tsx:88 selectedLogIds+ reasoning-effort pickerweb/src/components/ReasoningPicker.tsx在 chat sidebar + session switcher panelapps/desktop/src/app/session-switcher.tsx:16Chat tab + sessions 实时刷新dc5cb0a44+ sessions sort by 最近活动0d7abd555+ prefill 指令通知b936f92b2(/goal /undo) + vitest 入 dashboard npm test)— Gateway 鲁棒性 12 commit(cached agentmax_iterations/max_turns每轮 refresh from configgateway/run.py:1206-1214 _current_max_iterations()+:14802-14804+ 测 + Windows restart silent outage 修gateway/status.py:166-203 looks_like_gateway_command_line()严格 matcher +hermes_cli/gateway.py:321-490 _scan_gateway_pids()+hermes_cli/gateway_windows.py:1304-1325 _wait_for_gateway_absent()+:1327-1353 restart()hardened + Discord 非对话 metadata 跟踪gateway/run.py:429-439 _non_conversational_metadata()+plugins/platforms/discord/adapter.py:622-625 _DISCORD_NONCONVERSATIONAL_METADATA_KEYS=frozenset+:668-720 class _DiscordNonConversationalMessageTracker防 startup status message 切割 history backfill + Telegram/title命名 topicgateway/slash_commands.py:2805-2821propagate_schedule_telegram_topic_title_rename()非仅 auto-titles + Telegram opt-in 在线/离线指示gateway/platforms/telegram.py:477-494 _status_indicator_enabled/_status_online_text/_status_offline_text+:2245-2298 _set_status_indicator()async + Discord reply 上下文 hydrateplugins/platforms/discord/adapter.py:28-40 class _Snowflake+:4255-4257 _fetch_channel_context(reply_target=)+:4315-4382reply-anchored window scan + clarify dict-choice unwraptools/clarify_tool.py:23-53 _flatten_choice()+:88-90调 +:137-142 CLARIFY_SCHEMAdocstring 明确 options 仅在 choices[] 不在 question text + Discord 同 _flatten_choice + soft-boundary truncate buttons)— Kanban 5 commit(机器全局 singleton 锁gateway/kanban_watchers.py:26-59 _acquire_singleton_lock(lock_path)+:62-74 _release_singleton_lock+:660-680init +:1129-1143双退出释放 防 embedded dispatcher 多副本 +hermes_cli/kanban_db.py:128-132 RECLAIM_DEFER_GRACE_SECONDS=120+:3296-3305 release_stale_claims()defer 守 +:5154-5169 _worker_survived_termination()+:5172-5210 _defer_reclaim_for_live_worker()延 claim_expires by GRACE_SECONDS +:5449-5458 detect_stale_running()同守 +:5131-5145 _terminate_reclaimed_worker()ProcessLookupError → terminated=True + cross-platform fcntl/msvcrt + UTF-8 encoding)— OpenViking + Hindsight 6 commit(OpenViking structured sync attribution + tool parts;plugins/memory/openviking/__init__.py:124-125 _SYNC_TRACE_ENV+_OPENVIKING_RECALL_TOOL_NAMES+:163-164 _sync_trace_enabled()+:2461-2464空 tool_id batch skip guard +_TOOL_STATUS_*常量 + alias sets + 复用 env_var_enabled +agent/message_content.py _message_text/_message_matches_textstatic + Hindsightplugins/memory/hindsight/__init__.py:53 _MIN_CLIENT_VERSION="0.6.1"+:101-111 _ensure_cloud_client_dependency()lazy install +:1004在 import 前调 +plugin.yaml:5 hindsight-client>=0.6.1)— Agent 8 commit(Anthropic aux 经 streamagent/anthropic_adapter.py:2538-2589 _is_stream_unavailable_error/create_anthropic_message+run_agent.py:4079-4085 _anthropic_messages_create+ FTS5 trigram fallback 不禁 FTS5hermes_state.py:775-792 _is_fts5_unavailable_error/_is_tokenizer_unavailable_error+:858-862 _warn_fts5_unavailable()条件触发 + 非可重试 API 错误摘要_summarize_api_error()防 HTML 漏入对话 +hermes_cli/debug_bundle.py含 gui.log + 1d2e35967 session store 不可用 visible warning + e48554a3e worktree 互斥锁防多进程 clobber)— CLI/TUI 10 commit(/model切换默认跨会话持久hermes_cli/model_switch.py:362-391 resolve_persist_behavior()+:304-365 parse_model_flags()is_session flag +cli.py:6974+hermes_cli/config.py:1590 cli_refresh_interval=1.0状态栏 keep alive + viewport 宽度变化清屏c06898098 (#49120)+ 状态栏 idle 不隐1b04e4ede (#49105)+ tmux 内 fast-echo 关ab8f06381/e52fffb60防游标漂移含 SSH-from-tmux + TUI 托管 dashboard chat 不死15e3b64b7+ idle exit 重启12dfcfdf7+/update守 hosteda7b4fbcbc+ DASHBOARD_TUI_MODE 重用 + pending-input 经command.dispatch()169952563 (#48848))— Dashboard 8 commit(chat TUI argv 出 event loopd06104a9e (#48561)+/api/cron/firec34840e22+ DS Button prefix/size APId573e7c9e+ upload temp file disconnect 清理 + python-multipart 锁6752da9a7 (NS-501)+ Slack allowed users wildcard83c034bd5+ Slack setup hints + 验证 + sessions sort by 最近活动)— Sessions/Backup/Misc 10 commit(hermes_state.py递归 CTE 让 child session 继承祖先 title 跨 compression lineage6ad0bc20f/65d050cf0/8c70346e3+hermes_cli/backup.py EXCLUDED_BACKUP_DIRS排 .venv/node_modules/pycachee738c0833 (#48887)+ Stripe Projects skill docscfb55de5e (#48673)+ undici audit bumpb266ad748 (#49113)+ hashless npm via importNpmLock3ca0ef7e3 (#48883)+ Docker WebUI 只读源36851fa57 (#48541)+ Windows managed-node 路径解析7a7b56d49/fcc169057/d4e7dd609 (#49254)+ 多条 AUTHOR_MAP salvage:lgalabru→PR#43112 / salesondemandio→PR#42664 / OpenViking / carlos.dddo / Cdddo / JoaoMarcos44 / channkim→PR#47049 / Sahil-SS9→PR#48466/44919/44909/42209 / tt-a1i / xxchan)— 验证基线/tmp/hermes-agentclone @01f581d8d+ 4 个并行 research agent 实证(A: Gateway Multiplex + Chronos cron 11 commit / B: MCP late-connect + managed_scope + provider catalog 17 commit / C: Raft + simplify-code + Relay + Desktop UX 14 commit / D: Gateway 鲁棒性 + Kanban + Agent/CLI/TUI + Dashboard 40+ commit) -
2026-06-18-update: 164 commits 跨日同步(hermes-agent
d1ecebc → 03d9a95,仍 v0.16.0 未发新版;约 70 fix / 25 feat / 16 test / 12 chore / 10 refactor / 7 docs / 3 perf / 21 merge;~48h 双日窗口;285 文件 +25193/−1708)— ⭐ Relay/A2 Trust-Boundary 传输 Phase 0-3 主轴 23 commit(新文件gateway/relay/descriptor.py:77 CapabilityDescriptorfrozen dataclass JSON-serializable handshake payload +contract_version, platform, label, max_message_length, supports_draft_streaming/edit/threads, markdown_dialect, len_unit, emoji, platform_hint, pii_safe+to_json()/from_json()forward-compat +:76-120 from_platform_entry()+CONTRACT_VERSION=1additive-only;新gateway/relay/adapter.py:44-130 RelayAdapter(BasePlatformAdapter)从 descriptor 读MAX_MESSAGE_LENGTH/message_len_fn(chars/utf16)/supports_draft_streaming/supports_code_blocks +:32-41 _utf16_len/_LEN_FNS+:79-110 connect()注_on_inboundhandler +:139-149 on_interrupt(session_key, chat_id)→interrupt_session_activity+:190-221 send_follow_up(session_key, kind, content, metadata) → SendResulttoken-less A2 op +gateway/config.py:167 Platform.RELAY+:7-9 _PLATFORM_CONNECTED_CHECKERS RELAY checker;新gateway/relay/transport.py:1-75 RelayTransport(Protocol)lifecycle(connect/disconnect/handshake)+ inbound(set_inbound_handler)+ outbound(send_outbound/send_follow_up/get_chat_info/send_interrupt);新gateway/relay/ws_transport.py:102-299 WebSocketRelayTransportnewline-delimited JSON 帧协议 + 7 帧类型 hello/descriptor/inbound/outbound/interrupt/outbound_result/interrupt_inbound + uuidrequestId相关 per-request future + 30s handshake/outbound timeout + send_interrupt fire-and-forget +:57-100 _event_from_wireSessionSource snake_case wire→dataclass +:158-174 _upgrade_headersAuthorization Bearer 在/relayWS upgrade;新gateway/relay/auth.py:50-135 make_token/make_upgrade_token(gateway_id, secret, ttl_seconds)/verify_token(token, secrets)base64url(payload:exp:sig) HMAC_SHA256 多 secret 轮换窗 + Python port of connector'srelayAuthToken.ts/deliverySigning.ts字节级互证;新gateway/relay/inbound_receiver.py:204 InboundDeliveryReceiveraiohttp 双 POST routes/message和/interrupt验x-relay-signature/x-relay-timestampover 原始 raw request 字节(re-serialize 破 HMAC)+ 300s replay 窗 + per-tenant delivery key verify list;新hermes_cli/gateway_enroll.py:250 hermes gateway enroll子命令 (subcommands/gateway.py:50 cmd_gateway_enroll) 解 Nous Portal access token + POST{enrollmentToken, gatewayId}到 connector/relay/enroll+ 持久化GATEWAY_RELAY_ID/SECRET/DELIVERY_KEY到~/.hermes/.env+is_managed()拒;Phase 3gateway/relay/__init__.py:116-340 self_provision_if_managed()MANAGED + relay 已配 + secret 未钉时 in-process 自供给:resolve_nous_access_token()→ POST connector/relay/provision断言 endpoint+route keys → 设 env 让register_relay_adapter()读到 + 凭据仅驻内存(永不写~/.hermes/.env)+ 显式钉的 secret 尊重跳 self-provision +relay_endpoint()/relay_route_keys()/_provision_url()/_post_provision()+ 12 单测覆盖;237fa7d29删HERMES_GATEWAY_RELAYdark-launch flag 改配置驱动relay_url()读GATEWAY_RELAY_URL或gateway.relay_url+register_relay_adapter()URL 已配时注册无配时 no-op +gateway/run.py GatewayRunner.start()在插件发现后调 + 失败 log 不阻启;6 套测试:test_descriptor.py:66(6 测 roundtrip/frozen/unknown-key/optional defaults)+test_descriptor_from_entry.py:64+test_relay_adapter.py:77+test_relay_roundtrip.py:122(Discord+Telegram round-trip 泛化证明,utf16+markdown_v2 dialect)+test_relay_registration.py:55(配置驱动 gate)+test_relay_interrupt.py:69+test_ws_transport.py:179(live in-process websockets server real handshake/inbound/outbound/follow_up/disconnect pending waiter fail)+test_auth.py:167(upgrade token/deliver signature/rotation 窗)+test_inbound_receiver.py:150+test_no_stub_leak.py:44CI guard:production 路径不 import StubConnector +test_relay_sheds_crypto.pyA2 不变式:relay 路径不 import 平台 crypto(ed25519/HMAC/webhook sig)+test_relay_contract_conformance.py钉 contract docs ↔ Python 字段(SessionSource.to_dict()7 wire 键也加入文档)+ 整套 57 passed;测试用tests/gateway/relay/stub_connector.py:66 StubConnector(in-memory 测试专用 + canned send_result + push_inbound test driver);新docs/relay-connector-contract.md:143v1 契约 + §6 重写 A2 trust-boundary 模型:connector 是唯一 crypto/identity 边界 + §6.1 channel-auth schemes + SessionSource 判别器表(Discord guild_id REQUIRED)+ signed-body verify-at-edge + additive-only contract_version 政策) — ⭐ /billing 终端账单 #45449(新agent/billing_view.py 295 行surface-agnosticBillingState/parse_money/format_money/CardInfo/MonthlyCap/AutoReloaddataclass + fail-open builder + 新hermes_cli/nous_billing.py 406 行类型化 HTTP client 接 4 个/api/billing/*endpoint +BillingScopeRequired/BillingRateLimited/BillingAuthError异常 + Idempotency-Key 强制 +cli.py +657 行5 个 screen overview/buy→confirm→poll/auto-reload/monthly-limit(read-only)+_show_billinghandler + 2s 节流/5min 可取消 poll +tui_gateway/server.py +216 行billing.state/charge/charge_status/auto_reload/step_upJSON-RPC + 结构化 success enveloperesult.ok + result.error=+ 新ui-tui/src/app/slash/commands/billing.ts 332 行全 TUI overlay 状态机 +ConfirmReqoverlay 复用 +insufficient_scope→lazy step-up/no_payment_method→portal错分支 + 新ui-tui/src/components/billingOverlay.tsx 684 行+hermes_cli/auth.py +97 行 NOUS_BILLING_MANAGE_SCOPE/nous_token_has_billing_scope()/step_up_nous_billing_scope()lazy 重 auth 持久化按_login_nous方式但不弹模型 picker;6 套测试共 1266 行 51+6+7+16+12+53 行(billing_view 决策+预算+fail-open / CLI / scope-stepup / portal URL / RPC / vitest);端到端 Decimal money(server 发 decimal 串 → 保 Decimal → 仅显示格式化)+ poll loop token 缓存避锁争用 + 401 时重 resolve fresh + CLI 非交互(_app is None)渲文本+portal deep-link 永不 prompt + CommandDef 入_SLACK_VIA_HERMES_ONLY经 Slack/hermes保 50-cap 对齐 + 截图.github/pr-screenshots/45449/) — ⭐ OpenViking session-boundary race 12 commit 收口(4 并发原语:(1) state lock Lock 保护 session 旋转 sync_turn 不跨边界 (2) per-session writer registryplugins/memory/openviking/__init__.py:1664 _inflight_writers: Dict[str, Set[Thread]]+:2080-2102 _spawn_writer自注+自反注 +:2129-2156 _drain_writers(sid, timeout)loop+re-join + 全部 drain 才允许 commit (3) prefetch_generation 单调 int worker capture 长操作完成时 if 已升 → 拒写 (4) async finalize:2232-2260 _finalize_session_asyncdaemon offload drain+pending GET+commit POST 让命令线程立返/new//branch//resume//undo不卡;12 commit:813a4e383 (#28296):2373-2439 on_session_switchhook bounded join 10s + commit if turn_count>0 + drain stale prefetch /a30b40c73sync_turn:2309-2320capture sid before worker + on_session_end:2360-2370reset turn_count for 幂等 + 测test_end_then_switch_does_not_double_commit/eddbf291are-check is_alive after join 未 drain 跳 commit + on_memory_write 同 sid 快照 + prefetch_generation 拒 stale write /91e9459e1per-session writer dict 替单槽_sync_thread防 bounded join drop live worker /00c045b43综合硬化 /f3b813c02测试 preserve content/write writes /3ac6551ba:2399 rewound=bool(kwargs.get("rewound")):2411-2430rewound 时跳旋转只 invalidate prefetch /c83544890命令线程不卡 drain+commit /2a5d51c16 (#48206)adapt current api /4de4a4e2d (#47973)type-correct skill-scaffolding sentinels /5494c1e9b (#48262):858-863 _write_ovcli_config改用atomic_json_write(mode=0o600)共享 helper 关 chmod-after-write TOCTOU /99a20f8d9plugin 期望更新) — ⭐ Memory 单轮 batch ops #48507(tools/memory_tool.py:450-563 MemoryStore.apply_batch(target, operations)全 op 按最终预算校验 + 原子写 + 任一失败回滚整批 +:792-826 _apply_batch_write_gate跨 op auth +:839-922 memory_tool(operations=[{action,content?,old_text?}])dispatcher + 桥接外部 provideragent/agent_runtime_helpers.py:1842-1875+agent/tool_executor.py:1012-1050遍历 batch op 对 add/replace 调on_memory_write+agent/background_review.py:300-408batch op 显示;live 验证:consolidate-and-add 7→1 调用) — ⭐ Skills 用户修改 bundled-skill 发现+diff CLI(tools/skills_sync.py:825 list_user_modified_bundled_skills()用 manifest origin-hash 基线 +:813 _is_tracked_user_modification(origin_hash, user_hash)共用谓词防 sync loop/discovery 漂移 +:881 diff_bundled_skill(name)文件级difflib.unified_diff()检 modified/added/removed/binary +:836 _read_for_diff单读返 (bytes,text);CLIhermes_cli/skills_hub.py:1152 hermes skills list-modified [--json]+:1185 hermes skills diff+:1870+/skills list-modified/skills diffslash 镜像 +subcommands/skills.py:164/194argparse +hermes update提示在main.py:9063 + 6073两路径都点向新命令 + 不变式测test_update_modified_notice.py:505 行窗内必现 hint 不固定路径数;f6fac60e6refactor_skill_file_list()helper 去重 + diff 契约删user_present;25c590ccdrmtree guard 拒 SKILLS_DIR root(不只外部)+f1254c8ea (#48200):695 _rmtree_writable()必须严格 SKILLS_DIR 的 child 防坏路径拼接/恶意 manifest/折叠路径静默 wipe~/.hermes/+hermes_cli/config.py:2502-2510 pre_update_backup默 True + 5 case scope guardtests/tools/test_skills_sync.py:237;功能测test_skills_list_modified_diff.py132 行 6 测 pristine 不假阳/edited listed/diff pristine clean/diff modified+added/未知 ok=False/reset 一致) — ⭐ Langfuse trace state 按 turn/request id 隔离(plugins/observability/langfuse/__init__.py:247 _trace_key(task_id, session_id, turn_id="", api_request_id="")三 tier:Tier 1 turn-scopedtask:T:turn:U/session:S:turn:U/thread:PID:turn:U;Tier 2 request-scopedtask:T:api:R/...;Tier 3 legacy 裸 task_id/session:S;turn_id 优先(turn-scoped post_llm_call 无 api_request_id 必须 resolve 到 request hook 同 key)+:231 _scope_prefix抽取共用 task/session/thread fallback ladder 防漂移;:65 _MAX_TRACE_STATE=256+:713 _evict_stale_locked()在_STATE_LOCK下 insert 前调 LRU 驱逐非-finalizing turn(被打断/tool-only final/空 final content)防_TRACE_STATE无界增长 + 驱逐前结 root span;hook 签名升级:785 on_pre_llm_call/:843 on_pre_llm_request/:883 on_post_llm_call/:1050 on_pre_tool_call/:1056 on_post_tool_call全传 turn_id+api_request_id;端到端隔离tests/plugins/test_langfuse_plugin.py:254 TestTurnTraceIsolation2 turn(1 非-finalizing+2 normal)2 separate root trace 开(pre-fix 只 1,turn 2 merge into turn 1)+:381 test_non_finalizing_turns_do_not_grow_state_unboundedly50 turn vs cap=8 surviving keys turn 42-49 LRU 驱 0-41 +:402 test_trace_key_strings_unchanged_by_refactor钉所有 task/session/turn/api 组合精确输出防漂移) — ⭐ Anthropic OAuth wire mcp__ 双下划线前缀 #47723(关键 wire-format 变更:单下划线mcp_被 Anthropic 工具分类器算第三方 → HTTP 400 + 路由 extra-usage 计费 lane;agent/anthropic_adapter.py:375 _MCP_TOOL_PREFIX="mcp__"(之前"mcp_")+:2349+ tool prefix 跳已mcp_/mcp__防双前缀 +agent/transports/anthropic.py:91 MCP_PREFIX="mcp_"+:2370-2391 to_oauth_wire_name()归一化所有mcp到mcp__(裸 native + MCP server 工具如mcp_linear_get_issue):startswith("mcp__")不变 /startswith("mcp_")→"mcp__" + name[len("mcp_"):]/ else →MCP_TOOL_PREFIX + name;应用于 tool 定义和**消息历史** tool_use 块 +agent/transports/anthropic.py:132-151 normalize_response反向解经 registry 查找:registered name → single-underscore + bare(MCP server 工具)→ bare name(native)→ 兜底保留mcp_wire;测试重写:零单下划线到达 OAuth wire;mcp__圆 trip 解为 registered name 两类工具;实证:单mcp_工具翻整请求到 extra-usage /mcp__在 plan) — **⭐ Curator skill consolidation 改 opt-in #47840**(agent/curator.py:64 DEFAULT_CONSOLIDATE=False+:190-203 get_consolidate()读curator.consolidate默 False +:1428 run_curator_review(consolidate=None)None 读 config / True/False 覆盖 +:1546-1570not consolidate跳 fork aux-model review 整段直接写 prune-only;fc1119ca6rollback safety snapshot 自保护:可选 protect set 经snapshot_skills()穿到_prune_old()防 evict 正被恢复 snapshot;992b92238restore 收紧到 archive_skill() 的精确 14 位时间戳后缀防同前缀无关 archived skill) — **Dashboard 流式 multipart 上传 #47663**(之前 file 上传走 base64 data URL in JSON body 膨 33% + 内存缓冲 + 撞 proxy 502;新hermes_cli/web_server.py:1486-1560 upload_managed_file_streamUploadFile+Form按 1 MiB 块直读到 temp + 100 MB cap streaming 中 enforce 413(不 full buffer 后)+ 原子os.replace(partial/abort 不覆盖现有)+ 加python-multipart依赖;前端api.uploadFile改multipart/form-dataraw 字节)— **Docker supervised gateway --replace #47555 + 安装树自我修改硬化 #47490 + macOS launchd in-tree 推迟 #47842** + **runtime-pid 本机 only liveness + await-safe config-only scope /api/status + Chat tab session-end 恢复 #47674 + 完整 MCP catalog 明细 #48520** + **OpenViking 设置 UX 10 commit**(手动 setup path/密钥类型前置选/预创建 0600 关 TOCTOU/chmod 失败日志/15s health wait/_classify_runtime_openviking_health区分 responded vs unreachable/不健康端点跳 autostart)+ **Hindsight memory provider 入 Desktop 配置面板 #37546**(新apps/desktop/src/app/settings/provider-config-panel.tsx 1-182声明式 + schema-drivenhermes_cli/memory_providers.py 1-149 ProviderField/ProviderFieldOption+ GET/PUT/api/memory/providers/{name}/config+constants.ts:242 ENUM_OPTIONS'hindsight' 进 memory.provider)+ **xAI grok-composer-2.5-fast 入 OAuth picker + 200k ctx 修 + native web_search swap-only + incomplete-call 守 + Codex 设备码 429 重试 #47860 + session_id/x-client-request-id headers 复原 #47335**(agent/model_metadata.pygrok-composer 200000 /grok-composer-2.5-fast 262144+agent/transports/codex.py:60+/43+swap-only web_search 不额外授 +agent/codex_responses_adapter.py:69+不算 in_progress 为 incomplete +hermes_cli/auth.py:78+设备码 capped 指数退避 4 次 + raiseAuthError(code=CODEX_RATE_LIMITED_CODE)含 wait hint)+ **Model pickermax_models=0 ≠ unlimited语义锁 + 移除 50 cap #48279**(hermes_cli/model_switch.py:10+切片改is not Nonecheck /build_models_payload/list_authenticated_providers/list_picker_providers默改 None unlimited)+ **Prompt 跨平台 platform_hints override + context-file cap 按模型 ctx 自适配 #47846 + parallel-tool-call steer 去重**(agent/agent_init.py:1242读agent._platform_hint_overrides+agent/system_prompt.py:61-113 _resolve_platform_hint()append/replace/shorthand +hermes_cli/config.py:2173-2189 DEFAULT_CONFIG.platform_hints文档;agent/prompt_builder.py:961-984 _dynamic_context_file_max_chars()ctx_tokens40.06floor 20K ceiling 500K +:1540-1549 _truncate_content(context_length, read_path)标记点 truncated 文件路径引导 read_file;删GOOGLE_MODEL_OPERATIONAL_GUIDANCE重复 Parallel tool calls 段 + 注释修正)+ **Resume 跟随 compression-tip #48633 + /compress 跳旋转保护 + 旋转前 flush 待持久化消息 #47202**(hermes_state.py:2820-2841 resolve_resume_session_id()经get_compression_tip()forward 跟随 + 只跟end_reason='compression'parent,不混 delegation/branch;gateway/slash_commands.py:2588-2613仅当_compress_context产新 sid 才调rewrite_transcript;agent/conversation_compression.py:512-523 compress_context+cli.py:5975-5989 new_session旋前 flush + catch)+ **Kanban auto-subscribe calling session on create**(gateway sessions 用HERMES_SESSION_PLATFORM+HERMES_SESSION_CHAT_IDContextVars / TUI/desktop 用HERMES_SESSION_KEY子进程 env / 门kanban.auto_subscribe_on_create默 True)+ **Backup hermes import 跳易失 gateway 状态 #48243 + Update install-method stamp scope 改 code-tree #48188**(_IMPORT_SKIP_NAMES={gateway_state.json, gateway.pid, cron.pid, gateway.lock, processes.json}basename 跳防 hosted 实例 reconciler 读陈旧外来 state;detect_install_method()stamp 改驻 code tree(macOS~/Library/Application Support/Hermes// Linux~/.local/share/hermes/ Windows%APPDATA%\Hermes)防 Docker bind-mount$HERMES_HOME单 stamp 描述两安装)+ **Photon iMessage mixed attachment text 保留 #46818**(plugins/platforms/photon/adapter.py:119+处理 'group' content type 扁平化 text+attachment +_normalize_binary_payloadhelper + sidecarindex.mjs/patch-spectrum-mixed-attachments.mjs 155 行在 npm postinstall+sidecar 启动应用 + Windows pathToFileURL+CRLF↔LF)+ **cua-driver MCP 操作员环境 scrub #37878**(tools/computer_use/cua_backend.py:3+ _sanitize_subprocess_env()防 credential exfil 到第三方 cua-driver binary 含 ANTHROPIC_API_KEY 测试)+ **MCP catalog Unreal Engine 5.8**(optional-mcps/unreal-engine/manifest.yaml 54 行HTTP127.0.0.1:8000/mcp无 auth;Epic experimental Unreal MCP plugin 嵌在 Editor)+ **Agent empty-name 工具调用循环抑制 #47967/#48109 + 多模态用户内容持久化保留 + send_message tool 撤回 #47856**(agent/conversation_loop.py:26+empty-name → 短 anti-priming error 无 catalog dump / 非空 unknown 仍 catalog;run_agent.py:10+避免 text-only persist_user_message override 覆盖 ACP image block;toolsets.py:14+drop model-tool 注册 + 空 'messaging' toolset,send engine 保留给 cron/gateway notifier/hermes sendCLI)+ **search_files headroom densification #47866**(tools/file_operations.py:250-278 _densify_matches()path-grouped lossless 57.8% token 降;≥5 matches 触发;不变式:ripgrep matches path-ordered)+ **Approval glob allowlist #43051**(tools/approval.pyglob 命令 allowlist 守 + shell chaining 防)+ **Container 检测 cgroup-v2/containerd/CRI/K8s #47131**(hermes_constants.py:486+KUBERNETES_SERVICE_HOSTenv +kubepods/containerd/criomarker +/proc/self/mountinfofallback)+ **Windows 跨进程日志轮替**(hermes_logging.py:36+ ConcurrentRotatingFileHandler as RotatingFileHandler仅sys.platform=='win32'+ portalocker pywin32 锁 + concurrent-log-handler==0.9.29)+ **install.ps1 PowerShell host 解析 + EAP 松绑后 uv venv fail-fast + native stderr 松绑 #48352/#48341**(scripts/install.ps1:320 Get-PowerShellHostExe用Get-Process -Id $PIDPATH-independent +:186 Invoke-NativeWithRelaxedErrorActionEAP=Continue 包 git/uv 防 PowerShell 5.1 NativeCommandError +:1460-1471relax 后立刻捕$LASTEXITCODE非 0 throw 防伪成功)+ **Desktop 23 commit**(stranded session 窗恢复 #47655:43/:307 $resumeExhaustedSessionId+ ErrorState 含 Retry 按钮;session 删幂等 #48641hermes_cli/web_server.py:7046-7067+ absent → 200already_absent:True;secondary 窗 streaming #47919electron/session-windows.cjs:24-34 chatWindowWebPreferences backgroundThrottling:false主+secondary 共用 factory;PTY before-quit dispose #92e6d8c85electron/main.cjs:6554-6558;Electron 40.10.2 钉 #47792package.json:137 electronVersion: "40.10.2"+ 删 @electron-internal/extract-zip + nix npmDepsHash 刷新 + react-simple-icons @=13.11.1;electronDist 动态解析+self-heal #48091apps/desktop/scripts/run-electron-builder.cjs 57 行 require.resolve("electron/package.json")动态 +_try_redownload_electron_dist()镜像 retry;self-update 重 build retry once #48122apps/bootstrap-installer/src-tauri/src/update.rs:296-328 rebuild_needs_retry()+electron/update-rebuild.cjs:21-29 runRebuildWithRetry();oversized 消息不冻结markdown-text.tsx:461 MAX_MARKDOWN_CHARS=200_000+:463-500 HugeTextFallback content-visibility:auto+ ExpandableBlock;huge fenced block stack overflow 防markdown-preprocess.ts:154-160 extend()替 spread 防 V8 argument-count overflow;message-render 隔离markdown-text.tsx:60-66 preprocessWithTailRepair try/catch+directive-text.tsx:325-339 safeEmbeddedImages/safeDirectiveSegments;failed turn 跨 thread 隔离use-message-stream.ts:1102-1109 errorMessage toast稳 id;long user message 滚 #48619thread.tsx:830 USER_BUBBLE_BASE_CLASS overflow-hidden→overflow-y-auto;error banner dismiss #47985desktop-controller.tsx:753-785 dismissError双清;/title 前置创行 #47987tui_gateway/server.py:5004 _ensure_session_db_row;RTL list marker + quote bordermarkdown-text.tsx:541/546/549 dir="auto"+:525 code dir="ltr";named custom provider 不退 bare custom #48547agent/agent_init.py:1227-12334 站守;backend skew toast 24h snooze #47913store/updates.ts:99-145 SKEW_TOAST_COOLDOWN_MS;pre-session 模型选黏 + reasoning/fast 设置 #47447lib/model-status-label.ts:25-34 currentPickerSelection();self-improvement review summaryuse-message-stream.ts:1084-1109 review.summary持久 system 消息 +tui_gateway/server.py:1911-1926 _load_memory_notifications)+ **TUI Enter slash 完成 + MCP late refresh + MCP 计数 connected only #48425/#48403/#48402**(ui-tui/src/domain/slash.ts applyCompletiontrailing-space-only 算 noop fall-through 提交 +tui_gateway/server.py:3413 _schedule_mcp_late_refresh30s 等 discovery 后 rebuild snapshot 仅 pre-first-turn 安全 + 重 emit session.info +ui-tui/src/components/branding.tsx:223+ mcpConnected=filter(s.connected)替全部配置计数;mcpConnected==0时段整 drop)+ **CLI keystroke 延迟 + URL 不当 path 补全 + 弃用 login 优雅降级 #47701/#47706**(cli.py:12714 ThreadedCompleter(_completer)把补全移出 event loop /hermes_cli/commands.py:1291+ if "://" in word: return None拒 URL token /subcommands/login.py:10删choices=+description=让任何 provider 都到 handler 打 redirect 到hermes auth/hermes model)+ **hermes debug显 commit 日期 #48104**(hermes_cli/dump.py:59 _get_git_commit_date()跑git log -1 --format=%cd --date=short返 YYYY-MM-DD;Docker/wheel 无.git时返空 baked SHA 仍识别)+ **6 条 AUTHOR_MAP salvage**(iamlukethedev / srojk34 / infinitycrew39 / Adolanium / #47904 / Rivuza全进scripts/release.pyPython dict)+ **PR infographic 资源删除 #48261**(docs/assets/ns504-chat-session-reconnect.png 1024 字节+infographic/kanban-db-corruption-defense/infographic.png 1200 KB都无引用) — 验证基线/tmp/hermes-agentclone @03d9a95` + 5 个并行 research agent 实证(A: Desktop UI 23 commit / B: Gateway+Relay+A2+Compression+Docker+Update 32 commit / C: OpenViking+Memory+Curator+Dashboard 35 commit / D: Skills+Langfuse+CLI+TUI+Install 33 commit / E: Prompt+Billing+xAI+Codex+Anthropic+Picker+Photon+MCP-catalog+cua-driver+AUTHOR_MAP+Merges 41 commit) -
2026-06-16-update: 65 commits 单日同步(hermes-agent
cffd6e3c8 → d1ecebc,仍 v0.16.0 未发新版;约 25 fix / 18 feat / 6 chore / 5 test / 4 docs / 1 refactor / 6 merge;~28h 单日窗口;本期 65 commit 全部 committer date ∈ (2026-06-15 20:35 UTC, 2026-06-16 20:40 UTC] 的真正新增;cffd6e3c8..HEAD总 141 commit 中其余 76 个为前期 sync 已覆盖的旧 PR salvage(photon spectrum-ts/iMessage gRPC、yuanbao media pipeline middleware、agent char-based output-cap overflow、honcho identity-tree 各 sub-PR、apps/desktop sleep/wake recovery 等),本期不重复记录)— ⭐ Desktop composer model picker 全面替代 statusbar(PR #46959 4 commit):新文件apps/desktop/src/app/chat/composer/model-pill.tsx 72 行订阅$currentModel/$currentProvider/$currentFastMode/$currentReasoningEffort+formatModelStatusLabel+apps/desktop/src/store/model-presets.ts 86 行per-model effort/fast preset 本地化STORAGE_KEY="hermes.desktop.model-presets"+modelPresetKey(provider,model)="${provider}::${model}"+applyModelPreset({effort,fast}, ctx)在无ctx.sessionId时 no-op 避免写穿网关agent.reasoning_effort+apps/desktop/src/store/session.ts:18-234 个 composer localStorage keyhermes.desktop.composer.{model,provider,reasoning-effort,fast}+apps/desktop/src/app/shell/model-menu-panel.tsx:45 ModelMenuCloseContextReact Context 关闭 +989d5d0apps/desktop/src/lib/model-status-label.ts:71 /-\d{8}$/折叠日期 pinned snapshot +apps/desktop/src/store/model-visibility.ts:54-57 collapseModelFamilies同折叠(claude-opus-4-5-20251101 → claude-opus-4-5)+7d938ccagent/conversation_loop.py:303 _stored_prompt_matches_runtime(agent, prompt)比对Model:/Provider:行 vs runtime +tui_gateway/server.py:1684 _persist_live_session_system_prompt(session)经db.update_system_prompt重建 +:1705 _append_model_switch_marker(session, model, provider)追加[System: The active model for this chat has changed to {model} via provider {provider}…]进史历 +:2166-2168 _apply_model_switch接 — ⭐ Compact session window 家族 PR #46951 3 commit:apps/desktop/electron/main.cjs:5087 spawnSecondaryWindow({sessionId, watch, newSession})+:5148 createSessionWindow+:5155 createNewSessionWindow+apps/desktop/electron/preload.cjs:9 openNewSessionWindow:() => ipcRenderer.invoke('hermes:window:openNewSession')+apps/desktop/src/store/windows.ts:9 NEW_SESSION_WINDOW_FLAG="1"+:33 isNewSessionWindow()+:110-114 openNewSessionInNewWindow()+apps/desktop/src/lib/keybinds/actions.ts:69 {id:'session.newWindow', defaults:['mod+shift+n']}+apps/desktop/src/app/hooks/use-keybinds.ts:136调度 + i18nen.ts:192+zh.ts:188+0f75e99apps/desktop/src/app/shell/app-shell.tsx:86 hideTitlebarControls=isSecondaryWindow()(从isNewSessionWindow扩到所有 secondary)+ statusbar:194 !isSecondaryWindow()门 +apps/desktop/src/app/chat/index.tsx:127ChatHeader早返 +:311secondary 跳showIntro+67233d1新文件apps/desktop/src/store/session-sync.ts 25 行CHANNEL='hermes:sessions'BroadcastChannel +broadcastSessionsChanged()+onSessionsChanged(handler)+apps/desktop/src/app/desktop-controller.tsx:468-475订阅(跳 secondary 窗口)+apps/desktop/src/app/session/hooks/use-message-stream.ts:644title commit 后广播 +apps/desktop/src/app/session/hooks/use-session-actions.ts:476乐观创建后广播 +dd0e3e0apps/desktop/src/components/assistant-ui/thread-list.tsx:140主窗 padpt-[calc(var(--titlebar-height)+1.5rem)]→pt-[calc(var(--titlebar-height)-0.5rem)]— ⭐ Watch window subagent 流 PR #4706044e5848:tools/delegate_tool.py:870-876进度中继转发subagent.text(预览)+:1638-1647 _relay_child_text(delta)经child.run_conversation(..., stream_callback=_relay_child_text)+tui_gateway/server.py:907-913 _start_agent_buildlazy watch 跳过 +:2878-2884 _on_tool_progress对subagent.text跳父 emit +:2945-2951 _mirror_subagent_to_child把subagent.text映 child sidmessage.delta(subagent.start退化单次 header)+:4248-4258lazysession.resume在_child_run_active时早返空 history(WSL race 修)+ 窗口 chromeapps/desktop/src/app/chat/index.tsx:124-127 ChatHeader在isSecondaryWindow()早返(从isNewSessionWindow扩)+app-shell.tsx:83-86 hideTitlebarControls=isSecondaryWindow()+thread-list.tsx:147 secondaryTitlebarGap='calc(var(--titlebar-height) + 0.75rem)'(空格 load-bearing)+:265-270不透明拖条— 远端 gateway artifact 鉴权下载 PR #46895c6b0eb4:apps/desktop/src/lib/media.ts:62 mediaExternalUrl(path)远端感知 +:67 isRemoteGateway()分支构${conn.baseUrl}/api/files/download?path=…&token=…+apps/desktop/src/app/artifacts/index.tsx:128-133 artifactHref把file://与/路径都过mediaExternalUrl+hermes_cli/web_server.py:253 _QUERY_TOKEN_API_PATHS=frozenset({"/api/files/download"})+:1425 @app.get("/api/files/download")Content-Disposition: attachment、auth-gated、不在PUBLIC_API_PATHS中 + 测试apps/desktop/src/lib/media.remote.test.ts+tests/hermes_cli/test_web_server_files.py 60 行— 全局 remote profile REST 路由 PR #470110441b7f:apps/desktop/electron/connection-config.cjs:175 pathWithGlobalRemoteProfile(path, profile, opts)global-remote 模式 + 无每-profile override 时追加?profile=+:283导出 +apps/desktop/electron/main.cjs:66导入 +:5619 hermes:apihandler 调;后端hermes_cli/web_server.pyOAuth provider 路由按 profile scope + 新测tests/hermes_cli/test_web_oauth_dispatch.py 133 行— Electron pack 失败镜像 redownload PR #47266d1ecebc:hermes_cli/main.py:5113 _electron_dist_binary(project_root)(macElectron.app/.../Electron/winelectron.exe/linuxelectron)+:5130 _electron_dist_ok+:5144-5194 _redownload_electron_dist(project_root, env, *, mirror=None)清残 dist+path.txt+注ELECTRON_MIRROR跑node install.js+:5459-5463首次重试 +:5489-5493镜像重试用https://npmmirror.com/mirrors/electron/;redownload 仍失败时跳npm run pack+scripts/install.ps1/scripts/install.sh加Restore-ElectronDist/Test-ElectronDisthelper + 测tests/hermes_cli/test_gui_command.py +155 行—/browser限本地 gateway PR #47245a68ac0c:apps/desktop/src/lib/desktop-slash-commands.ts:33加'browser'进DesktopActionId+:107-112 /browserspecsurface:action('browser')+:152从 terminal-only blocklist 移除 +apps/desktop/src/app/types.ts:49-53新BrowserManageResponse {connected?, url?, messages?[]}+apps/desktop/src/app/session/hooks/use-prompt-actions.ts:1148-1219 browserhandler$connection.get()?.mode==='remote' → "local gateway only",否则connect|disconnect|status调requestGateway('browser.manage', {action, session_id, url?});同 PRtools/skill_manager_tool.py加_validate_delete_target守 tree-escape — 外部 provider 终端断开a0ec4f5:apps/desktop/src/app/right-sidebar/store.ts:16 $terminalInjection=atom(null)+:21-30 runInTerminal(command)置 takeover+injection +apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts:680-700 useEffect在status==='open'时订阅 + 写${command}\r至hermesDesktop.terminal.write+ 写完清 atom +apps/desktop/src/app/settings/providers-settings.tsx:34 GroupLabelhelper +:174第二个 "Other providers" header +:218 terminalDisconnect=!canDisconnect && Boolean(provider.disconnect_command) && canRunInTerminal()+:325-339 handleTerminalDisconnect调runInTerminal(command)+apps/desktop/src/types/hermes.ts加disconnect_command;后端hermes_cli/web_server.py返 per-OSdisconnect_command— Right-sidebar explorer refresh 始终可点 PR #462449d2ec8d:apps/desktop/src/app/right-sidebar/index.tsx:134 HEADER_ACTION_LABEL_REVEAL从peer-hover/project-label改group-hover/project-header+group-focus-within/project-header+:219 RightSidebarSectionHeaderdiv 挂group/project-headerclass + 测试 +75 行index.test.tsx— ⭐display.memory_notifications三态 off/on/verbose(3 feat + 2 fix):hermes_cli/config.py:1441 DEFAULT_CONFIG["display"]加"memory_notifications":"on"+agent/agent_init.py:303 agent.memory_notifications属性 +agent/background_review.py:626 summarize_background_review_actions(notification_mode=...)解析 mode + 构 Memory➕/✏️/➖预览(add/replace 120 char、remove 60 char)+gateway/run.py:14805-14812网关解析display.memory_notifications赋 agent + 文档website/docs/user-guide/features/memory.md:248-267新## Background review notifications段 + 测tests/run_agent/test_background_review.py:390/397/404/414/425 test_memory_notifications_{off_returns_nothing,on,verbose,default_is_on,skill_patch_off_silent_verbose_shows_diff};4cf9d80verbose skill change 预览tools/skill_manager_tool.py:616 _create_skill加_change:{description}+:667 _edit_skill同(message 改"updated (full rewrite)")+:764 _patch_skill加_change:{old,new}截 200 +agent/background_review.py渲📝 Skill '{name}' patched: "old" → "new"/created:/rewritten:+ 转发_summarize_background_review_actions进run_agent.py:1411;c2c55c4全 provider 共用 strip:新规范解析器agent/skill_commands.py:58 extract_user_instruction_from_skill_message()+ 标记常量_SKILL_INVOCATION_PREFIX/_SINGLE_SKILL_MARKER/_BUNDLE_MARKER/_BUNDLE_USER_INSTRUCTION/_BUNDLE_FIRST_SKILL_BLOCK/_RUNTIME_NOTE(~:44-53)+agent/memory_manager.py:435 MemoryManager._strip_skill_scaffolding静态方法 +prefetch_all(:458)/queue_prefetch_all(:485)/sync_all(:544)三调 + 新测tests/agent/test_memory_skill_scaffolding.py;e3adbb5前置plugins/memory/openviking/__init__.py:71 _derive_openviking_user_text()在queue_prefetch(:548)+sync(:588)调(c2c55c4 后改:42 from agent.skill_commands import extract_user_instruction_from_skill_message+:81调用) — ⭐ Hookssession:compress事件e76e7b5:init_agent接event_callback: Optional[Callable[[str, dict], None]]进agent/agent_init.py:198+:430赋值 +agent/conversation_compression.py:611-618触发 payload{platform, session_id, old_session_id, compression_count}+gateway/run.py:14374 _event_callback_sync桥_hooks_ref.emit(event_type, context)经asyncio.run_coroutine_threadsafe+:14747 agent.event_callback=_event_callback_sync+AIAgent.__init__在run_agent.py:388透传 kwarg;28f9247删from urllib.parse import urlparse, parse_qs, urlunparse死引 + 测tests/run_agent/test_compression_boundary_hook.py:165 TestSessionCompressEvent+:213 test_event_emitted_on_compression断compress_events+ctx["old_session_id"]/compression_count+test_no_callback_is_safe+test_callback_exception_does_not_break_compression—prompt.context_file_max_chars可配f6a42b1:hermes_cli/config.py:1110 "context_file_max_chars":20_000默认 +agent/prompt_builder.py:962 _get_context_file_max_chars()读 +:1516 _truncate_content(max_chars=None)+:1522警告"increase context_file_max_chars or trim the file!"+build_system_prompt在agent/system_prompt.py经drain_truncation_warnings()推agent._emit_status()+ 文档configuration.md:614/620/context-files.md:112/174/188/prompt-assembly.md:198;6ebc449截断警告 contextvar 隔离agent/prompt_builder.py:11 import contextvars+:984 _truncation_warnings = contextvars.ContextVar("context_file_truncation_warnings", default=None)+_record_truncation_warning(~:991)+drain_truncation_warnings()(:998)+ 测test_warnings_isolated_across_contexts—tool_progress_style → tool_progress_grouping改名(同日fc956b9引入→6373aba改名):gateway/display_config.py:35 _GLOBAL_DEFAULTS["tool_progress_grouping"]+:242 _normalise保accumulate|separate+gateway/run.py:13688解析 +:14027 can_edit = progress_grouping != "separate"+hermes_cli/config.py:1498 "tool_progress_grouping":"accumulate"+ 测tests/gateway/test_display_config.py:454-510 TestToolProgressGrouping+ 文档website/docs/user-guide/messaging/index.md:323-327— Codex pool-only rate-limit 不弹 relogin9a59ad7:新分类器hermes_cli/auth.py:3875 _codex_pool_rate_limit_status()扫auth_store["credential_pool"]["openai-codex"]找last_status="exhausted"+ code 429/quota/rate_limit +resolve_codex_runtime_credentials在:3809-3826 raise AuthError(code=CODEX_RATE_LIMITED_CODE, relogin_required=False)(不再 "missing credentials")+get_codex_auth_status()在:6003-6014返{logged_in:True, rate_limited:True, error_code:CODEX_RATE_LIMITED_CODE, reset_at}+ 常量:723 CODEX_RATE_LIMITED_CODE="codex_rate_limited"— xAI 默认grok-build-0.1bbc842d+f4ef70f:hermes_cli/models.py:113 _XAI_STATIC_FALLBACK[0]="grok-build-0.1"+:121 _XAI_TOP_MODEL="grok-build-0.1"+plugins/web/xai/provider.py:49 DEFAULT_MODEL="grok-build-0.1"+hermes_cli/model_setup_flows.py:520 _prompt_model_selectionfallback;docsplugins/web/xai/provider.py:22例 +website/docs/user-guide/features/web-search.md+zh-Hans+website/docs/guides/xai-grok-oauth.md;grok-4.3 仍在:114;聚合目录(Nous/OpenRouter)不动 — Models live+curated 合并 + curated-first + validate 兜底 PR #46857 3 commit:630b438hermes_cli/models.py:2263-2280Anthropic 分支curated = list(_PROVIDER_MODELS.get("anthropic", []))→merged = list(curated)→ 大小写 insensitivemerged_lowerset 追 live-only ID + 同 pattern 在 fetch_models 调用点~models.py:2376泛化 + 测tests/hermes_cli/test_provider_live_curated_merge.py 113 行;ee7b8a4:3585 validate_requested_model+:3947-3962"Model not in live /v1/models — check the curated catalog before rejecting"分支返{accepted:True, recognized:True, message:"Note: ... exists in the curated catalog — accepted."};658ac1d:1762 _model_in_provider_catalog(name_lower, providers)+:3952验证用纯目录 helper(无网)+:1861, 1896其他 catalog 成员检查走该 helper + 合并代码在:2263-2280保 curated 在前再追 live-only —model.base_url透传 fetch_models1b962f0:providers/base.py:162-217 fetch_models(*, api_key, base_url, timeout)解析顺序models_url → base_url → self.base_url + "/models"+hermes_cli/models.py:2374 live = _p.fetch_models(api_key=api_key, base_url=base_url or None)+ 子类 overrideplugins/model-providers/custom/__init__.py:42-52/openrouter/__init__.py:50-73+ 新测tests/providers/test_fetch_models_base_url.py 140 行;db44af0两 overlap user-defined provider 跨过滤测 22 行进tests/hermes_cli/test_inventory.py— 无 api_key 仍探针 /v1/models1039e90:hermes_cli/model_switch.py:1741-1758注释"With an api_key: always probe… Without an api_key AND no explicit models: probe anyway"+should_probe = bool(api_url) and discover and (bool(api_key) or not has_explicit_models)+fetch_api_models(api_key, api_url);7493de778 行新测tests/hermes_cli/test_user_providers_model_switch.py+scripts/release.py:420 "[email protected]":"chimpera"— 自定义 provider dedup 保留b7fa62c:hermes_cli/inventory.py:175-195先扫is_user_defined行收user_models然后主循环if row.get("is_user_defined"): continue才调_is_aggregator(slug)+ 回归测tests/hermes_cli/test_inventory.py— GLM-5.2 入 OpenRouter+Nousb2da39aPR #47391:hermes_cli/models.py:64 ("z-ai/glm-5.2","")进OPENROUTER_MODELS+:187 "z-ai/glm-5.2"进_PROVIDER_MODELS["nous"](在 glm-5.1 之前)+:263 "glm-5.2"进 zai picker + 重生成website/static/api/model-catalog.json— auxiliary auto 任务沿主 fallback chain PR #472354858942:agent/auxiliary_client.py:3106 _fallback_entry_api_key+:3117 _resolve_fallback_entry(... ←resolve_provider_client)+:3135 _try_main_fallback_chain读get_fallback_chain(load_config())迭代跳 failed/main/unhealthy +_resolve_auto接task参 +:3320-3333在 Step 2 插用户 fallback +resolve_provider_client(... task=None):3459— Telegram 富文本默认开 + 流式 final 仍 rich PR #46890a6364bf:gateway/platforms/telegram.py:428 _rich_messages_enabled默认翻True+:984 _needs_rich_rendering():富专用于 table/task-list//block-math +:1006 _rich_eligible()共享核心去expect_edits门 +:1257 async def _try_edit_rich(...)editMessageText+rich_message 路 +:2680-2681 if finalize and self._rich_eligible(content): rich_result = await self._try_edit_rich(...)— Rich-reply 跨重启 send-time 索引恢复01ae9b8+8ed16a7:新文件gateway/rich_sent_store.py:23 _MAX_ENTRIES=1000+:36 def record(...)+:68 def lookup(...)+ JSON store~/.hermes/state/rich_sent_index.json+gateway/platforms/telegram.py:1248-1249发送后 record(chat_id, message_id)→content+:6718-6720reply 时 text+caption 都空 →reply_to_text=rich_sent_store.lookup(str(chat.id), reply_to_id)+ 107 行新测 4 个(test_rich_reply_records_and_recovers_text/_lookup_miss_leaves_text_none/_native_quote_wins_over_lookup/_caption_wins_over_lookup)+3f80bca scripts/release.py:94 "[email protected]":"x1erra"— Slack/debugvia/hermesPR #472484d470b3:hermes_cli/commands.py:1057 _SLACK_VIA_HERMES_ONLY=frozenset({"credits","debug"})加debug(与 Telegram 对齐)+ check 点:1107— Mattermost notify-only flat-fallback16fc717+5a0e0d3:gateway/platforms/base.py:80 _mark_notify_metadata(metadata)浅克隆置notify=True应用:3899/:4005/:4055/:4282 _final_thread_metadata+plugins/platforms/mattermost/adapter.py:155 async def _thread_root_for_send从 reply_to/metadata 解析 root +:170 def _last_post_failure_is_broken_thread_root400/404+body 标识 +:181 async def _post_preserving_thread仅metadata.get("notify")且 broken-root 时 flat-fallback + 接:352/:534/:575/:663text/image/file/document 发送 — WhatsApp/emailsend_image(metadata=)e65d74b:gateway/platforms/whatsapp.py:843-862 async def send_image(... metadata: Optional[Dict[str, Any]] = None)+:862 super().send_image(..., metadata)fallback +gateway/platforms/email.py:675-683同 + 新契约测tests/gateway/test_media_metadata_contract.py 80 行+_accepts_metadata()helper 扫所有 adapter — PhotonspectrumProjectId收敛5b3fa26:plugins/platforms/photon/auth.py:15-17文档:post-unifyproject.id==spectrumProjectId+:168 def load_dashboard_project_id()优先spectrum_project_id而非 legacydashboard_project_id+:185entry-key fallback 链 +get_project()删 +create_project不再发spectrum: true切换始终 provisioned — ⭐ Honcho 网关身份树 gateway-gated 替换部署形状 PR #44431 merged2b34e8:bb5cb32 _migrate_pin_peer_name()在plugins/memory/honcho/cli.py:380-391poppinPeerName写pinUserPeer+ 克隆路径cli.py:51/56包 pinUserPeer + legacy 迁移;d7dfeed _gateway_platforms()在cli.py:394-408懒导gateway.config.load_gateway_config返已连平台或 None +cli.py:681-707无网关时 auto-skip 否则菜单[1] just me / [2] me + others / [3] only others / [s] skip / [e] edit raw keys+cli.py:724-735orphan-guard:un-pin 会孤悬 peerName 历史时重提 + 各分支cli.py:741/:754-758/:766-769scrub 后写pinUserPeer/userPeerAliases/runtimePeerPrefix;99feb03docsplugins/memory/honcho/README.md:140-144pinUserPeer/userPeerAliases/runtimePeerPrefix 表行 + pinPeerName 降 deprecated;23a7458website/docs/user-guide/features/honcho.md:160"Gateway Identity Mapping" 节 +:174解析器顺序 +:177orphan 警告 +:181deprecated 别名;2708c33+1544813隐私 alice + Telegram UID7654321跨 README/cli.py/测试/docs;后续6dde7d4docswebsite/docs/user-guide/features/memory-providers.md:98pinUserPeer 行 +:211"every non-agent gateway user collapses to peerName" 进 Gateway Identity Mapping 子段;c7513dfplugins/memory/honcho/README.md:140"every gateway runtime user collapses…" reframe 为 non-agent + pin-overrides-aliases +cli.py:458菜单提示词改 +honcho.md:168"every non-agent gateway user collapses to your peer. Pin overrides all aliases" 交叉引用session.py:335解析器优先级 — Skills 跳支持目录9137b86:agent/skill_utils.py:50 SKILL_SUPPORT_DIRS=frozenset(("references","templates","assets","scripts"))+:73 def is_skill_support_path(path)+:68 should_exclude_skill_pathORis_skill_support_path与既有EXCLUDED_SKILL_DIRS+tools/skills_tool.py:84/1027/1032/1043/1050/1077接_is_skill_support_path守skill_view/发现遍历 — shop-app → CLI 化 shop skill v1.0.1:5094325optional-skills/productivity/shop/SKILL.md:2-7 name:shop, version:1.0.1, prerequisites.commands:[curl,node]引catalog-mcp.md 236 行/direct-api.md 278 行/safety.md 36 行/legal.md,旧productivity/shop-app/SKILL.md删;d7668aadescription ≤60 char +:5 author: Joe Rinaldi Johnson (joerj123), Hermes Agent;e236bb8docs regen 删website/docs/optional/productivity/productivity-shop-app.md 354 行+ 新productivity-shop.md 238 行+ 更website/docs/reference/optional-skills-catalog.md+website/sidebars.ts;cf52370 scripts/release.py:59 "[email protected]":"joerj123"— TUI session-create no-race 测试隔离 PR #472302483200:tests/test_tui_gateway_server.py:4901-4942 test_session_create_no_race_keeps_worker_alive快照server._sessions→_saved_sessions+server._sessions.clear()+finally还原 +agent_ready.wait(timeout=2.0→10.0)并断言built返回值(之前默吞 timeout)+ 服务端引用点server.py:1011'replaced'check — 5 条 AUTHOR_MAP salvage(全进scripts/release.pyPython dict 而非tools/release/AUTHOR_MAP.json):3f80bca :94 x1erra/7493de7 :420 chimpera/1ac76a9 :52 MrDiamondBallz/db01910 :419 cyb0rgk1tty/cf52370 :59 joerj123/925b0d1 :95 zimigit2020— 验证基线/tmp/hermes-agentclone @d1ecebc+ 4 个并行 research agent 实证(A: Desktop UI 17 commit / B: Memory/Display/Gateway/Hooks/Prompt/Auth 15 commit / C: Models/xAI/Skills/Honcho 18 commit / D: Messaging Telegram/Slack/Mattermost/Photon/WhatsApp/AUTHOR_MAP 13 commit) -
2026-06-15-update: 77 commits 单日同步(hermes-agent
2a14e8957 → cffd6e3c8,仍 v0.16.0 未发新版;约 44 fix / 7 test / 4 feat / 4 chore / 3 docs / 2 🐛 fix / 2 refactor / 1 revert / 1 redact / 1 nix / 1 ci / 1 change / 1 unscoped / 5 merge;~31.5h 跨夜单日窗口;164 文件 +18569/−17867)— ⭐ feat — 异步后台子代理delegate_task(background=true)c66ecf0bc (#40946)(新文件tools/async_delegation.py 386 行—:96-97 _records注册表 +:124 active_count()+:152 dispatch_async_delegation()+:215-226lock 内原子容量检查 +:266 _finalize完成回调推type="async_delegation"event 进process_registry.completion_queue+:337 list_async_delegations()+:362 interrupt_all();tools/delegate_tool.py:2053 background:bool参 +:2090-2095batch+background 互斥拒 +:2243-2317父线程取get_current_session_key()+:2261-2270从parent_agent._active_children解绑让父中断/缓存 evict//new不杀后台 +:3037-3054schema +:3099注册;tools/process_registry.py:1549-1616 _format_async_delegation()渲[ASYNC DELEGATION COMPLETE — ]自包含块 +:1619 format_process_notification加evt_type=="async_delegation"路由;gateway/run.py:5393启动 schedule_async_delegation_watcher+:12337-123822s 轮询 + 非 async event 立即 requeue +_enrich_async_delegation_routing解析session_key+_inject_watch_notification;cli.py:981-982shutdowninterrupt_all+cli_commands_mixin.py:227-258/stop+:260-295/agents+tui_gateway/server.py:5598-5600TUI 按delegation_iddedup +hermes_cli/config.py:1778 delegation.max_async_children=3+ 测tests/tools/test_async_delegation.py 473 行 15 测试)— feat — Hindsight observation_scopes 可配置a376ca008(plugins/memory/hindsight/__init__.py:21文档HINDSIGHT_RETAIN_OBSERVATION_SCOPESenv +:330 _load_config读 +:381 _OBSERVATION_SCOPE_KEYWORDS={"per_tag","combined","all_combinations"}+:384 _normalize_observation_scopes()接受 keyword/JSON list-of-lists/扁平 tag list +:1240-1243/:1498-1499retain kwargs 注入 +:1614-1620tool retain 路径切client.aretain → client.aretain_batch因前者不接此参)— feat —/status显 model+contextead38107a(gateway/slash_commands.py:395-509 _handle_status_command()优先status_agent.model/provider/context_compressor.last_prompt_tokens/.context_length→ SessionDB row → user config + 新 locale 键gateway.status.model/model_provider/context/context_used+ 17 locale 同步 + 73 行测试)— feat — Display 显delegate_taskgoals5035fa902(agent/display.py:180 _delegate_task_goal_parts+:212-222 build_tool_preview渲"{count} tasks: Goal A | Goal B | Goal C"+:1057-1060 _get_cute_tool_message_impl渲"3x: Goal A | Goal B")— Auth — xAI OAuth 跨 profile 解析 + write-through global root + access skew 120→3600s(5 commit PR #43589 salvage):f1d6f0436hermes_cli/auth.py:3899 _xai_oauth_state_from_store()扫credential_pool["xai-oauth"]找含access_token+refresh_token条目 +:3937 _xai_oauth_state_has_usable_tokens()守 +:3946-3956 _read_xai_oauth_tokens()profile 缺 → 回退 global root;497352bc4:1087 _save_auth_store加target_path参 +:3996 _profile_has_own_xai_oauth_state()+:4007 _write_through_xai_oauth_to_global_root()守_global_auth_file_path() is None与 pytest 安全带:4030+:4061-4079 _save_xai_oauth_tokens在_auth_store_lock()内 write-through;febdddb41:111 XAI_ACCESS_TOKEN_REFRESH_SKEW_SECONDS=3600(原 120)适配 6h xAI access token;1227007ae scripts/release.py:1557AUTHOR_MAP[email protected]=capt-marbles;8844e091cmerge — MCP — fail-fast noninteractive OAuthdcc321695(tools/mcp_oauth.py:756-763 build_oauth_auth()现raise OAuthNonInteractiveError(...)在not _is_interactive() and not storage.has_cached_tokens()时,消息含hermes mcp login {server_name}hint +tools/mcp_oauth_manager.py:411/427-434 MCPOAuthManager镜像)— Security — Disk-cleanup protected walks 显式 frozenset + 后序 DFS(3 commit):c1a70a543/40699c329/a688d2a1bplugins/disk-cleanup/disk_cleanup.py:147 _EMPTY_DIR_PROTECTED_TOP_LEVEL=frozenset({"logs","memories","sessions","cron","cronjobs","cache","skills","plugins","disk-cleanup","optional-skills","hermes-agent","backups","profiles",".worktrees"})+:153 _EMPTY_DIR_SWEEP_PRUNE_DIRS=frozenset({".git","node_modules","venv",".venv","site-packages","__pycache__"})+:364-402 quick()空目录 sweep 重写sweep_stack: List[Tuple[Path, bool]]显式后序 DFS(替rglob("*")全遍历)防 gateway event loop 卡分钟级 — Privacy — API debug dump 全字段 redactad58dd51a + aab2e99ba(agent/agent_runtime_helpers.py:1228-1231 dump_api_request_debug()经redact_sensitive_text(force=True)+atomic_json_write+:1236 HERMES_DUMP_REQUEST_STDOUT也走 redacted +agent/redact.py:107 _PREFIX_PATTERNS新r"ntn_[A-Za-z0-9]{10,}"(Notion internal integration token)+ dump 现在无条件触发 API 错误)— Gateway scoped lock 第三 stale 分支ec05d2bc3(gateway/status.py:646-660 acquire_scoped_lock()新分支:PID + start_time 都非 None 且相等但not _looks_like_gateway_process(existing_pid)时调_read_process_cmdline检 cmdline 可读 →stale=True,防 Linux/systemd 启动期 PID+jiffystart_time重用让 cron/nginx/sshd 冒名 gateway) — Bedrockboto3>=1.34.59软守2cddc9c89(agent/bedrock_adapter.py:61 _MIN_BOTO3_VERSION=(1,34,59)+:64-88 _require_boto3()解析boto3.__version__三 int tuple,低版RuntimeError含升级 hint,parse 失败不阻塞 — 修 Ubuntu 24.04 系统boto3==1.34.46shadow venv pin 致converse_stream裸AttributeError) — s6 / Supervisor 5 修硬化:40d7c264f #46266hermes_cli/profiles.py:1271 _maybe_register_gateway_service()调register_profile_gateway(start_now=False)+service_manager.py:964-965写(tmp_dir / "down").touch()marker;61ee2dbfd #46291service_manager.py:756 _render_log_run加chown hermes:hermes "$HERMES_HOME/logs/gateways"非递归 +docker/stage2-hook.sh:319cont-init 预创父;b77096726 #46292:359 _write_gateway_desired_state(name, desired_state)+ 三 mutator (:821/:873/:883) 写 +container_boot.py:258 _read_desired_state优先desired_state字段防 transient 抹运维意图;c2b7669ad #46289:758加rm -f "$log_dir/lock"在 chown 后 s6-log exec 前清陈旧 lockfile;95715dcb0 #46483hermes_cli/main.py:467 _apply_profile_override守if profile_name is None and not os.environ.get("HERMES_S6_SUPERVISED_CHILD")让 supervisedgateway-default跳过 stickyactive_profile回退 — Container / Dashboard 4 修:4eb0ff639 #46290service_manager.py:118gate 从is_container() and _s6_running()改为裸_s6_running()修 Fly Firecracker microVM 上 s6 dispatch 路径全 inert;aca11c227 #46293container_boot.py:210 _strip_container_argv_prefix()+:237 _is_dashboard_container()+:439 main()在 reconcile 前跳过;80f8ffc74 #46487hermes_cli/main.py:10785-10790 cmd_dashboard()rerouteenv["HERMES_HOME"]=str(get_default_hermes_root())钉机器根防$HOME/.hermesfallback;f79551378 #45120scripts/install.ps1:1431-1442重建 venv 前taskkill /F /T /IM hermes.exe /FI "PID ne $myPid"+ 800ms sleep 释_bcrypt.pyd锁 — Tools — 文件工具尊重 session cwd(PR #46552 salvage 5 commit):d6a8d9dca_authoritative_workspace_root加新 "registered task/session cwd override" 步 +ddf7c7af8terminal_tool.py:1037-1052 resolve_task_overrides(task_id)单 helper 路由file_tools._registered_task_cwd_override与_get_file_ops+b0c99c12ddocstring 列四步顺序 +8fce54499file_tools.py:99-113 _sentinel_free_abs_cwd(raw)抽 sentinel + expanduser + isabs validation 尾段(用_TERMINAL_CWD_SENTINELSfrozenset:96)+6cb88a087merge — Cron —jobs.json跨进程 fcntl/msvcrt 锁e5b4cf7be + 733472952(cron/jobs.py:58-59 _jobs_file_lock=threading.RLock()+_jobs_lock_state=threading.local()重入追踪 +:70 _jobs_lock()contextmanager Unixfcntl.flock(LOCK_EX)/ Windowsmsvcrt.locking(LK_LOCK,1)跨进程 +:89-129depth-count 重入 +:554 _save_jobs_unlocked()private + 全 mutator 包with _jobs_lock():(create/update/remove/mark_job_run/advance_next_run/get_due_jobs/rewrite_skill_refs)+agent/curator_backup.py:459/466 _restore_cron_skill_links走_jobs_lock)— Process — completion 五态 + termination_sourcebe7c919bf #46659(tools/process_registry.py:103-104 ProcessSession.completion_reason: str = "exited"枚举exited|killed|lost|failed_start|already_exited+termination_source: str = ""枚举process.kill|kill_all|backend_lost|failed_start+kill_process(*, source="process.kill")+ 全 payload 含两字段 +:1619 format_process_notification按completion_reason选_status文本 + exit code -15/143 append", SIGTERM"+gateway/run.py:12337agent-notify 合成走format_process_notification({...}))— Messaging — WhatsApp group JID 路由 targetea49a7963 + 0d82060c7(tools/send_message_tool.py:47-49 _WHATSAPP_JID_RE匹配@g.us|s.whatsapp.net|lid|broadcast|newsletter+:520-525 _parse_target_refwhatsapp 分支返(target_ref, None, True)+gateway/channel_directory.py:26 CHANNEL_ALIASES_PATH=get_hermes_home()/"channel_aliases.json"+:29 _load_channel_aliases+:40 _apply_channel_aliases(platforms)在 rebuild 与 load 时都应用 +0d82060c7加入备份) — Desktop cluster:eae3836eb + f02484feb + 30377e108 + 45e2f4fdc@assistant-ui/store0.2.13 pin(package.json:38-41 overrides+.github/workflows/typecheck.yml:33-42新desktop-buildjob 跑npm run --prefix apps/desktop build让 vite break 在 CI 暴露 +nix/lib.nix:24 npmDepsHash="sha256-m9cjbjzi4SaFCjODfdrawS5e+1ag+MpRn528/upSNqo=");f3b32e9f5 + c23a2eec1 + c33e0457d #46836macOS Electron pack 重命名前补缺(apps/desktop/package.json:23 "prebuilder": ".../patch-electron-builder-mac-binary.cjs"+:138 "electronDist": "../../node_modules/electron/dist"+ 新脚本 60 行 darwin-only patchapp-builder-lib/out/electron/electronMac.js doRename()在 rename →Hermes前从 runtime dist 复缺失的Contents/MacOS/Electron修ENOENT);fbabf438a + bee13817fapps/desktop/src/store/profile.ts:213 ensureGatewayProfile()在 gateway swap 后 resync$connection,让 remote pool profile 激活为后台后 image 附件走image.attach_bytes而非路径image.attach;0bbf325a8 #46665dashboard 聊天侧栏 model card 经session.create传 management profile;ed20f5ed0 #42241/#46796tui_gateway/server.py:1957 _apply_model_switch(parsed_flags=...)+:7013-7030 config.set预解析显式--provider时绕开 broken-default agent build + Rendereruse-model-controls.ts发config.set替slash.exec;368fcf1ff #46772新apps/desktop/electron/windows-user-env.cjsparsereg query+main.cjs:243-265 resolveHermesHome()Windows 上先读 HKCU\Environment 注册表;8fe334b05 #44159apps/desktop/src/components/pane-shell/pane-shell.tsx:88 HOVER_REVEAL_EDGE_GUTTER='calc(0.5rem + 2px)';ae433634dapps/bootstrap-installer/tsconfig.json + shared/tsconfig.jsonES2023 — Install / Deps:a4ee1f223 + 98205da00 + 1db8f7ea8 + 39f479cba #46085scripts/install.sh:427-433 configure_managed_node_npm_prefix()+scripts/lib/node-bootstrap.sh:65-71 _nb_configure_npm_prefix()写prefix=$(dirname link_dir)进$HERMES_HOME/node/etc/npmrc让npm install -g落 on-PATH 命令链接目录;0bbff1fc7 #46744pyproject.toml:104 "websockets==15.0.1"入核 +:138 dev=[..., "setuptools==81.0.0"]从 82.0.1 降配torch>=2.11 caps setuptools<82;5f6be7f31 #46764:182 teams=["microsoft-teams-apps==2.0.13.4","aiohttp==3.13.4"]optional extra +tools/lazy_deps.py:159 "platform.teams"lazy-install +plugins/platforms/teams/adapter.py check_teams_requirements()调ensure_and_bind('platform.teams',...)— CI:9eb0bcd60删.github/workflows/nix-lockfile-fix.yml + nix.yml;29c698559nix/lib.nix:24 npmDepsHash刷新;92a456f71esbuild/vite 锁回升(vite ^8.0.16/esbuild ^0.28.1)+hermes_cli/main.pyautostash 防 update 时丢本地编辑;30377e108Desktop renderer build on PRs(见上@assistant-ui/store集群)— Discord — slash 100 cap PR #46078:5e851bc6b + 8f4a718f9 + cffd6e3c8(merge)plugins/platforms/discord/adapter.py:39 _DISCORD_MAX_APP_COMMANDS=100+:3530 slot_cap=_DISCORD_MAX_APP_COMMANDS-1保/skillgroup + skip 逻辑两循环 +:3613-3620一条警告 + 200 commands 回归测 — Web —revert(web)Parallel keyless search 撤回f3fe99863 #46350(plugins/web/parallel/provider.py净 -345 + 删两测试文件 +tools/web_tools.py-234 +pyproject.tomlSDK pin 撤)— Misc:a829e04d6 #46345 hermes_cli/profiles.py:458-486 _migrate_profile_config_if_outdated(profile_dir)用set_hermes_home_overridescopecheck_config_version()/migrate_config(interactive=False, quiet=True)到新 profile + 清 override 防伪 v0→latest 警告 +b2a476646/2a08b8c86 hermes_cli/dump.py:255-272env override ≠ config 时输出"{env_backend} (TERMINAL_ENV overrides ...)"+2f2e3616b tools/browser_tool.py:1180-1201 _get_session_inactivity_timeout()读browser.inactivity_timeout+5b2604df9 hermes_state.py:1133-1135v10 trigram 回填在 v11 FTS rebuild 前跳 +9df1a1a8d hermes_cli/doctor.py:791-802 providers_accepting_vendor_slugs加"nvidia"+60cc42e38 hermes_cli/inventory.py:160-188user-defined ↔ aggregator 模型去重 +ba3883cd1 + 49e743985MiniMax M3 reasoning extra_body 入plugins/model-providers/minimax/__init__.py MiniMaxProfile.extra_body_for()只在api.minimax.ioAND{"minimax-m3","minimax/minimax-m3"}两 predicate 都真时发{"reasoning_split":True}+975b9f0a5 #46646CONTRIBUTING.md 加 standard installer 节 +f7c1cbe66 #46795桌面下载链接到站点根 + 4 条 AUTHOR_MAP(f79b109f4 0xneobyte/c17469cb1 Veritas-7/1227007ae capt-marbles/c23a2eec1 #38673 salvaged)— 验证基线/tmp/hermes-agentclone @cffd6e3c8+ 4 个并行 research agent 实证 -
2026-06-14-update: 83 commits 单日同步(hermes-agent
0a865e5 → 2a14e8957,仍 v0.16.0 未发新版;约 54 fix / 6 perf / 6 feat / 5 test / 3 chore / 1 refactor / 1 docs / 1 style / 1 unscoped / 5 merge;~23.5h 单日窗口;166 文件 +8907/−692)— SSL CA bundle fail-fast guarda218a0f15 主轴 + 5 修新建agent/ssl_guard.py 94 行+agent/errors.py SSLConfigurationError+ escape hatchHERMES_SKIP_SSL_GUARD+hermes_cli/doctor.py:316-318"SSL / CA Certificates" 节 + 调用点上移到agent/agent_init.py:903-905 _create_openai_clientsetup 内 — MCP stdio config exfil-shape 拦截:972a9885e (#46083) + a27d7e68c (#46112)新hermes_cli/mcp_security.py 96 行双门匹配_SHELL_INTERPRETERSfrozenset +_EGRESS_PATTERNcurl|wget|nc|ncat|socat|/dev/tcp/|Invoke-WebRequest+_EXFIL_HINT_PATTERN.env|--data-binary|-X POST|+89bdb1e54hermes_cli/web_server.py:10659/10709 read_text(encoding="utf-8")— Agent — 模型 refusal 不重试改直透 content_filterc8ad2ca99 PR#460134 连:bb46bf8ceAnthropic + Chat Completions transport 把 refusal 映射finish_reason="content_filter"+12c84d6c7只在 refusal 是唯一 payload 时算终止 +10bd01972共享_content_policy_blocked_result()builderagent/conversation_loop.py:411-433+_CONTENT_POLICY_RECOVERY_HINT常量:405-408提hermes fallback add— Codex reasoning thinking-only069bfd654 + 1d584a301run_agent.py:905-936 _disable_codex_reasoning_replay()弹codex_reasoning_items+:3278-3343 _is_thinking_only_assistant()把item.type=="reasoning"列表项当 thinking-only — Gateway 中断 replay 清理5191c1c2c + 2c174bce2gateway/run.py:767-776 _is_interrupted_tool_result()识 exit_code 130/-1 +:779-822 _strip_interrupted_tool_tails()删被中断 assistant→tool 段 +:825-837 _AUTO_CONTINUE_NOTE_PREFIX="[System note: Your previous turn"+ 保新输入 — Gateway 启动 auto-resume 串行10bad2faf #46074gateway/run.py:4642-4699新_queue_startup_restore_event() / _drain_startup_restore_queue() / _finish_startup_restore()— Gateway repaired-turn 持久2b4873f7f #46071run_agent.py:1548-1641改_flushed_db_message_ids身份追踪取代位置切片防repair_message_sequence缩短历史时丢新尾 — Gateway intentional silence tokens293c04fef + 0e22bf643 #46105gateway/response_filters.py:13 SILENT_REPLY_TOKEN="NO_REPLY"+:18-23 LIVE_GATEWAY_SILENT_MARKERS=frozenset({"[SILENT]","SILENT","NO_REPLY","NO REPLY"})+:30-44 is_intentional_silence_response()精确匹配 ≤64 字符 + 全响应等于 token 才静默 — Gateway shell-supervisor guard7433d5f0e + 143679305hermes_cli/gateway.py:3798-3818 _running_under_gateway_supervisor()检INVOCATION_ID/HERMES_S6_SUPERVISED_CHILD/XPC_SERVICE_NAME!="0"+:3821-3858 _guard_supervised_gateway_conflict()+:3861-3880PID 文件 scoping — Gateway 回复消息媒体附件efbe1635d #46107gateway/platforms/telegram.py:5563-5606 _cache_replied_media()从msg.reply_to_message下载 + cache + 文本附[Replied-to '' saved at: ]— Profile / HOME 隔离b00060ce5 + 723c2331b + d842155da + 9f33d673ehermes_constants.py:362-395 get_subprocess_home()看TERMINAL_HOME_MODE=auto|real|profile+:398-405 apply_subprocess_home_env()设HERMES_REAL_HOME与HOME+ TUItui_gateway/server.py:1222-1236 _set_session_cwd()走 profile-scoped_session_db(session)helper — Skills cluster6c34088a1 PR#46237 + fc2b8b3d3 PR#462365 commit:7f245b003 #45966gateway/run.py:14376-14414跨进程缓存失效经 message_count 对比 +3bc4a2ff7:12801-12850 _refresh_agent_cache_message_count()每轮 rebase +7bbe7024c #46201全局/平台 disabled 并集 +ce19fdb7c解析点全跟进 +4e6d05c6a #46149agent/skill_utils.py:275 _RAW_CONFIG_CACHEmtime+size keyed — Skills bundled-update 备份崩溃安全3581131e7 + 9a2b97632tools/skills_sync.py:509-525/590-595/608-625三段孤儿.bak复原 / 清陈旧.bak防 move 失败 / restore 前清部分dest— Telegram rich messages 24h 内两次翻转:57c2a55be端点 404 退路 →12682d96b feat 配置 opt-out 还原→9459057d7 #46102math crash 守 →a1f51feb7 #46206(HEAD)默 False +prefers_fresh_final_streaming()无条件返 False(gateway/platforms/telegram.py:426 _coerce_bool_extra("rich_messages", False)) — Email SMTP_SSL port 465 + IPv4 兜底04d4471d7 + cf7d5932fgateway/platforms/email.py:354-394 _connect_smtp()合并 4 call site;port 465 走smtp_ssl_cls(...),否则SMTP+starttls;超时/连接错 retry_connect(ipv4_only=True);:110 _IPv4SMTP_SSL用AF_INET/SOCK_STREAM— Models — ZAI GLM-5.2 1M 上下文bff78a34d+ Kimi K2.7 Code 原生 picker2a14e8957 #46309agent/model_metadata.py:270 "glm-5.2": 1_048_576(needle-in-haystack 789K 实证)+hermes_cli/models.py:60/181/260/285全链路 +provider_model_ids()对{"kimi-coding","kimi-coding-cn"}合并 curated 与 live 保留 K2.7-code — OpenRouter 元数据磁盘缓存13a1bd0f8 #46114agent/model_metadata.py:116-119 cache/openrouter_model_metadata.json+ 紧凑 JSONatomic_json_write(indent=0)+:110 _MODEL_CACHE_TTL=36001 小时 + 内存→磁盘→live/api/v1/models三级回退 — Perf wave:afc861550 #46065Webhook 增量 prune(Deque懒 O(stale) +_RATE_WINDOW_SECONDS=60.0)+110687914 #45831tools/process_registry.py:132 _completion_event: threading.Event+:1098-1127 wait()替sleep(1)+8f278403d #45948_rpc_server_loop(stop_event)settimeout5→0.05+5105c3651 #46079api-server_normalize_chat_contentO(n²)→O(n) +4b5ba112a #45979agent/conversation_loop.py:74-100 _image_error_max_dimension()解析 provider 错文本 clamp[512, 8000]— Misc:bf8effad0 #43852 utils.py:63 atomic_replace()跨设备 EXDEV/EBUSY →copyfile+copystat+fsync+unlink兜底 +85e6232a0Anthropic proxy/v1支持(build_anthropic_client()剥尾 +_endpoint_speaks_anthropic_messages()识/anthropic/v1)+8d5d36d79 #28479 model_tools.py:1115-1125透session_id到registry.dispatch+e986e3fc6 + 1b16c4817Provider OAuth 账号移除DELETE /api/providers/oauth/{provider_id}守_require_token+_oauth_provider_disconnect_hint+1fa761f8d #36142Search 超时保部分结果limit_reason="search_timeout"+288f7026eWeixin "Personal" 重标 +d76a58bd1sudo profile system install + 3 条 AUTHOR_MAP — 验证基线/tmp/hermes-agentclone @2a14e8957+ 4 个并行 research agent 实证 -
2026-06-13-update: 391 commits 跨日同步(hermes-agent
6c752ca3a → 0a865e5,仍 v0.16.0 未发新版;约 211 fix / 39 chore / 35 feat / 21 test / 18 refactor / 10 docs / 9 perf / 30 merge;~48h 双日窗口;含两批 historic salvage 2026-05-19~05-23 ≈167 commit 在本期并入;446 文件 +31366/−4724)— Desktop UX 大改d62979a (#44630)(composer status stackapps/desktop/src/store/composer-status.ts 257 行合并$subagentsBySession/$backgroundStatusBySession/$todosBySession+ 实时 subagent 窗口openSessionInNewWindow+ 用户气泡 `` 流式中可编辑thread.tsx:976+BrailleSpinner → GlyphSpinner改名)+ Stick-to-bottombbf020e (#45263)(use-stick-to-bottom: ^1.1.6+76b9386删thread-virtualizer.tsx 481 行改thread-list.tsx 307 行 useStickToBottom+scroll-to-bottom-button.tsx 59 行+withSessionBusyRetry包所有prompt.submit)+ Perf 三连492c402 (#45343)(7c226cc ChatRuntimeBoundary隔$messages订阅 +edc36f3 remend-tail.ts 108 行LRUBLOCK_CACHE_MAX+REVEAL_MIN_COMMIT_MS = 33+3cf7d43warm AudioContext 省 850ms)+ Worktree-aware 侧栏e906726(git-worktrees.cjs 174 行+use-worktree-info.ts 68 行+workspace-groups.ts 326 行+WorkspaceHeader/ReorderableList抽取) — WhatsApp Business Cloud API 新平台984e6cb(gateway/platforms/whatsapp_cloud.py 1956 行+whatsapp_common.py 367 行+setup_whatsapp_cloud.py 530 行;HMAC webhook + wamid dedup + 原生按钮 + opus 语音;Platform.WHATSAPP_CLOUD在gateway/run.py:6229-6239)— Photon iMessage spectrum-ts 3.0→3.1573c4e6/9bfff6e(pkg:15 "spectrum-ts": "3.1.0"+markdown()builder 经PHOTON_MARKDOWN+/react//unreactsidecar 端点)+156f4fb add_reaction/remove_reactionAPI +05470aa action='unreact' send_message + tools/send_message_tool.py:173-177+0a963d8 hermes photon telemetryCLI 切换 — Telegram 富文本永远 ona59d5e3 (#45584)+7c0605b流式 final 仍富文本(prefers_fresh_final_streaming+RICH_MESSAGE_MAX_CHARS=32768) — 安全 fail-closed wave:fc46354 fix(security)own-policy adapter 无 allowlist 时 fail-closed(WhatsApp/WeCom/Weixin/QQBot/Yuanbao)gateway/authz_mixin.py:90-150,271-301+3380563 /api/status受门时删hermes_home/config_path/env_path/gateway_pid/gateway_health_urlweb_server.py:1679-1681+c6a992e _host_derived_api_key()注册标签链尾兜底runtime_provider.py:103+5908822/9514ddbAPI key 不漏到非权威端点 +4ead464 secure_parent_dir拒 chmod/和len(parts) < 3+5edb346profile 下 write-deny/.envagent/file_safety.py— Gateway auto-resume 重复 agent 防御6e2fd95 + 63097ee(_schedule_resume_pending_sessions在asyncio.create_task前占_AGENT_PENDING_SENTINEL槽gateway/run.py:4498-4602+ 全路径回归test_restart_resume_pending.py)+ JSONL 抄写降级 4 commit(b4b118c/351fdcc/024a8e3/1d27be0state.db唯一存储;磁盘既有.jsonl不动) + Kanban 6 修(34120a0 sticky block+7bcdced respawn defer blocker_auth+88ee58f stale 不计 failure+7552e0f/7c622b6idx 后置 migration +cb125c2 (#45590)worker toolsets 钉 profile) — Billing/credits7ba5df0 (#44776)(agent/account_usage.py:342 CreditsView+cli.py:8399 _show_credits+ gatewayslash_commands.py:2945+ TUIserver.py:4773+c196269充值时不提示) — Dashboard profile-scope 全量(62b4618 (#45598)会话+分析 +88dbf95 (#44792)Channels +_profile_scope(profile)包所有端点)+28bf8fb feat clone profiles from any source+d206e1f本地文件浏览 home +9102d4aWin11 host 显示 +a118b94 (#45150)skill install 加--yes— CLI 持久 approval scrollback4474873 (#44702)+aa07983/bd66e7e/311ff96 Codex token 自愈(hermes_cli/auth.py:3527 _recover_codex_tokens_from_cli从~/.codex重导) + xAI 退役迁移 cluster(新hermes_cli/xai_retirement.py:16 RETIREMENT_DATE="May 15, 2026"+hermes_cli/migrate.py cmd_migrate_xairuamel 圆滑改写 +b4ba425doctor 表面 +a8a05c8启动告警 +b4afc65encrypted reasoning replay +64a9a19 (#28952)钉 x.ai 源 +a0c0312xAI Web Search plugin 560 行 +ca192cfopt-in TTS 停顿) — Bitwarden Secrets Manager552e9c7 (#30035)(agent/secret_sources/bitwarden.py 515 行+_BWS_VERSION="2.0.0"+install_bws()懒载到~/.hermes/bin/bwsSHA-256 校验 +secrets_cli.py setup/status/sync/disable/install) — Context Compression 重构波 11 commit(aec3885保近期轮 +434c684/c7bee8f自动聚焦近期用户轮 +8905ee6/5d0408dflush 游标 clamp/snapshot +691ff7c (#29824)末助手 reply 留 tail +2fef3e2 (#29824)合并 tail 拆分 +0db5cb8_SUMMARY_END_MARKER提至:92+749b721两 role 都附 marker +956af7f (#38389)COMPRESSED_SUMMARY_METADATA_KEY = "_compressed_summary"下划线前缀 wire 自剥 +286ecd2/8e5b759_MEDIA_DIRECTIVE_RE剥摘要器输入) — Perf wave:544c31b (#28866)agent-loop 47% per-conv 函数调用削减(load_config_readonly快路径 +agent/redact.py重写 +_resolved_api_call_timeout缓存)+6bd4311 (#29006)adaptive subprocess poll 省 ~195ms/工具调用 +6cb9917 (#28957)压缩可行性检查延后 — Models / Providers:957a8ffBedrock 受限 Claude 省采样参数 +eed61a1GeminisystemInstruction加 role +c8e5f34 (#36141)剥google//gemini/自前缀 +5acd185Moonshot union 数组 +4fd9397Codex chatgpt.com 移 extra_headers +7d11fa4Codex final_answer 完成顶层 incomplete 响应 +bc060c7 (#45492)移 unavailableclaude-fable-5+643dc82自定义 provider 会话身份保真 +e256f4a不恢复 bare billing provider{"auto","openrouter","custom"}+4b646bc (#45587)辅助保主 base_url +6a159be (#27132)ollama/vllm/llamacpp别名信任 — Delegation 默认子代理时钟移除bba9b51 (#45149)(DEFAULT_CHILD_TIMEOUT: Optional[float] = None) — MCP5affecb (#44550)capability-gatetools/list让 prompt-only MCP server 也连 — Skills hub:2ee69d0 (#44500)ClawHub 浏览预算允许 unlimited +fc7e04e/8f92327/c6a380eidentifier 级去重 +1899c8fyoutube 经 uv +3fde8c1 (#30042)排除依赖/venv +4373e80 (#45616)Pages 部署回退健康索引 — Computer-use:e02a7e5/531efe7SOM/vision 路由auxiliary.vision+5aa4727app= 过滤无匹配明示 +4cc1887保 capture_after 的 app context +18cd1e5type_text MCP 名修正 + drag 动作 — Approval allow_permanent81436e1/55a18e6端到端透传到 TUI + Desktop 提示 — Update / Installer:aedb8ac (#28669)post-pull 语法校验 + 自动回滚 +573b964/c814d3d安装前清 unmerged-index +9b01c4d (#45145)不弹 polkit +2a7308b (#26670)Windows hermes.exe 与并发实例隔离 +78c11d9更新前停 Windows gateway — Platform:f82cb48 + 1185dfd.xls/.doc/.ppt加SUPPORTED_DOCUMENT_TYPES+gateway/platforms/{signal.py,email.py}+plugins/platforms/simplex/adapter.pyDOCUMENT 兜底 +0fd34e8 (#44778)Teams 文档/视频/音频缓存 — TUI:2667601reasoning-only 助手轮在恢复时仍可见 +b6c7ebf (#44953)provider_routing透传 +b3f5e17/81cdbbd/d6df38b长 approval 命令换行 — Misc:05b9c84/652dd9cTelegram Bot API 10.1 富文本 +6724daa (#45592)CLI idle timer +0333a99 (#45582)session-only analytics 合并 +dba6380ca/d1f23bb2dsalvage Yuanbao wechat forwarde20e0bd (#43508) -
2026-06-11-update: 212 commits 跨日同步(hermes-agent
a5d05cf30 → 6c752ca3a,仍 v0.16.0 未发新版;约 131 fix / 25 feat / 9 chore / 6 test / 6 refactor / 3 style / 3 docs / 3 change / 1 revert / 1 perf / 15 merge / 5 misc;~48h 双日窗口)— Cron Recipes → Automation Blueprints 改名 + 14 蓝图 catalog(1593ca540上线 →e8b757845/e976faac7硬化 →cb29e8a82rebrand:cron/recipe_catalog.py → cron/blueprint_catalog.py 713 行,tools/recipes → tools/blueprints,/cron-recipe → /blueprint(alias/bp),hermes://cron-recipe/ → hermes://blueprint/,dashboard/api/cron/recipes → /api/cron/blueprints;BlueprintSlot/AutomationBlueprint/fill_blueprint/blueprint_form_schema/blueprint_slash_command/blueprint_deeplink/blueprint_catalog_entry;slot 4 typetime/enum/text/weekdays+WEEKDAY_PRESETS;14 个 blueprint;终结于同一cron.jobs.create_job,无第二套 job 引擎;Electronhermes://URL scheme + single-instance lock)+ Suggested Cron Jobs9a09ea69f(cron/suggestions.py 257 行+cron/suggestion_catalog.py 154 行4 个 catalog entry;4 来源catalog/recipe/usage/integration;dedup+latch 按 key、pending cap、accept 走同一create_job;tools/blueprints.py:217 register_blueprint_suggestion)+ memory/skillswrite_approval布尔门(96af61b6e (#38199)上线三态on|off|approve→095f526b1 (#43354)重构为 booleanwrite_approval默 false +_config_version 28→29migration →70d5d7e39 (#43452)修 inline prompt callback + gateway staging +/skillsgateway review;tools/write_approval.py 493 行write_approval_enabled/evaluate_gate;gateway/memory pending|approve|reject|mode+/skills pending|approve|reject|diff|mode;acd7932c0文档 cross-link)+ Dashboard 统一多 profile 管理875aa8f16 (#44007)1419+/310− 跨 21 文件(web_server.py +566 行profile参数 query/body 加到/api/config|env|mcp/servers|mcp/catalog|model/info|model/set全走_profile_scope();chat PTY?profile=让 childHERMES_HOME指向 profile dir;CLIdashboard走机器 dashboard--isolated保旧;前端ProfileProvider/ProfileSwitcher全局 selector URL-persisted;body.profile>?profile=;amberProfileScopeBanner)+73dd58499 (#44220)MCP loop HERMES_HOME 上下文 propagate(OAuth token-store 跨 profile 修) +d986bb0c6 (#39084)Profile Builder +a09343cc9 (#44231)SKILL.md editor + cron modal attach-skill +fa7f24e89Webhook enable from dashboard +9c051f57c (#44286)Anthropic API Key 检 +9c16ca879 (#44237)model 标准化 + backup confirm +c7bfc938d (#44374)Config 页 profile 路径 +63a421d4c (#42578)_require_token全部走 OAuth gate +7df3aa34b (#43214)public_url 静默拒绝 warn — Coding-Context Posture3e74f75e4 (#43316)(agent/coding_context.py 731 行ContextProfile/RuntimeMode;4 域:System prompt operating brief + per-model edit-format tuning + skill index demote + Toolset collapse;activationagent.coding_context: auto|focus|on|off;subagent 自动继承;不 memoize)+ Skill index demote 而非 hide(ee1a744ac (#44342)API 改名compact_skill_categories,每 skill 名字仍在 prompt 一行 names-only;4d6a133a9 (#44387)一天后反转:demotion 只在 focus 模式下) +a4f179c50 (#44411)GPT/Codex steer V4A 单文件编辑(OpenAI codex-rsapply_patch唯一 file editor) — Parallel Web Search & Extracte0e2571711206+/98− 跨 15 文件(keyless 免费 Search MCPsearch.parallel.ai/mcpStreamable-HTTP JSON-RPC;keyed v1 RESTclient.search/extract;parallel-web 0.4.2→0.6.0)+0a5762c78mcp-web-client中性 identity +93764b930/32a73010bkeyless web default 永远兜底 — Bedrocke24c935cf (#44293)IAM 拒绝InvokeModelWithResponseStream时自动 fallbackconverse()(agent/bedrock_adapter.py:211 is_streaming_access_denied_error) — Anthropic 交错 thinking 5 连:aaccaada2顺序保真anthropic_content_blocks端到端 verbatim +529bb1c3dstrip output-only SDK 字段 +7a1eed826redact replayed tool input + 加宽 400 classifier +86e10dd87thinking-modified 400 路由 recovery +9f95f72b9strip api_messages +efcbbde48in-memory only — SUMMARY_PREFIX 4 连:8f8cad7ec (#41607)抗陈旧任务 +d5e2fbf24historical context framing +acb2954d8历史 prefix 冻 +6c752ca3aHEAD 收紧 wording(topic-overlap 三句塌缩成 WINS+discard 两句) — OpenRouter183d86b3e (#43436)reasoning_effort 改 verbosity for adaptive Anthropic — Streaming615ad9792 (#43570)socket read timeout floor 到 stale-stream 180/240/300s — Params19c07c403newer OpenAI 系列max_completion_tokens名匹配 +2ce3ae3d1错分类不误判 unsupported-param — Model 选择:af978ecb1/243cada15昂贵模型确认 +57c671499 (#43103)Anthropic aliases 保留 +5a4297a11MiniMax M3 hardcode 1M — Desktop registry-driven slash + /resume/handoff3ffbdfbcc (#42351)1914+/478− 跨 31 文件 — Desktop composer 解耦 + 草稿 localStorage 6 连(c710868fb/292192f7d/d7d281fa3/18d61bd06/3d14f01fd/fdc0d1956/65ddc7c4aper-session 附件) — Desktop VS Code Marketplace 主题 + 可调终端 pane + Floating HUD(27a321157.vsixzlib 手写 zip reader + WCAG AA +8f73d0d94 (#42521)resizable terminal pane +Ctrl+\`` toggle +833410e02ANSI palette + Cmd-K HUD +ab5f1a1f1 (#43111)Mac 风^Tab/^⇧Tab/^1-9switcher +b96bd4808 (#43219)per-window chat +d33965396 (#43188)TUI titlebar session name) — **Desktop 远端 FS/api/fs/*5 连**(51f47f9a9 web_server.py:1439-1514+db79e9013facade +8878484f8remote-picker.tsx 177 行 +56a0f48ba/9121834b3tighten/scope) + **Desktop 远端 attach 5 连**(4906dcfc2stage OS dropsfile.attach/image.attach_bytes覆盖每 drop surface + 缩略图/spinner/race/16MB toast 4 连) — **Desktop misc 18 修**(1770263cc (#43234)default project dir +0d3e2cc53 (#43487)lineage dedup + 9 个 #4xxxx 修 + Nous overlay HUD/filled icons) — **Sessions 3 连**:e96ca1a0dempty 退出/轮转清理(hermes_state.py:3697 delete_session_if_empty+cli.py:5863 _discard_session_if_empty)+04b3f1953归档压缩 lineage +218452b05 (#43149)sqlite_master自愈(PRAGMA writable_schema=ONsurgery) — **Agent binary @file 引用 actionable**7ffc216bc+ **PDF/DOCX/音频附件 note 改写**(e7ae145acPDF/DOCX +13650ab7f音频 +4e9be3ee3test) — **Telegram 5 连**(3b4c715e1stripped-text fallback + tail-only delete guard + re-finalize skip +590b3c0d7partial overflow recover +da818510estream consumer cancelled finalize +d0e017bac (#44245)voice/audio >20MB pre-download gate +9ca969734 (#42090)transcribe tuple) — **Gateway 9 连**(13f1efdd1 (#43968)终端 header 折叠 +a8f404b29 (#40831)launchd domain probe +fa32af886/984e69ff6restart 去重 + post-Telegram QR auto-restart +5cf6e28a2 (#42675/#43236)容器重启 auto-start +f456f302d (#44267)临时 HERMES_HOME 拒写 service definition +264ac72b6/cb2c13055restart watcher env scrub +6a30cfca8 (#37556)post-delivery 前停 typing) — **Matrix4717989c1 (#18505)** room context 隔离 + handle_sync + allowed_users authz + i18n key + slash_commands mixin port — **Discord 7 连**:c3464ecf4 (#44383)runtime gateway task exit 恢复 +020ef76cf/08b1c44a5connect timeout cancel +311900842/aea0b7397voice-off 不断开 +e5580f43c/4eadef18aDISCORD_ALLOWED_ROLES端到端 — **Skills hub 7 连**:298bb93d3 (#43398)live per-source 进度 +105625d65overall_timeout 真 honor + ClawHubCATALOG_WALK_BUDGET_SECONDS+eee1da45f (#43395)cold start bound +9caa12f4efrontmatter name 解析 +0a593f132/d1383a6b1.envHERMES_HOME-aware +fdc90346e (#43221)red-team skills 移 optional(95%→25% block rate) — **Plugins/Web 3 连**:114e26573失败 sweep 不缓存 +93764b930/32a73010bkeyless 兜底 — **Cron 5 连**:7d8d000b1 (#43956)per-job profile revert +acd4f34e6/f7a6d6a6aprovider "custom" resolve +702f4df19 (#41976)容器重启 ownership +b4170f3ac (#43223)no-skills 不严检 — **CLI/TUI**:8972a151a (#44265)状态栏 idle clock +2f1951234 (#43439)全平台 UTF-8 stdout/stderrTextIOWrapper.reconfigure()+b2043cf15/5508f4bc5TUI/whatsapp-bridge UTF-8 +f8fd30942 (#43320)/d03cdd63e (#43036)one-shot cleanup +0b5b7ddfd/help quick commands +3c489fda8Slack 50-cap aliases — **Install/Update/Backup 7 连**:899acfe42winget 0x8A15002B 陈旧注册修 +9662b76d5PATH merge +a5c32cdf3 (#42172)中断 venv 自愈 +cedd9b6d4SSH 跳 passive +dd40600e0/ed2b9e43cbackup SQLite 同位 + 嵌套 skill 纳入 — **Tooling 20 连**:a72bb0375 (#38749)Docker 缩减 +5d8c44a39 (#30399)matrix 预装 +464276228Langfuse data URI redact +47e77ae16Curator atomic +dca11b665/e71d74682MCP stdio +3edd09a46 (#44205)WhatsApp stale bridge restart +4cecb1a13/90f4b3040/3bfbb3f2anpm audit / TS 6 / CI typecheck +72154ad87CI uv cache +f082b4ec5/07ac18590exit-4 runner +af3c8b80bpid-file race +6110aed9b (#43669)free model 抑 +15813336c/e4a1b35a3.env mode +1c055a4c5Grok Build code +6b330522e (#42641)AGENTS.md 设计哲学 — **TTS Gemini**:5718811depersona +2c1920822audio tag rewrite(tools/tts_tool.py +143 行`) -
2026-06-09-update: 105 commits 跨日同步(hermes-agent
754154a9c → a5d05cf30,仍 v0.16.0 未发新版;约 56 fix / 17 feat / 11 test / 5 chore / 3 refactor / 2 docs / 1 ci / 1 style / 8 merge)— Photon iMessage4e4d27875 feat: gRPC-native iMessage channel (no webhook)主轴收官(删 aiohttp webhook receiver + HMAC-SHA256 验签 +PHOTON_WEBHOOK_*5 个 env + CLIwebhook register/list/delete3 子命令;改GET /inboundNDJSON 长连接 + 25s heartbeat + consumer-state-machine;adapter docstring 重写 "Bidirectional bridge via spectrum-ts SDK gRPC stream";plugin.yaml:4 0.1.0 → 0.2.0;project_id 语义改写为 spectrumProjectId)+ 20 commit 跟进硬化(92dfd70d6 (#42732)生产硬化六件套:5 条 npmoverrides钉补丁版钳 protobufjs GHSA-66ff-xgx4-vchm + 4 个 @opentelemetry OTLP exporter CVE /crypto.timingSafeEqual替!==token compare / 2 MiB body size cap / re-subscribe capped exponential backoff + jitter /unhandledRejection处理 / dedup 按 insertion order 严格淘汰 4000 entries;b3aef57f2TYPE_CHECKING包 httpx 修类型 + connect 局部 client ref 防 race;9fb83eaa2spectrum-ts^1.18.0+npm install spectrum-ts@latest;314af28e8 + dbf2470d4入站附件/语音 base64 inline cap 20MiB → cache image/audio/document + voice MessageType + force_audio kwarg;4615e08d3 (#42397)出站 6 方法 override (send_image/_file/_voice/_video/_document/_animation) 经 spectrum-tsattachment()/voice()builder +/send-attachment端点 + cron multimedia +validate_media_delivery_path二次校验;fdf48c63c/e79e44af7/0d25cae04API 收敛走spectrumText/spectrumReply/spectrumTyping后又删 replyTo(实测 iMessage 不可靠)+ typing 统一space.send(spectrumTyping(state));2130ef68bflattenGroups: true;064665688/92179352f/3b983e779Home channel 支持裸 E.164 + DM GUID +_PHONE_PLATFORMS加 photon + setup 自动 allowlist +_env_enablementhome_channel seed;e9b26c7c8/84e4b4b9a/b58ff9345彩色 banner +assignedPhoneNumber取号 + auth.json 持久化 phone numbers;033765890user API 全迁 Spectrum backend Basic auth +DEFAULT_SPECTRUM_HOST="https://spectrum.photon.codes";37561c214device client_idhermes-agent → photon-cli修 400 invalid_client + token 双重 validate(PhotonDashboardAuthError+validate_photon_token先/api/auth/get-session再/api/projects/);637cf94bestrip_markdown+_send_with_retry(max_retries=2, base_delay=2.0)指数退避)— SimpleX 1.1.0 大演进0c2e81df0(PR #27978 salvage:群组SIMPLEX_GROUP_ALLOWED逗号分隔或*默认 disabled +chat_id=group:;入站文件 rcvFileDescrReady→rcvFileComplete 延迟流程 +_pending_file_transfers;原生出站媒体send_image/video/document/voice全按