Commit graph

41 commits

Author SHA1 Message Date
易良
548ca3da25
test(e2e): make fake OpenAI reachable from Docker sandbox (#6302)
* test(e2e): make fake OpenAI reachable from docker sandbox

* test(e2e): harden fake OpenAI server routing
2026-07-04 11:06:53 +00:00
易良
75645caf47
test(e2e): stabilize plan mode tool-control assertion (#6176) 2026-07-02 12:07:11 +00:00
Shaojin Wen
ee6746ec65
fix(test): count result messages instead of assistant messages in multi-model E2E test (#4341)
Resolve turn-completion on isSDKResultMessage (one per turn) instead of isSDKAssistantMessage (which fires multiple times per turn: thinking + text), fixing the consistently-failing multi-model E2E test.
2026-05-20 10:42:51 +08:00
Shaojin Wen
5ce2f2854b
fix(test): clear boundedPromise timers to prevent unhandled rejections (#4220)
boundedPromise timeouts could fire after test completion,
causing vitest to exit with code 1 due to unhandled
rejection. Add clear() method and cleanup all pending
timers in the finally block.
2026-05-17 08:28:22 +08:00
易良
1936420dcb
ci(e2e): stabilize MCP/CLI flows and cancel stale main runs (#4039)
* test(e2e): stabilize MCP tool message flow

* ci(e2e): cancel stale main E2E runs

* test(e2e): accept paired MCP tool results

* test(e2e): stabilize monitor tool check

* test(e2e): stabilize run_shell_command file-listing assertion

The model consistently picks list_directory over run_shell_command
for file-listing prompts. Make the prompt explicit about which tool
to use, matching the approach taken for the MCP tool flow test.
2026-05-12 16:09:30 +08:00
易良
04729d646c
test: stabilize main e2e flakes (#3992)
* test: stabilize main e2e flakes

* test: stabilize macos e2e assertions
2026-05-10 21:50:04 +08:00
Shaojin Wen
d119b60bf0
test(sdk): align tool-control E2E with prior-read enforcement (#3898)
* test(sdk): align tool-control E2E with prior-read enforcement

Three tests in tool-control.test.ts broke deterministically after the
prior-read enforcement landed. Each seeded test.txt then prompted a
direct write — the new guard now rejects the write before canUseTool
fires, with "File X has not been fully read in this session...".

- updatedInput-application + allowedTools-bypass tests: drop the seed
  so write_file takes the new-file path (exempt from enforcement).
- asyncGenerator-deny test: keep seed (assertion requires unchanged
  content), rewrite prompt to "Read X then write Y" — the pattern
  used by 27 passing tests in the same file. Also fix a latent bug
  where canUseTool returned `updatedInput: {}` for non-write tools,
  which would erase file_path on read_file (SDK `?? toolInput` only
  catches nullish, not empty objects).

* test(sdk): address self-review on #3898

- Fix the same `updatedInput: {}` reverse-pattern at line 1545 in
  the multi-turn asyncGenerator test. The CLI side at
  permissionController.ts:444 does `if (updatedInput && typeof
  updatedInput === 'object')` — an empty object is truthy, so it
  silently replaces args. Mirror the pass-through fix from line ~1457.
- In the deny test, add `expect(toolNames).toContain('read_file')`
  before the canUseTool-deny assertion. If the model skips the
  read-first instruction, prior-read enforcement would surface
  EDIT_REQUIRES_PRIOR_READ rather than the canUseTool deny message,
  causing a confusing toContain mismatch. Fail fast with a clear
  signal instead.
2026-05-07 19:35:51 +08:00
Shaojin Wen
d40f3e975e
fix(test): restore abort-and-lifecycle stdin-close test to pre-#3723 version (#3777)
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
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
* fix(test): restore abort-and-lifecycle stdin-close test to pre-#3723 version

#3723 rewrote `should handle control responses when stdin closes
before replies` in a way that flipped its semantics:

- Old: canUseTool sleeps 1s before allowing; asyncGenerator awaits
  `inputStreamDonePromise` so stdin closes WHILE the control reply
  is still in flight; expects `original content` (the in-flight
  tool must NOT execute). Tests CLI robustness when stdin closes
  before replies — matching the test name.

- New: canUseTool returns `allow` immediately; stdin stays open
  until the second result arrives; expects `updated`. Requires
  the LLM to actually call write_file → receive tool result →
  reply 'done'. The test name still says "stdin closes before
  replies", but it no longer tests that.

The new version times out (testTimeout 5min, retry x2 = 900s) on
both macOS and Linux on every push since #3723, because it depends
on LLM tool-calling behavior that isn't deterministic on the CI
endpoint. CI history shows the pre-#3723 version was stable across
30+ runs.

This restores only the test file. The shared permissionFlow,
coreToolScheduler/Session wiring, and e2e workflow `npm run bundle`
step from #3723 are kept intact.

* test(integration): add timeout and unify loop into race chain

Address review feedback on the restored test:

- firstResultPromise / secondResultPromise now have a 30s setTimeout
  reject path, matching the pattern used by canUseToolCalledPromise
  and inputStreamDonePromise (15s). Without these, a hang in the
  result stream falls back to the global Vitest testTimeout (5min)
  with no useful diagnostic.

- loop() is now retained as `loopPromise` and joined into the await
  chain via `Promise.race`. If the iterator throws or the consumer
  exits unexpectedly, the failure surfaces directly to the test
  instead of becoming an unhandled rejection while the test waits
  on side-channel promises.

* test(integration): close pseudo-pass paths in stdin-close lifecycle test

Address review feedback. Each change maps to a specific finding:

- Guard canUseTool by toolName === 'write_file' AND file_path against
  the target absolute path. The model may issue read_file or call
  write_file with an unexpected path; those must not satisfy the
  permission-control timing harness, otherwise the test could pass
  without exercising the intended path.

- Capture the second SDK result and assert it's defined, so the
  Promise.race below can no longer short-circuit silently.

- Replace `Promise.race([..., loopPromise])` with a rejection-only
  loopError partner. Loop completion alone (e.g. iterator ends before
  canUseTool is invoked) must not short-circuit the awaited
  milestones; only loop errors should fail the test.

- Restore absolute path via `helper.getPath('test.txt')` and embed it
  in the prompt, so the file the test asserts on is unambiguously
  the same one the model is asked to write.

- Wrap timing promises in a `boundedPromise` helper that clears its
  timeout on resolve, eliminating dangling timers on success runs.

- Drop the unconditional `console.log(JSON.stringify(...))` in the
  consumer loop to reduce CI retry noise.

Out of scope (acknowledged but deferred): the test still requires
the model to actually emit a write_file tool call; with the new
15s/30s bounded timeouts, an LLM that fails to call write_file now
fails fast with a labeled error ("canUseTool callback not called
timeout after 15000ms") instead of hanging to the global 5-min
testTimeout. Making the test fully model-independent would require
a control-only path that doesn't go through tool dispatch — out of
scope for this regression fix.

* test(integration): defer phase timers in stdin-close lifecycle test

Address review suggestion: the 15s budgets on canUseToolCalled and
inputStreamDone started counting at promise creation, but those phases
only begin after firstResult (30s budget) resolves. On a slow CI run
where the first LLM round-trip exceeds 15s, those timers would reject
before their phase even starts, surfacing a misleading
"canUseTool callback not called" error when the actual cause was
first-result latency.

Add an explicit `startTimer()` to boundedPromise and arm each timer
only when its phase actually begins:

- firstResult: armed immediately (begins with the query).
- canUseToolCalled / inputStreamDone / secondResult: armed inside
  createPrompt right after firstResult resolves, so first-turn latency
  cannot eat into their budgets.

This also makes timeout errors point at the correct phase if any of
them does fire.
2026-05-02 21:39:43 +08:00
John London
4cd9f0cbe4
feat(core): add shared permission flow for tool execution unification (#3723)
* docs: scaffold branch for #3247 tool execution unification

Placeholder commit to establish the branch for PR creation.
Actual refactoring will be done in subsequent commits.

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

* feat(core): add shared permission flow for tool execution unification

This addresses #3247 by consolidating duplicated tool execution behavior
across Interactive, Non-Interactive, and ACP modes behind shared execution
utilities.

- Add permissionFlow.ts: shared L3→L4 permission evaluation logic
- Add permissionFlow.test.ts: comprehensive test coverage (17 tests)
- Export from index.ts for use across all execution modes

Why: Permission handling logic was duplicated in CoreToolScheduler and
Session.runTool(). This shared module ensures consistent behavior across
all modes and provides a single source of truth for future fixes.

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

* fix(e2e): add bundle step to E2E workflow and fix canUseTool test

- Add 'npm run bundle' to E2E workflow so dist/cli.js exists for SDK tests
- Fix 'should handle control responses when stdin closes before replies' test:
  - Use helper.getPath() for absolute file path
  - Make prompt explicitly invoke write_file tool
  - Remove inputStreamDonePromise timeout that caused false failures
  - Add q.endInput() to signal stdin done
  - Assert canUseTool was called and file content is updated

* fix(core): wire evaluatePermissionFlow() and address PR review feedback

Address review feedback on PR #3723:
- Wire evaluatePermissionFlow() in coreToolScheduler.ts (both call sites)
- Wire evaluatePermissionFlow() in Session.ts (ACP mode)
- Delete TOOL_EXECUTION_UNIFICATION.md (had literal \n artifacts)
- Add PermissionFlowPermission union type for stronger typing
- Document the 'default' permission state in docstring
- Use needsConfirmation/isPlanModeBlocked/isAutoEditApproved helpers

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 22:10:37 +08:00
顾盼
aeeb2976d6
feat(web-search): remove built-in web_search tool, replace with MCP-based approach (#3502)
* feat(web-search): add GLM (ZhipuAI) web search provider

- Add GlmProvider class implementing BaseWebSearchProvider using the
  ZhipuAI Web Search API (https://open.bigmodel.cn/api/paas/v4/web_search)
- Support multiple search engines: search_std, search_pro, search_pro_sogou,
  search_pro_quark
- Support optional config: maxResults, searchIntent, searchRecencyFilter,
  contentSize, searchDomainFilter
- Truncate query to 70 characters per API limit
- Register 'glm' in the provider discriminated union (types.ts) and
  createProvider() switch (index.ts)
- Add GlmProviderConfig to settingsSchema, ConfigParams, and Config class
- Add --glm-api-key CLI flag and GLM_API_KEY env var support in webSearch.ts
- Forward GLM_API_KEY in sandbox environment
- Update provider priority list: Tavily > Google > GLM > DashScope
- Add 17 unit tests for GlmProvider and 4 integration tests in index.test.ts
- Update docs/developers/tools/web-search.md with GLM configuration,
  env vars, CLI args, pricing, and corrected DashScope billing info
- Fix stale OAuth/free-tier references in web-search.md

Closes #3496

* docs(web-search): fix DashScope note and add GLM server-side limitations

* fix(web-search): make DashScope provider work with standard API key, remove qwen-oauth dependency

- DashScopeProvider.isAvailable() now checks config.apiKey instead of authType
- Remove OAuth credential file reading and resource_url requirement
- Use standard DashScope endpoint: dashscope.aliyuncs.com/api/v1/indices/plugin/web_search
- Read DASHSCOPE_API_KEY env var and --dashscope-api-key CLI flag
- Forward DASHSCOPE_API_KEY into sandbox environment
- Update integration test to detect DASHSCOPE_API_KEY
- Update docs to reflect new API key based configuration

* feat(web-search): remove built-in web search tool

The web_search tool and all related provider implementations are removed.
Web search functionality will be provided via MCP integrations instead,
which is the direction the broader agent ecosystem is moving.

Removed:
- packages/core/src/tools/web-search/ (entire directory)
- packages/cli/src/config/webSearch.ts
- integration-tests/cli/web_search.test.ts
- ToolNames.WEB_SEARCH, ToolErrorCode.WEB_SEARCH_FAILED
- webSearch config in ConfigParams, Config class, settingsSchema
- CLI options: --tavily-api-key, --google-api-key, --google-search-engine-id,
  --glm-api-key, --dashscope-api-key, --web-search-default
- Sandbox env forwarding for TAVILY/GLM/DASHSCOPE/GOOGLE search keys
- web_search from rule-parser, permission-manager, speculation gate,
  microcompact tool set, and builtin-agents tool list

* fix: remove websearch reference

* docs: remove websearch tool

* docs: add break change guide

* fix review
2026-04-24 11:29:02 +08:00
tanzhenxin
63f1963377
Merge pull request #2698 from QwenLM/refactor/subagent-model-selection
feat: add cross-provider model selection for subagents
2026-04-01 16:17:54 +08:00
mingholy.lmh
4219101397 test(sdk): improve permission message pattern matching
Support both 'declined' and 'denied' variants for permission denied messages in tool control tests.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-27 16:36:06 +08:00
tanzhenxin
ad20049a4e Merge remote-tracking branch 'origin/main' into refactor/subagent-model-selection 2026-03-27 11:56:29 +08:00
tanzhenxin
5d58b2f112 feat: simplify subagent model configuration with model selector
Refactor subagent model configuration from nested modelConfig object to a simple model string field for better UX and clarity.

Changes:
- Replace modelConfig object with model string in SubagentConfig interface
- Add model-selection.ts utility for parsing and validating model selectors
- Support 'inherit' keyword and bare model IDs (e.g., 'glm-5', 'claude-sonnet-4-6')
- Maintain backward compatibility by parsing legacy modelConfig frontmatter
- Update validation to reject cross-provider authType-prefixed selectors
- Update SDK types (TypeScript and Java) to reflect new schema
- Add comprehensive tests for model selection and validation
- Update documentation with model selection examples

Breaking changes:
- modelConfig.frontmatter field deprecated in favor of model field
- Cross-provider model selectors (e.g., 'openai:gpt-4') not supported for subagents

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-27 11:49:45 +08:00
Mingholy
849a7327eb
Potential fix for code scanning alert no. 110: Replacement of a substring with itself
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-26 21:41:10 +08:00
mingholy.lmh
3edbf561e6 test(sdk): remove debug executable path 2026-03-26 21:14:35 +08:00
mingholy.lmh
9db176a07b test(sdk): improve abort test reliability with partial message handling
- Use includePartialMessages and isSDKPartialAssistantMessage for more reliable abort triggering
- Remove flaky tool name assertions that could fail when tools aren't registered (issue #2653)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-26 21:02:30 +08:00
mingholy.lmh
6aab02f13f test(sdk): add tool control pattern matching tests
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-24 22:31:59 +08:00
mingholy.lmh
0da574d800 test: simplify tool control test by removing redundant tool restrictions
Remove excludeTools and allowedTools configurations from the test
as coreTools is sufficient for limiting available tools. Update
canUseTool expectation to verify write_file is properly called.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-23 19:30:03 +08:00
tanzhenxin
19ed08098b refactor(core): rename task tool to agent
- Update tool name aliases to map 'task' to 'agent' as legacy alias
- Add proper 'agent' tool name aliases (Agent, AgentTool)
- Update canonical-to-rule display mapping from 'task' to 'Agent'
- Update tests to expect 'agent' instead of 'task'
- Fix debug log message from [TaskTool] to [Agent]

This completes the tool renaming from "task" to "agent" for clarity,
as "agent" better describes the tool's purpose of delegating to
subagents.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-20 15:50:06 +08:00
mingholy.lmh
79083ffd50 Fix SDK message event pairing and improve content block handling
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-18 18:10:23 +08:00
mingholy.lmh
eea92fc8db fix: ensure message_start and message_stop are always paired in SDK stream events
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-18 18:10:23 +08:00
tanzhenxin
cef0be1b63 test(sdk): simplify integration tests for reliability
- Replace verbose prompts with simple 'Say hello' prompts
- Remove fragile text content assertions that depend on specific model responses
- Simplify test logic to focus on message flow rather than content validation
- Add permissionMode: 'default' and test file setup for read-only tool tests

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-16 11:23:57 +08:00
mingholy.lmh
ee5e47bb5f fix: sandbox user permission in integration tests
- Allow SANDBOX_SET_UID_GID to control user identity in integration tests
- Fix project naming from gemini-cli to qwen-code
- Use random UUID in tests to avoid conflicts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-15 11:02:32 +08:00
mingholy.lmh
82dc79629c feat: enhance session ID handling and error propagation 2026-02-13 21:41:38 +08:00
mingholy.lmh
5d939fdb83 feat: add --session-id support for CLI and SDK
- Add --session-id flag to CLI for specifying custom session ID
- Add sessionId option to SDK QueryOptions
- Implement UUID validation for session IDs
- Pass session ID from SDK to CLI via --session-id argument
- Add integration tests for session-id functionality
- Update unit tests for ProcessTransport

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-13 21:40:57 +08:00
mingholy.lmh
7311a01874 fix: sdk mcp tests 2026-02-09 11:54:20 +08:00
mingholy.lmh
1e05359881 ci(sdk-release): add CLI source selection for SDK releases
- Replace cli_ref input with cli_source choice (build_from_source or npm_latest)
- Add support for bundling latest stable CLI from npm
- Add bundle-cli-from-npm.js script for npm-based CLI bundling
- Fix property naming in nonInteractiveCli.ts (outputUpdateHandler)
- Improve integration tests for subagents
- Skip creating issue on failure during dry-run mode

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-05 20:57:01 +08:00
mingholy.lmh
b05de7a187 test: improve sdk integration tests 2026-01-27 17:10:36 +08:00
mingholy.lmh
f578ff07a2 fix: cli input stream handling and error management, improve e2e and unit tests 2026-01-23 13:56:38 +08:00
mingholy.lmh
50bf65b10b test: skip flaky & ambigous sdk e2e test case 2026-01-13 20:04:19 +08:00
mingholy.lmh
8c109be48c refactor: unified allow list of supported commands in ACP or non-interactive mode 2025-12-26 17:55:03 +08:00
tanzhenxin
b64d636280 anthropic provider support follow-up 2025-12-25 15:24:42 +08:00
tanzhenxin
b9a2cc7bdf Add chat recording toggle (CLI + settings) and disable recording in tests 2025-12-15 13:48:38 +08:00
mingholy.lmh
8b5b8d2b90 test: skip unstable e2e test 2025-12-06 18:41:19 +08:00
mingholy.lmh
22943b888d test: clean up integration test by removing unnecessary console logs 2025-12-05 22:11:27 +08:00
mingholy.lmh
96d458fa8c chore: rename @qwen-code/sdk-typescript to @qwen-code/sdk 2025-12-05 21:47:26 +08:00
mingholy.lmh
c218048551 fix: prevent sending control request when query is closed 2025-12-05 18:46:51 +08:00
mingholy.lmh
322ce80e2c feat: implement SDK MCP server support and enhance control request handling
- Added new `SdkMcpController` to manage communication between CLI MCP clients and SDK MCP servers.
- Introduced `createSdkMcpServer` function for creating SDK-embedded MCP servers.
- Updated configuration options to support both external and SDK MCP servers.
- Enhanced timeout settings for various SDK operations, including MCP requests.
- Refactored existing control request handling to accommodate new SDK MCP server functionality.
- Updated tests to cover new SDK MCP server features and ensure proper integration.
2025-12-05 13:14:54 +08:00
mingholy.lmh
57b519db9a test: skip qwen-oauth e2 case in sandbox 2025-12-04 20:39:51 +08:00
mingholy.lmh
3056f8a63d feat(tests): move SDK integration tests to integration-tests to share globalSetup 2025-12-04 17:10:23 +08:00