Skip to content

merge: v0.17.0 + our custom extensions (memory, token saving, sisterhood)#1

Merged
Jasper6439 merged 1 commit into
mainfrom
custom/v0.17-merge
Jun 20, 2026
Merged

merge: v0.17.0 + our custom extensions (memory, token saving, sisterhood)#1
Jasper6439 merged 1 commit into
mainfrom
custom/v0.17-merge

Conversation

@Jasper6439

Copy link
Copy Markdown
Owner

Summary

Merge upstream v0.17.0 with our v0.16 custom extensions.

Custom files added (50+)

  • Memory architecture (L1-L6): memory_router, memory_compressor, memory_indexer, unified_recall, topic_memory, cross_session
  • Token saving (16-layer): dynamic_tool_loader, dynamic_token_optimizer, task_complexity, prompt_optimizer
  • Sisterhood: sisterhood_enhancements, sisterhood_workflow, rewoo, reflexion, graph_engine
  • Proactive Triage: triage, command_validator, loop_controller
  • Translation: local_translator (EN→ZH via Ollama)
  • Tools: semble_search, skills_search_tool, ocr_tool, tool_profiles, tool_resolver
  • Scripts: market_scanner, zhihu_collector, unified_memory

Core file patches

  • gateway/run.py: translate_response hook + triage import
  • tools/memory_tool.py: memory_char_limit 8192
  • agent/conversation_loop.py: session_key passing for topic-personality

What upstream v0.17 already includes

  • MEMORY_GUIDANCE, PARALLEL_TOOL_CALL_GUIDANCE (in prompt_builder.py)
  • platform_hint, volatile_parts, memory_enabled (in system_prompt.py)
  • apply_batch, memory_notifications (in memory_tool.py, agent_init.py)

50+ custom files added:
- Memory architecture (L1-L6): memory_router, memory_compressor, memory_indexer, unified_recall, topic_memory, cross_session
- Token saving (16-layer): dynamic_tool_loader, dynamic_token_optimizer, task_complexity, prompt_optimizer
- Sisterhood: sisterhood_enhancements, sisterhood_workflow, rewoo, reflexion, graph_engine
- Proactive Triage: triage, command_validator, loop_controller
- Translation: local_translator (EN→ZH via Ollama)
- Tools: semble_search, skills_search_tool, ocr_tool, tool_profiles, tool_resolver
- Scripts: market_scanner, zhihu_collector, unified_memory

6 core files patched:
- gateway/run.py: translate_response hook + triage import
- tools/memory_tool.py: memory_char_limit 8192
- agent/conversation_loop.py: session_key passing for topic-personality
- agent/agent_init.py: (upstream already has our features)
- agent/system_prompt.py: (upstream already has our features)
- agent/prompt_builder.py: (upstream already has our features)
@Jasper6439
Jasper6439 merged commit 241a4e3 into main Jun 20, 2026
Jasper6439 pushed a commit that referenced this pull request Jun 27, 2026
…eation snapshot (NousResearch#44585)

An unpinned cron job follows the global default provider (config.yaml
model.default + resolve_runtime_provider). If that global state is changed
after the job is created — e.g. a temporary switch to a paid provider like
nous/claude-fable-5 — the job silently inherits it on its next tick and spends
real money. This is the reported $7.73 incident: a job created under a
free/default provider later inherited a temporary paid switch.

Fix (ask #1 only) preserves the legitimate "unpinned job should follow
model.default" use case by detecting *drift* rather than freezing the model:

- create_job (cron/jobs.py): for UNPINNED, agent-backed jobs (no explicit
  provider, not no_agent), snapshot the provider that resolution WOULD pick
  right now into a new optional `provider_snapshot` field, resolved via the
  same resolve_runtime_provider() path the ticker uses. Fail-open to None on
  any resolution error so job creation never breaks.

- run_job (cron/scheduler.py): right after runtime resolution, if the job has
  a provider_snapshot AND is unpinned AND the currently-resolved provider
  DIFFERS from the snapshot, fail closed for that run — make no paid call and
  deliver a loud, actionable alert naming both providers and telling the user
  to pin explicitly (`cronjob action=update job_id=.. provider=..`).

Back-compat: jobs with no snapshot (pre-existing jobs, no_agent jobs, or any
job whose creation-time resolution failed) behave exactly as before — the
guard only engages when a snapshot exists. Explicitly-pinned jobs (job.provider
set) are unaffected since they don't drift with global state.

Tests: tests/cron/test_cron_provider_pin.py covers snapshot-matches (runs),
snapshot-differs (fail closed, no agent constructed), no-snapshot back-compat,
None-snapshot back-compat, explicitly-pinned (runs regardless), plus create_job
snapshot capture/skip/fail-open. The fail-closed case is load-bearing (fails
without the guard).

Issue NousResearch#44585 asks NousResearch#2-4 (hard-stop a running job, gateway-stop containment,
fail-closed on provider mutation) are out of scope for this change.
Jasper6439 pushed a commit that referenced this pull request Jun 27, 2026
* fix(windows): harden gateway scheduled task

* fix(windows): launch gateway scheduled task via console-less wscript

The Scheduled Task ran the gateway through cmd.exe, which allocates a
console. During logon Windows broadcasts CTRL_CLOSE_EVENT to console
process groups, reaping cmd.exe and the half-initialized gateway with
STATUS_CONTROL_C_EXIT (0xC000013A) - which Task Scheduler treats as a
user cancel, so RestartOnFailure never fires and the gateway vanishes on
every reboot (issue NousResearch#45599 root cause #1).

Add a console-less .vbs launcher (wscript.exe -> pythonw.exe, both
GUI-subsystem) mirroring the gateway.cmd env + argv, and point the task
action at it. The .cmd stays for the Startup-folder fallback and /Run.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

---------

Co-authored-by: Jeff <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Jasper6439 pushed a commit that referenced this pull request Jul 5, 2026
…ture

get_copilot_api_token now returns (api_token, base_url); the auth-remove
suppression test still mocked it as a bare string, mis-unpacking into the
credential-pool seed path and failing with 'No credential #1'.
Jasper6439 pushed a commit that referenced this pull request Jul 5, 2026
…_id signature churn

Two independent bugs evicted the cached gateway AIAgent on every turn,
preventing the prompt cache from ever warming:

1. Model normalization mismatch: the post-run fallback-eviction check
   compared _agent.model (stripped in AIAgent.__init__) against the raw
   _resolve_gateway_model() config string. For vendor-prefixed config on
   native providers (e.g. 'deepseek/deepseek-v4-pro' vs 'deepseek-v4-pro')
   this was always unequal, so the agent was evicted after every
   successful run. Normalize _cfg_model the same way (skip aggregators).

2. Discord triggering message_id leaked into the cached system prompt via
   build_session_context_prompt()'s Discord IDs block. message_id changes
   every turn, so the agent-cache signature (computed from the ephemeral
   prompt) changed every Discord turn -> rebuild every message. The id is
   now injected per-turn into the user message (where per-turn content
   belongs and does not touch the cache signature); the cached IDs block
   carries a static pointer to it, preserving reply/react/pin via the
   discord tools.

Adapted from NousResearch#28846. Bug #1 fix is the contributor's; bug NousResearch#2 reworked to
be non-destructive (keeps the triggering-id capability instead of deleting
it). Redundant auto-reset eviction (already on main via NousResearch#9893/NousResearch#48031) and
the wrong-premise reset_context_note plumbing from the original PR were
dropped.

Co-authored-by: Hermes Agent <[email protected]>
Jasper6439 pushed a commit that referenced this pull request Jul 5, 2026
… fail on '(empty)' sentinel

Two related bugs caused subagent delegation to silently return empty summaries
with 0 tokens when the user configured delegation.provider=bedrock alongside
delegation.base_url=https://bedrock-runtime.<region>.amazonaws.com.

Root cause #1 — misrouting in _resolve_delegation_credentials():
  The configured_base_url branch unconditionally forced provider='custom' and
  api_mode='chat_completions', only specializing for chatgpt.com, anthropic,
  and kimi hosts. Bedrock (and other native-SDK providers) fell through as
  'custom' + chat_completions, which then POSTed OpenAI-shaped JSON at
  Bedrock's native API. Bedrock rejected the payload and returned nothing,
  which looked like an empty LLM response to the child agent.

  Fix: when provider is one of {bedrock, vertex, google, google-genai}, skip
  the base_url short-circuit and fall through to resolve_runtime_provider(),
  which knows how to construct the proper SDK client. base_url can still be
  forwarded through that path for regional overrides.

Root cause NousResearch#2 — '(empty)' sentinel accepted as success:
  After N retries of empty LLM responses, run_agent.py emits the literal
  string '(empty)' as final_response. _run_single_child then hit
  `elif summary:` — '(empty)' is truthy, so status became 'completed' and
  the parent surfaced a blank result with no error. Users saw api_calls=4,
  tokens=0, duration~0.4s, status=completed.

  Fix: treat final_response.strip() == '(empty)' as a failure so the parent
  surfaces it instead of silently accepting zero-content 'success'.

Both paths were reproduced in a live Hermes TUI session on us-west-2 Bedrock
(provider=bedrock, model=us.anthropic.claude-sonnet-4-6) and are covered by
new tests in tests/tools/test_delegate.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant