Requesty (added in #474) is an OpenAI-compatible gateway whose capabilities
were a copy of OpenRouter's: same provider/model naming, same
extra_body.reasoning opt-in, no adapter code of its own. Built-in slots are
kept for providers with their own behaviour; a gateway that speaks an
existing wire format is configured through that provider, and #1532 (API
Route) is being closed on the same grounds.
Migration, identical request shape: LANGCHAIN_PROVIDER=openrouter,
OPENROUTER_BASE_URL=https://router.requesty.ai/v1, OPENROUTER_API_KEY=<the
Requesty key>. Past news and contributor credits in the READMEs are left
as history; the supported-provider lists drop it.
The temperature self-heal for Claude models that reject `temperature`
retries after popping the top-level `temperature` key. langchain-anthropic
1.4.x, on an anthropic SDK whose `Messages.create` no longer accepts
sampling parameters as named arguments, relocates `temperature` into
`extra_body` before the request is sent, so the retry still carried
`extra_body={"temperature": 0.0}` and failed with the same HTTP 400.
Drop `temperature` from `extra_body` as well when the model is a remembered
rejecter, keep any other `extra_body` keys, and omit `extra_body` entirely
once it is empty so an empty object is never sent.
Tests mirror the relocating payload shape with a fake ChatAnthropic base:
the retry is clean, unrelated `extra_body` keys survive, and models that
still accept `temperature` are untouched.
Signed-off-by: averatec0773 <575907690@qq.com>
Next-generation Claude models reject any request carrying `temperature`
with HTTP 400 "`temperature` is deprecated for this model." (issue
#1223). The native Anthropic Messages path already classifies the error,
retries once without the field and remembers the model, but the generic
OpenAI-compatible branch still sent `temperature` unconditionally, so
LANGCHAIN_PROVIDER=openai with OPENAI_BASE_URL pointed at Anthropic's
compatibility endpoint failed on every call.
Extend the same self-heal to ChatOpenAIWithReasoning: reuse
_is_anthropic_temperature_unsupported_error and the process-wide
_ANTHROPIC_TEMPERATURE_UNSUPPORTED set, retry sync/async generate and
both stream paths once without the field, and omit temperature up front
for remembered models in _get_request_payload. _astream's stream_usage
fallback moves to a named _astream_with_usage_fallback to mirror the
sync layering; behavior is unchanged.
Models that accept `temperature` are unaffected. Regression tests feed
the verbatim 400 body through mocked endpoints and fail on the
pre-fix code.
Signed-off-by: lorenzozanee <wyz0707@proton.me>
Problem
-------
Next-gen Claude models (e.g. claude-opus-5, claude-opus-4-8, claude-sonnet-5)
reject the "temperature" request field with HTTP 400 "temperature is deprecated
for this model." for ANY value, while older models (claude-opus-4-5,
claude-sonnet-4-5, ...) still accept it. _build_anthropic unconditionally
forwarded the global default temperature=0.0, so every run on a next-gen model
failed before producing output. Model names are not predictable (opus-4-5
accepts it, opus-4-8 does not) and the rejection is value-independent, so
neither a fixed model allowlist nor an "omit when 0.0" shortcut is a correct
fix.
Solution
--------
Add a temperature-safe ChatAnthropic subclass (_make_temperature_safe_anthropic)
that wraps all four generation entry points (_generate, _agenerate, _stream,
_astream). When the API reports temperature as unsupported it drops the field
and retries once, then records the model in a process-wide set so subsequent
requests omit it up front (no repeated failed request). Models that accept
temperature keep their configured deterministic value unchanged. The subclass
is built from the lazily-imported class and cached per base class, preserving
the optional langchain-anthropic dependency boundary and existing test doubles.
Correct for any temperature value, current and future model names, and the
streaming path the Web UI relies on.
Tests
-----
Add regression tests in agent/tests/test_llm.py: self-heal retry drops
temperature and remembers the model, temperature is preserved for supporting
models, and the error matcher only triggers on temperature-unsupported errors.
Full test_llm.py suite: 58 passed.
Self-fix on merge: moved langchain-anthropic from core dependencies to an
[anthropic] optional extra (like [deepseek]) — _build_anthropic lazy-imports it
and raises an actionable install hint, so the base install stays lean. Resolved
llm.py conflicts against #563's centralized get_llm_credentials + the anthropic
native adapter-mode branch. Closes#694.
kimi-k3 rejects any temperature other than 1 ("invalid temperature:
only 1 is allowed for this model"), same as kimi-k2, but the forcing
guard only matched the kimi-k2 prefix — so a default
LANGCHAIN_TEMPERATURE=0.0 config fails on every request with kimi-k3.
Replace the hardcoded prefix tuple with a K-family regex
(kimi-k<digits> + kimi-for-coding) so kimi-k3 and future K-series
reasoning models are covered without another whack-a-mole patch.
Verified against the Kimi for Coding endpoint: both kimi-k3 and its
k3 alias return the temperature error; moonshot-v1-* models are
unaffected. Note: bare aliases like "k3" are intentionally out of
scope for the name-based guard.
Co-Authored-By: Claude <noreply@anthropic.com>
Two related provider architecture improvements:
1. Keep explicit provider choice when it is a gateway (OpenRouter/Requesty)
(#549): The existing explicit-provider check already protects gateway
users from silent misrouting — provider="openrouter" returns
openrouter capabilities regardless of model name. Added regression
tests covering all gateway + model-name-prefix combinations.
2. Centralize credential resolution (#553): Extract the duplicated
provider→env_name→os.getenv→credential chain that was copy-pasted
across _sync_provider_env() and provider_diagnostics() into a
single get_llm_credentials() in capabilities.py. The new function
inherits the existing provider resolution logic, so every consumer
benefits from consistent behavior.
Additional fixes from code review:
- Remove unused base_env variable in provider_diagnostics() — use
caps.api_key_env directly, eliminating the redundant
provider_env_names() call.
- Add 3 base_url resolution tests covering the fallback chain
(provider-specific → OPENAI_BASE_URL → OPENAI_API_BASE).
- Run black to fix formatting violations on import lines.
Note: _sync_runtime_env() in settings_routes.py is a WRITE operation
(saves Web UI settings to env vars) and follows a fundamentally
different pattern from the READ path above — intentionally left out
of this refactor.
Backward compatibility: The default provider="openai" + model-name
inference (e.g. model="glm-4.6" → zhipu) is preserved. Users who
rely on this convenience behavior are unaffected.
Closes#549, closes#553
Signed-off-by: shadowinlife <shadowinlife@gmail.com>
_sync_provider_env() resolves the correct provider-specific base URL (e.g.
switching to OpenRouter) but wrote it to OPENAI_BASE_URL with setdefault, so a
stale value from a previous provider configuration silently won. The OpenAI
SDK reads OPENAI_BASE_URL directly, so requests kept hitting the old endpoint
with the new (still-valid) key attached — surfacing as a 401 "User not found"
from the wrong provider, not an actual key problem. Fixes#482.
Verified locally: full backend suite green (same pre-existing unrelated
failures as main), env-var CI gate passes, ruff clean, 13/13 provider-sync
tests pass including the new regression case.
Co-authored-by: Andrew Barnes <Bortlesboat@users.noreply.github.com>
GLM thinking models (glm-4.5+/glm-5.x) stream chain-of-thought as
reasoning_content; without capture the capability layer dropped it at the
ChatOpenAI boundary. Enable capture_reasoning (DeepSeek posture: no replay
on assistant turns until verified live against bigmodel).
Fixes#458. Refs discussion #337.
Add a first-class `glm` alias of the existing `zhipu` provider so a model
name like `glm-4.6`/`glm-5.1` resolves to the Zhipu capability record and
base URL instead of silently falling back to the OpenAI slot.
- capabilities.py: share one `_ZHIPU_CAPABILITIES` record between `zhipu`
and the new `glm` alias (mirrors kimi/moonshot), and infer `zhipu` for
model ids starting with `glm`.
- llm_providers.json: register a `glm` entry aliasing the Zhipu env names
and default model so onboarding/diagnostics surface it.
- tests: cover the alias, model-name inference, env-name resolution, the
unchanged openai fallback, and the new registry default.
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Add MiniMax-M3 as the new default model and retain MiniMax-M2.7 as
the legacy alternative (incl. -highspeed). Update llm_providers.json
registry, cli onboard provider choices, .env.example example, and the
provider-default regression tests.
Signed-off-by: Octopus <liyuan851277048@icloud.com>
Signed-off-by: octo-patch <liyuan851277048@icloud.com>
Append /v1 automatically when LANGCHAIN_PROVIDER=ollama so remote hosts
like http://host:11434 work with ChatOpenAI without manual path suffixes.
Co-authored-by: Cursor <cursoragent@cursor.com>
Bug fixes
- CompositeEngine no longer misroutes bare Chinese-futures codes like
RB2410 to GlobalFuturesEngine. _is_china_futures moved into a shared
_market_hooks module with a case-normalized product table and a
non-CN exchange guard. 9 new regression cases (RB2410 / rb2410 /
RB2410.SHFE / CL.NYMEX / M2412.CBOT / CF2412.ICE / AU2412.COMEX /
FG2412.EUREX / bare CN-collision still routes Chinese).
- Session FTS5 indexes now persist timestamps so cross-session search
can sort by date. Same path also fixes a re-upsert that was
wall-clocking every session's started_at on title-rename.
- Vite dev-mode proxy gained the missing /alpha entry; AlphaZoo page
resolves on npm run dev.
Cleanup
- Deleted swarm/api_models.py + swarm/mailbox.py + SwarmDashboard.tsx
(dead modules / orphaned UI after swarm-via-agent flow).
- Deleted SessionService.resume_attempt + get_attempts + get_attempt
+ SessionStore.list_attempts + Attempt.mark_waiting_user chain
(half-baked human-in-the-loop from initial commit).
- Deleted ChatLLM.achat (async sibling never called) and
_extract_balanced_json (only-tested helper).
- Deleted american_exercise_value in options_portfolio.py
(driver inlines bs_price logic).
- Deleted _compute_ic_series_reference in factor_analysis_core.py
(kept-as-reference, no callers).
- Collapsed MEMORY_TYPES duplication between cli.py and
memory.persistent; restored set-equality invariant assert.
- Deleted runSwarm (~197 LOC), swarmDash state, swarmCancelRef
write-only ref (orphaned by new agent-driven swarm flow).
- Dropped 76 unused 'vw = vwap(...)' boilerplate lines across
gtja191 alphas + their now-unused vwap imports.
- Cleared 11 F401 unused-import sites in tools/, agent/, providers/.
Test infrastructure
- test_e2e_harness_v2.py (real-LLM e2e) gated behind
VIBE_TRADING_RUN_LIVE_E2E so CI no longer flips shape based on
env-key presence. CI workflow now has explicit --ignore.
- test_auto_compact_with_long_history: monkeypatch TOKEN_THRESHOLD so
the test deterministically triggers compact instead of relying on
unrelated LLM behaviour.
- test_compact_tool_explicit: assertion corrected — compact tool is
special-cased in loop._process_tool_calls and does NOT emit
tool_call events. Assert on the 'compact' event instead.
- TestSwarmE2E: per-test @pytest.mark.timeout overrides matching the
internal 300s poll deadlines; cancel test now polls for terminal
state instead of fixed sleep(3).
Tooling
- ruff per-file-ignores for factors/zoo/** (3783 → 0 F401 noise);
F841 stays active in zoo to catch real formula bugs.
- frontend tsconfig: noUnusedLocals + noUnusedParameters as
regression guards.
- highlight.js hoisted to direct dependency (was transitive via
rehype-highlight).
- Vite proxy: dropped unused /run, /skills, /health, /api, /system;
added /alpha.
Annotations
- direction parameter renamed to _direction in 6 calc_commission
signatures (reserved for future borrow-fee asymmetry).
- _MARGIN_PER_CONTRACT in global_futures.py annotated as reference
data.
- Backtest engines' _calc_pct_change variants cross-reference each
other in docstrings.
Docs
- 2026-05-18 news entry added to README.md / README_zh.md /
README_ja.md / README_ko.md / README_ar.md; 2026-05-15 entry
rolled into the Earlier news <details>.
- Contributors heading: v0.1.7 cycle → v0.1.8 cycle in all 5
READMEs.
126 files changed, +363 / -1276.
build_llm() now returns ChatOpenAIWithReasoning (introduced in 73b179a)
instead of ChatOpenAI. The minimax temperature clamping tests were still
patching ChatOpenAI directly, so the fake was never hit and the real
subclass was instantiated — causing KeyError: 'temperature' on assert.
* fix: update MiniMax provider config and fix temperature handling
- Update .env.example: replace deprecated MiniMax-Text-01 with
MiniMax-M2.7 and document MiniMax-M2.7-highspeed as the faster
alternative; add note that temperature must be > 0
- Fix temperature clamping in build_llm(): MiniMax rejects
temperature=0.0 (requires range (0.0, 1.0]); auto-clamp to 1.0
when the default 0.0 is configured for the minimax provider
- Add unit tests: MiniMax env-var mapping, base URL propagation,
temperature clamping from 0.0, and preservation of explicit values
* fix: clamp MiniMax temperature to 0.01 instead of 1.0
0.01 stays closest to the user's intent (deterministic output) while
satisfying the MiniMax API constraint of temperature > 0.
---------
Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: warren618 <haozhe_wu@connect.hku.hk>