Commit Graph
32 Commits
Author SHA1 Message Date
Haozhe Wu 051aeb5509 refactor(providers): remove the Requesty built-in provider
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.
2026-09-21 20:35:37 +08:00
averatec0773 47c274719a fix(providers): strip relocated extra_body.temperature in the Anthropic self-heal
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>
2026-09-02 02:56:19 -05:00
lorenzozanee e339d91ff7 fix(providers): self-heal temperature rejection on the OpenAI-compatible path
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>
2026-08-29 04:51:39 +08:00
huanghua01 6ec7b510ed fix(providers): preserve shared HTTP clients
Signed-off-by: huanghua01 <huanghua01@zhuanzhuan.com>
2026-08-22 22:09:46 +08:00
cgycorey 8a66de1190 fix(llm): route configured reasoning effort through Responses API 2026-08-13 20:01:04 +01:00
Haozhe Wu 6543b88f21 fix(providers): normalize Ollama runtime URL at source
Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-08-12 02:35:21 +08:00
Haozhe Wu ed4d6df767 Merge pull request #1011 from yrk111222/feat/add-modelscope-provider
feat(providers): add ModelScope as an OpenAI-compatible provider
2026-08-09 18:30:08 +08:00
warren618 5ec7dec2be fix(providers): disable sync and async proxy routing 2026-08-08 22:32:00 +08:00
yrk eeaefe9e19 feat(providers): add ModelScope as an OpenAI-compatible provider
Signed-off-by: yrk <2493404415@qq.com>
2026-08-07 15:42:05 +08:00
yagnikpipaliya d2f12a3e72 fix(anthropic): self-heal models that deprecate the temperature field (#890)
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.
2026-07-28 13:38:11 +08:00
Haozhe Wu 2400bbcbaa Merge PR #695: feat(providers): add native Anthropic Messages API support
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.
2026-07-20 18:55:21 +08:00
Haozhe Wu add7b3f364 Merge PR #563: refactor(providers): centralize credentials + fix gateway misroute (closes #549, #553)
# Conflicts:
#	agent/src/providers/capabilities.py
#	agent/tests/test_llm.py
2026-07-20 18:32:08 +08:00
Haozhe Wu 3b9dba55eb Merge PR #565: feat: add SiliconFlow CN and Global providers 2026-07-20 18:31:33 +08:00
Jelech 39ea99a4d9 feat(providers): support ANTHROPIC_MAX_TOKENS configuration 2026-07-20 10:51:58 +08:00
sambazhuandClaude 03adce85a3 fix(providers): force temperature=1 for the whole Kimi K-series
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>
2026-07-17 16:05:02 +08:00
Jelech f21d8620fd feat(providers): support ANTHROPIC message 2026-07-17 13:31:44 +08:00
shadowinlife d35e6d8f9b refactor(providers): centralize credentials + fix gateway misroute (#549, #553)
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>
2026-07-16 15:30:48 +08:00
zhanghuiying 58bf8818a4 feat: add SiliconFlow CN and Global providers
Signed-off-by: zhanghuiying <20434979+UNHNQ@users.noreply.github.com>
2026-07-16 14:34:34 +08:00
Andrew BarnesandAndrew Barnes 7d912f7623 fix(providers): replace stale OpenAI base URL (#484)
_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>
2026-07-13 12:06:15 +08:00
Haozhe Wu ff04624d13 fix(providers): capture GLM reasoning content on the zhipu provider
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.
2026-07-10 12:48:23 +08:00
Haozhe Wu 848d1392cb fix: integrate startup and provider quick wins
Fix Docker/server startup when mounted router-like routes do not expose path.
Preserve the first CLI turn entered at the resume prompt, align loader fetch signatures, refresh Codex OAuth defaults, add Kimi for Coding and opencode-compatible provider mappings, and clean up Tushare reference fence typos.

Fixes #450.
Integrates #437, #448, #446, #435, #449, #444.
Reported-by: Penn-Live
Co-authored-by: shadowinlife <shadowinlife@gmail.com>
Co-authored-by: morluto <williamlin1327@gmail.com>
Co-authored-by: Carls <yxhuang@uibe.edu.cn>
Co-authored-by: Sankalp Singh <iamsankz@gmail.com>
Co-authored-by: flash1234pku <53250768+flash1234pku@users.noreply.github.com>
2026-07-09 13:35:45 +08:00
Matt Van HornandMatt Van Horn 43ffd041c0 feat(providers): add glm/zhipu provider alias and model-name inference (#247)
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>
2026-06-17 01:17:20 +08:00
Octopus bcc3ae6405 feat: upgrade MiniMax default model to M3 (#162)
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>
2026-06-02 00:52:45 +08:00
Faijan KhanandCursor c1f3898056 fix(providers): normalize remote Ollama base URLs without /v1 (#129)
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>
2026-05-19 12:55:59 +08:00
Haozhe Wu 8a6c578a76 chore: cleanup pass — 3 latent bug fixes + 913 LOC net delete
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.
2026-05-18 15:16:24 +08:00
ykj@hku 1cbbaab88e feat: add OpenAI Codex OAuth provider option (#65)
Adds the openai-codex OAuth provider, login command, Settings metadata, supported default model, and focused adapter regression tests.
2026-05-01 00:39:15 +08:00
warren618 e6ceb5a3b3 refactor(providers): collapse reasoning_content path helpers
Follow-up to f866e5f trimming fallbacks and single-use constants:

  * Collapse _REASONING_FIELDS + _preserve into ChatOpenAIWithReasoning._capture
    (walrus := + or-chained field normalization).
  * Inline extra_body branch in build_llm (kwargs-dict dance removed).
  * Rename _normalize_finish_reason → _dedupe_finish_reason, inline marker
    tuple, switch to endswith() for precision, drop `or "stop"` double default.
  * _parse_response: drop `or []` and `tc.get(..., default)` defenses —
    LangChain BaseMessage contract already guarantees these fields.

No behavior change. Net -44 lines, 64/64 tests green. Smoke re-verified on
Moonshot official and OpenRouter kimi-k2-thinking (effort=medium).
2026-04-19 14:58:06 +08:00
warren618 f866e5fb14 fix(providers): cover streaming path and OpenRouter relay for reasoning_content (#39)
PR #41 only hooked _create_chat_result (non-streaming); swarm workers
use llm.stream() which goes through _convert_chunk_to_generation_chunk
and dropped reasoning_content silently. @codewings' breakpoint never
firing confirmed the miss.

Adds _convert_chunk_to_generation_chunk override. Also handles two
neighbouring quirks found during verification:

  * OpenRouter renames the field to "reasoning" (ships reasoning_details
    alongside). Normalize both variants to the canonical
    additional_kwargs["reasoning_content"].
  * OpenRouter emits finish_reason on every stream chunk;
    AIMessageChunk.__add__ concatenates them into "stopstop" /
    "tool_callstool_calls". Dedupe in _parse_response so ReAct equality
    checks survive.
  * LANGCHAIN_REASONING_EFFORT env forwarded as extra_body.reasoning.effort
    for relays (e.g. OpenRouter) that require explicit thinking activation.

Removed 3-way getattr fallback in _parse_response; downstream reads
single canonical key.

Verified end-to-end (tests/_smoke_reasoning.py + _smoke_swarm_roundtrip.py):
  * Moonshot kimi-k2-thinking (official) — stream + non-stream + 2-round ReAct
  * DeepSeek deepseek-reasoner (official) — stream + non-stream + 2-round ReAct
  * OpenRouter moonshotai/kimi-k2-thinking with effort=medium
  * OpenRouter qwen/qwen3-coder-flash — non-thinking path unaffected

Tests: 66 passed (12 new: 2 field normalization, 7 finish_reason dedupe,
3 extra_body passthrough).
2026-04-19 14:49:51 +08:00
warren618 b6adee5651 fix(tests): patch ChatOpenAIWithReasoning in minimax temperature tests
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.
2026-04-19 12:22:38 +08:00
jiakeboge 0bd40354bc feat: support Z.ai coding platform (#35)
* feat: support Z.ai coding platform (#34)

* fix: address PR feedback (unit tests, docs cleanup, news revert)
2026-04-15 21:19:11 +08:00
e8e86e1a1d fix: update MiniMax provider config and clamp temperature=0 to 0.01 (#33)
* 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>
2026-04-15 21:17:15 +08:00
warren618 483de22b7d test: add 236 unit tests + CI pytest integration
- 13 test files covering: market detection, loader registry/fallback,
  engine market rules (ChinaA T+1/涨跌停, Crypto funding/liquidation,
  US/HK commission), signal alignment, metrics, optimizer, provider mapping
- CI: fix branch master→main, add pytest step (e2e excluded)
- pyproject.toml: add pytest config + dev dependencies
- .gitignore: expose unit tests, keep e2e local-only
2026-04-10 14:36:11 +08:00