Commit Graph

695 Commits

Author SHA1 Message Date
m4 2e5db60dc5 fix(merge): keep the Ai4Sci runtime working on upstream v0.3.0's dependency stack
The runtime (llm/runtime.py, stream/stop.py) is a separate development line
whose stop adapter drives LangGraph internals. Upstream v0.3.0 bumps its
dependencies for currency, and two exact-version assertions in that adapter
turned the bump into a silent regression: stop ownership was refused, so
cancellation/continuation runs never reached a terminal state.

Resolved without touching the adapter's logic:

- stream/stop.py: claim ownership by *capability* instead of an exact version
  string. The internals the adapter swaps (_graph_aiter / _pump_cond /
  _exhausted / _aborting / _anext_task / _mux) and the SQLite saver's
  connection lock are present and identical in langgraph 1.2.6 and 1.2.11, and
  langgraph-checkpoint-sqlite 3.1.1 exposes the same barrier as 3.0.3. A new
  patch release can no longer disable stop ownership by being newer; a release
  that really drops the internals still fails closed with
  CHECKPOINT_STOP_ADAPTER_UNSUPPORTED.
- EvoScientist.py: supply TodoListMiddleware only when deepagents' own default
  chain lacks it. deepagents 0.7 dropped it (upstream adds one back); 0.6.x
  still ships it, and a second instance collides by name in
  langchain's create_agent.
- backends.py: fall back to a shape-compatible DeleteResult when deepagents
  has no delete support, so upstream v0.3.0's delete refusals import and run on
  either line.
- tests/test_backends.py: gate the delete-behaviour tests on the framework
  actually providing backend deletion instead of asserting a specific stack.

Verified: 4216 passed / 33 skipped / 29 failed / 16 errors — every remaining
failure is pre-existing on the untouched pre-merge tree except two
(a google-stream cleanup-order assertion and one webui launcher test).
2026-09-13 17:48:44 +08:00
m4 4c338ed914 fix(merge): resolve integration gaps found by running the v0.3.0 test suite
Post-merge validation fixes (upstream v0.3.0 + Ai4Sci fork):

- llm/patches.py: restore the two module-level patch calls the merge dropped
  (_patch_openai_empty_sse_keepalive, _patch_deepagents_extracted_document_text)
  and make _is_ccproxy_codex accept an explicit base_url/api_key so the
  invocation plan can classify an endpoint without mutating the process env.
- llm/models.py: an explicit per-call plan now wins over
  EVOSCIENTIST_USE_RESPONSES_API (env is only a default), an explicit caller
  `reasoning` block survives an explicit use_responses_api=False, and the
  third-party (openrouter) default effort stays the fork's fixed `medium`.
- EvoScientist.py: sub-agent stacks pass NO_OP_SINK as `events` instead of None.
- middleware/error_normalization.py: platform-generated diagnostics
  (ModelOutputTruncatedError) keep their actionable text while provider SDK
  errors still get the canned redacted message.
- pyproject.toml: hold google-genai 1.x (langchain-google-genai>=4.3.7,<4.4)
  because llm/gemini_interactions.py drives the 1.x Interactions API; this is
  also what deepagents 0.7.13 requires.
- config/settings.py: restore upstream's use_responses_api config field.
  `reasoning_effort` stays deleted on purpose — Ai4Sci keeps reasoning an
  invocation-plan parameter, never a deployment-env override.
- tests: align upstream tests that encode replaced behaviour (ccproxy
  responses-api context, reasoning-effort-overrides-env, fingerprint coverage)
  with the fork's contracts.
2026-09-13 16:57:03 +08:00
m4 470cf75722 merge: bring upstream v0.3.0 (72 commits) into Ai4Sci fork
Merged upstream/main (418abca, release v0.3.0) into our fork on a
dedicated branch. 21 conflicting files resolved; main worktree untouched.

Resolution policy and key decisions:
- Keep Ai4Sci runtime endpoints, durable dispatch, workspace scopes and
  the HITL/DynamicReview approval chain (approval path is product-critical).
- Adopt upstream model registry (llm/registry.py): our 136 model entries
  are a strict subset of upstream's 180, so dropping our inline table
  loses nothing and gains 44 new models.
- Adopt upstream native EvoChatDeepSeek; drop our obsolete
  _patch_deepseek_reasoning_passback monkey patch.
- Keep our six patches.py additions, ported onto upstream's new
  _OpenAICompatContent class: stable tool-call ids, tool-history
  sanitization, drop_reasoning_metadata, empty-SSE keepalive,
  extracted-document-text patch, _has_assistant_tool_protocol.
- Keep our skill-budget middleware path (skills=None) instead of passing
  skills through, to avoid double loading.
- Keep sanitized error labels (_safe_error_label) while adopting
  upstream's injected MiddlewareEventSink for fallback narration.
- Keep port 3076 and the LANGGRAPH_SERVER_URL override; adopt upstream's
  host/probe-host handling and CONFIG_DRIFT_SINCE_LAUNCH.
- Adopt upstream dependency stack: deepagents 0.7.6, langchain-quickjs
  0.3.7, langgraph-api 0.14; keep our extra deps (rfc8785, pillow,
  firecrawl-anydoc, nest-asyncio).
- Align call sites with upstream APIs: create_tool_selector_middleware
  now takes events= instead of track_stream_selection=.
2026-09-13 16:07:27 +08:00
m4 d4b53bfb08 test: cover stop contract, execution adapters, checkpointer race and runtime identity
Docker / build (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Build / build (push) Has been cancelled
2026-09-13 15:12:17 +08:00
m4 ea99ce9f7e feat(runtime): host execution registry, web checkpointer, stop control and sandbox cancellation 2026-09-13 15:12:17 +08:00
m4 57bae2e6ae feat(llm): scoped model runtime, history rebuild and gateway proxy streaming 2026-09-13 15:12:17 +08:00
Xi Zhang 418abca4f4 release: v0.3.0 (#462) 2026-09-11 21:45:42 +01:00
jfilipiuk 0410b40f57 feat: inherit the caller's model for async sub-agent launch and update (#446)
* feat: inherit the caller's model for async sub-agent launch and update

* docs: tighten middleware related docstrings
2026-09-11 17:58:50 +01:00
mikemikimike a486b85851 fix: normalize string blocks in Anthropic history (#449)
* fix: normalize string blocks in Anthropic history

* fix: preserve content blocks for Anthropic-routed providers

* test: cover Anthropic replay content blocks

* fix: address MiniMax Anthropic review feedback
2026-09-10 23:20:42 +00:00
jfilipiuk be8c23861d feat: dispatch newly installed experts in the background without /new (#420)
* refactor: rename AGENTS.md to EXPERT.md per EvoSkills convention

* feat: resolve newly installed experts on start_async_task miss

* chore: reword the /expert invite hint to state the dispatch boundary

* docs: note the resolve-on-miss caller in build_expert_async_subagent_specs

* fix: thread the construction cfg through resolve-on-miss and symmetric setdefault

* fix: guard agent_map iteration against concurrent resolve-on-miss writes

* fix: warn once per broken expert on repeated resolve-on-miss walks

* fix: scope the /expert invite hint to newly installed experts

* docs: note live uninstalls as a resolve-on-miss limitation

* chore: isolate the warn-once collision test key from the route-specs suite
2026-09-10 22:47:35 +00:00
Faych 9bd7a37a77 fix: _extract_retry_after returns None for non-retryable errors (#394)
* fix: _extract_retry_after returns None for non-retryable errors

* fix: update _extract_retry_after to handle generic transient errors with default retry delay

* fix: extend base _non_retryable_patterns in channel subclasses

* fix(channels): merge structured SDK error check into non-retryable step

* fix(channels): decouple status code and SDK error code extraction in retry logic

- Independently evaluate HTTP status codes and structured SDK error codes
- Fix misleading doc comments for Feishu and DingTalk patterns
- Remove redundant try-except AttributeError on getattr with default
- Expand test coverage for dual-signal matrix and header parsing

* refactor(channels): simplify status code and SDK error extraction via channel overrides

- Handle httpx and aiohttp exceptions in base Channel class
- Override _extract_status_code and _extract_sdk_error_code in SlackChannel and DiscordChannel
- Replace mock exception types in comprehensive test suite with real httpx and aiohttp errors
- Add dedicated Slack and Discord retry error extraction test suites

* fix(channels): clean up Slack and Discord error code extraction

- Remove defensive string checks and attribute guards in SlackChannel
- Directly access exc.response.status_code and exc.response.get('error') in SlackChannel
- Remove unnecessary _extract_sdk_error_code override in DiscordChannel
- Use real SlackApiError, SlackResponse, and discord.HTTPException in unit tests

* refactor: reorder retry logic to prioritize non-retryable checks, remove aiohttp dependency, and clean up exception handling in base and channel modules.

* test(channels): skip Slack/Discord retry tests when the SDK extra is absent

The retry-extraction tests build real SlackApiError / discord.HTTPException
objects, but slack-sdk and discord.py are optional extras that the dev
dependency group does not install. Under CI's `uv sync --dev` all nine
tests failed with ModuleNotFoundError raised from the channel override.

Gate both test classes with skipif(find_spec(...) is None) so the suite is
green without the extras and the tests still run wherever they are installed.

* refactor(channels): replace retry-delay lookup with _extract_retry_delay

_extract_retry_after still read the server-supplied delay by probing
exc.retry_after and exc.response.headers via getattr/hasattr, the last
remnant of the pattern the extractors moved away from. Replace both steps
with one overridable hook, _extract_retry_delay, implemented against the
real exception types:

- base: httpx.HTTPStatusError -> Retry-After header (httpx.Headers is
  case-insensitive; HTTP-date form remains unsupported)
- SlackChannel: SlackApiError -> Retry-After, matched case-insensitively
  because SlackResponse.headers is a plain dict whose casing depends on the
  HTTP client (same approach as slack_sdk's RateLimitErrorRetryHandler)
- TelegramChannel: telegram.error.RetryAfter.retry_after (int, or timedelta
  under PTB_TIMEDELTA)
- DiscordChannel: discord.RateLimited.retry_after, which the old duck-typed
  getattr matched and would otherwise have been lost

Drop the isinstance(retry, bool) and val >= 0 guards; no SDK produces those.
Delete the test that asserted the duck-typed attribute; add real-object tests
for each override, guarded like the existing SDK-dependent classes.

* ci: install the all-channels extra so SDK-dependent channel tests run

The Slack, Discord, and Telegram retry tests build real SDK exception
objects and are skipped when the SDK is absent. CI only ran `uv sync --dev`,
so those tests never executed there. Install the existing all-channels
extra alongside the dev group; the skipif guards remain for lean local runs.

* fix(channels): honor HTTP-date Retry-After and tolerate malformed values

RFC 9110 allows Retry-After as either delay-seconds or an HTTP-date. The
httpx path treated a date as unparseable and fell back to the 1.0 s default,
so a 503 asking for a specific wait was retried too early. Add
Channel._parse_retry_after, which returns delay-seconds as-is and converts
an HTTP-date to the non-negative seconds until it (tz-less dates read as
UTC).

SlackChannel used a bare float() on the header. A non-numeric value raised
inside the retry predicate, which escapes retry_async and drops the chunk
instead of retrying. Route Slack through the same helper so a bad header
falls back to _rate_limit_delay.

Addresses CodeRabbit review comments on base.py:866 and slack/channel.py:229.

* fix(channels): treat HTTP 400 and 404 as non-retryable

Both are permanent for a given request, so retrying burns the attempt
budget for nothing. Add them to _non_retryable_status_codes alongside
401/403.

Deliberately not a 4xx range check: 408 and 425 are retryable by
definition and 429 is handled by the rate-limit path. A test pins 408 as
still retryable so the range shortcut is not reintroduced later.

Partially addresses CodeRabbit's outside-diff comment on base.py:749-750.

* fix(channels): guard Slack retry extractors against raw aiohttp responses

slack_sdk attaches the bare aiohttp.ClientResponse to SlackApiError when a
JSON-declared body fails to parse. That object has neither status_code nor
get(), so _extract_status_code raised AttributeError inside should_retry,
replacing the original error and skipping the remaining attempts. Narrow
both extractors to SlackResponse/AsyncSlackResponse so such errors fall
through to the message patterns and retry as before. Add a wire-level
regression test against a local aiohttp server.

---------

Co-authored-by: Dinos Papakostas <dinospk1999@gmail.com>
Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>
2026-09-10 22:25:12 +00:00
Xi Zhang b36c19a22a fix(llm): honor openrouter_app_title only alongside a custom referer (#453)
OpenRouter keys app pages by HTTP-Referer; X-Title only renames that
page. A custom openrouter_app_title on the default referer therefore
renamed the shared EvoScientist app page for everyone. Force the default
title whenever the resolved referer is the default, silently, so usage
keeps being attributed to EvoScientist; a private fork still overrides
both together.
2026-09-07 17:22:18 +08:00
Xi Zhang dae67e9299 release: v0.2.10 (#452) 2026-09-05 08:30:02 +01:00
X-iZhang dedd53bad6 feat(models): add gpt-6-astra (openai + openrouter) 2026-09-05 07:26:10 +01:00
Xi Zhang a45563ea7f feat(scheduler): optional rubric acceptance checklist for scheduled tasks (#451)
Scheduled tasks gain an optional `rubric`: an acceptance checklist graded
after each run by deepagents' RubricMiddleware (LLM-as-a-judge on the
auxiliary model) with one revision retry. No `rubric` key = no-op.

- cron/schedule.py: create_schedule/run_now carry the rubric in the run
  input and cron metadata only when non-blank
- middleware/scheduler.py: schedule_task gains `rubric`; list marks graded rows
- commands/implementation/schedule.py: `/schedule add ... --rubric`,
  `/schedule run` forwards the stored rubric, list gets a Rubric column
- subagents/_factory.py: RubricMiddleware mounted last on the scheduler
  graph so a needs_revision jump skips the memory lifecycle until the
  accepted run; grader is read-only (ls + read_file, eviction off),
  bounded by a 12-call budget, and gets an explicit structured-output
  strategy on OpenRouter (Gemini JSON mode, Anthropic tool calling);
  warns at build for anthropic/claude-fable-5.1 via OpenRouter, which
  grades under neither strategy today
- tests: 17 new cases; fix two pre-existing fixture leaks (callable
  backend stub in test_hitl, import-under-patch in test_async_subagent_factory)
2026-09-05 07:04:26 +01:00
Xi Zhang 7dbb68d807 feat(memory): first-contact profile bootstrap with USER_PROFILE frontmatter (#450) 2026-09-05 06:46:39 +01:00
m4 382ed305cc fix: preserve tool interrupt and cancellation control flow 2026-09-04 06:55:41 +08:00
m4 324011ab3f fix: restrict tool callback tolerance to read-only effects 2026-09-03 22:40:36 +08:00
m4 812e05d29d fix: contain tool-effect callback transport failures 2026-09-03 22:21:59 +08:00
m4 561e161123 fix: fail-closed internal identity and preserve billing error semantics
Build / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
- Gateway internal identity: when a service token is configured, reject
  wrong/missing tokens even from loopback (closes SSRF/local bypass).
- Terminal metering: classified AgentControlError propagates without
  retry; exhausted retries raise BILLING_UNAVAILABLE instead of a
  generic RuntimeError, keeping error attribution accurate.
2026-09-03 18:45:31 +08:00
X-iZhang ee14afe3a3 feat(models): add gemini-3.8-flash (google-genai + openrouter) and meta/muse-spark-1.3 (openrouter) 2026-09-03 04:49:10 +01:00
m4 5d893c1dc6 [verified] fix: close 0.3.0 release security gaps
Docker / build (push) Has been cancelled
Build / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
2026-09-03 10:42:46 +08:00
m4 c683f6e739 feat: prepare EvoScientist 0.3.0
Docker / build (push) Has been cancelled
Build / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
Add bounded document ingestion, controlled web search, recoverable session support, subagent timeouts, and the native sandbox runtime contract. Unify package versioning and add release-focused regression coverage.
2026-09-03 06:55:56 +08:00
X-iZhang 8d68dfa652 feat(models): add claude-fable-5-1 (anthropic + openrouter) 2026-09-02 02:44:48 +01:00
Xi Zhang a95f5d4c45 release: v0.2.9 (#447)
* feat(llm): add GLM-5.3-Flash, Qwen3.8-Flash, and Tencent HY4 preview

GLM-5.3-Flash on Zhipu, Zhipu Coding Plan and OpenRouter; Qwen3.8-Flash on
DashScope, DashScope Coding Plan and OpenRouter; HY4 preview on OpenRouter.
All three get explicit 1M-class context-window entries so they are not
caught by the glm-5 family fallback (203K) or the 200K default.

* chore: update wechat_group image asset

* chore: update version to v0.2.9

uv.lock moves to deepagents 0.7.11 with its raised dependency floors
(langchain 1.3.18, langchain-core 1.6.1, langchain-anthropic 1.7.0,
langchain-google-genai 4.3.7, langsmith 0.11.2); langgraph stays 1.2.11.

* docs: use umbrella provider names in v0.2.9 changelog
2026-08-29 04:51:35 +01:00
jfilipiuk 99075345ab fix: bound cache-eviction race test by deadline to fit Windows CI timeout (#436)
* fix: bound cache-eviction race test by deadline to fit Windows CI timeout

* test: start cache-eviction race workers from a shared barrier and assert progress

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-08-25 11:10:53 +00:00
Xi Zhang 8383f343ae release: v0.2.8 (#435)
* chore: update version to v0.2.8
2026-08-21 09:52:43 +01:00
jfilipiuk 3d6cc959e3 fix: cut deployed-graph rebuild from 15s to <1s by deferring observation-index reads (#427)
* fix: defer eager observation-index build to first model call

* fix: add mtime-keyed cache to list_observation_documents to avoid re-parsing unchanged files

* fix: return a copy of the cached document list and strengthen the deletion test

* fix: copy cached document list on read and write to prevent caller mutations

* fix: split global and project cache to avoid duplicate parsing and cross-project invalidation

* fix: bump mtime explicitly in cache modification test for Windows NTFS resolution

* fix: bound project observation cache with LRU eviction

* fix: deduplicate path logic and strengthen cache typing

* fix: group cache tests under TestObservationCache with autouse fixture and fix f-string interpolation

* fix: reject non-positive observation cache cap in config validation

* fix: cache resolved observation docs and config cap to avoid repeated work

* fix: use st_mtime_ns and st_size in cache signature for NTFS reliability

* test: clear EVOSCIENTIST_MAX_CACHED_PROJECTS in test env cleanup fixtures

* test: cover per-file observation cache semantics

* fix: replace layered observation caches with per-file parse cache

* fix: serialize observation parse cache transactions
2026-08-21 06:49:32 +00:00
m4 ce0bec1f91 fix: gateway proxy reads delta.message and detects truncated SSE
Standardize the stream delta on LangChain's own message dict (delta.message)
instead of a bespoke {text, tool_calls} shape, and raise when the stream ends
without the [DONE] sentinel so mid-stream truncation is no longer silent.
2026-08-20 15:32:27 +08:00
m4 3683cbfc13 fix: propagate streamed-model attempt id via shared configurable
The legacy BaseChatModel.astream path does not forward run_manager to
_astream, so the per-call tracing run_id was unreachable and the stream
fell back to the conversation run_id, which the gateway's
verify_model_attempt rejected (401 RUN_ATTEMPT_NOT_ACCEPTED). Publish the
tracing run_id into the shared configurable dict from
on_chat_model_start and read it back in _attempt_id.
2026-08-20 15:32:18 +08:00
Mani Saint-Victor c7be701abf docs: add subscription OAuth recipe (Claude + ChatGPT/Codex) (#326)
* docs: add subscription OAuth recipe (Claude + ChatGPT/Codex)

Standalone guide for running EvoScientist on Claude Pro/Max and ChatGPT
Plus/Pro subscriptions via ccproxy OAuth, previously only partially
covered inside the macOS deployment recipe.

Documents the two Codex-route pitfalls from #323 with their exact error
strings — ccproxy's default model mappings silently rewriting gpt-* to
gpt-5.3-codex, and the backend's client-identity gate ('requires a newer
version of Codex') — plus the manual ccproxy TOML fix for self-managed
instances, account-tier model availability, verification probes, and a
troubleshooting table. Adds the recipe to the docs index.

* docs: correct subscription OAuth guidance

* docs: remove stale Codex client version guidance

* docs: show the config section to add instead of a clobbering heredoc

* docs: correct reasoning_effort default behavior on the Codex route

* docs: drop private helper import from the Codex probe

* docs: warn that local ccproxy config files shadow the global one

---------

Co-authored-by: Dinos Papakostas <dinospk1999@gmail.com>
2026-08-20 08:14:11 +01:00
m4 386c8130ea feat: add streaming _astream to gateway proxy chat model 2026-08-20 09:11:10 +08:00
m4 8d7d95a20d feat: classify provider prompt-cache strategy (explicit/implicit/none) 2026-08-20 08:27:23 +08:00
m4 836ff5c939 test: make openrouter reasoning env-ignored test non-vacuous 2026-08-20 08:18:32 +08:00
m4 8764f2012f fix: default reasoning effort to medium instead of high 2026-08-20 08:13:57 +08:00
m4 7605136189 fix: pass cfg explicitly to web_full middleware
Docker / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
Build / build (push) Has been cancelled
2026-08-19 22:55:05 +08:00
m4 b68fdf6d57 feat: disable agent observation writes in web deploy
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-19 21:59:38 +08:00
m4 4445379f0a feat: resolve memory middleware dir per-call from configurable 2026-08-19 21:50:47 +08:00
m4 5041807a8e feat: resolve observation tool memory_dir per-call from configurable 2026-08-19 21:43:23 +08:00
m4 8376f56ab4 feat: native sandbox execution, dynamic review middleware, and workspace files
Adds native sandbox execution runtime, dynamic review middleware, and
workspace file handling, with supporting stream events, prompt, and scope
registry changes plus architecture docs.
2026-08-19 20:00:09 +08:00
jax-novita bcee009917 Add Novita AI as an LLM provider (#422)
* Add Novita as an LLM provider

Registers Novita (novita.ai) as an OpenAI-routed provider, following the
same pattern as Requesty/Atlas Cloud/SiliconFlow: a base_url + API key env
var entry in _OPENAI_ROUTED_PROVIDERS, a handful of model registry entries
(DeepSeek/Qwen/GLM), onboarding wizard support (constants/steps/wizard/
helpers), a key validator using the auth-preflight sentinel pattern (Novita's
/v1/models endpoint returns the public catalog even for an invalid key, so
auth must be checked via a chat completion instead), and a host-to-provider
mapping entry for error attribution.

* Recommend Novita's current flagship models

The models listed for Novita were older ids that no longer reflect what
the platform leads with. Point the recommendations at the three current
flagships instead, each verified against api.novita.ai:

  moonshotai/kimi-k3              1M context, native vision
  zai-org/glm-5.2                 1M context, long-horizon agentic work
  deepseek/deepseek-v4-flash-0731 1M context, cheapest of the three

Context windows, output limits, input modalities and pricing were taken
from the live /openai/v1/models response rather than carried over.

* Keep branch CI workflow files unchanged (no workflow OAuth scope)

Co-authored-by: multica-agent <github@multica.ai>

* ci: restore workflow files to match main

---------

Co-authored-by: jax-novita <jax-novita@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Dinos Papakostas <dinospk1999@gmail.com>
Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-08-18 08:16:45 +00:00
LinxXu 47c8da3e5b fix(llm): bound routed reasoning and surface empty truncation (#425)
* fix(llm): bound routed reasoning and surface empty truncation

Default DashScope Qwen 3.8 Max requests to low reasoning effort and forward explicit reasoning controls to custom OpenAI-compatible endpoints.

Detect length-limited responses that exhaust their budget during reasoning without producing content or tool calls, and surface a provider-aware error instead of ending the turn silently.

Add regression coverage for routed reasoning configuration, truncated empty responses, and valid content/tool-call responses.

* fix(middleware): reject empty structured text blocks

* fix(llm): address reasoning truncation review feedback

* fix(llm): validate DashScope reasoning effort

* fix(llm): document DashScope reasoning support
2026-08-18 08:28:19 +01:00
Xi Zhang 1b324906fd feat(onboard): add NVIDIA BioNeMo Agent Toolkit to recommended skill packs (#431)
Add a "BioNeMo Skills" entry to the onboard Step 7 checkbox so users can
opt into the 31 life-science skills (protein folding, docking, generative
chemistry, genomics, protein design) with one selection.

The pack installs through the existing GitHub shorthand path — no installer
change. Source points at the toolkit's plugin skills directory
(plugins/bionemo-agent-toolkit/skills), which is the flat aggregate of all
31 skills; installing from the repo root would only reach 14 because the
remaining skills sit three levels deep.

Closes #333
2026-08-17 11:09:36 +01:00
jfilipiuk b500ccc311 fix: prevent session-emptying crash on resume commands (#428)
* fix: prevent session-emptying crash on resume commands

* docs: fix stale docstrings in goto=None crash tests and patch

- Correct checkpoint corruption claim: the error state replaces the
  previous conversation state (messages: [], files: {}), it IS corrupted.
- Replace WebUI-specific language with UI-agnostic wording.
- Remove references to uncommitted local notes files.
- Add upstream issue reference (langchain-ai/langgraph#5656).

* fix: wrap _control_branch instead of reimplementing, use dataclasses.replace, add END routing and session preservation tests

* fix: rebind map_cmd on already-loaded consumers, rewrite crash-path tests to exercise __start__ via checkpoint deletion
2026-08-17 07:10:37 +00:00
Xi Zhang 1d02a909d3 release: v0.2.7 (#430)
* chore: update version to v0.2.7

* feat(llm): add gemini-3.7-flash, deepseek-v4-pro-0813, grok-4.6, glm-5.3

* chore: refresh WeChat group QR code
2026-08-14 19:30:26 +01:00
Xi Zhang 71d5649414 fix(cli): adapt /compact offload to deepagents 0.7.6 session-id API (#429) 2026-08-14 18:41:13 +01:00
houren Antony da15b70535 fix(channels): reject unsigned webhook POSTs on encryption-configured channels (#401)
Closes #392 (uncontroversial part).

WeChat (`_handle_message`) and Feishu (`_handle_event`) gated their
signature/decryption checks behind a condition the REQUEST controls:

- WeChat: `if encrypt and self._crypto:` -- a POST with no `<Encrypt>`
  element took the false branch and reached `_safe_process_message`
  without any verification, even when `encoding_aes_key` + `token` were
  configured.
- Feishu: `if self.config.encrypt_key and "encrypt" in body:` -- a
  plaintext body skipped decryption entirely and was processed directly.

Since the webhook port is the channel's only inbound boundary, an
attacker could POST forged plaintext and reach the agent, spoofing
`sender_id` / `FromUserName` (and, with an empty allowlist, passing the
sender gate).

Fix: when encryption is configured, an inbound POST MUST carry the
encrypted field (`<Encrypt>` / `encrypt`) -- otherwise it is rejected
with 403 and never reaches the agent. Plaintext mode (no encryption
configured) is unchanged, so existing plaintext deployments are not
affected. The remaining fail-closed question (what to do when
credentials are entirely unset) is left for the maintainers to decide
as the policy part of the issue.

Regression tests (9 new):
- WeChat: plaintext rejected / missing Encrypt rejected / bad signature
  rejected / valid signature decrypts and processes / plaintext still
  accepted when no crypto.
- Feishu: plaintext rejected / non-dict body rejected / encrypted body
  decrypts and processes / plaintext still accepted when no encrypt_key.

93 tests in the two channel files pass; full suite 3045 passed, 13
skipped; ruff clean.

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-08-14 17:25:57 +01:00
m4 5a581c78a2 feat: add scoped model runtime configuration
Build / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
Introduce provider, model, and invocation contracts with encrypted configuration persistence. Add web runtime fencing, route fallback, recovery middleware, workspace scoping, and comprehensive tests.
2026-08-14 22:03:04 +08:00
houren Antony 932c934485 fix(mcp): give stdio subprocess a real stderr fd under redirected streams (#423)
* fix(mcp): give stdio subprocess a real stderr fd under redirected streams (#418)

On Windows the Textual TUI redirects sys.stderr to an in-memory capture
(textual.app._PrintCapture) whose fileno() returns -1. The MCP SDK forwards
that stderr to stdio server subprocesses via subprocess.Popen(stderr=...),
and Popen rejects the invalid handle with OSError: [Errno 9] Bad file
descriptor — so only stdio servers fail to load (HTTP/SSE are unaffected).

Wrap mcp.client.stdio.stdio_client so that, whenever the configured errlog
has no usable fileno, it falls back to sys.__stderr__ (or os.devnull in GUI
hosts). Idempotent, no-op when the SDK is absent, warns if the SDK renames
stdio_client. Adds 9 regression tests and a troubleshooting note.

* fix(mcp): validate live fd and close fallback errlog after stdio session

Address CodeRabbit review on #423:
- _stdio_errlog_is_usable now os.fstat()s the fd to reject closed streams
  that still report their former positive fileno (prevents a deferred
  [Errno 9] from subprocess.Popen).
- The stdio_client wrapper owns the devnull fallback it allocates and
  closes it once the session exits, so repeated MCP reloads no longer leak
  file descriptors. Caller-provided usable errlogs pass through untouched.
- Tests cover the closed-fd case, the fd-leak/closure invariant, and
  confirm langchain-mcp-adapters binds the patched stdio_client.

* fix(mcp): rebind adapter stdio_client, forward errlog by kw, harden tests

Address CodeRabbit round-2 review on #423:
- The patch now also rebinds langchain_mcp_adapters.sessions.stdio_client,
  which the adapter captures via a 'from' import at module load — so the
  wrapped function reaches the adapter regardless of import order.
- errlog is forwarded to the SDK by keyword (original(server, *args,
  errlog=errlog, **kwargs)) so a future SDK inserting a positional
  parameter before errlog can't mis-bind the fallback.
- The fallback stream is now allocated inside the async context manager,
  so it is closed on session exit even if the CM is constructed but never
  entered (narrower fd-leak path).
- test_closed_fd_rejected now reaches the os.fstat branch (stale positive
  fd stub) instead of the ValueError path; test_adapter_binds_patched_stdio_client
  documents and asserts the import-order-independent rebind.

* fix(mcp): close fallback errlog when stdio_client construction fails

Address CodeRabbit round-3 review on #423: move the original(server, *args,
errlog=errlog, **kwargs) construction inside the try block so a failure
during subprocess/client setup still reaches the finally and closes the
wrapper-owned os.devnull stream. Added test_fallback_closed_when_construction_fails
covering the path.

* refactor(mcp): track fallback ownership via (stream, opened_by_us)

Address din0s review on #423:
- _safe_stdio_errlog() now returns (stream, opened_by_us); the wrapper closes
  the fallback only when opened_by_us is True, instead of inferring ownership
  from needs_fallback + an identity check against sys.__stderr__. Simpler and
  less likely to regress.
- Removed dead try/finally in test_closed_fd_rejected.
- Added test_wrapped_stdio_client_swaps_explicit_bad_errlog covering the
  'not _stdio_errlog_is_usable(errlog)' branch (explicit bad errlog, not the
  default sentinel).
- Updated test_safe_errlog_returns_usable_stream for the tuple return.

---------

Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
2026-08-13 17:39:45 +00:00
ADITYA 1f3e8f57a3 fix: resolve subagent tools at execution decision (#381)
* fix: defer subagent tool resolution

Signed-off-by: Aditya Datta <crazyme07071996@gmail.com>

* fix: preserve inherited subagent tools

* test: cover injected subagent tools

* style: format subagent regression

---------

Signed-off-by: Aditya Datta <crazyme07071996@gmail.com>
2026-08-11 14:13:04 +01:00