886 Commits

Author SHA1 Message Date
lilei
31d97fc85b
fix(memory): select FTS5 matches by composite score (#8005)
* fix(memory): select FTS5 matches by composite score

Score every SQL-filtered match before selecting the final composite top-k.
Keep candidate retention bounded with a streaming heap and preserve the
existing scoring formula and adapter-level filtering behavior.

Add regressions for confidence and time-decay reversals, category filters,
result prefixes, ties, and the public DeerMem storage path.

Fixes #8003

* fix(memory): report matched and retained FTS5 rows

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-09 21:16:18 +08:00
qkycir
f9767c65d5
fix(sandbox): run scoped env commands concurrently (#7841)
* fix(sandbox): run scoped env commands concurrently

* test(sandbox): gate concurrent command admission deterministically

* fix(sandbox): keep releasing scopes visible to client close

* docs(sandbox): clarify scoped env ownership and capacity

* fix(sandbox): retain cancellation ownership while scopes drain

* fix(sandbox): bound Bash admission to provisioned session capacity
2026-11-09 20:18:30 +08:00
Evan
3e59e22b4c
fix(subagents): keep tests_passed evidence per call when a provider reuses its id (#8012)
* fix(subagents): keep tests_passed evidence per call when a provider reuses its id

Tool-call ids are unique per response, not per conversation. Some providers
number calls per response, so two turns can both issue call_0.

The bash evidence for tests_passed acceptance assumed one call per id in two
places:

- _harvest_bash_executions built one id -> command map over the whole
  conversation, so every result under a reused id was labelled with the
  last call's command. A passing subset run (pytest tests/unit) became
  evidence for the full suite when a later call_0 ran pytest tests and had
  no result yet.
- update_bash_executions merged values chunks by tool_call_id. A dict keeps
  a key's first position, so a later run under a reused id overwrote the
  earlier entry in place. With call_0 failing, call_1 passing and call_0
  failing again, the merged list ended on the stale pass and the leaf held.

Pair results through pair_tool_call_results, which answers a call only from
its own response, and merge chunks by result message id, keeping the call id
for entries without one. Each run stays a separate entry in execution order,
so the latest run decides the leaf again.

* fix(subagents): key the summary cache per run and document id-less calls

- Cache full-output test summaries by result message id (call id only
  without one), so reused call ids keep one cache slot per run.
- Update the bash_executions field doc and the subagents guide to the
  result-id merge, and state that calls without an id record no
  evidence (the leaf stays UNVERIFIED).
- Tests pin both: one classification per run under a reused id, and no
  evidence for a call with a missing or empty id.

* chore(subagents): drop the stray empty deerflow/executor.py

The previous commit added a 0-byte module at the package root by mistake.
Nothing imports deerflow.executor; the real module is deerflow/subagents/executor.py.
2026-11-09 19:59:47 +08:00
王一帆
463361c5ba
feat(weknora): allow opt-in shared retrieval for authenticated users (#7944)
* feat(weknora): allow opt-in shared authenticated retrieval

* docs(weknora): clarify shared retrieval identity requirements

* docs(weknora): clarify durable batch authentication limits

* docs(gateway): keep agent guidance within hard size limit

---------

Co-authored-by: Totoro <msy626836554@gmail.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-09 17:06:05 +08:00
Hyacinth-of-Security
c738c5ef8b
fix(skills): give a bracketed literal in the userinfo slot no host on every Python (#8017)
* fix(skills): give a bracketed literal in the userinfo slot no host on every Python

`_http_host` answered from `urlsplit(url).hostname`, which decides the
ambiguous authority `http://[::1]@Example.COM/api` differently across
interpreters: 3.12 reads the bracketed part as userinfo and returns the host
`example.com`, 3.13 rejects the authority and `urlsplit` raises, so the helper
returns None. The same URL got two different answers depending on the runtime.

The answer is not cosmetic: `_is_outbound_url` compares it against
`_LOCAL_HTTP_HOSTS`, so whether a URL counts as local or outbound moved with the
interpreter. The test table added with the surrounding refactor (#7950) already
states the intended answer, None, which is why `tests/test_skillscan_native.py`
fails on 3.12 and passes on 3.13.

The bracketed-literal case is now rejected before `hostname` is read, so the
answer no longer depends on that URL-parsing change, and the shape keeps the
treatment the other malformed authorities get: no host, therefore outbound.

The test table also gains a bracketed literal with an IPv6 host and a port
(`http://[2001:DB8::1]@example.com:8443/api`), so a fix that only special-cased
the exact URL from the failure cannot pass.

On 3.12: `tests/test_skillscan_native.py` goes from 1 failed / 387 passed to 388
passed, and the skillscan suite (834 tests) passes. Reverting only the
orchestrator change puts both bracketed cases back to failing.

* fix(skills): reject raw brackets in URL userinfo

---------

Co-authored-by: lxcxjxhx <lxcxjxhx@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-09 16:49:37 +08:00
Hyeonsang Cho
7bb92cea10
fix(threads): keep the owner row when deleting checkpoints fails (#7992)
* fix(threads): keep the owner row when deleting checkpoints fails

DELETE /api/threads/{id} treated the checkpoint delete as best-effort: a
failure was logged at DEBUG, the threads_meta row was removed anyway and
the request returned success. Read routes allow a thread without a meta
row as an untracked legacy thread, so the surviving checkpoints (title,
messages, goal) became readable by every signed-in user through
GET /threads/{id}, /state, /history and /goal, and the owner could not
retry because DELETE requires the row.

A failed checkpoint delete now logs the exception and returns a generic
500 before the meta row is touched, so the thread stays owned and the
owner can retry. The remaining cleanup steps stay best-effort; their
reads are owner-scoped.

* docs(changelog): reference #7992 for the thread delete checkpoint fix

* fix(threads): require checkpoint deletion before dropping ownership

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-09 11:53:56 +08:00
Wenchao An
97746ad725
fix(frontend): open file chooser from attachment button (#8018) 2026-11-09 09:57:11 +08:00
Zeren Wang
0d04322d41
feat(hitl): add human-in-the-loop approval for high-risk tool calls (#7979)
* feat(hitl): add human-in-the-loop approval for high-risk tool calls

* fix(hitl): address approval review findings

* docs(hitl): keep agent guidance under size limit

* fix(hitl): guard approval pause recovery

* docs(hitl): shrink inherited guidance

* fix(hitl): harden approval admission and recovery
2026-11-09 09:52:35 +08:00
lilei
24884e8120
fix(task-continuity): count distinct archived search sources (#7956)
* fix(task-continuity): count distinct archived search sources

* docs(task-continuity): explain archive search ranking trade-off

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-09 09:07:20 +08:00
Eilen Shin
aaca3eeaeb
refactor(agent): ground runtime decisions in structured evidence (#7986)
* refactor(agent): ground runtime decisions in structured evidence

Use producer status and structured errors for tool recovery, preserve memory context without lexical confirmation, and remove predetermined receipt and skill conclusions.

Require explicit MCP discovery and authenticated schedule trial actions. Preserve authorization, ownership, isolation, and bounded execution; update documentation and regression coverage.

* test(sandbox): expect read_file initialization error callback

* fix(agent): address evidence review follow-ups

* fix(agent): preserve retry budgets for OpenAI transport errors

* fix(agent): expose tool execution status in model requests

Project validated execution metadata and exact tool text into request-only JSON so status survives provider serialization. Preserve stored results and receipt hashes, cover SDK and graph boundaries, and migrate replay input hashes without changing recorded responses.

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 22:00:23 +08:00
Evan
d8e085630a
fix(agents): keep todo reminders in Goal turns after an earlier provider stop (#8004)
* fix(agents): keep todo reminders in Goal turns after an earlier provider stop

TodoMiddleware skipped completion reminders whenever runtime.context held
safety_capped or model_length_capped. The worker keeps that key across the
run's hidden Goal continuation turns so the run record reports the first
cap, and an unmet Goal continues after these provider stops (it stands down
only on loop and token caps). After one capped response, every continuation
turn therefore lost its todo reminders and could stop with unfinished items.

Loop and token stops stay run-level and are still read from the context.
Provider safety and length stops now apply to the response they ended,
identified by the safety_termination / model_length_termination marker that
those guards stamp on it. The check still runs before the parent hook, so a
capped response cannot be resumed by the parallel-write retry.

* refactor(agents): import provider-stop markers from the guards that stamp them

TodoMiddleware matched the safety and length markers by string literals that
duplicated the guards' own. Each guard now exports its marker and stop reason
as module constants, used at its stamp and check sites and imported by
TodoMiddleware, so a rename in a guard cannot silently disable suppression.

Comment that completion_reminder_hard_stop_reasons is the inventory surface
and only its run-level entries are read from runtime.context, and run the
worker-level Goal continuation test for the safety guard too, which
overwrites stop_reason instead of keeping the first one.

---------

Co-authored-by: Totoro <msy626836554@gmail.com>
2026-11-08 19:19:56 +08:00
Hyeonsang Cho
8924c5844a
fix(scheduler): pause a task whose schedule no longer computes (#7993)
* fix(scheduler): pause a task whose schedule no longer computes

Admission validates every schedule, but a stored one can stop computing
later: a zone the installed tz database no longer has, or a cron
expression a newer croniter rejects. The scheduler recomputes next_run_at
inside the shared poll, and that raise escaped:

- dispatch_task recomputed it in its except block after a successful
  launch, so run_once aborted the claimed batch and left the occurrence
  in "launching" with no last_error;
- once the launch lease expired, recover_expired_launch_claims found the
  durable run and raised again for every poll, before claim_due_tasks,
  so no other scheduled task was admitted for the rest of the process.

Runtime cursor writes (launch, launch repair, queue timeout, launch
failure, finalization) now use stored_next_run_at, which returns the
reason instead of raising. A live recurring task is paused with
"schedule can no longer be computed: ..." as its last_error and no next
run; a once task keeps its normal outcome. Resume re-validates the
schedule, so it reports the problem until the schedule is fixed.

run_once also isolates the lease-recovery pass, like the terminal-run
reconciliation next to it, so a failed pass no longer skips admission.

* docs(changelog): reference #7993 for the unschedulable task fix
2026-11-08 13:39:34 +08:00
Harvey DU
3aefc56f5f
fix(gateway): keep batch cancellation running when the scheduler store fails (#7971)
* fix(gateway): keep batch cancellation running when the scheduler store fails

_run_completion_hook awaited scheduled_task_service.handle_run_completion
before batch_continuations.source_finished, so a scheduler store outage
aborted the hook and skipped batch cancellation entirely: a claimed
follow-up of a hard-stopped run stayed in the dispatching state instead
of being cancelled.

The scheduler notification is now best-effort (logged as non-fatal);
batch cancellation always runs.

Fixes #7969.

* fix(gateway): isolate batch cancellation failures and trace completion warnings

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 12:52:05 +08:00
alexcastgonz
b315cf2c9e
fix(telegram): wait for retry_after before retrying a new message (#7990)
* fix(telegram): honor retry_after when retrying a new message

A 429 on sendMessage or sendRichMessage slept 2**attempt and dropped
the reply before Telegram's flood wait expired. Wait the longer of
that backoff and the server hint, and leave other channels unchanged.

Fixes #7989

* fix(telegram): bound new reply flood waits

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 09:51:43 +08:00
Eilen Shin
2a8927c5e1
feat(models): add StepFun provider preset (#7988)
* feat(models): add StepFun provider preset

* fix(models): standardize the StepFun preset label

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 09:49:43 +08:00
LuckVd
1dae5eb363
fix(sandbox): exempt expression division after closers from the host-bash guard (#7448)
* fix(sandbox): exempt expression division after closers from the host-bash guard

A single-segment absolute-path match directly after ')', ']' or '}' is
division in an inline expression (python3 -c, perl, node -e, $((...)) ),
not a host path; #7023 exempted this shape only inside single-quoted awk
programs. Per-closer rules keep unknown-value path builds rejected:
digits only after ')' and '}' ($1/1024 rationale), an identifier after
')' only when the paren closes a name(...) call, any segment after ']'.
Literal tokens ('ls /2') are unchanged.

Fixes #7444

* fix(sandbox): scope division exemptions to parsed expressions

* docs(sandbox): fit inherited guidance within the hard limit

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 09:49:07 +08:00
Hyeonsang Cho
4e90f5d771
fix(docker): keep local config out of the image build context (#7958)
* fix(docker): keep local config out of the image build context

backend/Dockerfile copies the backend tree wholesale (COPY backend ./backend),
and frontend/Dockerfile does the same for frontend/. .dockerignore excluded
.env files and runtime data, but not the local configuration: config.yaml,
the config.yaml.bak that make config-upgrade writes beside it,
extensions_config.json and legacy mcp_config.json. The config resolvers still
read these from the legacy backend/ location, so on a checkout that keeps them
there every locally built gateway image (dev and prod) carried the model API
keys and MCP credentials in its layers, under the file Compose mounts over at
runtime. frontend/.env.local, the documented place for BETTER_AUTH_SECRET in
local development, was copied into the frontend image the same way, where
next build and next start also read it.

Exclude those files at the root and in backend/, and .env*.local at any depth.
None has tracked content; the build's file list is otherwise unchanged.

* docs(changelog): reference #7958 for the Docker build-context fix

* fix(docker): keep local HTTPS keys and snapshot credentials out of images

frontend/.gitignore also ignores *.pem, the mkcert key pair for local HTTPS,
and COPY frontend ./frontend shipped it into the dev and prod frontend images.
Exclude frontend/*.pem.

The trailing !backend/extensions/sources/** re-inclusion wins over every
earlier rule, so a hand-edited extension snapshot could still carry .env files
or keys into the gateway image. Exclude, after the re-inclusion, exactly the
files the extension manager already refuses to snapshot; a test pins that set
to the manager's own _SENSITIVE_FILENAMES and _SENSITIVE_SUFFIXES.

The test's matcher now translates patterns as Docker does (** across segments,
* within one, character classes, parent-directory matches), so it can model
the mid-path ** rules; its predictions agree with BuildKit on every test path.

The README and changelog now say that a locally built frontend image no longer
inlines NEXT_PUBLIC_* values from frontend/.env.local.

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-08 07:56:27 +08:00
Colin Lin
c953ab65f5
fix(subagents): drain abandoned capacity waiters before cancellation (#7900)
* fix(subagents): drain abandoned capacity waiters before cancellation

Continue the unmerged queued-waiter cleanup approach from #7571, with deterministic cancellation and timeout controls.

Co-authored-by: 熊小雨 <1178327328@qq.com>

* test(subagents): gate capacity timeout cleanup deterministically

---------

Co-authored-by: linkangjun <331227811+linkangjun@users.noreply.github.com>
Co-authored-by: 熊小雨 <1178327328@qq.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-07 23:34:41 +08:00
golemon
372baf762f
fix(agent): prevent todo reminders from resuming runs after hard stops (#7955)
* fix(agent): stop todo reminders after run hard limits

Respect loop_capped and token_capped before scheduling completion reminders, and include the behavior in the assembly policy fingerprint.

Cover sync and async agent graphs, blocked post-stop tools, preserved Todo state, and continuation from the same thread checkpoint. Validation: 316 targeted tests passed.

* docs(agent): explain todo behavior after hard stops

Document that loop and token hard stops suppress Todo completion reminders while retaining unfinished tasks for later runs.

* docs(changelog): record todo hard-stop fix

Add English and Chinese Unreleased entries referencing issue #7953.

* fix(agent): mark safety stops with partial responses

* fix(agent): honor provider stops before todo retries

* docs(agent): clarify todo behavior after provider stops

* test(agent): isolate todo safety-chain runtime dependencies

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Co-authored-by: Totoro <msy626836554@gmail.com>
2026-11-07 21:43:16 +08:00
Totoro
3f9a78e02e
fix(goal,artifacts): verify completion and artifact handoff (#7961)
* fix(goal,artifacts): verify completion and artifact handoff

* fix(goal,artifacts): harden shared artifact handoff

* docs(agents): shrink inherited guidance to fit chain budget

---------

Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>
2026-11-07 18:21:49 +08:00
MasterZRC
d0007090c2
fix(sandbox): retain ports when restricted cleanup is unconfirmed (#7917)
* fix(sandbox): reconcile ports after restricted creation failures

* fix(sandbox): guard creation ports through concurrent teardown

* fix(sandbox): narrow restricted startup port cleanup

---------

Co-authored-by: Totoro <msy626836554@gmail.com>
2026-11-07 16:07:15 +08:00
Zhiqiang Yan
aadc816f0b
fix(knowledge): retain later evidence that fits the output budget (#7942) 2026-11-07 16:01:47 +08:00
Hyeonsang Cho
d658b13c79
fix(channels): keep Feishu cards within the card size limit (#7798)
* fix(channels): keep Feishu cards within the card size limit

Card text was unbounded and ASCII-escaped, so an answer of about 4,400 CJK
characters made the card request body exceed Feishu's 30 KB limit (230025).
The final patch and its reply fallback were both rejected, the answer was
lost and the running card stayed on its last streamed text.

Cards are now serialized without ASCII escapes and budgeted by the bytes
their text adds to the request body. A streamed update shows what fits; a
longer final answer continues in up to 10 cards replied to the same source
message, split at line breaks, and a retry resumes after the cards already
delivered.

* docs(changelog): reference #7798 for the Feishu card size fix

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-07 15:52:59 +08:00
VicFei
a3d21e5e4d
feat(skills): expose MiniMax resolution/duration in video-generation (#7912)
* feat(skills): expose MiniMax resolution/duration in video-generation

Hailuo 2.3 accepts explicit resolution (768P/1080P) and duration (6/10s)
in the /v1/video_generation body, but the skill sent neither — and its
SKILL.md told the caller --aspect-ratio is ignored for MiniMax without
offering any alternative, leaving cost/quality/length uncontrollable.
Read MINIMAX_VIDEO_RESOLUTION and MINIMAX_VIDEO_DURATION from the
environment and pass them through when set (unset keeps the API defaults
byte-for-byte); values are passed through unvalidated beyond the integer
check so newer tiers (H3 per-second 4-15s) need no script change. Document
both knobs in SKILL.md with a draft/final example. Fixes #7911.

* fix(skills): address MiniMax video override review

---------

Co-authored-by: vicfei <4058491+vicfei@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-07 15:52:35 +08:00
Zhiqiang Yan
b8e1ca98a0
fix(jsonify): keep HTTPX TLS setup off the event loop (#7932)
* fix(jsonify): keep HTTPX TLS setup off the event loop

* fix(jsonify): retain cleanup diagnostics during repeated cancellation
2026-11-07 14:10:18 +08:00
Tanishq
2a16b26960
fix(compaction): build the manual-compaction summarization models off the event loop (#7806)
compact_thread_context built the summarization middleware inline on the
Gateway event loop, and with it the run-profile model and any separately
configured summary model. When the provider reads local credential files
(the Codex provider reads the Codex CLI auth.json while it is constructed),
each POST /api/threads/{thread_id}/compact did synchronous file IO on the
shared loop, once for every model it built, so other requests and streams
waited for it. The route passes no app_config, so the call also read the
live config on the loop first, which stats and hashes config.yaml on every
call. #7767 listed this site in the utils guidance as not covered.

Build the middleware through run_assembly, as #7484 and #7767 do for the
one-shot helpers, skill moderation and the goal evaluator, and read the live
config in that pool too when no app_config is passed. The lead agent already
builds the same middleware there through run_agent's agent factory call.
Model resolution, the memory-flush policy, the disabled, failed and
pending-work outcomes and the written checkpoint are unchanged, and
cancellation during construction neither starts the summary call nor writes
a checkpoint.

tests/blocking_io/test_compaction_model_offloop.py builds real
CodexChatModels under the strict Blockbuster gate. On main, compaction
reported itself disabled because every model build hit BlockingError
(os.stat), and the /compact handler answered 500 because the gate rejected
its config read first.

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-06 21:46:14 +08:00
lilei
d8b0d24a84
fix(summarization): preserve native document text during compaction (#7825)
* fix(summarization): preserve native document text during compaction

* fix(summarization): retain metadata for opaque documents

* docs: keep agent guidance within size limits

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-06 21:42:13 +08:00
liyinlong
8d7e48e5e7
fix(memory): restore facts from older backups (#7921)
* fix(memory): restore facts from older backups

Use the current snapshot revision for existing facts during backup import so saved contents can be restored after later edits. Preserve manifest and fact preconditions, scope isolation, and caller-owned input data.

* refactor(memory): share import revision preconditions

* docs(memory): fit import guidance within chain budget

* fix(memory): validate backup revisions before restoration

---------

Co-authored-by: liyinlong <173714821+lilong555@users.noreply.github.com>
2026-11-06 21:39:18 +08:00
lilei
7e64330dd1
fix(memory): avoid recursive tool-argument admission (#7928)
* fix(memory): avoid recursive tool-argument admission

* fix(memory): track argument redaction changes without deep equality
2026-11-06 21:24:57 +08:00
yi-coding
eab978f04d
fix(skills): publish complete data-analysis cache generations (#7861)
* fix(skills): publish complete data-analysis cache generations

* fix(skills): clean cache builds when manifest preparation fails

* fix(skills): clean cache generations after failed replacement

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-06 21:12:41 +08:00
哈基米
ee006e0c86
fix(community): initialize InfoQuest TLS clients off the event loop (#7899)
* fix(community): initialize InfoQuest TLS clients off the event loop

InfoQuest's fetch, web search and image search constructed
httpx.AsyncClient inline in their coroutines, so the default transport
loaded the TLS trust store synchronously on the agent event loop
(~125 ms per call in a local probe). RAGFlow, LightRAG, You.com,
GroundRoute and Webz already construct their clients with
asyncio.to_thread; InfoQuest was the missed sibling.

Move the three constructions to asyncio.to_thread and cover all three
methods in the blocking-I/O TLS test. Requests, cleanup, timeouts and
responses stay on the event loop.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* docs: qualify the off-loop HTTPX provider list

The list is not exhaustive; several community clients still construct
their client inline. Use non-exhaustive wording until the follow-up
sweep lands.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* docs: correct the off-loop provider list after merging main

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-06 10:26:42 +08:00
Totoro
593ba49458
feat(subagents): continue requested batch work and schedule explicit prerequisites (#7839)
* feat(subagents): continue native batches and honor item dependencies

* docs: link native batch follow-up changelog entries

* test(migrations): pin isolated history-seed upgrade to 0050

* fix(subagents): preserve follow-up scope, blockers and fair scheduling

* test(memory): freeze capacity evaluation time

* fix(subagents): guard follow-up admission and retain run controls

* fix(subagents): enforce runs:cancel on tool cancellation of follow-up batches

* style(tests): format test_batch_followup_host with ruff

* fix(subagents): drop the admission checkpoint check and keep SDK cancel compatible

The checkpoint check inside run admission waited on the checkpoint saver's
lock while holding the SQLite write lock, which could make another chat's
checkpoint write fail. Remove it; dispatch still checks the conversation
before admission.

A follow-up waiting for an unanswered question now keeps its claim until the
lease expires instead of rereading the conversation every poll. Cancel passes
the caller's run authority only to submitters that take it, so existing SDK
submitters keep the two-argument call. Document that retrying a prerequisite
by hand does not requeue its blocked items, and list 0052 as the migration head.

---------

Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 15:10:21 +08:00
Wenchao An
c1f9064e9b
fix(models): route managed OpenAI GPT-6 presets through Responses (#7870)
* fix(models): route managed OpenAI GPT-6 presets through Responses

* test(memory): pin capacity scenarios to a stable clock

* fix(models): honor Flash mode for managed OpenAI GPT-6

* fix(models): reconcile preset effort with explicit reasoning contracts

* test(memory): share the fixed clock with updater capacity tests

* fix(models): normalize GPT-6 reasoning overrides and sampling

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 14:30:42 +08:00
asts
59beff5799
fix(mcp): load personal transport TLS trust off the event loop (#7909) 2026-11-05 14:27:52 +08:00
huyengiang101086-spec
8331afa759
fix(agents): pair null call IDs with empty result IDs (#7837)
* fix(agents): pair null call IDs with empty result IDs

* fix(agents): treat producer sentinel IDs as absent when pairing

Middleware producers spell a missing provider ID three ways: "" is canonical,
str(tool_call.get("id", "")) yields "None" once the key is present with a
null value, and the artifact/deferred/knowledge middlewares fall back to
"missing_tool_call_id". Only "" reached the pairing pass, so a result carrying
either sentinel was dropped as an orphan and the middleware's guidance was
replaced by the interrupted placeholder — the exact outcome this PR set out to
avoid, just through a different spelling.

Route every absent spelling through one canonicalisation used by the pairing
gate, the candidate comparison and the turn-completeness count.

---------

Co-authored-by: huyengiang101086-spec <270684046+huyengiang101086-spec@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 14:07:15 +08:00
哈基米
713a861e75
fix(channels): ignore non-finite WeChat server longpoll timeouts (#7898)
* fix(channels): ignore non-finite WeChat server longpoll timeouts

The getupdates response's longpolling_timeout_ms was passed through
float() with only TypeError/ValueError handled. A huge JSON integer
raised OverflowError before the message loop and cursor write, so the
same batch was re-polled forever, while Infinity/NaN were stored and
turned the next request timeout into inf/nan.

Apply the same positive-finite rule the channel already uses for
configured timing values: catch OverflowError and reject non-finite
results, keeping the previous valid timeout.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix(channels): bound WeChat server long-poll hints

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 12:07:31 +08:00
一片一片
459fc8ca43
fix(todos): keep an unusable stored todo list from failing every model call (#7803)
* fix(todos): keep an unusable stored todo list from failing every model call

`todos` is a reducer channel that `POST /threads/{id}/state` and run input can
Overwrite directly, but neither boundary validated its shape. The todo
middleware rendered it with `entry.get(...)` in both `before_model` and
`after_model`, so a non-object entry — or a value that is not a list — raised
AttributeError on every model call, permanently for that thread.

Validate caller-written todos beside `goal` in `_normalize_external_todos`: a
list of objects with string content and a known status, or HTTP 400. The
middleware now reads the channel through `_usable_todos` and ignores entries of
any other stored shape, so checkpoints and direct integrations written before
this boundary still run.

* fix(todos): normalize stored todos in token-usage attribution

TokenUsageMiddleware reads the same stored `todos` channel through
`_build_attribution` whenever the last AIMessage calls write_todos, and
`token_usage.enabled` defaults on, so a value the todo middleware now tolerates
still aborted the step here. Route the stored list through `_normalize_todos`
before reading entries.

Document that a caller-written todo without a status is accepted as pending and
cover that shape at both external boundaries.

* docs: keep backend agent guidance within size budgets

* fix(todos): keep the channel metadata strip on caller-written todos

The dedicated todos branch in strip_server_owned_state_metadata replaced the
generic list branch, which stripped server-owned metadata from every entry. A
caller could therefore persist additional_kwargs.original_user_content,
untrusted_input, or artifact.knowledge_sources on a todo entry. Re-apply the
per-entry strip after normalization, keeping None and empty lists untouched.

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 07:28:33 +08:00
Wenchao An
2145c9ab1f
feat(models): discover provider catalogs and search chat models (#7871)
* feat(models): discover provider catalogs and search chat models

* docs(models): scope catalog guidance to owning directories

* test(guidance): register model catalog scoped instructions

* test(memory): pin capacity scenarios to a stable clock

* fix(models): guard catalog imports and align picker interactions

* test(memory): share the fixed clock with updater capacity tests

* fix(models): clear provider filters removed by catalog refresh

* refactor(models): share connection fields across model forms

* fix(models): keep active provider filters clearable

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-05 06:43:01 +08:00
MasterZRC
2ceda05bf9
fix(sandbox): release ports after definite CLI spawn failures (#7887)
* fix(sandbox): release ports after definite CLI spawn failures

* test(memory): pin hybrid capacity evaluation clock
2026-11-04 21:44:45 +08:00
Cordis798
4c4a4e9858
fix(community): initialize search TLS clients off the event loop (#7889)
Co-authored-by: Cordis798 <284918518+Cordis798@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-04 20:54:43 +08:00
easT-T
3dd9e8841f
fix(frontend): preserve live subtask steps during history backfill (#7864)
* fix(frontend): preserve live subtask steps during history backfill

* test(deermem): keep updater eviction fixtures fresh

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-04 20:16:09 +08:00
周龙杰
900a5173b1
fix(github-research): disclose truncated trees (#7815)
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-04 10:40:59 +08:00
yetuge
6f24bc7c36
fix(title): build the title model off the Gateway event loop (#7813)
Thread title generation runs inside the agent graph (aafter_model), and it
built its configured model inline. create_chat_model can read local CLI
credentials while it is constructed (Codex auth.json, Claude Code credential
files), so the first turn of every new thread read them on the shared loop
and other requests waited for it.

Build the provider through run_assembly, the dedicated assembly pool the
one-shot helpers, skill moderation, the goal evaluator and start_run already
use. Inference still awaits on the loop, and the sync path is unchanged.

A Blockbuster regression builds the real Codex provider: on main the gate
rejects the credential read, the broad fallback swallows it, and the local
fallback title replaces the model's title; with the change the provider is
constructed on a worker thread and the model's title is kept.
2026-11-04 04:31:57 +08:00
easT-T
3b627af8e7
fix(frontend): release rejected run-input attempts before retrying (#7790) 2026-11-02 15:31:05 +08:00
minibeartwo
7c3d2551b6
feat(frontend): add a token usage dashboard for the console APIs (#7636)
* feat(frontend): add token usage dashboard over console APIs

* fix(frontend): address token usage dashboard review feedback

* fix(frontend): route usage runs to their custom agent chats

* docs(frontend): keep agent guidance within the module budget
2026-11-02 15:29:46 +08:00
spud
21175ba46f
fix(runtime): persistently fence stale run event producers (#7619)
* fix(runtime): fence revoked run event producers

* fix(runtime): reduce off-mode producer guard locking

* docs: keep inherited guidance within size budget

* chore(runtime): remove development phase labels

* fix(persistence): normalize libpq SSL options for asyncpg connections

* docs(runtime): clarify producer fencing behavior in off mode

* test(persistence): align migration TLS probes with channel-binding rejection

* fix(runtime): authorize fenced Gateway history seeding

* fix(scheduler): preserve takeover identity in recovery publication

* fix(scheduler): report unconfirmed recovery publication

* fix(runtime): preserve history messages before the first human turn

* fix(runtime): clarify run creation failure diagnostic

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-02 15:26:42 +08:00
linkangjun
3f86f071f3
fix(middlewares): prevent todo retries after text-only output caps (#7605)
* fix(middlewares): prevent todo retries after text-only output caps

* docs(middlewares): clarify text-only output cap markers

* test(subagents): isolate cleanup test from shared assembly pool

* docs(middlewares): keep cap guidance within chain budget

---------

Co-authored-by: linkangjun <331227811+linkangjun@users.noreply.github.com>
2026-11-02 10:46:59 +08:00
王一帆
d0ec8dcc5d
feat(knowledge): add optional ingestion and status center (#7518)
* feat(knowledge): add optional ingestion and status center

* docs(knowledge): record upstream CI budget fix and regression results

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-02 10:42:21 +08:00
Cordis798
92325bd126
fix(community): load retrieval TLS trust off the event loop (#7738)
Co-authored-by: Cordis798 <284918518+Cordis798@users.noreply.github.com>
2026-11-02 10:35:15 +08:00
N
98b72af732
fix(auth): allow demoting disabled administrators (#7769) 2026-11-02 09:26:00 +08:00