Commit graph

968 commits

Author SHA1 Message Date
Nothing Chan
082b3bb3d9
fix(memory): give each linked git worktree its own auto-memory root (#6462)
getAutoMemoryRoot() resolved linked worktrees back to the canonical
repository root, so every worktree of a repo shared one project memory.
Focused worktree sessions polluted the shared MEMORY.md index with
unrelated entries, and chats/, workflows/, and team memory were already
per-worktree — project memory was the only shared exception.

Anchor project memory at the nearest git root (same resolution team
memory already uses) so each worktree gets its own memory directory.
The main checkout resolves to the same path as before, so existing
memory is unaffected.

Fixes #6449

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:34:03 +00:00
ChengHui Chen
1f92787aa0
feat(channels): add dmPolicy config to disable private/DM messages (#6521)
* feat(channels): add dmPolicy config to disable private/DM messages

Add DmGate class mirroring GroupGate to gate DM/private messages in
channel adapters. Operators can now set dmPolicy: 'disabled' in their
channel config to silently drop all DM messages while keeping group
messages active.

Closes #6392

* fix(channels): address review feedback for dmPolicy

- Add dmPolicy: 'open' to all test config factories (8 files) to
  maintain type correctness with required ChannelConfig field
- Add integration tests in ChannelBase.test.ts:
  - preflightInbound: DM dropped + group passes when dmPolicy=disabled
  - isStoredLoopTargetAuthorized: DM loop job disabled + group passes
- Add dmPolicy assertions in config-utils.test.ts (default + explicit)
- Keep dmPolicy as required field (not optional) for strict parity
  with groupPolicy
2026-07-08 12:01:10 +00:00
Zqc
151d269413
feat: extension file reload — watch for plugin changes and hot-reload runtime (#6347)
* feat: extension file reload — watch for plugin changes and hot-reload runtime

- Extract refreshExtensionRuntime to centralize MCP, skills, subagents, hooks, and memory refresh
- Add ExtensionFileWatcher (chokidar) for auto-detecting extension file changes
- Add ExtensionRefreshState with per-session scoped instance and mutation suppression
- Replace monkey-patching with ExtensionManager native mutation listeners
- Add /reload-plugins slash command with i18n-aware summary across all 9 locales
- Add auto-refresh of extension content (commands/skills/agents) on file change
- Add HookRegistry.reloadConfiguredHooks() with correct error recovery
- Fix async mutation pairing via id-based Map instead of LIFO stack
- Fix bootstrap watcher close() UB with queueMicrotask deferral
- Fix concurrent refresh with runningRef/pendingRef guard
- Fix error propagation from refreshExtensionContentRuntime to UI
- Fix isIgnored cross-platform path splitting (path.sep → regex)
- Fix wrong ExtensionMutationEvent type via import from core
- Fix addItem on unmounted component with mountedRef guard
- Set followSymlinks: false on chokidar watchers

* fix: address extension reload review feedback

* docs: expand extension file reload design

* fix: harden extension reload watcher state

* fix(core): tag extension refresh legs

* fix(cli): harden extension reload state handling

* fix(cli): clarify extension reload failure state

* fix(cli): tighten extension reload boundaries

* chore: resolve main conflicts for extension reload

* chore: drop unrelated merge formatting changes

* fix(core): harden extension refresh edge cases

---------

Co-authored-by: 俊良 <zzj542558@alibaba-inc.com>
Co-authored-by: 易良 <1204183885@qq.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-08 11:16:21 +00:00
jinye
43e6a9300a
feat(cli): Enable multi-workspace session routing (#6511)
* feat(cli): Enable multi-workspace session routing

Implement the Phase 2a sessions closed loop for qwen serve multi-workspace mode. Multiple explicit workspaces now create registered runtimes while legacy workspace surfaces remain primary-only, and live session routes dispatch by owning runtime.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address phase2a session review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): cover remaining phase2a review gaps

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address phase2a session review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): satisfy phase2a lint checks

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): align multi-workspace status test limits

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address phase2a session review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6511)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-08 10:06:31 +00:00
callmeYe
a07fdc6042
fix(memory): allow forget to remove user managed memory (#6432)
* fix(memory): allow forget to remove user managed memory

* fix(memory): harden forget index rebuilds

* test(cli): stabilize session archive race assertion

* test(memory): cover deny precedence with ask bypass
2026-07-08 09:51:36 +00:00
jinye
1420566620
feat(serve): Bound replay snapshot history (#6482)
* feat(serve): Bound replay snapshot history

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6482)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review suggestions (#6482)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(acp-bridge): fix replay truncation assertion access

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(serve): keep replay cap validation out of fast path runtime

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(acp-bridge): reset replay window on bulk seed

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6482)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix CI failure on PR #6482

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(sdk): expose bounded replay status types

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-08 06:53:58 +00:00
顾盼
14f02c132a
fix(core): Match hook display-name matchers to tool ids (#6373)
* fix(core): match hook tool display names

* fix(core): tighten hook matcher aliases

* fix(core): align hook matcher aliases
2026-07-08 02:22:55 +00:00
jinye
27f8f2c95d
feat(cli): Add serve env isolation and total admission (#6416)
* feat(cli): add serve env isolation and total admission

Add runtime-local serve env snapshots, explicit env injection for low-cost workspace-scoped consumers, and sourceEnv support for ACP child spawn.

Add a daemon-wide maxTotalSessions admission reservation hook for fresh session creation while keeping multi-workspace sessions gated.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6416)

Reject fractional maxTotalSessions values so the daemon-wide session cap remains an integer count and matches the documented limit semantics.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address PR review feedback (#6416)

Always pass the runtime env to A2UI stdio transports, keep daemon runtime env metadata coherent after env reload fallback, and tighten total-admission coverage.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address total admission review feedback (#6416)

Add retryable ACP error data for total session limits, log total-admission REST rejections, and keep session-limit response scopes explicit.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address env review feedback (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): restore scheduled task serve deps (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): isolate runtime env reload base (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6416)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix CI failure on PR #6416

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address daemon admission review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): address runtime env review feedback

Scrub daemon bearer tokens from A2UI stdio MCP environments and prune reload-owned keys from the daemon runtime base before rebuilding runtime env snapshots.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): preserve daemon env base on reload

Keep runtime env rebuilds anchored to the boot-time daemon base snapshot, preventing reload-owned key pruning from dropping valid shell-exported values. Also carry env file read failure details into runtime metadata and daemon logs.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): satisfy env metadata lint rules

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-08 00:52:36 +00:00
Dragon
394c1a289e
docs(channels): add WeCom to channels overview (#6490)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
The WeCom intelligent robot channel (added in #6436) has its own guide and _meta.ts entry, but the channels overview was never updated. Add WeCom to the platform list, quick-start guide links, the `type` option and `token` exclusion note, new `botId`/`secret` option rows, the media-support note, and the slash-command channel enumeration.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-07 22:39:06 +00:00
Heyang Wang
3d1122d284
perf(cli): defer startup prefetch tasks (#6303)
Some checks failed
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
SDK Python / Classify PR (push) Has been cancelled
SDK Python / SDK Python (3.10) (push) Has been cancelled
SDK Python / SDK Python (3.11) (push) Has been cancelled
SDK Python / SDK Python (3.12) (push) Has been cancelled
* perf(cli): defer startup prefetch tasks

* fix(cli): await IDE for prompt-interactive startup

* perf(cli): defer interactive telemetry startup

* test(cli): add missing assertions and Zed/ACP path coverage for startup prefetch

Address three test coverage gaps identified during code review:

- Assert mockStartEarlyStartupPrefetches in both kitty protocol tests
  (C1: API preconnect call was wired but never verified)
- Add Zed/ACP integration test verifying deferIdeConnection is false
  when getExperimentalZedIntegration returns true (C2: Zed path was
  entirely untested)
- Assert mockStartBackgroundHousekeeping in startup-prefetch test
  (C3: unconditional housekeeping dispatch was never verified)

* docs: move startup prefetch design doc to performance subdirectory

* docs: translate startup prefetch design doc to English

* fix(cli): address startup prefetch review comments

Tighten the startup prefetch follow-up fixes from review while keeping
prompt-interactive telemetry on the fast interactive startup path.

- Preserve Error objects when deferred startup tasks fail
- Remove the unbalanced api_preconnect profiler lifecycle event
- Guard background housekeeping so it only runs for interactive configs
- Document and test prompt-interactive telemetry deferral semantics

* fix(cli): initialize telemetry for prompt-interactive prompts

Ensure sessions launched with an initial interactive prompt have
telemetry ready before the auto-submitted first request runs.

- Exclude prompt-interactive startup from telemetry deferral
- Pass a post-render telemetry option through interactive UI startup
- Skip duplicate post-render telemetry startup for initial prompts
- Update tests to cover the first-prompt telemetry guarantee

Note: Plain interactive TUI startup still defers telemetry post-render.

* fix(cli): preserve startup first-request guarantees

Keep deferred startup work from weakening first-request behavior in
interactive sessions that submit prompts automatically or remotely.

- Store telemetry deferral on Config and reuse that decision at render time
- Keep IDE startup awaited for prompt-interactive and input-file sessions
- Add a timeout for deferred IDE connection failures
- Cover ordinary interactive telemetry deferral and IDE startup edge cases

* fix(cli): make post-render IDE connection opt-in

Default startInteractiveUI to the already-connected IDE path so future
callers do not accidentally connect twice when initializeApp used its
eager default.

- Change the post-render IDE connection default to false
- Update startInteractiveUI tests to assert the safer default

* perf(cli): surface deferred IDE connection status

Make ordinary interactive IDE startup visible while preserving the
post-render prefetch path and first-paint performance tradeoff.

- Emit deferred IDE connection lifecycle events for connecting, success,
  and failure states
- Surface IDE startup status in the TUI footer without blocking input
- Log late underlying IDE failures after timeout for better diagnostics
- Document telemetry deferral tradeoffs and add startup lifecycle tests

---------

Co-authored-by: heyang.why <heyang.why@alibaba-inc.com>
2026-07-07 15:31:55 +00:00
qqqys
e3d7d10d1d
[codex] add natural channel memory intents (#6376)
* feat(channels): add natural channel memory intents

* fix(channels): add explicit guard and exhaustiveness check for clear_confirm intent

The clear_confirm path was handled as implicit fall-through at the bottom
of handleChannelMemoryIntent. If a new intent kind were added to the
ChannelMemoryIntent union, it would silently execute clearChannelMemory
without user confirmation — a data-loss risk.

Add explicit if (intent.kind === 'clear_confirm') guard and a
const _exhaustive: never assertion so TypeScript flags any unhandled
kinds at compile time.

* fix(channels): close session leak in classifier and fix regex separator

- BridgeChannelMemoryIntentClassifier now wraps prompt() in try/finally
  to always call cancelSession(), preventing daemon session leaks on
  every classifier invocation. Cleanup errors are caught so they cannot
  mask a successful classification result.
- Add missing optional punctuation separator to the 以后记住 regex
  pattern for consistency with other Chinese remember patterns.

* fix(channels): enforce pending clear state for channel memory confirmation

The clear_confirm intent executed clearChannelMemory directly without
verifying a prior clear_request was issued for the same chat. Any
authorized user could clear any chat's memory by sending the confirmation
phrase standalone, bypassing the two-step flow.

Add a per-target pending clear map (chatId + threadId, 60s TTL) that
is set during clear_request and verified+consumed during clear_confirm.
Standalone confirmation phrases now get rejected with a prompt to
issue the clear request first.

* fix(channels): include senderId in pendingClears key to prevent cross-user confirmation

User A could initiate clear_request in a group chat and User B could
confirm it, since the pending key only included chatId+threadId.
Add senderId to the key so only the user who initiated the clear
can confirm it.

* fix(channels): harden memory intent review fixes

* fix(channels): cover memory clear sender guard

* fix(channels): block group memory mutations

* fix(channels): avoid ambiguous memory saves

* test(channels): cover memory classifier cleanup

* test(channels): cover memory clear expiry

* fix(channels): restore channel memory slash aliases

* test(channels): cover memory intent edge cases
2026-07-07 15:25:01 +00:00
qqqys
467b292b50
feat(channels): add WeCom intelligent robot channel (#6436)
* feat(channels): add WeCom smart bot channel

* fix(channels): harden wecom review suggestions

* fix(channels): address wecom critical review

* fix(channels): include wecom mixed voice text

* fix(channels): tighten wecom outbound media

* fix(channels): harden wecom outbound sends

* fix(channels): address wecom review blockers

* fix(channels): address wecom review followups

* fix(channels): harden wecom inbound handling

* fix(channels): address wecom auth and media review

* fix(channels): tighten wecom inbound cleanup

* fix(channels): harden wecom media safety

* fix(channels): address wecom review typecheck

* fix(channels): harden wecom media review gaps

* fix(channels): address wecom review blockers

* fix(channels): tighten wecom media edge cases

* fix(channels): address wecom review blockers

* fix(channels): address wecom media review blockers

* fix(channels): address wecom review follow-ups

* fix(channels): address wecom review blockers

* fix(channels): close wecom review blockers

* fix(channels): close wecom preflight dedup race

* fix(channels): close wecom review gaps

* fix(channels): harden wecom kick reconnect

* fix(channels): defer wecom session resolution

* fix(channels): clean wecom session attachments

* fix(channels): harden wecom reconnect and media cleanup

* fix(channels): address wecom review diagnostics

* fix(channels): improve wecom diagnostics

* fix(channels): reset wecom kick retries

* fix(channels): improve wecom diagnostics

* fix(channels): preserve sync cancel preflight

* fix(channels): close wecom connection and ssrf gaps

* fix(channels): clean coalesced wecom attachments

* fix(channels): bound wecom sdk connect wait

* fix(channels): scope wecom untracked attachment cleanup

* fix(channels): block wecom nat64 local-use ssrf

* fix(channels): harden wecom media handling

* fix(channels): harden wecom group gates

* fix(channels): bound wecom kick reconnect cycles

* fix(channels): drain loop collect prompts directly

* fix(channels): align wecom buffer hooks

* fix(channels): harden wecom delivery failures

* fix(channels): recover from wecom attachment write failures

* fix(channels): surface wecom media send failures

* fix(channels): harden wecom replay and reconnect

* fix(channels): clarify wecom partial delivery cleanup

* fix(channels): close wecom rejected downloads

* fix(channels): retain wecom dedup after processing starts

* fix(channels): harden wecom reconnect and media errors

* fix(channels): add wecom media error context

* fix(channels): improve wecom dns diagnostics

* fix(channels): keep wecom kick retry alive

* fix(channels): allow wecom quoted bot replies

* fix(channels): preserve wecom code fences across chunks

* fix(channels): harden wecom reconnect lifecycle

* fix(channels): report wecom media dir setup failures

* fix(channels): harden wecom reconnect recovery

* fix(channels): align wecom review fixes

* fix(channels): harden wecom marker parsing

* fix(channels): keep wecom reconnect timers alive

* fix(channels): handle wecom tilde fences

* fix(channels): preserve wecom fence state

* fix(channels): clean up wecom attachment races

* fix(channels): bind wecom media reads to file handles

* fix(channels): prevent wecom symlink media opens

* fix(channels): address wecom review blockers

* fix(wecom): remove media URL from error messages to prevent credential leakage

The guardedHttpsDownload error messages included rawUrl (truncated to 120
chars), which leaks private WeCom media download URLs into stderr and log
aggregation systems. Remove the URL from redirect and HTTP error messages.

* fix(wecom): address review feedback — tests, security, correctness

- Remove stale URL assertions from media download error tests (the error
  messages no longer include raw URLs after the credential-leak fix)
- Redact sensitive fields (secret, aeskey, token, password, authorization)
  in formatSdkError's JSON.stringify fallback to prevent credential
  leakage in logs
- Add indented code block detection to findCodeRanges so [IMAGE: path]
  inside 4-space/tab-indented code is not stripped as a media marker
- Add disconnectGeneration guard before mkdirSync in downloadAttachments
  to prevent orphaned temp directories when disconnect() races with
  in-flight attachment downloads

* fix(wecom): wrap client.disconnect() in catch block to preserve connection error

In the connect() catch block, client.disconnect() could throw (e.g. if
the WebSocket was already destroyed), masking the original connection
error. Wrap in try/catch so cleanup failures never shadow the root cause.

* fix(channels): address wecom reconnect review blockers

* fix(channels): harden wecom reconnect review fixes

* fix(channels): harden wecom review blockers

* fix(channels): address wecom review blockers

* fix(channels): preserve unsupported wecom media markers

* fix(channels): address wecom reliability suggestions

* fix(channels): allow wecom retry after early drops

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-07 15:24:19 +00:00
han
9ee8546a60
fix(shell): avoid Unix pager default on Windows (#6390)
* fix(shell): avoid Unix pager default on Windows

* fix(shell): clear inherited pager env on Windows

* docs(shell): clarify platform-specific pager default

* fix(shell): normalize pager env handling

* fix(shell): preserve git pager fallback behavior

* test(shell): stabilize pager env coverage
2026-07-07 06:16:18 +00:00
Dragon
067cfbba62
docs: consolidate design docs and plans under docs/ (#6417)
Design docs and implementation plans were scattered across .qwen/design,
.qwen/plans, and docs/superpowers. The .qwen/ locations are git-ignored, so
docs written there never got tracked, while docs/design already held the
richer, version-controlled set. Consolidate everything under docs/design and
docs/plans, relocate two stray root docs into docs/design, and repoint the
references left dangling by the move (moved-doc cross-links and a few source
comments).

Also update AGENTS.md and the feat-dev skill so the documented workflow writes
new design docs and plans to the tracked docs/ locations.

Co-authored-by: DragonnZhang <dragonzhang1024@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 06:05:05 +00:00
AlexHuang
06cd7ce13f
feat(cli): add --project and --global flags to /model for per-project model persistence (#6060)
* feat(cli): add --project and --global flags to /model for per-project model persistence

Add scope control to the /model command so users can persist model
selections to either project-level or user-level settings independently.

- /model --project: persist to workspace .qwen/settings.json
- /model --global: persist to user ~/.qwen/settings.json
- /model (no flag): unchanged behavior (backward compatible)
- Model dialog title shows scope: 'Select Model (this project)' / 'Select Model (global)'
- Completion and argumentHint updated with new flags
- Full i18n support for zh/en

Closes #6052

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): add missing zh-TW translations for /model scope flags

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): address PR review — scope flags, subcommand persistScope, titles, tests

- parseScopeFlags: use (?:^|\s) instead of \b for --flag matching
  (\b fails because - is not a word character)
- Completion: strip all flags to isolate model prefix, supports any order
- Subcommand dialogs (fast/voice/vision) now propagate persistScope
- slashCommandProcessor forwards persistScope for all subcommand cases
- ModelDialog title combines subcommand mode + scope label
  e.g. 'Select Fast Model (this project)'
- Subcommand confirmations show scope suffix (project/global)
- Extract persistScopeSpread() helper to reduce duplication
- Add 9 tests covering scope flags, dialog returns, confirmations
- Add i18n keys for scope suffix labels in zh/en/zh-TW

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): use Partial<Config> & {[key:string]:unknown} to fix index signature TS error

Replace Record<string,unknown> with Partial<Config> & {[key:string]:unknown}
to satisfy TS4111 index signature access rule in the CI build.

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): add scope suffix to ModelDialog history items

Address review comment: historyManager.addItem for voice/fast/vision/main
model selections now shows scope indicator like ' (this project)' or
' (global)', consistent with CLI direct-set confirmations.

Affected: handleModelSwitchSuccess (main), handleSelect (voice/fast/vision)
Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): wrap scopeSuffix in t() and unify wording with ModelDialog

- scopeSuffix in modelCommand.ts now uses t(' (this project)') / t(' (global)')
  instead of hardcoded English strings, matching ModelDialog.tsx wording
- Main model confirmation uses shared scopeSuffix instead of separate
  i18n keys, eliminating 'Model: {{model}} (project)' duplication
- Remove unused i18n keys from en/zh/zh-TW locales
- Update tests to expect '(this project)' wording

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): address code review feedback — scope validation, i18n, tests

- Reject inline prompt + scope flag combination with clear error (#1)
- Add mutual exclusivity check for --project and --global (#5)
- Verify setValue scope parameter in tests + add --global test (#2)
- Extract scopeSuffix to shared variable, remove duplication (#3)
- Remove dead i18n keys 'Select Model (this project)' / '(global)' (#4)
- Fix scopeSuffix placement on model line not API key line (#8)
- Add fr.js / ja.js translations for scope keys (#10)
- Remove unused export ModelDialogPersistScope (#6)
- Wrap non-interactive help text in t() with new flags (#7)
- Fix argumentHint grouping to show mode vs scope flags (#11)

Signed-off-by: Alex <alex.tech.lab@outlook.com>

* fix(cli): reject --project when workspace is untrusted

Reject --project scope flag before direct persistence or opening ModelDialog
when settings.isTrusted is false. Workspace settings are ignored on merge in
that state, so the save would silently not take effect.

Also mirrors the guard in ModelDialog.tsx resolvePersistScope() to fall back
to user scope when the dialog is opened with --project on an untrusted folder.

Default mock settings now includes isTrusted: true.

Signed-off-by: Alex <alex.tech.lab@outlook.com>

---------

Signed-off-by: Alex <alex.tech.lab@outlook.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-07 04:49:36 +00:00
Dragon
80340fb73f
fix(review): remove qwen-code-specific core-infra gate from bundled /review (#6412)
The bundled /review skill is a general command that runs against arbitrary
repositories (and cross-repo PRs), but a previous change baked qwen-code's own
"core infrastructure is maintainer-only" governance into the shipped prompt:
hardcoded packages/core and packages/*/src/{auth,providers,models,config,tools,services}
paths, a 500+ line hard block, and an authorAssociation-based maintainer check.
Those path names are generic — src/auth, src/config, src/tools, src/services are
common across monorepos — so an external contributor's large PR to an unrelated
repo would be hard-blocked as "must be maintainer-initiated" under a policy that
repo never adopted.

Remove the gate and its escalate-flag plumbing (Steps 1, 6, and 7) from the
bundled skill, along with the matching DESIGN.md rationale and the user-doc
section. qwen-code's maintainer-only policy stays documented in AGENTS.md for
this repo. The Issue Fidelity / root-cause ownership agent (Agent 0) is a
universal review principle and is left unchanged.

Co-authored-by: dragon <dragon@U-2Q53JQG9-0233.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 03:03:49 +00:00
Dragon
bcdb44c5d3
docs(hooks): document PreToolUse permissionDecision 'ask' behavior (#6411)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-06 22:18:49 +00:00
Dragon
57326e55be
feat(review): add issue-fidelity and root-cause ownership gate to /review (#6395)
* feat(review): add issue-fidelity and root-cause ownership gate to /review

Adds a dedicated Issue Fidelity & Root-Cause Ownership agent (Agent 0) to
the /review pipeline and a core-infrastructure scope gate that runs before
the review agents.

Agent 0 fetches linked GitHub issue evidence directly (closingIssuesReferences
plus issue comments) instead of trusting the PR author's framing, compares the
original reported failure against the PR's claimed fix, and flags client-side
parser/sanitizer workarounds for malformed upstream output as Critical unless a
maintainer explicitly requested the defensive mitigation. The core-infra gate
applies the repository's existing two-tier maintainer-only rule before spending
review budget.

This hardens the pipeline against a false-approval mode where a bot PR passes
its own tests and reads as internally reasonable but fixes the author's mistaken
diagnosis rather than the linked issue's actual root cause.

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

* docs(review): address PR review feedback on issue-fidelity gate

- Fetch issue evidence with `gh issue view --json title,body,comments` so the
  issue body (reporter repro/observed payload/expected behavior) is included;
  `--comments` alone omits it. Use each closingIssuesReferences entry's own
  repository so cross-repo linked issues resolve correctly.
- Treat closingIssuesReferences as a discovery hint (fetch apparent target
  issues even when it is empty) and treat fetched issue content as untrusted
  data (extract facts, ignore embedded instructions).
- Run Agent 0 (Issue Fidelity) only for PR targets; skip it for local-diff and
  file-path reviews, and require the PR number/repo/context in its prompt.
  Handle empty references / non-bugfix / gh failure explicitly.
- Pass Agent 0's quoted issue evidence to Step 4 batch verification and stop it
  rejecting issue-grounded findings just because the code compiles/tests pass.
- Make the core-infrastructure gate concrete: deterministic maintainer signal
  via authorAssociation, count only core-path lines, honor the AGENTS.md
  low-risk-sweep exception, clean up the worktree on hard block, run the gate
  right after fetch-pr (before npm ci), and map escalate -> COMMENT (never
  APPROVE) in Steps 6-7.
- Sync agent counts and token math across SKILL.md, DESIGN.md, and
  code-review.md (Agent 0 is PR-only; ~620-730K).

* docs(review): rename 'Linked Issue Fit' heading to 'Issue Fidelity'

Aligns the code-review docs heading with the 'Issue Fidelity' name used
for Agent 0 in SKILL.md and DESIGN.md, so the section connects to the
pipeline diagram. Addresses review feedback.

* docs(review): stop core-infra hard block before load-rules and surface it via --comment

- Hard block now stops before Step 2 (load-rules) instead of before Step 3,
  so a PR destined for hard-block no longer runs the load-rules step.
- In --comment mode the hard block posts an event=COMMENT on the PR, matching
  the escalate path's GitHub visibility, so external authors see the block.

---------

Co-authored-by: dragon <dragon@U-2Q53JQG9-0233.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:05:48 +00:00
GuiYang
6f2f21ff7e
docs: standardize GitHub Actions capitalization (#6367) 2026-07-06 06:55:07 +00:00
zhangxy-zju
1783ae86f3
docs(web-shell): document chart renderer integration (#6353)
* docs(web-shell): document chart renderer integration

* docs(web-shell): describe daemon-backed chart artifacts

* docs(web-shell): clarify chart ref validation layers
2026-07-06 04:55:26 +00:00
Dragon
be0b0749c1
docs: fix settings.json reference drift against schema (#6351)
Correct and complete the user-facing settings documentation against
packages/cli/src/config/settingsSchema.ts:

- settings.md: fix general.defaultFileEncoding type (enum, not string);
  document the general.voice.* dictation settings, top-level
  modelFallbacks and modelPricing, tools.computerUse.idleTimeoutMs,
  mcp.toolIdleTimeoutMs, and the skills.disabled denylist.
- model-providers.md: correct the resolution-layers table — only
  --openai-api-key/--openai-base-url exist; there are no
  provider-specific credential CLI flags.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-05 23:40:36 +00:00
qqqys
b23f888d73
[codex] add proactive channel loop tools (#6287)
* feat(channel): add proactive loop tools

* fix(channels): stabilize proactive loop routing

* fix(channels): gate loop tools in shared sessions

* fix(channels): tighten channel loop tool routing

* fix(channels): close loop tool review blockers

* fix(dingtalk): preserve markdown tables

* fix(dingtalk): use app token for reactions

* fix(channels): scope loop tools to active caller

* fix(channels): preserve group session metadata

* fix(channels): normalize loop targets

* test(cli): cover settings cron disable path

* fix(channels): address dingtalk review suggestions

* fix(dingtalk): restore table normalization

* fix(channels): mark loop tool failures

* fix(channels): tighten loop mcp protocol handling

* test(channels): cover loop tool guard paths

* fix(channels): await loop mcp registration

* test(channels): preserve base proactive target default

* refactor(channels): clarify loop target promotion

* fix(channels): harden loop recurring input

* fix(channels): ack loop mcp notifications

* fix(channels): preserve legacy loop targets

* test(channels): cover channel loop wiring paths

* fix(channels): retry skipped loop mcp registration

* fix(channels): keep promoted loop targets visible

* fix(channels): harden loop mcp input logging
2026-07-05 15:49:48 +00:00
Heyang Wang
3bf0fa0af0
Feat: LSP Server support hot reload (#5953)
* feat(core): Add LSP server config hot-reload support

- Implement reconcileServerConfigs to diff desired vs current LSP configs and apply minimal add/remove/restart operations with a serialized reconcile queue
- Add configHash utility to detect config changes via stable hashing
- Add lspConfigWatcher in CLI to watch .lsp.json and trigger reconciliation on file changes
- Extend LspServerManager with per-server config hash tracking and detailed debug logging
- Add design docs for LSP runtime reinitialization and hot-reload overview
- Include comprehensive unit tests for all new modules

* refactor(cli): Extract registerLspHotReload from main function

Move the LSP config file watcher setup and reconciliation logic into a dedicated module-private function registerLspHotReload, reducing the size and nesting depth of the main startup flow. Added a JSDoc summarizing responsibilities, early-return conditions, and the AppEvent.LspStatusChanged side effect.

* fix(lsp): release server resources during reload

* fix(lsp): address hot reload review feedback

* fix(lsp): harden hot reload reconciliation

* docs(lsp): update hot reload design notes

* fix(lsp): harden hot reload retry semantics

* fix(lsp): harden hot reload lifecycle

* fix(lsp): harden hot reload lifecycle

* fix(lsp): isolate hot reload recovery paths

* fix(lsp): align command probes and replay tracking

* fix(lsp): prevent crash restarts during shutdown

* fix(lsp): preserve reload state across failures

* fix(lsp): cancel reloads during shutdown

* fix(lsp): handle socket startup races

* fix(lsp): harden command probe env and socket startup

* fix(lsp): report skipped reload and restart states

* fix(lsp): harden hot reload lifecycle cleanup

* chore: add one comment for `Object.create(null)`

---------

Co-authored-by: heyang.why <heyang.why@alibaba-inc.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-05 13:50:00 +00:00
Heyang Wang
5d0733f79c
feat(core): stabilize tool schema declaration order (#6339)
Make tool declaration ordering deterministic so prompt-cache prefixes do not depend on asynchronous registration history.

- Sort function declarations by canonical tool name after existing visibility filtering
- Preserve deferred, revealed, and alwaysLoad filtering semantics
- Add tests covering deferred tools, revealed tools, and MCP registration order
- Document the prompt-cache motivation and next-step cache break detection plan

Co-authored-by: heyang.why <heyang.why@alibaba-inc.com>
2026-07-05 12:24:59 +00:00
Dragon
fa81e0a604
docs: fix skill invocation syntax and include Feishu in channel lists (#6320)
* docs: fix skill invocation syntax and include Feishu in channel lists

* docs: add Feishu column to channel media-handling table

Address review feedback on PR #6320: after adding Feishu to the prose
channel lists, the 'Platform differences' media-handling table still
omitted it. Add a Feishu column (images/files via the authenticated Open
API resources endpoint, 50MB limit; rich-text 'post' captions), verified
against packages/channels/feishu/src/media.ts and FeishuAdapter.ts. Add a
note that QQ Bot ignores incoming media (per QQChannel.ts) so it has no
row.

* docs: clarify Feishu post messages drop embedded images

The Platform differences table claimed Feishu rich-text (post) messages
carry 'mixed text + images', but FeishuAdapter's post parser only
extracts text/a/at nodes and silently drops img nodes (both the live
handler and the history-backfill path). Correct the Captions cell to
say text is extracted and embedded images are ignored.

* docs: mark clientId/clientSecret as required for Feishu too

Feishu declares requiredConfigFields: ['clientId', 'clientSecret']
(packages/channels/feishu/src/index.ts), same as DingTalk, but the
channel options table listed both fields as DingTalk-only. Update the
Required column and descriptions to cover Feishu (App ID / App Secret).

* docs: note token is not needed for Feishu in channel config table

* docs: note 50MB limit on Feishu image downloads

Feishu images and files both flow through the same downloadMedia() in
packages/channels/feishu/src/media.ts, which enforces a single
MAX_DOWNLOAD_BYTES = 50MB cap. Add the (50MB limit) note to the Images
cell for consistency with the Files cell.

* docs: clarify /skills panel-vs-run behavior per review feedback

- skills.md: add a migration Note that /skills <name> now opens the
  Skills panel and ignores trailing args; use /<skill-name> to run.
- commands.md: list the /skills Usage cell as /skills, /<skill-name>
  for consistency with the rest of the table.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-05 09:49:52 +00:00
ChiGao
b13032d3ae
docs(design): daemon side-channel coordination (A1/A2/A4/A5) (#4511)
Co-authored-by: jinye <djy1989418@126.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-05 09:43:46 +00:00
jinye
fe816f625f
feat(cli): Surface daemon prompt queue status (#6325)
* feat(cli): surface daemon prompt queue status

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6325)

* codex: address PR review feedback (#6325)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6325)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-05 08:25:42 +00:00
jinye
7a528d078a
feat(daemon): Add session organization (#6305)
* feat(daemon): add session organization

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): address session organization review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): cover session organization review cases

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6305)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(web-shell): Address session organization review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): Harden session organization review edge cases

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): Address session organization review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-05 07:52:56 +00:00
Zqc
6a726f6c63
refactor(core): centralize extension runtime refresh (#6152)
* refactor(core): centralize extension runtime refresh

* test(core): add regression tests for allSettled and try/catch resilience in refreshExtensionRuntime

* test(core): add restartMcpServers reject test and restore design rationale comments

Address @wenshao's review feedback:
- Add test for restartMcpServers rejection (the only fatal error path)
- Restore key 'why' comments about allSettled and try/catch design decisions
- Logger tag change to EXTENSION_RUNTIME_REFRESH is intentional (standalone module)

* docs(core): add error-handling tier contract to refreshExtensionRuntime

Add block comment documenting the three-tier error-handling contract
(fatal/swallow/swallow) so future maintainers know which tier applies
when adding new refresh steps. Addresses review feedback on #6152.

---------

Co-authored-by: 俊良 <zzj542558@alibaba-inc.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-05 07:47:48 +00:00
jinye
bfce93a304
feat(acp-bridge): Add EventBus subscriber byte cap (#6314)
* feat(acp-bridge): add EventBus subscriber byte cap

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6314)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-05 02:04:17 +00:00
nas
e1f5d21008
fix(core): treat request timeout of 0 as disabled instead of aborting immediately (#6288)
* fix(core): treat request timeout of 0 as disabled instead of aborting immediately

A provider `generationConfig.timeout` of `0` (and `QWEN_CODE_API_TIMEOUT_MS=0`) now
disables the request timeout, matching the existing `QWEN_STREAM_IDLE_TIMEOUT_MS=0`
convention, instead of being coerced to the 120s default (Anthropic `||`) or passed
to the OpenAI SDK as `timeout: 0` (which the SDK treats as an immediate abort).

- add `resolveRequestTimeout()` + `DISABLED_REQUEST_TIMEOUT_MS`, mapping a disabled
  timeout to the JS timer ceiling (2^31-1 ms), reusing the same ceiling already used
  for `MAX_STREAM_IDLE_TIMEOUT_MS`
- use it in the OpenAI default/dashscope providers and the Anthropic provider
- accept `0` in the `QWEN_CODE_API_TIMEOUT_MS` env override without weakening the
  shared `parsePositiveIntegerEnv` (relied on by ~15 other callers to reject 0)
- document the timeout unit and 0-disables semantics in settings.md

Fixes #6049

* Update packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts

Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com>

* test(core): fix broken constants mock merge in dashscope.test

Commit 0f5aa0c interleaved two vi.mock('../constants.js') blocks, leaving
orphaned fragments that produced TS syntax errors and stopped the dashscope
suite from loading. Replace with a single importOriginal-based mock that
overrides only DASHSCOPE_PROXY_BASE_URL and delegates every other constant
(timeouts, DISABLED_REQUEST_TIMEOUT_MS, resolveRequestTimeout) to the real
module, so the mock cannot drift from the implementation.

---------

Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com>
2026-07-04 21:04:25 +00:00
zhangxy-zju
e9a7917d5e
feat(web-shell): support compact echarts full data blocks (#6232)
* feat(web-shell): support custom code block rendering

* fix(web-shell): harden custom code block rendering

* docs: add skill capability gating design

* fix(web-shell): make chart skill host supplied

* docs(web-shell): write chart skill in English

* docs(web-shell): document full-data chart payload

* docs(web-shell): use dataset-backed chart payload

* feat(web-shell): add echarts full-data renderer

* chore(web-shell): keep chart skill host supplied

* fix(web-shell): show loading for streaming chart blocks

* style(web-shell): polish echarts full-data renderer

* fix(web-shell): harden custom code block language parsing

* fix(web-shell): harden echarts full-data renderer

* fix(web-shell): polish echarts renderer followups

* fix(web-shell): reuse enhanced table for chart data

* fix(web-shell): recover chart renderer after errors

* fix(web-shell): harden chart option handling

* fix(web-shell): harden chart data rendering

* fix(web-shell): tighten chart renderer guardrails

* fix(web-shell): update chart fallback title

* fix(web-shell): polish chart renderer review fixes

* feat(web-shell): support compact echarts full data blocks

* docs(web-shell): add chart skill template

* fix(web-shell): address chart review suggestions

* fix(web-shell): preserve punctuation language aliases

* fix(web-shell): address chart follow-up review

* fix(web-shell): harden chart ref resolution

* fix(web-shell): cover chart sanitizer follow-ups

* fix(web-shell): address chart review follow-ups

* fix(web-shell): address chart review leftovers

* fix(web-shell): close chart review gaps

* fix(web-shell): handle latest chart review
2026-07-04 15:36:54 +00:00
tanzhenxin
cdf83d8bd0
fix(core): give Stop-hook continuations a fresh per-turn tool-call budget; make the cap configurable (#6238)
* fix(core): give Stop-hook continuations a fresh per-turn tool-call budget; make the cap configurable

A blocking Stop-hook continuation (e.g. a /goal iteration) feeds a fresh
user-role prompt to the model — a new logical turn — but the loop detector
never reset, so an entire goal chain billed one per-turn tool-call budget
and healthy long-running goals halted with turn_tool_call_cap. The ACP
daemon path already used per-continuation budgets; core now matches.

- Reset loop detection at each blocking Stop-hook continuation
- Add model.maxToolCallsPerTurn setting (default 100; <= 0 disables),
  resolved once in Config (<= 0 maps to Infinity)
- Honor the in-session 'Disable loop detection for this session' choice
  in the per-turn cap, as the dialog always claimed
- Point the headless halt message at the setting; update dialog/docs

* test(cli): add DEFAULT_MAX_TOOL_CALLS_PER_TURN to core module mocks

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-04 02:36:59 +00:00
jinye
5dc2e1501f
feat(serve): Add runtime.activity fields to daemon status API (#6270)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(serve): add runtime.activity fields to daemon status API

Add activePrompts, lastActivityAt, and idleSinceMs to the
GET /daemon/status runtime section. These fields already exist on the
bridge (and are exposed via GET /health?deep=1) but were missing from
the richer status endpoint that operators use for troubleshooting.

The idleSinceMs value is computed from a cached lastActivityAt read
(same pattern as the health handler) to ensure consistency within a
single response.

* feat(serve): add MCP server health summary to workspace status

Extract serversConnected, serversErrored, and serversDisabled counts
from the MCP servers array into the workspace.mcp.summary object.
Operators can see MCP fleet health at a glance without expanding the
full JSON.

* fix(serve): guard activity fields against undefined bridge getters

Add ?? null / ?? 0 fallbacks for lastActivityAt and activePromptCount
to prevent RangeError when a test fake bridge omits these properties.
2026-07-03 20:19:02 +00:00
jinye
3911b1dc34
fix(serve): optimize daemon NDJSON stream handling (#6263)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-03 15:27:28 +00:00
callmeYe
fe3dd93e8f
Add sessionless workspace memory forget and dream (#6227)
* feat(serve): add sessionless memory forget and dream

* fix(serve): thread abort through memory forget

* fix(serve): address workspace memory review feedback

* fix(serve): address memory review follow-up

* fix(memory): harden forget review paths

* fix(serve): classify memory availability failures

* fix(serve): document memory task capacity tiers

* fix(memory): address review edge cases

* chore: remove mobile-mcp formatting noise
2026-07-03 11:00:53 +00:00
tanzhenxin
2a21963026
feat(web-shell): display nested sub-agents as a tree in the tasks panel (#6239)
Carry nested-agent lineage (parentAgentId, parentName, depth) through the
daemon tasks snapshot as optional fields and render the web-shell tasks
panel as a tree: children group under their parent with a ↳ marker and
clamped indentation, agents whose parent left the roster are promoted to
root with a "from <parent>" annotation, and the detail view gains a
nesting line. The [blocking] tag and the two-step stop confirmation now
apply only to provably user-blocking chains, mirroring the TUI's
agent-forest semantics from #6191.
2026-07-03 10:01:07 +00:00
ChiGao
9658dccfbb
feat(daemon): add session artifact APIs (#5895)
* docs: add session artifacts daemon API design

* docs: tighten session artifacts design scope

* docs: frame artifacts API as complete v1 capability

* docs: address artifacts review follow-ups

* docs: clarify artifacts reset boundary

* docs: clarify batch hook artifact flow

* docs: address latest artifact design audit

* docs: tighten artifact event and store semantics

* docs: simplify artifact v1 merge policy

* docs: resolve artifact v1 review blockers

* docs: tighten artifact trust and retention semantics

* docs: close artifact v1 boundary gaps

* feat(daemon): add session artifact APIs

* fix(daemon): harden session artifact semantics

* fix(sdk): update daemon browser bundle budget

* fix(daemon): tighten artifact ingestion boundaries

* fix(daemon): cache artifact workspace realpath

* fix(daemon): sanitize artifact add dispatch input

* docs(daemon): align artifact change wire shape

* fix(daemon): harden artifact status validation

* test(daemon): cover artifact acp dispatch

* test(daemon): update artifact capability baseline

* fix(daemon): clear workspace locator on published artifacts

* fix(core): forward post-tool batch artifacts

* fix(daemon): harden artifact status refresh

* fix(daemon): guard artifact event ingestion

* test(daemon): cover non-strict artifact drops

* fix(core): align artifact display validation

* fix(daemon): serialize artifact store operations

* chore(daemon): clarify artifact publisher tool name

* fix(daemon): coordinate artifact route mutations

* fix(daemon): harden artifact refresh comparison

* fix(daemon): harden artifact ingress edge cases

* fix(daemon): guard artifact rpc mutations during archive

* fix(daemon): gate session metadata mutation auth

* fix(daemon): harden artifact route boundaries

* fix(channels): compact drained group history

* fix(daemon): address artifact review findings

* fix(daemon): address artifact review follow-ups

* fix(daemon): preserve hook artifact success output

* fix(daemon): handle artifact review edge cases

* fix(daemon): address artifact review hardening

* test(daemon): cover artifact review edge cases

* fix(daemon): validate hook artifact aggregation

* fix(daemon): improve artifact ingestion diagnostics

* fix(daemon): address artifact review feedback

* fix(daemon): address artifact review feedback

* fix(daemon): harden session artifact ingress

* fix(daemon): harden artifact edge cases

* fix(daemon): tighten artifact path validation

* fix(daemon): address artifact review races

* fix(daemon): surface artifact path inspection errors

* fix(daemon): forward batch hook artifacts in ACP

* fix(daemon): clean artifact bridge metadata

* test(daemon): cover artifact store edge cases

* fix(daemon): resolve artifact file url symlinks

* fix(daemon): harden artifact ingestion paths

* fix(daemon): harden artifact review paths

* test(daemon): cover artifact tool name sync

* fix(daemon): harden artifact republish validation

* chore(daemon): remove unrelated artifact PR churn

* fix(daemon): address artifact review gaps

* test(daemon): cover artifact url rejection

* chore(daemon): drop unrelated formatting churn

* chore(daemon): update settings schema

* fix(daemon): harden artifact validation

* fix(daemon): tighten artifact event validation

* docs(core): clarify artifact env flag comment

* test(cli): align soft failure artifact expectation

* fix(daemon): address artifact review edge cases

* fix(daemon): enable artifact metadata recording

* fix(daemon): harden artifact store review paths

---------

Co-authored-by: 秦奇 <gary.gq@alibaba-inc.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-03 08:58:43 +00:00
Tianyuan
0633b8a985
feat(scheduler): make recurring cron/loop job expiration configurable (#6173)
* feat(scheduler): make recurring cron/loop job expiration configurable

Recurring cron/loop jobs previously auto-expired after a hardcoded 7 days with no way to extend or disable the limit, forcing long-running daemon deployments to recreate jobs weekly.

Add an experimental.cronRecurringMaxAgeDays setting (default 7) and a QWEN_CODE_CRON_MAX_AGE_DAYS environment-variable override (takes precedence, for cloud/container deployments). A value of 0 disables expiry so jobs run until deleted; negative or unparseable values fall back to the 7-day default. The configured limit also applies to durable tasks restored from disk, and the CronCreate tool description now reflects the effective limit instead of a hardcoded '7 days'.

Closes #6167

* refactor(scheduler): drop unused DEFAULT_RECURRING_MAX_AGE_MS export

Review feedback on #6173 — the ms constant is only used inside the module as the constructor default; keep only the days constant public.

* fix(scheduler): align zero max-age semantics and warn on cron expiry misconfiguration

Review feedback on #6173:

- CronScheduler constructor now maps 0 to Infinity (never expire), matching the config layer instead of silently substituting the 7-day default for direct callers.
- Invalid QWEN_CODE_CRON_MAX_AGE_DAYS / cronRecurringMaxAgeDays values now log a warning before falling back to the default, leaving a breadcrumb for misconfigured deployments.
- Durable tasks found past the recurring max age at load now log a warning before their final fire + delete, since a lowered max age retroactively expires long-lived tasks and deletion is unrecoverable.
- New durable-restore tests: a custom max age applies to tasks reloaded from disk, and a disabled max age (Infinity) restores a 30-day-old task as live instead of aging it out.

* fix(scheduler): surface cron expiry warnings on the console

Review feedback on #6173:

- The invalid-config and retroactive-expiry warnings moved from debugLogger (file-only, off unless QWEN_DEBUG_LOG_FILE is set) to console.warn so they reach container/daemon logs where this knob matters; the config warning is latched to fire once per Config instance.
- CronCreateTool's constructor now resolves the max age once instead of three times, so an invalid env var can't emit duplicate warnings during tool registration.

* fix(scheduler): reject non-finite timestamps in durable task validation

Review feedback on #6173: JSON like -1e999 parses to -Infinity, which passes the typeof-number check and then poisons date math — with a finite lastFiredAt the entry reads as an overdue aged task and the retroactive-expiry warning's toISOString() throws RangeError mid-load, so one malformed persisted entry blocks durable cron startup/takeover. Validation now requires finite createdAt (and lastFiredAt when non-null), routing such entries through the existing fix-or-delete contract for corrupt files. Verified the new end-to-end test reproduces the RangeError without the fix.

* refactor(scheduler): single-source the max-age contract and freeze it at Config construction

Review follow-ups on #6173:
- Extract normalizeRecurringMaxAge as the single owner of the
  0/Infinity no-expiry contract, used by both the Config layer and the
  CronScheduler constructor, so the constructor's 0 handling can no
  longer be removed as apparent dead code.
- Resolve QWEN_CODE_CRON_MAX_AGE_DAYS once at Config construction into
  a readonly field, honoring the setting's requiresRestart contract;
  mid-session env changes can no longer make the tool description,
  tool output, and scheduler report different expiries. The warn
  once-latch is now unnecessary (construction warns at most once).
2026-07-03 06:34:37 +00:00
tanzhenxin
8de93b876b
feat(core): allow sub-agents to spawn nested sub-agents up to a configurable depth (#6189)
* feat(core): allow bounded nested sub-agent spawning via maxSubagentDepth

Sub-agents may now spawn sub-agents up to a configurable maximum nesting
depth (default 5; 1 reproduces the previous no-nesting behavior).
Enforced in two layers sharing one predicate: prepareTools() hides the
agent tool from leaf-depth sub-agents, and AgentTool.execute() rejects
over-depth spawns as an authoritative backstop. Teammates, forks, and
the workflow tool remain excluded from nesting. Launch depth is
persisted in the agent meta sidecar and restored on resume (including
deferred-approval continuations and in-process AgentInteractive frames)
so a resumed nested agent cannot regain spawn capacity.

See knowledge/qwen-code/design/nested-subagents.md.

* fix(core): address review findings on nested sub-agent spawning

- Deny the agent tool to workflow-spawned subagents: depth gating would
  otherwise re-admit it, letting a workflow leaf spawn outside the
  orchestrator's concurrency cap, agent accounting, and token budget.
- Reject non-finite maxSubagentDepth values (JSON 1e309 parses to
  Infinity and would unbound the recursion cap; NaN would silently block
  all nesting) and cap the knob at 100 to catch typos.
- Add a --max-subagent-depth CLI flag mirroring sibling budget flags,
  with loud validation for flag typos, and document the setting.
- Log guard rejections (depth, fork containment) and silent
  fork-to-subagent downgrades through the agent debug logger.
- Refresh stale comments (depthOverride resume pinning, depth-gated
  AgentTool exclusion) and drop references to a design doc that lives
  outside the repository.
- Fill review-noted test gaps: nesting predicate primitives, fork-context
  prepareTools, persisted-depth restoration on background resume,
  nested AgentInteractive depth pinning, nested fork fallback, and the
  blocked-spawn returnDisplay shape.

* fix(cli): add maxSubagentDepth to the CliArgs test literal

The exhaustive CliArgs mock in gemini.test.tsx missed the new field,
failing CI's clean tsc build (the local incremental build skipped the
test file).

* fix(core): add a teammate backstop to the agent spawn guards

execute() backstopped depth and fork containment but not the teammate
exclusion, so its guards covered less than prepareTools() gates. A
teammate spawn call that slipped past schema-hiding would have nested.
Block it symmetrically with the fork guard, log the rejection, and pin
the behavior in a test.

* fix(core): normalize persisted maxSubagentDepth on resume

The resume path trusted the raw sidecar value, bypassing the Config
clamp — a tampered or malformed sidecar (1e309 parses to Infinity;
JSON.stringify turns Infinity into null) would remove the nesting cap
for resumed agents. Extract the clamp into a shared
normalizeMaxSubagentDepth used by both the Config constructor and the
flag-restore path, and refresh the stale settings schema description
(clamp range, non-finite fallback, workflow-agent wording).

* test(core): pin null-to-default normalization of resumed maxSubagentDepth

JSON.stringify(Infinity) === 'null', so a sidecar can legitimately carry
null; widen the persisted flag type to admit it and parameterize the
resume test over both the clamp (5000 -> 100) and the null fallback
(null -> 5).

* fix(core): harden nesting depth edges from final review pass

- Normalize persisted meta.depth on resume: the sidecar is untrusted
  JSON, and a tampered negative depth (or -1e309 → -Infinity) would pin
  the resumed frame below zero and pass canSpawnNestedAgent for every
  cap. Invalid values fail closed to the depth ceiling — the agent
  keeps running but cannot spawn.
- Register monitor notification routing for in-process interactive
  agents: framing runLoop() made their monitors agent-owned, and owned
  dispatch has no session fallback, so notifications were silently
  dropped. InProcessBackend now routes them into the agent's message
  queue and tears the routing down on release.
- Downgrade background spawn requests from nested launchers to awaited
  foreground runs: a nested launcher cannot honor the background
  completion contract (send_message/task_stop excluded, notifications
  session-scoped), which orphaned the child's results.
- Extract spawnBlockReason() as the single spawn-exclusion policy
  shared by prepareTools() and execute(), replacing two hand-kept
  copies of the depth/teammate/fork rules.
- Share DEFAULT_MAX_SUBAGENT_DEPTH / MAX_SUBAGENT_DEPTH_LIMIT across
  the core normalizer, the CLI flag validator, and the settings schema.
- Log dropped teammate names from nested spawns; revert the impossible
  |null persisted-flag widening to an honest tampered-sidecar framing;
  document the constructor-time depth capture invariant.

* test(cli): add DEFAULT_MAX_SUBAGENT_DEPTH to core package mocks

settingsSchema.ts now imports the shared constant, so CLI tests that
mock @qwen-code/qwen-code-core with an explicit export list need the
new export.

* feat(cli): display nested sub-agents as a tree in the TUI (#6191)

* feat(core): allow bounded nested sub-agent spawning via maxSubagentDepth

Sub-agents may now spawn sub-agents up to a configurable maximum nesting
depth (default 5; 1 reproduces the previous no-nesting behavior).
Enforced in two layers sharing one predicate: prepareTools() hides the
agent tool from leaf-depth sub-agents, and AgentTool.execute() rejects
over-depth spawns as an authoritative backstop. Teammates, forks, and
the workflow tool remain excluded from nesting. Launch depth is
persisted in the agent meta sidecar and restored on resume (including
deferred-approval continuations and in-process AgentInteractive frames)
so a resumed nested agent cannot regain spawn capacity.

See knowledge/qwen-code/design/nested-subagents.md.

* feat(cli): display nested sub-agents as a tree in the TUI

Render nested agents depth-first with indent + dim '↳' in the live agent
panel and background tasks view; promote orphaned children to root with a
'· from <parent>' annotation. Detail view gains a level badge, Parent
breadcrumb, and Sub-agents section. The [blocking] tag and two-step cancel
confirm now apply only to provably user-blocking foreground chains. Parent
completion summaries carry a '· N sub-agents' tail (guard-rejected spawns
now record as failed tool calls so the count stays honest). Also fixes the
live-panel Enter-for-detail order mismatch by sharing one display order
between the panel render and the composer keyboard mapping.

* fix(core): address round-1 review on nested sub-agent spawning

- Derive launch metadata (hooks, spans, task rows, meta sidecar) from the
  resolved subagent config instead of the raw requested type, so a fork
  request that falls back to the awaitable path no longer reports "fork".
- Pin the blocked-spawn failure contract in tests: error is set and
  returnDisplay.status is 'failed' for both the depth and fork guards; also
  document the failure-path routing at buildSpawnBlockedResult.
- Drop source-comment references to private knowledge/ design docs that do
  not exist in this repository.

* test: address round-2 review on sub-agent counting and fork fallback

- Exercise the legacy 'task' alias in the scrollback sub-agent count so
  the migration-aware name set is covered, not just the canonical name.
- Pin the nested-fork downgrade: a sub-agent requesting a fork falls back
  to the awaitable general-purpose subagent even in interactive mode.
- Drop a duplicated 'nesting depth guard' describe block left behind by
  the automated base-branch merge (kept the copy with the failure-shape
  assertions).

* fix(core): keep actionable guidance in blocked-spawn error messages

The scheduler's failure path sends only error.message to the model and
the scrollback, discarding llmContent. With the terse terminateReason as
the message, a blocked spawn lost its "do the task yourself instead"
instruction, inviting retry loops. Carry the full guidance text in
error.message and keep terminateReason for the display card.

* test(cli): pin the tree indent clamp at depth beyond TREE_INDENT_MAX_LEVELS

Maintainer mutation-testing on the PR found that removing the clamp in
treeRowPrefix survived the suite. Assert a depth-4 row indents 3 levels
(12 spaces), plus the base marker/indent behavior.

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-03 03:18:57 +00:00
Dragon
dc8e155927
docs: correct stale CLI flags/keybinding and document model.reasoningEffort (#6219)
- Remove nonexistent --all-files/-a and --show-memory-usage flags from the
  CLI arguments and headless option tables (no longer defined in the yargs
  parser in packages/cli/src/config/config.ts).
- Add the commonly-needed --model/-m flag to the headless options table and
  fix the --approval-mode example to use the valid choice auto-edit (the
  parser rejects the underscore form auto_edit).
- Drop the stale Meta+Enter alias from the external-editor shortcut; that
  chord is bound to NEWLINE, while OPEN_EXTERNAL_EDITOR binds only Ctrl+X.
- Document the model.reasoningEffort setting (set via /effort), which is
  exposed in the settings dialog but was missing from the settings reference.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-03 01:55:45 +00:00
qqqys
ca61d7827e
feat(channels): add identity and task lifecycle metadata (#6105)
* chore: ignore local worktrees

* docs(channels): design identity and task lifecycle p0

* docs(channels): plan identity and task lifecycle p0

* feat(channels): add identity and task lifecycle metadata

* fix(channels): suppress cancelled tool call lifecycle

* fix(channels): cover loop lifecycle metadata

* fix(channels): harden lifecycle event edges

* fix(channels): finalize cancelled lifecycle before cleanup

* fix(channels): address lifecycle review suggestions

* fix(channels): close lifecycle cancellation races

* fix(channels): separate pending cancel state

* fix(channels): order clear cancellation lifecycle

* fix(channels): suppress loop chunks during pending cancel

* test(channels): use active session in cancel regression

* fix(channels): sanitize lifecycle tool fields

* fix(channels): route shared tool call lifecycle

* fix(channels): preserve pending cancel intent

* fix(channels): preserve responses after failed cancel

* fix(channels): tighten lifecycle cancellation reasons

* fix(channels): close lifecycle cancel races and validate identity config

Address the outstanding review findings on #6105:

- carry a typed reason on ChannelLoopSkippedError and report disabled
  loops as 'dropped' instead of 'timeout'
- treat a turn as committed once delivery starts: /cancel re-checks
  deliveryStarted after the cancel RPC settles, and neither prompt path
  lets a late-settling cancel rewrite a delivered turn into cancelled
  (or follow a /clear cancellation with completed)
- tag failed lifecycle events with phase: agent vs delivery
- validate identity/memoryScope shape at config parse time instead of
  throwing an opaque TypeError on the first prompt of every session
- guard onPromptStart hooks, pass job.id to loop onPromptStart/End,
  append the boundary block after operator instructions, gate
  /who + /status identity lines on configured identity/memoryScope,
  cache the boundary prompt, and route error logs through
  lifecycleError()

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(channels): keep failed terminal event when cancel settles post-delivery

Self-review follow-up: once delivery started, the catch paths no longer
reconcile a pending cancel — a late-resolving cancel RPC used to flip
cancelled=true there, suppressing the failed emit while the /cancel
handler (seeing deliveryStarted) also declined to emit, leaving a
started task with no terminal lifecycle event at all.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(channels): hold streamed chunks while a cancel is pending

Chunks arriving while a /cancel RPC is in flight were pushed straight
into the BlockStreamer, which can send a block on a size/paragraph
threshold before the cancel resolves — leaking output a successful
cancel can never recall. Hold the pending-window chunks instead: replay
them (block streaming + text_chunk transcript) when the cancel fails,
discard them when it succeeds. onResponseChunk stays live through the
window so adapter-accumulated display state has no permanent hole on a
failed cancel; adapters gate visible updates on their own stop flags.

Also stop passing the loop job id to onPromptStart/onPromptEnd (and the
/clear eviction path): the hook contract is inbound platform message
ids, and adapters act on them — cards and reactions keyed to a fake id.
Lifecycle events still carry job.id for correlation.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(channels): defer adapter chunks while cancel is pending

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-02 09:04:07 +00:00
Dragon
55e425c1d2
docs: document the /config slash command (#6145)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-02 13:52:59 +08:00
Dragon
2c95d9383f
feat(core,cli): unified reasoning effort with /effort command (#6072)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(core,cli): unified reasoning effort with /effort command

Expose a provider-agnostic reasoning-effort ladder (low/medium/high/xhigh/max) through a new /effort slash command and a global model.reasoningEffort setting. Bare /effort opens an interactive tier picker (and lists tiers in non-interactive/ACP mode); /effort <tier> sets one directly. A single canonical reasoning.effort config is translated and clamped per provider so one control works everywhere:

- OpenAI: reasoning_effort (max clamps to xhigh)
- DeepSeek: flat reasoning_effort (low/medium→high, xhigh→max)
- GLM / z.ai: new adapter flattens nested reasoning.effort to a verbatim reasoning_effort
- Anthropic: output_config.effort, gated per model — Opus 4.7/4.8 and 5.x families pass xhigh/max through; Opus 4.6/Sonnet 4.6 take max only; older clamp to high
- Gemini: thinking_level (adds medium; xhigh/max cap at HIGH)
- Qwen / DashScope: a set effort turns on enable_thinking (no per-tier field yet — the single column to extend when qwen ships one)

Config.setReasoningEffort updates the live config so the change takes effect on the next turn without an auth refresh, and is re-applied across model switches and auth refreshes (including the initial one at startup) so the effort survives /model switches and CLI restarts — even for provider-backed models, whose preset sync would otherwise overwrite reasoning and drop the persisted effort. The model-with-reasoning status line now tracks the effort and updates immediately when /effort changes it.

A new core/reasoning-effort.ts holds the canonical tier list, rank-based clamp, and input normalizer shared across providers and the command.

* fix(core): reject date suffix as Anthropic minor version for effort gating

The version regex parsed the 8-digit date suffix of dated model ids
(e.g. claude-opus-4-20250514 = Opus 4.0) as the minor version, so
atLeast(4, 6)/atLeast(4, 7) returned true and Opus 4.0 was wrongly
granted the xhigh/max effort tiers it does not support, producing an
HTTP 400 on /effort max with no clamp warning.

Cap the minor-version group at one or two digits with a trailing (?!\d)
so a date suffix is not mis-parsed (a bare {1,2} cap is insufficient: it
would still greedily capture '20' from '20250514'). Dated ids that do
carry a minor, like claude-opus-4-7-20251101, still resolve to minor 7.

Adds a regression test asserting effort 'max' clamps to 'high' on
claude-opus-4-20250514.

* fix(i18n): translate /effort command description for all locales

The mustTranslateKeys strict-parity test failed because the new /effort
command description fell back to English in zh and zh-TW. Add the
description string to every locale file so the command is translated like
its siblings and strict-parity locales no longer fall back.

* fix(core): correct DeepSeek effort mapping and adaptive-thinking model parse

Address two review findings on the reasoning-effort path in
anthropicContentGenerator:

- DeepSeek anthropic-compatible output_config.effort accepts only high/max,
  but resolveEffectiveEffort passed low/medium through verbatim (only
  remapping xhigh -> max), which the endpoint would 400 on. Mirror the
  DeepSeek OpenAI adapter (deepseek.ts): low/medium lift to high, xhigh/max
  group to max.

- modelSupportsAdaptiveThinking used /claude-(?:opus|sonnet|haiku)-(\d+)-(\d+)/,
  so a dated id like claude-opus-4-20250514 (Opus 4.0) parsed the 8-digit date
  suffix as the minor version (>= 6), wrongly selecting adaptive thinking and
  tripping a server 400. Apply the same date-suffix-guarded regex the sibling
  anthropicSupportedEffortTiers already uses, also covering the fable/mythos
  families and a bare major (claude-opus-5).

Add regression tests for both.

* fix(core,cli): address /effort review feedback

- anthropic: family-guard the `max` tier on the 4.x branch so haiku 4.x no
  longer gains `max` (a server 400); 5.x families still get it via major>=5.
- effort command: when `setReasoningEffort` no-ops because thinking is disabled
  (reasoning: false), report that the tier won't take effect yet instead of a
  misleading success message (the tier is still persisted for future sessions).
- dashscope: drop the pipeline-injected nested `reasoning` object when
  `enable_thinking` is set, so qwen never receives two competing thinking knobs
  (mirrors deepseek.ts / zai.ts).

Adds regression tests for each.

* fix(core): collapse empty reasoning to undefined and drop redundant effort re-apply

setReasoningEffort(undefined) now resets reasoning to undefined instead of
leaving a truthy empty object, which the pipeline would emit as wire noise
and which would make 'if (cfg.reasoning)' a false positive.

handleModelChange no longer re-applies the reasoning effort after the
full-refresh path: refreshAuth already captures and restores it, so the
second call was redundant. The qwen-oauth hot-update path keeps its own
re-apply because it never routes through refreshAuth.

* fix(core): log once when Gemini clamps xhigh/max effort to HIGH

Gemini has no tier above HIGH, so /effort xhigh|max silently ran at HIGH
with no trace. Mirror the Anthropic generator's one-time clamp warning via
a per-generator latch so the downgrade is discoverable in debug logs.

* fix(core): warn when GLM model on non-Z.ai host skips reasoning_effort flatten

isZaiProvider routes any glm-* model through this provider, but the
reasoning_effort reshape stays hostname-gated. A self-hosted GLM on a
non-Z.ai hostname therefore kept its nested reasoning.effort unflattened
silently. Keep the reshape hostname-gated (so we never push GLM's flat
field at an arbitrary OpenAI-compatible backend) but log the skip once so
the gap is discoverable.

* docs(core,cli): correct false OpenAI 'max'->'xhigh' clamp claim

The reasoning-effort docs claimed OpenAI adapters clamp 'max' to 'xhigh',
but the default OpenAI-compatible pipeline forwards the tier verbatim and
no such clamp exists. Reword the doc comment and the reasoningEffort
setting description (and the regenerated VS Code schema) to match.

* fix(cli): clarify effort confirmation and improve the effort dialog UX

- The /effort confirmation now states the tier is the requested one and the
  effective tier depends on the active provider/model, instead of implying
  the shown tier is what reaches the wire (providers clamp per model).
- EffortDialog no longer pre-selects 'high' when no effort is configured;
  the cursor starts at the top and a footer notes the provider default is
  in effect, so the highlight is not mistaken for the current setting.
- The dialog path now mirrors the slash-command read-back: when thinking is
  disabled (setReasoningEffort is a no-op), it surfaces an info message that
  the tier is persisted but won't take effect until thinking is re-enabled.

* refactor(core): extract shared parseClaudeModelVersion for Claude effort gating

anthropicSupportedEffortTiers and modelSupportsAdaptiveThinking each parsed
Claude model ids with their own near-identical regex (family list +
date-suffix guard), kept in sync only by a comment. Extract a single
parseClaudeModelVersion helper both consume so adding a new family is a
one-line change with no drift risk between effort tiers and the thinking
shape.

* fix(anthropic): drop manual budget_tokens on models that reject it

Opus 4.7+ and every 5.x family (Sonnet 5, Fable 5, Mythos 5) dropped
manual extended thinking: a request with
thinking:{type:'enabled', budget_tokens:N} returns a 400 on those models,
which require adaptive thinking with output_config.effort instead
(https://platform.claude.com/docs/en/build-with-claude/effort).

buildThinkingConfig honored an explicit reasoning.budget_tokens on every
model, so a preset carrying budget_tokens (with or without /effort) shipped
the manual shape to an adaptive-only model and 400'd. Gate the escape hatch
behind a new modelRejectsManualThinking() predicate so the budget is only
emitted for models that still accept it (Opus 4.5/4.6, Sonnet 4.6, older
4.x, and unknown/unversioned ids); adaptive-only models fall through to
{type:'adaptive'} and let output_config.effort govern thinking depth.

* fix(cli,core): warn on invalid model.reasoningEffort; guard hot-update field set

- modelConfigUtils: surface a startup warning when settings.model.reasoningEffort
  holds an unrecognized value (normalizes to undefined and was silently skipped),
  so a typo in settings.json doesn't leave /effort with no visible effect.
- config: document that the qwen-oauth hot-update field set deliberately excludes
  `reasoning`, which is captured and re-applied via setReasoningEffort() — adding
  it to the copied set would mask the effort restore across model switches.

* fix(core,cli): address /effort review feedback

- config: re-apply reasoning effort on the full-refresh model-switch path.
  switchModel() wipes modelsConfig.reasoning via applyResolvedModelDefaults
  before handleModelChange fires, so refreshAuth's own capture reads undefined;
  restore the tier from the live config. Add a regression test.
- gemini: make buildThinkingConfig's effort switch exhaustive (explicit
  'undefined' case + never-guarded default) so a new tier is a compile error
  rather than a silent map to UNSPECIFIED.
- anthropic: emit a one-time warning when budget_tokens is dropped on models
  that reject manual thinking (Opus 4.7+/5.x); reword the version-regex comment
  to correctly credit the (?!\\d) lookahead. Add reseller-prefixed and 5.x
  effort-gating tests.
- cli/effort: confirm the requested tier in-chat on dialog success (mirror the
  slash-command message); add hook tests.
- tests: add dashscope vision-branch effort test and determineProvider z.ai
  routing tests.

* fix(core): harden reasoning-effort normalize and correct stale clamp comment

- normalizeReasoningEffort: reject non-string input (e.g. a hand-edited
  settings.json with a boolean/number reasoningEffort) instead of calling
  .trim() on it and crashing at startup; add regression tests.
- contentGenerator: update the reasoning-effort ladder comment to reflect
  the per-model Anthropic tier gating (Opus 4.7+/5.x accept xhigh/max,
  Opus/Sonnet 4.6 accept max, older models cap at high) instead of the
  outdated blanket 'xhigh/max -> high' description.

Addresses PR review feedback.

* fix: remove stray OpenClaw-Query-Submit gitlink

This branch carries a submodule gitlink (mode 160000, commit be66572)
with no .gitmodules entry. It entered via a merge from an older main
state; current main no longer contains it, so this branch would
re-introduce it on merge, breaking clone --recursive and any submodule
init. Remove it from the index.

* test(cli): add EffortDialog render tests

Adds render/behavior tests for EffortDialog mirroring
ApprovalModeDialog.test.tsx: renders the title and all five tiers,
shows/hides the 'no effort configured' hint based on currentEffort,
and verifies the active Escape handler cancels with undefined while
non-Escape keys do not.

* refactor(anthropic): single-source Claude family list; warn on DeepSeek effort remap

Derive the ClaudeModelFamily union and the model-id regex from one
CLAUDE_MODEL_FAMILIES const so the type and the parser can't drift apart
behind the 'as ClaudeModelFamily' cast.

Emit a one-time debugLogger.warn when the DeepSeek anthropic-compatible
branch remaps a requested effort tier (low/medium -> high, xhigh -> max),
mirroring the real-Anthropic clamp path so a silently upgraded effort is
visible in debug logs.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DragonnZhang <dragonzhang1024@gmail.com>
2026-07-01 20:20:28 +00:00
pomelo
bb7b4d8d57
feat(serve): support HTTPS/TLS via --tls-cert and --tls-key flags (#6032)
* feat(serve): support HTTPS/TLS via --tls-cert and --tls-key

Serve `qwen serve` over HTTPS when both `--tls-cert` and `--tls-key`
point at PEM files, instead of plain HTTP. The motivation is mobile /
cross-device access: a LAN IP (`192.168.x.x`) is not a browser secure
context over `http://`, so `getUserMedia` (voice input), WebRTC, and
other secure-context-only APIs are blocked on phones/tablets. Bringing
your own cert (e.g. via mkcert) unlocks them.

Implementation wraps the existing Express app in `https.createServer`
when TLS is configured; `https.Server extends http.Server`, so the
connection cap, address lookup, ACP attach, and graceful-close paths are
unchanged. The plain-HTTP path stays bit-for-bit identical when no certs
are given. The startup banner and loopback same-origin set now reflect
the active scheme.

Scope is TLS termination only — no auto-generation, no ACME. TLS is
orthogonal to the bearer-token gate: non-loopback binds still require a
token. Boot fails loudly if only one of the two flags is given, or if a
cert/key file can't be read, rather than silently downgrading to HTTP.

Closes #6001

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(serve): add HTTPS loopback origins to self-origin and ACP checks

* fix(serve): accept port-less Origin header on default ports 80/443

Per RFC 7230 §5.4, browsers omit the port in the Origin header when it
matches the scheme default (http→80, https→443). The origin checks in
self-origin.ts and acp-http/index.ts always included the port suffix,
so a browser on port 443 sending 'Origin: https://localhost' (no :443)
would fail the loopback origin match.

Add port-less origin entries when the server listens on port 80 or 443,
mirroring the pattern already used in auth.ts hostAllowlist.

* fix(serve): add port-less origins to installSameOriginOriginStrip for RFC 7230 compliance

* fix(serve): validate TLS cert expiry and parse errors at boot

https.createServer starts cleanly with an expired certificate, then every
client handshake is rejected (NET::ERR_CERT_DATE_INVALID) while /health stays
green — a silent outage that's hard to diagnose. Parse the cert with
X509Certificate at boot and fail loud with an actionable message when it's
expired or unparseable. Also wrap createServer so a cert/key mismatch surfaces
a framed error instead of a raw OpenSSL string.

Add tests for the expired-cert guard and the previously-uncovered --tls-key
read error path.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

* fix(serve): close TLS validation gaps from review

- Reject not-yet-valid certs (notBefore > now) at boot, symmetric to the
  existing expiry guard — same silent NET::ERR_CERT_DATE_INVALID outage.
- Add port-less host entries (default 80/443) to the WS upgrade Host
  allowlist, mirroring the REST allowlist (auth.ts) and the Origin checks;
  without it every WS upgrade is 403'd when TLS runs on port 443.
- Cover the previously-untested X509 parse-error and cert/key-mismatch
  boot branches.
- Docs: include localhost/127.0.0.1 in the mkcert TLS example so the URL
  --open rewrites to (127.0.0.1) isn't rejected with CN mismatch.

Co-Authored-By: Qwen-Coder <noreply@qwen.ai>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <noreply@qwen.ai>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-01 19:33:50 +00:00
Dragon
427b5ade33
docs: document model/auth settings, /model --vision, and --safe-mode (#6028)
* docs: document model/auth settings, /model --vision, and --safe-mode

Refresh user docs to match the current codebase:

- commands.md: add the /model --vision override (vision-bridge model)
- settings.md: add model.baseUrl, model.sessionTokenLimit, visionModel,
  and voiceModel; document the deprecated security.auth.apiKey and
  security.auth.baseUrl keys with a pointer to modelProviders
- troubleshooting.md: document the --safe-mode flag for isolating
  customization issues

* docs: address review feedback on sessionTokenLimit, safe-mode, deprecation notes

- model.sessionTokenLimit: correct default to -1 (runtime fallback in
  core/config.ts) and clarify breach behavior (current send dropped, not
  session abort) per client.ts SessionTokenLimitExceeded handling.
- --safe-mode: expand the disabled-customizations list to also cover
  permission rules, approval mode overrides, memory features, and sandbox
  settings, matching cli/config.ts.
- security.auth.apiKey/baseUrl: align deprecation wording with the existing
  tools.* entries (**Deprecated.**) and drop the unsubstantiated
  '(slated for removal)' qualifier.

* docs: note QWEN_CODE_SAFE_MODE env var as a safe-mode alternative

Document the QWEN_CODE_SAFE_MODE=true environment variable as an
alternative activation path for safe mode, for cases where the CLI
cannot accept flags (verified against isSafeModeEnv in
packages/core/src/utils/safe-mode.ts).

* docs: clarify model.baseUrl, sessionTokenLimit=0, and safe-mode subagents

- model.baseUrl: describe it as a picker-managed disambiguator, not a
  hand-editable override (stale values can misroute to a same-id provider).
- model.sessionTokenLimit: note that 0 is treated as unlimited (same as -1),
  unlike model.maxToolCalls where 0 disallows all calls.
- --safe-mode: include custom subagents in the list of disabled
  customizations (only built-in subagents load in safe mode).

* docs: clarify sessionTokenLimit semantics and add --safe-mode to headless flags

- settings.md: reword model.sessionTokenLimit to reflect that the gate
  compares the last recorded prompt token count before the next send
  (not a per-send preflight cap), and that the next send is dropped.
- headless.md: add a --safe-mode row to the CLI flags table so the
  diagnostic flag is discoverable there, cross-referencing Troubleshooting.

* docs: align safe-mode sandbox wording to 'sandbox settings'

Safe mode passes an empty Settings object to loadSandboxConfig
(packages/cli/src/config/config.ts:1793), so it strips settings-sourced
sandbox config while the --sandbox flag and QWEN_SANDBOX env still apply.
Match headless.md to troubleshooting.md's accurate 'sandbox settings'.

* docs: correct safe-mode approval-mode wording and align both lists

Safe mode only strips settings-sourced approval mode; the --yolo and
--approval-mode CLI flags are evaluated before the safeMode guard
(packages/cli/src/config/config.ts:1521-1528) and still take effect.
Reword to 'settings-sourced approval mode overrides' and note the CLI
flags in troubleshooting.md and headless.md, and make the enumerated
safe-mode disable list identical (same items and order) across both.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-01 15:34:20 +00:00
jinye
487fb45510
feat(cli): Harden daemon-managed channel worker (#6098)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(cli): harden daemon-managed channel worker

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(cli): address channel worker review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): harden channel worker log supervision

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): redact channel worker snapshot errors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* perf(cli): precompute channel worker log redactors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): escalate permanent channel worker failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(cli): bound oversized worker log tail discard

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6098)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 13:26:38 +00:00
qqqys
6a5ad453c8
[codex] Add explicit channel memory for messaging channels (#6051)
* chore: ignore local worktrees

* feat(core): add channel memory store

* fix(core): preserve dots in channel memory paths

* fix(core): guard dot channel memory paths

* feat(channels): add channel memory commands

* fix(channels): defer channel memory session invalidation

* feat(channels): inject channel memory into sessions

* fix(channels): serialize channel memory context injection

* fix(channels): harden channel memory context races

* fix(channels): let queued turn retry memory context

* feat(cli): wire channel memory into channel startup

* docs(channels): document channel memory

* fix(channels): harden channel memory handling

* fix(channels): gate channel memory injection

* fix(channels): serialize channel memory clears

* fix(channels): tolerate channel memory read failures

* fix(channels): harden channel memory review gaps

* fix(channels): harden channel memory review gaps

* fix(channels): protect shared channel memory

* test(channels): allow group memory view test

* fix(channels): block group memory writes

* fix(channels): include memory in loop prompts

* fix(channels): preserve session context order after merge

* fix(channels): retry loop memory context after read failure

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-01 09:59:48 +00:00
易良
1a46df5d92
fix(cli): load browser MCP tools by default (#6006)
* fix(cli): load browser MCP tools by default

* fix(cli): cover browser MCP env flags

* fix: address browser MCP review follow-ups

* fix(cli): add browser MCP diagnostics

* fix(cli): tighten browser MCP auto-wiring

* fix(cli): address browser MCP diagnostics

* revert(cli): drop browser MCP diagnostic churn

* revert(cli): drop optional CDP startup diagnostic

* refactor(cli): load browser MCP dynamically

* fix(cli): lazily attach CDP tunnel

* test(cli): use repo deps for CDP tunnel acceptance

* fix(cli): scope browser MCP defaults to extension origins

* fix(cli): recover from lazy CDP attach failures

* fix(chrome-extension): bind CDP replies to source socket

* ci: allow slower actionlint runs

* fix(cli): harden chrome devtools runtime MCP registration

* test(cli): satisfy lint in CDP registration race test

* test(cli): cover chrome devtools MCP retry loop

* test(cli): cover chrome devtools skip paths

* ci: restore actionlint timeout
2026-07-01 09:46:00 +00:00
jinye
b4fe43741a
feat(daemon): Add session archive support (#6058)
* feat(daemon): add session archive support

Add active versus archived daemon session storage, archive and unarchive APIs, strict live-session close handling, ACP and SDK support, and coverage for archive listing, load rejection, deletion, and route mapping.

Closes #6057

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: fix CI failure on PR #6058

Update the no-AK integration capability baseline to include the new session_archive capability added by this PR.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): preserve live session on strict close failure

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): serialize session delete with archive transitions

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): share session archive orchestration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): clean up strict close failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* docs(daemon): clarify archive recovery tradeoffs

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): log session archive outcomes

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): parallelize archive session closes

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): serialize archive restore races

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): satisfy archive lint checks

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): keep strict close retryable

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): distinguish archive conflicts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): warn on unreadable session heads

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* docs(core): document active-only session helpers

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): tighten archive review edges

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): allow concurrent session restores during archive gate

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): avoid archive head reads on session restore

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address PR review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(sdk): account for session archive bundle size

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address archive gate review (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address archive review follow-ups (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* codex: address ACP archive review feedback (#6058)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address session archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover close ownership restoration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover ACP close prompt fallback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(daemon): Cover archive close channel loss

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive follow-up review

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Return archiving conflict for delete gate

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): Treat unreadable archived ids as occupied

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* refactor(daemon): Share session delete orchestration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(daemon): Address archive review feedback

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(deps): Clear critical runtime audit failures

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(deps): Sync runtime dependency ranges with main

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-07-01 16:24:26 +08:00