@qwen-code/qwen-code 0.15.6-preview.0 → 0.15.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,7 +40,7 @@ You need to have the language server for your programming language installed:
40
40
 
41
41
  ### .lsp.json File
42
42
 
43
- You can configure language servers using a `.lsp.json` file in your project root. This uses the language-keyed format described in the [Claude Code plugin LSP configuration reference](https://code.claude.com/docs/en/plugins-reference#lsp-servers).
43
+ You can configure language servers using a `.lsp.json` file in your project root. Each top-level key is a language identifier, and its value is the server configuration object.
44
44
 
45
45
  **Basic format:**
46
46
 
@@ -104,9 +104,9 @@ Example:
104
104
 
105
105
  #### Required Fields
106
106
 
107
- | Option | Type | Description |
108
- | --------- | ------ | ------------------------------------------------- |
109
- | `command` | string | Command to start the LSP server (must be in PATH) |
107
+ | Option | Type | Description |
108
+ | --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
109
+ | `command` | string | Command to start the LSP server. Supports bare command names resolved via `PATH` (e.g. `clangd`) and absolute paths (e.g. `/opt/llvm/bin/clangd`) |
110
110
 
111
111
  #### Optional Fields
112
112
 
@@ -148,6 +148,8 @@ For servers that use TCP or Unix socket transport:
148
148
 
149
149
  Qwen Code exposes LSP functionality through the unified `lsp` tool. Here are the available operations:
150
150
 
151
+ Location-based operations (`goToDefinition`, `findReferences`, `hover`, `goToImplementation`, and `prepareCallHierarchy`) require an exact `filePath` + `line` + `character` position. If you do not know the exact position, use `workspaceSymbol` or `documentSymbol` first to locate the symbol.
152
+
151
153
  ### Code Navigation
152
154
 
153
155
  #### Go to Definition
@@ -315,7 +317,7 @@ LSP servers are only started in trusted workspaces by default. This is because l
315
317
  - **Trusted Workspace**: LSP servers start if configured
316
318
  - **Untrusted Workspace**: LSP servers won't start unless `trustRequired: false` is set in the server configuration
317
319
 
318
- To mark a workspace as trusted, use the `/trust` command or configure trusted folders in settings.
320
+ To mark a workspace as trusted, use the `/trust` command.
319
321
 
320
322
  ### Per-Server Trust Override
321
323
 
@@ -338,11 +340,12 @@ You can override trust requirements for specific servers in their configuration:
338
340
 
339
341
  ### Server Not Starting
340
342
 
341
- 1. **Check if the server is installed**: Run the command manually to verify
342
- 2. **Check the PATH**: Ensure the server binary is in your system PATH
343
- 3. **Check workspace trust**: The workspace must be trusted for LSP
344
- 4. **Check logs**: Look for error messages in the console output
345
- 5. **Verify --experimental-lsp flag**: Make sure you're using the flag when starting Qwen Code
343
+ 1. **Verify `--experimental-lsp` flag**: Make sure you're using the flag when starting Qwen Code
344
+ 2. **Check if the server is installed**: Run the command manually (e.g. `clangd --version`) to verify
345
+ 3. **Check the command**: The server binary must be in your system `PATH`, or specified as an absolute path (e.g. `/opt/llvm/bin/clangd`). Relative paths that escape the workspace are blocked
346
+ 4. **Check workspace trust**: The workspace must be trusted for LSP (use `/trust`)
347
+ 5. **Check logs**: Look for `[LSP]` entries in the debug log (see Debugging section below)
348
+ 6. **Check the process**: Run `ps aux | grep <server-name>` to verify the server process is running
346
349
 
347
350
  ### Slow Performance
348
351
 
@@ -351,41 +354,34 @@ You can override trust requirements for specific servers in their configuration:
351
354
 
352
355
  ### No Results
353
356
 
354
- 1. **Server not ready**: The server may still be indexing
357
+ 1. **Server not ready**: The server may still be indexing. For C/C++ projects with clangd, ensure `--background-index` is in the args and a `compile_commands.json` (or `compile_flags.txt`) exists in the project root or a parent directory. Use `--compile-commands-dir=<path>` if it is in a build subdirectory
355
358
  2. **File not saved**: Save your file for the server to pick up changes
356
359
  3. **Wrong language**: Check if the correct server is running for your language
360
+ 4. **Check the process**: Run `ps aux | grep <server-name>` to verify the server is actually running
357
361
 
358
362
  ### Debugging
359
363
 
360
- Enable debug logging to see LSP communication:
364
+ LSP debug logs are automatically written to session log files in `~/.qwen/debug/`. To check LSP-related entries:
361
365
 
362
366
  ```bash
363
- DEBUG=lsp* qwen --experimental-lsp
364
- ```
365
-
366
- Or check the LSP debugging guide at `packages/cli/LSP_DEBUGGING_GUIDE.md`.
367
-
368
- ## Claude Code Compatibility
367
+ # View the latest session log
368
+ grep '\[LSP\]' ~/.qwen/debug/latest
369
369
 
370
- Qwen Code supports Claude Code-style `.lsp.json` configuration files in the language-keyed format defined in the [Claude Code plugins reference](https://code.claude.com/docs/en/plugins-reference#lsp-servers). If you're migrating from Claude Code, use the language-as-key layout in your configuration.
371
-
372
- ### Configuration Format
370
+ # Common error messages to look for:
371
+ # "command path is unsafe" → relative path escapes workspace, use absolute path or add to PATH
372
+ # "command not found" → server binary not installed or not in PATH
373
+ # "requires trusted workspace" → run /trust first
374
+ ```
373
375
 
374
- The recommended format follows Claude Code's specification:
376
+ You can also verify the server process is running:
375
377
 
376
- ```json
377
- {
378
- "go": {
379
- "command": "gopls",
380
- "args": ["serve"],
381
- "extensionToLanguage": {
382
- ".go": "go"
383
- }
384
- }
385
- }
378
+ ```bash
379
+ ps aux | grep clangd # or typescript-language-server, jdtls, etc.
386
380
  ```
387
381
 
388
- Claude Code LSP plugins can also supply `lspServers` in `plugin.json` (or a referenced `.lsp.json`). Qwen Code loads those configs when the extension is enabled, and they must use the same language-keyed format.
382
+ ## Extension LSP Configuration
383
+
384
+ Extensions can provide LSP server configurations through the `lspServers` field in their `plugin.json`. This can be either an inline object or a path to a `.lsp.json` file. Qwen Code loads these configs when the extension is enabled. The format is the same language-keyed layout used in project `.lsp.json` files.
389
385
 
390
386
  ## Best Practices
391
387
 
@@ -406,7 +402,7 @@ qwen --experimental-lsp
406
402
 
407
403
  ### Q: How do I know which language servers are running?
408
404
 
409
- Use the `/lsp status` command to see all configured and running language servers.
405
+ Check the debug log for `[LSP]` entries (`grep '\[LSP\]' ~/.qwen/debug/latest`), or verify the process directly with `ps aux | grep <server-name>`.
410
406
 
411
407
  ### Q: Can I use multiple language servers for the same file type?
412
408
 
package/cli.js CHANGED
@@ -34688,8 +34688,7 @@ var init_uiTelemetry = __esm({
34688
34688
  candidates: 0,
34689
34689
  total: 0,
34690
34690
  cached: 0,
34691
- thoughts: 0,
34692
- tool: 0
34691
+ thoughts: 0
34693
34692
  }
34694
34693
  }), "createInitialModelMetricsCore");
34695
34694
  createInitialModelMetrics = /* @__PURE__ */ __name(() => ({
@@ -34796,7 +34795,6 @@ var init_uiTelemetry = __esm({
34796
34795
  bucket.tokens.total += event.total_token_count;
34797
34796
  bucket.tokens.cached += event.cached_content_token_count;
34798
34797
  bucket.tokens.thoughts += event.thoughts_token_count;
34799
- bucket.tokens.tool += event.tool_token_count;
34800
34798
  }
34801
34799
  }
34802
34800
  processApiError(event) {
@@ -91686,8 +91684,7 @@ var init_qwen_logger = __esm({
91686
91684
  input_token_count: event.input_token_count,
91687
91685
  output_token_count: event.output_token_count,
91688
91686
  cached_content_token_count: event.cached_content_token_count,
91689
- thoughts_token_count: event.thoughts_token_count,
91690
- tool_token_count: event.tool_token_count
91687
+ thoughts_token_count: event.thoughts_token_count
91691
91688
  })
91692
91689
  });
91693
91690
  this.enqueueLogEvent(rumEvent);
@@ -142095,10 +142092,6 @@ function logApiResponse(config2, event) {
142095
142092
  model: event.model,
142096
142093
  type: "thought"
142097
142094
  });
142098
- recordTokenUsageMetrics(config2, event.tool_token_count, {
142099
- model: event.model,
142100
- type: "tool"
142101
- });
142102
142095
  }
142103
142096
  function logLoopDetected(config2, event) {
142104
142097
  QwenLogger.getInstance(config2)?.logLoopDetectedEvent(event);
@@ -143904,7 +143897,6 @@ var init_types4 = __esm({
143904
143897
  output_token_count;
143905
143898
  cached_content_token_count;
143906
143899
  thoughts_token_count;
143907
- tool_token_count;
143908
143900
  total_token_count;
143909
143901
  response_text;
143910
143902
  prompt_id;
@@ -143925,7 +143917,6 @@ var init_types4 = __esm({
143925
143917
  this.output_token_count = usage_data?.candidatesTokenCount ?? 0;
143926
143918
  this.cached_content_token_count = usage_data?.cachedContentTokenCount ?? 0;
143927
143919
  this.thoughts_token_count = usage_data?.thoughtsTokenCount ?? 0;
143928
- this.tool_token_count = usage_data?.toolUsePromptTokenCount ?? 0;
143929
143920
  this.total_token_count = usage_data?.totalTokenCount ?? 0;
143930
143921
  this.response_text = response_text;
143931
143922
  this.prompt_id = prompt_id;
@@ -171583,7 +171574,7 @@ __export(geminiContentGenerator_exports, {
171583
171574
  createGeminiContentGenerator: () => createGeminiContentGenerator
171584
171575
  });
171585
171576
  function createGeminiContentGenerator(config2, gcConfig) {
171586
- const version2 = "0.15.6-preview.0";
171577
+ const version2 = "0.15.6";
171587
171578
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
171588
171579
  const baseHeaders = {
171589
171580
  "User-Agent": userAgent2
@@ -295733,9 +295724,9 @@ var init_LspServerManager = __esm({
295733
295724
  handle2.status = "FAILED";
295734
295725
  return;
295735
295726
  }
295736
- const consent = await this.requestUserConsent(name4, handle2.config, workspaceTrusted);
295737
- if (!consent) {
295738
- debugLogger101.info(`User declined to start LSP server ${name4}`);
295727
+ const trusted = await this.checkWorkspaceTrust(name4, handle2.config, workspaceTrusted);
295728
+ if (!trusted) {
295729
+ debugLogger101.info(`Workspace trust check failed, not starting LSP server ${name4}`);
295739
295730
  handle2.status = "FAILED";
295740
295731
  return;
295741
295732
  }
@@ -296039,21 +296030,35 @@ var init_LspServerManager = __esm({
296039
296030
  });
296040
296031
  }
296041
296032
  /**
296042
- * Check path safety
296033
+ * Check path safety.
296034
+ *
296035
+ * Allows:
296036
+ * - Bare command names (resolved via PATH, e.g. "clangd")
296037
+ * - Absolute paths (explicit user intent, e.g. "/usr/bin/clangd")
296038
+ *
296039
+ * Blocks:
296040
+ * - Relative paths that escape the workspace (e.g. "../../bin/evil")
296043
296041
  */
296044
296042
  isPathSafe(command2, workspacePath, cwd6) {
296045
296043
  if (!command2.includes(path87.sep) && !command2.includes("/")) {
296046
296044
  return true;
296047
296045
  }
296046
+ if (path87.isAbsolute(command2)) {
296047
+ return true;
296048
+ }
296048
296049
  const resolvedWorkspacePath = path87.resolve(workspacePath);
296049
296050
  const basePath = cwd6 ? path87.resolve(cwd6) : resolvedWorkspacePath;
296050
- const resolvedPath = path87.isAbsolute(command2) ? path87.resolve(command2) : path87.resolve(basePath, command2);
296051
+ const resolvedPath = path87.resolve(basePath, command2);
296051
296052
  return resolvedPath.startsWith(resolvedWorkspacePath + path87.sep) || resolvedPath === resolvedWorkspacePath;
296052
296053
  }
296053
296054
  /**
296054
- * 请求用户确认启动 LSP 服务器
296055
+ * Check whether the workspace trust level allows starting an LSP server.
296056
+ *
296057
+ * Auto-allows in trusted workspaces. In untrusted workspaces, blocks
296058
+ * servers that require trust (`trustRequired` or global
296059
+ * `requireTrustedWorkspace`), and cautiously allows the rest.
296055
296060
  */
296056
- async requestUserConsent(serverName, serverConfig, workspaceTrusted) {
296061
+ async checkWorkspaceTrust(serverName, serverConfig, workspaceTrusted) {
296057
296062
  if (workspaceTrusted) {
296058
296063
  return true;
296059
296064
  }
@@ -464633,7 +464638,7 @@ __name(getPackageJson, "getPackageJson");
464633
464638
  // packages/cli/src/utils/version.ts
464634
464639
  async function getCliVersion() {
464635
464640
  const pkgJson = await getPackageJson();
464636
- return "0.15.6-preview.0";
464641
+ return "0.15.6";
464637
464642
  }
464638
464643
  __name(getCliVersion, "getCliVersion");
464639
464644
 
@@ -473703,7 +473708,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds, options2) => {
473703
473708
 
473704
473709
  // packages/cli/src/generated/git-commit.ts
473705
473710
  init_esbuild_shims();
473706
- var GIT_COMMIT_INFO = "6b24b1fc6";
473711
+ var GIT_COMMIT_INFO = "cf5f447fd";
473707
473712
 
473708
473713
  // packages/cli/src/utils/systemInfo.ts
473709
473714
  async function getNpmVersion() {
@@ -474743,6 +474748,7 @@ var bugCommand = {
474743
474748
  return t4("submit a bug report");
474744
474749
  },
474745
474750
  kind: "built-in" /* BUILT_IN */,
474751
+ argumentHint: "<description>",
474746
474752
  supportedModes: ["interactive", "non_interactive", "acp"],
474747
474753
  action: /* @__PURE__ */ __name(async (context2, args2) => {
474748
474754
  const bugDescription = (args2 || "").trim();
@@ -512539,7 +512545,7 @@ function areModelMetricsCoreEqual(a2, b2) {
512539
512545
  if (a2.api.totalRequests !== b2.api.totalRequests || a2.api.totalErrors !== b2.api.totalErrors || a2.api.totalLatencyMs !== b2.api.totalLatencyMs) {
512540
512546
  return false;
512541
512547
  }
512542
- if (a2.tokens.prompt !== b2.tokens.prompt || a2.tokens.candidates !== b2.tokens.candidates || a2.tokens.total !== b2.tokens.total || a2.tokens.cached !== b2.tokens.cached || a2.tokens.thoughts !== b2.tokens.thoughts || a2.tokens.tool !== b2.tokens.tool) {
512548
+ if (a2.tokens.prompt !== b2.tokens.prompt || a2.tokens.candidates !== b2.tokens.candidates || a2.tokens.total !== b2.tokens.total || a2.tokens.cached !== b2.tokens.cached || a2.tokens.thoughts !== b2.tokens.thoughts) {
512543
512549
  return false;
512544
512550
  }
512545
512551
  return true;
@@ -513024,7 +513030,6 @@ var ModelStatsDisplay = /* @__PURE__ */ __name(({
513024
513030
  const hasThoughts = entries.some(
513025
513031
  ({ metrics: metrics2 }) => metrics2.tokens.thoughts > 0
513026
513032
  );
513027
- const hasTool = entries.some(({ metrics: metrics2 }) => metrics2.tokens.tool > 0);
513028
513033
  const hasCached = entries.some(({ metrics: metrics2 }) => metrics2.tokens.cached > 0);
513029
513034
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
513030
513035
  Box_default,
@@ -513133,14 +513138,6 @@ var ModelStatsDisplay = /* @__PURE__ */ __name(({
513133
513138
  values: getModelValues((m3) => m3.tokens.thoughts.toLocaleString())
513134
513139
  }
513135
513140
  ),
513136
- hasTool && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
513137
- StatRow2,
513138
- {
513139
- title: t4("Tool"),
513140
- isSubtle: true,
513141
- values: getModelValues((m3) => m3.tokens.tool.toLocaleString())
513142
- }
513143
- ),
513144
513141
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
513145
513142
  StatRow2,
513146
513143
  {
@@ -546062,6 +546059,7 @@ init_esbuild_shims();
546062
546059
  init_dist4();
546063
546060
  init_acp();
546064
546061
  init_zod();
546062
+ init_types21();
546065
546063
 
546066
546064
  // packages/cli/src/utils/acpModelUtils.ts
546067
546065
  init_esbuild_shims();
@@ -547353,13 +547351,14 @@ var Session3 = class {
547353
547351
  abortController.signal,
547354
547352
  "acp"
547355
547353
  );
547356
- const availableCommands = slashCommands.map(
547357
- (cmd) => ({
547354
+ const availableCommands = slashCommands.map((cmd) => {
547355
+ const acceptsInput = cmd.kind !== "built-in" /* BUILT_IN */ || cmd.completion != null || cmd.argumentHint != null || cmd.subCommands != null && cmd.subCommands.length > 0;
547356
+ return {
547358
547357
  name: cmd.name,
547359
547358
  description: cmd.description,
547360
- input: cmd.argumentHint ? { hint: cmd.argumentHint } : null
547361
- })
547362
- );
547359
+ input: acceptsInput ? { hint: cmd.argumentHint ?? "" } : null
547360
+ };
547361
+ });
547363
547362
  let availableSkills;
547364
547363
  try {
547365
547364
  const skillManager = this.config.getSkillManager();
@@ -548221,7 +548220,7 @@ var QwenAgent = class {
548221
548220
  async initialize(args2) {
548222
548221
  this.clientCapabilities = args2.clientCapabilities;
548223
548222
  const authMethods = buildAuthMethods();
548224
- const version2 = "0.15.6-preview.0";
548223
+ const version2 = "0.15.6";
548225
548224
  return {
548226
548225
  protocolVersion: PROTOCOL_VERSION,
548227
548226
  agentInfo: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwen-code/qwen-code",
3
- "version": "0.15.6-preview.0",
3
+ "version": "0.15.6",
4
4
  "description": "Qwen Code - AI-powered coding assistant",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,7 +21,7 @@
21
21
  "bundled"
22
22
  ],
23
23
  "config": {
24
- "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.15.6-preview.0"
24
+ "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.15.6"
25
25
  },
26
26
  "dependencies": {},
27
27
  "optionalDependencies": {