@qwen-code/qwen-code 0.15.12-preview.2 → 0.15.12-preview.3
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.
- package/bundled/qc-helper/docs/configuration/settings.md +10 -10
- package/bundled/qc-helper/docs/features/lsp.md +87 -10
- package/bundled/qc-helper/docs/qwen-serve.md +46 -15
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +11 -11
- package/bundled/stuck/SKILL.md +124 -0
- package/chunks/{agent-UQY6A6OS.js → agent-LIAWUWAO.js} +3 -3
- package/chunks/{ca-VQSV6JHA.js → ca-S3XJMT6P.js} +26 -0
- package/chunks/{chunk-SOIEFHIK.js → chunk-5QQ5FGTU.js} +0 -99
- package/chunks/{chunk-2WFU3IUH.js → chunk-AJSOD5IR.js} +4417 -2250
- package/chunks/{chunk-MXBWOU2L.js → chunk-AOJ3BBY7.js} +12 -12
- package/chunks/{chunk-FSYKVGER.js → chunk-GC5RXNL2.js} +1 -1
- package/chunks/{chunk-PCL3EJGY.js → chunk-XLQ4E5PS.js} +3918 -3677
- package/chunks/{contextCommand-MQRG6RMG.js → contextCommand-SVLAZMQL.js} +4 -4
- package/chunks/{de-M2IPQRBS.js → de-MNR4SMAI.js} +26 -0
- package/chunks/{edit-3KCBTA25.js → edit-VNAZBIZR.js} +7 -3
- package/chunks/{en-N5GMPCVT.js → en-NRN4QBAT.js} +27 -0
- package/chunks/{enter-worktree-VWS5QZTU.js → enter-worktree-FOF5YZIV.js} +3 -3
- package/chunks/{exit-worktree-RVXFWAPD.js → exit-worktree-Y6QVAO3C.js} +3 -3
- package/chunks/{exitPlanMode-UL5DILDG.js → exitPlanMode-QZKO7GH7.js} +3 -3
- package/chunks/{fr-BTHRYEXO.js → fr-OFJFHLCR.js} +26 -0
- package/chunks/{geminiContentGenerator-O2OPGHJG.js → geminiContentGenerator-DYHZPKJX.js} +1 -1
- package/chunks/{glob-57BSREPN.js → glob-G7XATELV.js} +3 -3
- package/chunks/{grep-XO5JOC7T.js → grep-4SETMY47.js} +3 -3
- package/chunks/{ja-D63TAEBO.js → ja-V6OQ6VL7.js} +26 -0
- package/chunks/{monitor-BECPGO3K.js → monitor-JTLJBJ7H.js} +21 -12
- package/chunks/{openaiContentGenerator-KEZQHIRM.js → openaiContentGenerator-3H7XOZBW.js} +2 -2
- package/chunks/{pt-XUV7FSKC.js → pt-ZLE6SA4A.js} +26 -0
- package/chunks/{qwenContentGenerator-RPMRXTNH.js → qwenContentGenerator-FAU3QPYO.js} +4 -4
- package/chunks/{read-file-LGHEIQNH.js → read-file-WWUQVNCZ.js} +1 -1
- package/chunks/{ripGrep-6SFSXZ2G.js → ripGrep-WCOAIWL6.js} +3 -3
- package/chunks/{ru-7KHWMN3A.js → ru-A4OHIUNN.js} +26 -0
- package/chunks/{serve-27O2AFE3.js → serve-VJEEEXA6.js} +780 -104
- package/chunks/{shell-J7K5KYCH.js → shell-IAOKGIJ6.js} +3 -3
- package/chunks/{skill-2R7P4ATS.js → skill-NHW6222K.js} +2 -2
- package/chunks/{src-CGEDVW67.js → src-OWV5HVQQ.js} +82 -12
- package/chunks/{tool-search-XOH3ZWVS.js → tool-search-MSJ6SXLI.js} +1 -1
- package/chunks/{write-file-74NQ27Q2.js → write-file-RKCENFZ5.js} +7 -3
- package/chunks/{zh-VGHU6XBB.js → zh-RN3JULHO.js} +27 -0
- package/chunks/{zh-TW-O36Q4V7E.js → zh-TW-XZEHEV5S.js} +27 -0
- package/cli.js +7440 -5056
- package/locales/ca.js +40 -0
- package/locales/de.js +40 -0
- package/locales/en.js +41 -0
- package/locales/fr.js +41 -0
- package/locales/ja.js +39 -0
- package/locales/pt.js +39 -0
- package/locales/ru.js +39 -0
- package/locales/zh-TW.js +40 -0
- package/locales/zh.js +40 -0
- package/package.json +2 -2
|
@@ -470,15 +470,15 @@ Configures connections to one or more Model-Context Protocol (MCP) servers for d
|
|
|
470
470
|
|
|
471
471
|
Configures logging and metrics collection for Qwen Code. For more information, see [telemetry](/developers/development/telemetry).
|
|
472
472
|
|
|
473
|
-
| Setting | Type | Description
|
|
474
|
-
| ------------------------------------------ | ------- |
|
|
475
|
-
| `telemetry.enabled` | boolean | Whether or not telemetry is enabled.
|
|
476
|
-
| `telemetry.target` | string | Informational label for the telemetry destination (`local` or `gcp`). Does not control exporter routing; set `telemetry.otlpEndpoint` or `telemetry.outfile` to configure where data is sent.
|
|
477
|
-
| `telemetry.otlpEndpoint` | string | The endpoint for the OTLP Exporter.
|
|
478
|
-
| `telemetry.otlpProtocol` | string | The protocol for the OTLP Exporter (`grpc` or `http`).
|
|
479
|
-
| `telemetry.logPrompts` | boolean | Whether or not to include the content of user prompts in the logs.
|
|
480
|
-
| `telemetry.includeSensitiveSpanAttributes` | boolean |
|
|
481
|
-
| `telemetry.outfile` | string | Path to write telemetry to a file. When set, overrides OTLP export.
|
|
473
|
+
| Setting | Type | Description | Default |
|
|
474
|
+
| ------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
|
475
|
+
| `telemetry.enabled` | boolean | Whether or not telemetry is enabled. | |
|
|
476
|
+
| `telemetry.target` | string | Informational label for the telemetry destination (`local` or `gcp`). Does not control exporter routing; set `telemetry.otlpEndpoint` or `telemetry.outfile` to configure where data is sent. | |
|
|
477
|
+
| `telemetry.otlpEndpoint` | string | The endpoint for the OTLP Exporter. | |
|
|
478
|
+
| `telemetry.otlpProtocol` | string | The protocol for the OTLP Exporter (`grpc` or `http`). | |
|
|
479
|
+
| `telemetry.logPrompts` | boolean | Whether or not to include the content of user prompts in the logs. | |
|
|
480
|
+
| `telemetry.includeSensitiveSpanAttributes` | boolean | When enabled, attaches verbatim user prompts, system prompts, tool inputs/outputs, and model responses to native OTel span attributes (in addition to log-to-span bridge spans). ⚠️ Streams sensitive data — file contents, shell commands, conversation history — to your OTLP backend. | `false` |
|
|
481
|
+
| `telemetry.outfile` | string | Path to write telemetry to a file. When set, overrides OTLP export. | |
|
|
482
482
|
|
|
483
483
|
### Example `settings.json`
|
|
484
484
|
|
|
@@ -576,7 +576,7 @@ For authentication-related variables (like `OPENAI_*`) and the recommended `.qwe
|
|
|
576
576
|
| `QWEN_TELEMETRY_OTLP_ENDPOINT` | Sets the OTLP endpoint for telemetry. | Overrides the `telemetry.otlpEndpoint` setting. |
|
|
577
577
|
| `QWEN_TELEMETRY_OTLP_PROTOCOL` | Sets the OTLP protocol (`grpc` or `http`). | Overrides the `telemetry.otlpProtocol` setting. |
|
|
578
578
|
| `QWEN_TELEMETRY_LOG_PROMPTS` | Set to `true` or `1` to enable or disable logging of user prompts. Any other value is treated as disabling it. | Overrides the `telemetry.logPrompts` setting. |
|
|
579
|
-
| `QWEN_TELEMETRY_INCLUDE_SENSITIVE_SPAN_ATTRIBUTES` | Set to `true` or `1` to
|
|
579
|
+
| `QWEN_TELEMETRY_INCLUDE_SENSITIVE_SPAN_ATTRIBUTES` | Set to `true` or `1` to attach verbatim user prompts, system prompts, tool I/O, and model responses to native OTel span attributes (and keep `prompt` / `function_args` / `response_text` on log-to-span bridge spans). Any other value disables it. | Overrides the `telemetry.includeSensitiveSpanAttributes` setting. ⚠️ Streams sensitive data to your OTLP backend. |
|
|
580
580
|
| `QWEN_TELEMETRY_OUTFILE` | Sets the file path to write telemetry to. When set, overrides OTLP export. | Overrides the `telemetry.outfile` setting. |
|
|
581
581
|
| `QWEN_SANDBOX` | Alternative to the `sandbox` setting in `settings.json`. | Accepts `true`, `false`, `docker`, `podman`, or a custom command string. |
|
|
582
582
|
| `QWEN_SANDBOX_IMAGE` | Overrides sandbox image selection for Docker/Podman. | Takes precedence over `tools.sandboxImage`. |
|
|
@@ -344,7 +344,7 @@ You can override trust requirements for specific servers in their configuration:
|
|
|
344
344
|
2. **Check if the server is installed**: Run the command manually (e.g. `clangd --version`) to verify
|
|
345
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
346
|
4. **Check workspace trust**: The workspace must be trusted for LSP (use `/trust`)
|
|
347
|
-
5. **Check logs**:
|
|
347
|
+
5. **Check logs**: Start Qwen Code with `--debug`, then search for LSP-related entries in the debug log (see Debugging section below)
|
|
348
348
|
6. **Check the process**: Run `ps aux | grep <server-name>` to verify the server process is running
|
|
349
349
|
|
|
350
350
|
### Slow Performance
|
|
@@ -361,19 +361,78 @@ You can override trust requirements for specific servers in their configuration:
|
|
|
361
361
|
|
|
362
362
|
### Debugging
|
|
363
363
|
|
|
364
|
-
LSP
|
|
364
|
+
LSP does not have a separate debug flag. Use Qwen Code's normal debug mode together with the LSP feature flag:
|
|
365
365
|
|
|
366
366
|
```bash
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
qwen --experimental-lsp --debug
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Debug logs are written to the session debug log directory. To check LSP-related entries:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# Default runtime directory
|
|
374
|
+
rg "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
|
|
375
|
+
# Or, without ripgrep:
|
|
376
|
+
grep -E "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
|
|
377
|
+
|
|
378
|
+
# If QWEN_RUNTIME_DIR is configured
|
|
379
|
+
rg "LSP|Native LSP|clangd|connection closed" "$QWEN_RUNTIME_DIR/debug/latest"
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Useful entries include:
|
|
383
|
+
|
|
384
|
+
- `[LSP] ...`: Logs emitted by the native LSP service and server manager.
|
|
385
|
+
- `[CONFIG] Native LSP status after discovery: ...`: LSP server configuration discovered for the session.
|
|
386
|
+
- `[CONFIG] Native LSP status after startup: ...`: Server startup result, including ready/failed counts.
|
|
387
|
+
- `[STATUS] LSP status snapshot for /status: ...`: Status snapshot printed when running `/status` in debug mode.
|
|
369
388
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
389
|
+
You can also run `/status` in the CLI to see a short LSP summary:
|
|
390
|
+
|
|
391
|
+
```text
|
|
392
|
+
LSP: disabled
|
|
393
|
+
LSP: enabled, 1/1 ready
|
|
394
|
+
LSP: enabled, 0/1 ready (1 failed)
|
|
395
|
+
LSP: enabled, no servers configured
|
|
396
|
+
LSP: enabled, status unavailable
|
|
374
397
|
```
|
|
375
398
|
|
|
376
|
-
|
|
399
|
+
For per-server details, run `/lsp`:
|
|
400
|
+
|
|
401
|
+
```text
|
|
402
|
+
**LSP Server Status**
|
|
403
|
+
|
|
404
|
+
| Server | Command | Languages | Status |
|
|
405
|
+
|--------|---------|-----------|--------|
|
|
406
|
+
| clangd | `clangd` | c, cpp | READY |
|
|
407
|
+
| pyright | `pyright-langserver` | python | FAILED - startup failed |
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Common error messages to look for:
|
|
411
|
+
|
|
412
|
+
```text
|
|
413
|
+
command path is unsafe -> relative path escapes workspace, use absolute path or add to PATH
|
|
414
|
+
command not found -> server binary not installed or not in PATH
|
|
415
|
+
requires trusted workspace -> run /trust first
|
|
416
|
+
LSP connection closed -> server started but exited or closed stdio before replying to initialize
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
For clangd startup failures, verify the server directly from the project root:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
clangd --version
|
|
423
|
+
clangd --check=/path/to/file.cpp --log=verbose
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
C/C++ projects should usually provide a `compile_commands.json` or `compile_flags.txt`. If the compile database is in a build directory, pass it to clangd:
|
|
427
|
+
|
|
428
|
+
```json
|
|
429
|
+
{
|
|
430
|
+
"cpp": {
|
|
431
|
+
"command": "clangd",
|
|
432
|
+
"args": ["--background-index", "--compile-commands-dir=build"]
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
377
436
|
|
|
378
437
|
```bash
|
|
379
438
|
ps aux | grep clangd # or typescript-language-server, jdtls, etc.
|
|
@@ -402,7 +461,25 @@ qwen --experimental-lsp
|
|
|
402
461
|
|
|
403
462
|
### Q: How do I know which language servers are running?
|
|
404
463
|
|
|
405
|
-
|
|
464
|
+
Start Qwen Code with LSP and debug mode enabled:
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
qwen --experimental-lsp --debug
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Then run `/status` for a short summary, `/lsp` for per-server status, or inspect the debug log:
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
# Default runtime directory
|
|
474
|
+
rg "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
|
|
475
|
+
# Or:
|
|
476
|
+
grep -E "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
|
|
477
|
+
|
|
478
|
+
# If QWEN_RUNTIME_DIR is configured
|
|
479
|
+
rg "LSP|Native LSP|<server-name>" "$QWEN_RUNTIME_DIR/debug/latest"
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
LSP uses Qwen Code's normal `--debug` mode; there is no separate LSP debug flag.
|
|
406
483
|
|
|
407
484
|
### Q: Can I use multiple language servers for the same file type?
|
|
408
485
|
|
|
@@ -173,16 +173,48 @@ To host **multiple workspaces** (one user, several repos; or several users on th
|
|
|
173
173
|
|
|
174
174
|
To handle multiple **users** (each with their own quota, audit log, sandbox) or to scale beyond one process's reach (cold-start budget, FD count, RSS), spawn one daemon per workspace per user behind an external orchestrator. That orchestrator (multi-tenancy / OIDC / Quota / Audit / k8s) is **out of scope** for the qwen-code project — see issue [#3803](https://github.com/QwenLM/qwen-code/issues/3803) "External Reference Architecture" for the design pointers.
|
|
175
175
|
|
|
176
|
+
## Loading and resuming a persisted session
|
|
177
|
+
|
|
178
|
+
The daemon exposes ACP's `session/load` and `session/unstable_resumeSession` over HTTP via two routes:
|
|
179
|
+
|
|
180
|
+
| Route | Use when |
|
|
181
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
182
|
+
| `POST /session/:id/load` | The client has **no** history rendered (cold reconnect, picker-then-open). The daemon replays every persisted turn through SSE so subscribers see the full transcript. Capability tag: `session_load`. |
|
|
183
|
+
| `POST /session/:id/resume` | The client already has the turns on screen and only needs the daemon-side handle back. Model context is restored on the agent side without UI replay — the SSE stream stays clean. Capability tag: `unstable_session_resume`. |
|
|
184
|
+
|
|
185
|
+
The TypeScript SDK exposes both as static factories on `DaemonSessionClient`:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { DaemonClient, DaemonSessionClient } from '@qwen-code/sdk';
|
|
189
|
+
|
|
190
|
+
const client = new DaemonClient({ baseUrl: 'http://127.0.0.1:4170' });
|
|
191
|
+
|
|
192
|
+
// Cold reconnect — daemon will replay history through SSE.
|
|
193
|
+
const session = await DaemonSessionClient.load(client, 'persisted-id');
|
|
194
|
+
|
|
195
|
+
// Or, if your UI already has the history, skip the replay:
|
|
196
|
+
// const session = await DaemonSessionClient.resume(client, 'persisted-id');
|
|
197
|
+
|
|
198
|
+
for await (const event of session.events()) {
|
|
199
|
+
// First the replayed `session_update` frames (load only),
|
|
200
|
+
// then live events.
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Pre-flight `caps.features.session_load` / `caps.features.unstable_session_resume` before calling — older daemons return `404`. Concurrent same-action requests for the same id coalesce; cross-action races (a `load` racing a `resume`) get `409 restore_in_progress` with `Retry-After: 5`. See the [protocol reference](../developers/qwen-serve-protocol.md) for the full error envelope.
|
|
205
|
+
|
|
206
|
+
Note: history replay is bounded by the SSE ring (default 4000 frames). Long histories with chatty turns can exceed that — earliest frames are dropped silently. For very long sessions, prefer `resume` and rely on the client's local persisted UI.
|
|
207
|
+
|
|
176
208
|
## Durability model
|
|
177
209
|
|
|
178
|
-
**Sessions are ephemeral in Stage 1
|
|
210
|
+
**Sessions are still ephemeral in Stage 1 across daemon restarts**, but persisted sessions on disk can be reloaded:
|
|
179
211
|
|
|
180
|
-
- A child process crash publishes `session_died` and removes the session from the daemon's maps.
|
|
181
|
-
- A daemon restart loses every in-flight session.
|
|
182
|
-
- Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 4000 frames) — `Last-Event-ID` reconnect succeeds but state may be incoherent. For mobile / flaky-network clients, plan to re-
|
|
212
|
+
- A child process crash publishes `session_died` and removes the live session from the daemon's maps. The persisted on-disk session **can** be reloaded via `POST /session/:id/load` if a fresh agent child is spawnable.
|
|
213
|
+
- A daemon restart loses every in-flight live session. The persisted sessions remain on disk and can be loaded against a new daemon process, subject to the same workspace binding rules.
|
|
214
|
+
- Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 4000 frames) — `Last-Event-ID` reconnect succeeds but state may be incoherent. For mobile / flaky-network clients, plan to re-open SSE on long drops or call `POST /session/:id/load` to replay from disk.
|
|
183
215
|
- File operations (`writeTextFile`) are atomic across crashes (write-then-rename); they aren't atomic across daemon restarts in the sense of replaying — the file write either landed or it didn't.
|
|
184
216
|
|
|
185
|
-
If your integration needs cross-restart durability
|
|
217
|
+
If your integration needs server-side cross-restart durability beyond what `session/load` covers (e.g. server-managed retry queues), you still need application-level state recovery. Don't hold long-running, restart-sensitive state inside the daemon's session.
|
|
186
218
|
|
|
187
219
|
## Stage 1.5+ runtime guarantees
|
|
188
220
|
|
|
@@ -190,22 +222,21 @@ Stage 1's contract is sized for prototyping. Per [#3889 chiga0 downstream-consum
|
|
|
190
222
|
|
|
191
223
|
**Blockers for serious downstream use:**
|
|
192
224
|
|
|
193
|
-
1.
|
|
194
|
-
2.
|
|
195
|
-
3. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity.
|
|
225
|
+
1. **`loadSession` / `unstable_resumeSession` over HTTP** — without this, no integration can survive a child crash or daemon restart, and any orchestrator coordinating the daemon can't recover state either.
|
|
226
|
+
2. **Persistent client identity (pair tokens + per-client revocation)** — Stage 1 uses one shared bearer; a leaked token revokes everyone, and `originatorClientId` is client-self-declared rather than daemon-stamped from authenticated identity.
|
|
196
227
|
|
|
197
228
|
**Reliability baseline:**
|
|
198
229
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
230
|
+
3. **Client-initiated heartbeat path** — distinguish "agent thinking" from "daemon dead" without waiting for the 15s server heartbeat.
|
|
231
|
+
4. **`permission_already_resolved` event** when a vote loses the first-responder race — currently UIs have to infer state from a `404`.
|
|
232
|
+
5. **Larger / per-session-configurable replay ring** — default 4000 covers short drops; mobile / chatty-turn workloads need 8000+ or per-session config.
|
|
233
|
+
6. **`slow_client_warning` event before `client_evicted`** — soft backpressure so well-behaved slow clients can self-throttle (trim render depth, drop chunks) before being terminated.
|
|
203
234
|
|
|
204
235
|
**Integration ergonomics:**
|
|
205
236
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
237
|
+
7. **`POST /session/:id/_meta` for IM-style context** — per-session key-value attached to subsequent prompts (chat id, sender, thread id) replaces the per-channel improvisation.
|
|
238
|
+
8. **`/capabilities` actual feature negotiation** — `protocol_versions: { acp: '0.14.x', daemon_envelope: 1 }` so clients can detect drift instead of falling through to "unknown frame, ignore".
|
|
239
|
+
9. **First-class durability documentation** (this section) — already shipped above.
|
|
209
240
|
|
|
210
241
|
The full convergence roadmap is tracked on [#3803](https://github.com/QwenLM/qwen-code/issues/3803).
|
|
211
242
|
|
|
@@ -24,11 +24,11 @@ This document lists the available keyboard shortcuts in Qwen Code.
|
|
|
24
24
|
| `!` | Toggle shell mode when the input is empty. |
|
|
25
25
|
| `?` | Toggle keyboard shortcuts display when the input is empty. |
|
|
26
26
|
| `\` (at end of line) + `Enter` | Insert a newline. |
|
|
27
|
-
| `Down Arrow` |
|
|
27
|
+
| `Down Arrow` | Row down, then snap to end, then history next. |
|
|
28
28
|
| `Enter` | Submit the current prompt. |
|
|
29
29
|
| `Meta+Delete` / `Ctrl+Delete` | Delete the word to the right of the cursor. |
|
|
30
30
|
| `Tab` | Autocomplete the current suggestion if one exists. |
|
|
31
|
-
| `Up Arrow` |
|
|
31
|
+
| `Up Arrow` | Row up, then snap to start, then history prev. |
|
|
32
32
|
| `Ctrl+A` / `Home` | Move the cursor to the beginning of the line. |
|
|
33
33
|
| `Ctrl+B` / `Left Arrow` | Move the cursor one character to the left. |
|
|
34
34
|
| `Ctrl+C` | Clear the input prompt |
|
|
@@ -39,8 +39,8 @@ This document lists the available keyboard shortcuts in Qwen Code.
|
|
|
39
39
|
| `Ctrl+H` / `Backspace` | Delete the character to the left of the cursor. |
|
|
40
40
|
| `Ctrl+K` | Delete from the cursor to the end of the line. |
|
|
41
41
|
| `Ctrl+Left Arrow` / `Meta+Left Arrow` / `Meta+B` | Move the cursor one word to the left. |
|
|
42
|
-
| `Ctrl+N` |
|
|
43
|
-
| `Ctrl+P` |
|
|
42
|
+
| `Ctrl+N` | Row down, then snap to end, then history next. |
|
|
43
|
+
| `Ctrl+P` | Row up, then snap to start, then history prev. |
|
|
44
44
|
| `Ctrl+R` | Reverse search through input/shell history. |
|
|
45
45
|
| `Ctrl+Y` | Retry the last failed request. |
|
|
46
46
|
| `Ctrl+Right Arrow` / `Meta+Right Arrow` / `Meta+F` | Move the cursor one word to the right. |
|
|
@@ -59,13 +59,13 @@ This document lists the available keyboard shortcuts in Qwen Code.
|
|
|
59
59
|
|
|
60
60
|
## Radio Button Select
|
|
61
61
|
|
|
62
|
-
| Shortcut
|
|
63
|
-
|
|
|
64
|
-
| `Down Arrow` / `j` | Move selection down. |
|
|
65
|
-
| `Enter`
|
|
66
|
-
| `Up Arrow` / `k` | Move selection up. |
|
|
67
|
-
| `1-9`
|
|
68
|
-
| (multi-digit)
|
|
62
|
+
| Shortcut | Description |
|
|
63
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| `Down Arrow` / `j` / `Ctrl+N` | Move selection down. |
|
|
65
|
+
| `Enter` | Confirm selection. |
|
|
66
|
+
| `Up Arrow` / `k` / `Ctrl+P` | Move selection up. |
|
|
67
|
+
| `1-9` | Select an item by its number. |
|
|
68
|
+
| (multi-digit) | For items with numbers greater than 9, press the digits in quick succession to select the corresponding item. |
|
|
69
69
|
|
|
70
70
|
## IDE Integration
|
|
71
71
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stuck
|
|
3
|
+
description: Diagnose frozen, stuck, or slow Qwen Code sessions on this machine. Scans for problematic processes, high CPU/memory usage, hung subprocesses, and debug logs. Use /stuck or /stuck <PID> to focus on a specific process.
|
|
4
|
+
argument-hint: '[PID or symptom]'
|
|
5
|
+
allowedTools:
|
|
6
|
+
- run_shell_command
|
|
7
|
+
- read_file
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /stuck — diagnose frozen/slow Qwen Code sessions
|
|
11
|
+
|
|
12
|
+
The user thinks another Qwen Code session on this machine is frozen, stuck, or very slow. Investigate and present a diagnostic report.
|
|
13
|
+
|
|
14
|
+
## What to look for
|
|
15
|
+
|
|
16
|
+
Scan for other Qwen Code processes (excluding the current one — exclude the PID you see running this prompt). Since Qwen Code is a Node.js CLI (`#!/usr/bin/env node`), the process name (`comm` column) is always `node` (or `bun` if run with Bun). Identify Qwen Code sessions by looking at the `command` column for a script path inside a directory whose name starts with `qwen-code` (matches `qwen-code/`, `qwen-code-dev/`, worktree clones, etc.) — anchored to the start of the path or after `/` so unrelated names like `analyze-qwen-code/` don't false-match — or a bin invocation ending in `/qwen` (the global symlink). Avoid loose `qwen-code` substring matching: it false-positives on plugin brokers that merely pass a qwen-code path as `--cwd`.
|
|
17
|
+
|
|
18
|
+
Signs of a stuck session:
|
|
19
|
+
|
|
20
|
+
- **High CPU (>=90%) sustained** — likely an infinite loop. Sample twice, 1-2s apart, to confirm it's not a transient spike.
|
|
21
|
+
- **Process state `D` / `U` (uninterruptible sleep)** — often an I/O hang. Linux uses `D`, macOS/BSD uses `U`. The `state` column in `ps` output; first character matters (ignore modifiers like `+`, `s`, `<`).
|
|
22
|
+
- **Process state `T` (stopped)** — user probably hit Ctrl+Z by accident.
|
|
23
|
+
- **Process state `Z` (zombie)** — parent isn't reaping.
|
|
24
|
+
- **Very high RSS (>=4GB)** — possible memory leak making the session sluggish.
|
|
25
|
+
- **State `S` with low CPU** — the most common hang signature: a hung HTTPS request to the model API. Not a process-level red flag on its own, but combined with the user reporting "stuck", treat it as a strong signal to run the network check in step 3.
|
|
26
|
+
- **Stuck child process** — a hung `git`, `node`, or shell subprocess can freeze the parent. Check `pgrep -P <pid>` (then `ps -p` for state — see step 3) for each session.
|
|
27
|
+
|
|
28
|
+
## Argument validation
|
|
29
|
+
|
|
30
|
+
If the user gave an argument, treat it as a PID **only if it consists entirely of digits 0-9**. Anything else — letters, whitespace, punctuation — fails the check, in which case treat it as a free-text symptom description (guidance for the report only, never substituted into shell commands). The strict digit-only whitelist is safer than enumerating shell metacharacters.
|
|
31
|
+
|
|
32
|
+
## Investigation steps
|
|
33
|
+
|
|
34
|
+
**Preamble — resolve the runtime base directory.** Required for both paths below (sidecar enumeration in step 1, debug log lookup in step 3, and the PID fast path). The base directory is taken from (in priority order): `QWEN_RUNTIME_DIR` env var, the `advanced.runtimeOutputDir` setting, `QWEN_HOME` env var, and finally `~/.qwen`.
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
RUNTIME_DIR="${QWEN_RUNTIME_DIR:-}"
|
|
38
|
+
[ -z "$RUNTIME_DIR" ] && command -v jq >/dev/null && RUNTIME_DIR=$(jq -r '.advanced.runtimeOutputDir // empty' "${QWEN_HOME:-$HOME/.qwen}/settings.json" 2>/dev/null)
|
|
39
|
+
# `advanced.runtimeOutputDir` may be `~/...` or relative; mirror Storage.resolvePath() before using in globs
|
|
40
|
+
[ -n "$RUNTIME_DIR" ] && RUNTIME_DIR="${RUNTIME_DIR/#\~/$HOME}"
|
|
41
|
+
[ -n "$RUNTIME_DIR" ] && case "$RUNTIME_DIR" in /*) ;; *) RUNTIME_DIR="$(cd "$RUNTIME_DIR" 2>/dev/null && pwd)" || RUNTIME_DIR="" ;; esac
|
|
42
|
+
RUNTIME_DIR="${RUNTIME_DIR:-${QWEN_HOME:-$HOME/.qwen}}"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
(If `jq` isn't installed, the settings layer is silently skipped — the env-var / default fallback covers the common case.)
|
|
46
|
+
|
|
47
|
+
**Fast path for targeted diagnosis** — if a digit-only PID argument was given, skip step 1 enumeration. Validate that the PID is a live current-user Qwen Code process before dumping any details:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
kill -0 <pid> 2>/dev/null || { echo "PID <pid> is dead, or owned by another user"; exit 0; }
|
|
51
|
+
ps -p <pid> -o command= -ww 2>/dev/null | grep -qE '((^|/)qwen-code[^ /]*/[^ ]*\.(js|ts|mjs|cjs)( |$)|/qwen( |$))' || { echo "PID <pid> is yours but is not a Qwen Code process — refusing to dump details"; exit 0; }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If either guard prints, stop the diagnostic and surface the message verbatim. Otherwise, gather stats and the sidecar mapping, then jump to step 3:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
ps -p <pid> -o pid=,pcpu=,rss=,etime=,state=,comm=,command= -ww
|
|
58
|
+
grep -El '"pid"[[:space:]]*:[[:space:]]*<pid>\b' "$RUNTIME_DIR"/projects/*/chats/*.runtime.json 2>/dev/null
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Note: as in step 2, the `command=` column may include credentials passed as CLI args (e.g., `--openai-api-key=sk-…`). Redact such values to `***` before quoting them in the report.
|
|
62
|
+
|
|
63
|
+
`-E` is required so `\b` is interpreted as word boundary (BSD `grep` without `-E` treats `\b` as a backspace character, silently returning nothing on macOS). The `-l` flag returns the matching sidecar file path; the basename (stripped of `.runtime.json`) is the session ID for step 3's debug log read. If multiple sidecars match (rare — happens only after PID reuse leaves a stale file), prefer the most recently modified one: `ls -t <matches> | head -n 1`.
|
|
64
|
+
|
|
65
|
+
Otherwise (no arg, or symptom-only arg), run the general path below:
|
|
66
|
+
|
|
67
|
+
1. **Enumerate live sessions via the runtime sidecar** (preferred, reliable):
|
|
68
|
+
|
|
69
|
+
Qwen Code writes a `runtime.json` sidecar for each interactive session at `"$RUNTIME_DIR"/projects/<sanitized-cwd>/chats/<sessionId>.runtime.json`. Each file contains `{schema_version, pid, session_id, work_dir, hostname, started_at, qwen_version}` — the authoritative source of `(pid, session_id, work_dir)` mappings.
|
|
70
|
+
|
|
71
|
+
Filter to live `(pid, sidecar-path)` pairs in one shot. Use Node (guaranteed available — qwen-code requires it) instead of `jq` (often missing on default macOS / minimal Linux) so this path doesn't silently degrade:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
node -e 'const fs=require("fs"); for (const f of process.argv.slice(1)) { try { const p=JSON.parse(fs.readFileSync(f,"utf8")).pid; if (p) { try { process.kill(p,0); console.log(p+" "+f); } catch {} } } catch {} }' "$RUNTIME_DIR"/projects/*/chats/*.runtime.json 2>/dev/null
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
PID reuse is rare but possible — when you cross-reference with `ps` in step 2, skip pairs whose live PID's command line no longer looks like a Qwen Code process.
|
|
78
|
+
|
|
79
|
+
**If the command emits nothing** (no sidecars, or no live PIDs), fall through to step 2 — `ps` is the working fallback.
|
|
80
|
+
|
|
81
|
+
2. **List Qwen Code processes via `ps`** (macOS/Linux) — used to enrich each live session with CPU/RSS/state/uptime, and to catch sessions that may have started before the sidecar feature existed:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
ps -xo pid=,pcpu=,rss=,etime=,state=,comm=,command= -u "$(id -u)" -ww | grep -E '((^|/)qwen-code[^ /]*/[^ ]*\.(js|ts|mjs|cjs)( |$)|/qwen( |$))' | grep -v grep
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`-u "$(id -u)"` restricts the scan to the current user — on shared hosts this avoids exposing other users' Qwen process paths/arguments into the chat. `-ww` disables column truncation so long "qwen" paths aren't cut off. The `comm` column will be `node` or `bun`, not `qwen`; filter to rows where the `command` column contains a qwen path (e.g., `qwen-code/dist/cli.js`, or a bin symlink ending in `/qwen`). Cross-reference with the PIDs from step 1.
|
|
88
|
+
|
|
89
|
+
Note: `ps` reports `rss` in **kilobytes** on both macOS and Linux. To report in MB, divide by 1024; to report in GB, divide by 1048576. The 4GB threshold is `4194304` KB — compare the raw `rss` value against that, or compare the GB value against 4. Do not divide once and then compare against 4; that would flag every process >4MB as "very high RSS".
|
|
90
|
+
|
|
91
|
+
Note: full command lines may contain credentials passed as CLI args (e.g., `--openai-api-key=sk-…`). Redact such values to `***` before quoting them in the report.
|
|
92
|
+
|
|
93
|
+
3. **For anything suspicious**, gather more context. If the process state alone explains the problem (`T` = accidentally stopped, `Z` = parent not reaping), skip directly to the report — child / log / stack inspection adds nothing. Otherwise:
|
|
94
|
+
- Child processes (with state, so a hung `git` / `node` shows up): `CHILDREN=$(pgrep -P <pid> | tr '\n' ',' | sed 's/,$//'); [ -n "$CHILDREN" ] && ps -p "$CHILDREN" -o pid=,ppid=,pcpu=,state=,etime=,command= -ww`. Single `ps` call (avoids forking one per child) and `-ww` so long child command lines aren't truncated.
|
|
95
|
+
- If high CPU: sample again after 1-2s to confirm it's sustained
|
|
96
|
+
- **Network hang** — if CPU is low and state is `S` despite the user reporting "stuck", the most likely cause is a hung HTTPS request to the model API. macOS: `lsof -nP -i -p <pid> 2>/dev/null | head -20` (the `-nP` flags skip reverse-DNS and port lookups, which can themselves hang). If `lsof` itself feels slow, prefix with `timeout 10` (or `gtimeout 10` on macOS with Homebrew coreutils). Linux: `ss -tnp 2>/dev/null | grep "pid=<pid>,"`. Note that `ss -tnp`'s `-p` requires root or `CAP_NET_ADMIN` — without it, the PID column shows `-` and the grep returns empty. If you see no matches but `ss -t 2>/dev/null` does show ESTABLISHED sockets, fall back to `lsof -nP -i -p <pid>` rather than reporting "no connections". A long-lived `ESTABLISHED` connection to a model host (dashscope, openai, anthropic, etc.) with no recent traffic is the smoking gun.
|
|
97
|
+
- **Debug log** — start with `"$RUNTIME_DIR"/debug/latest` (symlink to the most recent session); if it matches the suspicious PID's session, that's usually the right one. Otherwise infer the session ID from the sidecar and read `"$RUNTIME_DIR"/debug/<session-id>.txt`. Bound the read with `tail -n 200 <path>` — debug logs can be GB-sized. The last few hundred lines typically show what the session was doing before hanging. Debug logs may contain prompts, file contents, or tokens from other sessions — paste only lines relevant to the hang, and never quote secrets/API keys you happen to see.
|
|
98
|
+
|
|
99
|
+
4. **Consider a stack dump** for a truly frozen process (advanced, optional):
|
|
100
|
+
- macOS: `sample <pid> 3` gives a 3-second native stack sample. If `sample` itself seems to hang (the target's Mach task port may be wedged on a kernel-level freeze), wrap it: `timeout 15 sample <pid> 3` (or `gtimeout 15 ...` on Homebrew coreutils). Stack frames may include function arguments containing API keys or tokens held in memory — redact such values to `***` before including the dump in the report.
|
|
101
|
+
- Linux: `cat /proc/<pid>/stack` for kernel stack (read-only, no `ptrace` permissions needed). Avoid `strace -p` for this purpose: it requires `CAP_SYS_PTRACE` (often denied under `kernel.yama.ptrace_scope=1`), and `strace -c` blocks until the target exits — it would hang on the very kind of stuck process you are diagnosing.
|
|
102
|
+
- This is big — only grab it if the process is clearly hung and you want to know _why_
|
|
103
|
+
|
|
104
|
+
## Report
|
|
105
|
+
|
|
106
|
+
Present a structured diagnostic report directly to the user with these sections:
|
|
107
|
+
|
|
108
|
+
**For each stuck/slow session found:**
|
|
109
|
+
|
|
110
|
+
- PID, CPU%, RSS (in MB), process state, uptime, full command line
|
|
111
|
+
- Child processes and their states
|
|
112
|
+
- Your diagnosis of what's likely wrong
|
|
113
|
+
- Relevant debug log tail if you captured it
|
|
114
|
+
- Stack dump output if you captured it
|
|
115
|
+
- Suggested next step for the user to decide (e.g., "user may consider `kill <pid>` if the session is unresponsive", "likely waiting on I/O — check disk", "accidentally stopped — user can resume with `kill -CONT <pid>`"). Do not execute these actions yourself — present them as options for the user.
|
|
116
|
+
|
|
117
|
+
**If every session looks healthy**, tell the user directly — no diagnostic dump needed. Mention how many sessions you checked and that none showed signs of being stuck.
|
|
118
|
+
|
|
119
|
+
**If no sessions are found at all** (zero sidecars and zero matching `ps` rows), say so explicitly: which `RUNTIME_DIR` you searched and that `ps` returned no qwen-related processes for the current user. Suggest the session may have already exited.
|
|
120
|
+
|
|
121
|
+
## Notes
|
|
122
|
+
|
|
123
|
+
- Don't kill or signal any processes — this is diagnostic only.
|
|
124
|
+
- If the user gave an argument (e.g., a specific PID or symptom), focus there first.
|
|
@@ -7,19 +7,19 @@ import {
|
|
|
7
7
|
hasRebuiltToolRegistry,
|
|
8
8
|
rebuildToolRegistryOnOverride,
|
|
9
9
|
resolveSubagentApprovalMode
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AJSOD5IR.js";
|
|
11
11
|
import "./chunk-5P5XGNYH.js";
|
|
12
12
|
import "./chunk-K5PGHDBN.js";
|
|
13
13
|
import "./chunk-O4PICXES.js";
|
|
14
14
|
import "./chunk-TW522KN6.js";
|
|
15
15
|
import "./chunk-MLZQVCF3.js";
|
|
16
16
|
import "./chunk-JMZQICAL.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-5QQ5FGTU.js";
|
|
18
18
|
import "./chunk-B7ZL7HUA.js";
|
|
19
19
|
import "./chunk-77WXWU44.js";
|
|
20
20
|
import "./chunk-OCC4MZRS.js";
|
|
21
21
|
import "./chunk-CAWKL3UC.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-XLQ4E5PS.js";
|
|
23
23
|
import "./chunk-SYCJMSIJ.js";
|
|
24
24
|
import "./chunk-UWCTAVOD.js";
|
|
25
25
|
import "./chunk-OFEVLU4C.js";
|
|
@@ -108,6 +108,32 @@ var ca_default = {
|
|
|
108
108
|
"Generate a one-line session recap now": "Generar ara un resum de la sessi\xF3 en una sola l\xEDnia",
|
|
109
109
|
"Rename the current conversation. --auto lets the fast model pick a title.": "Canviar el nom de la conversa actual. --auto permet que el model r\xE0pid tri\xEF un t\xEDtol.",
|
|
110
110
|
"Rewind conversation to a previous turn": "Rebobinar la conversa fins a un torn anterior",
|
|
111
|
+
"Rewind Conversation": "Rebobinar la conversa",
|
|
112
|
+
"No user turns to rewind to.": "No hi ha torns d'usuari per rebobinar.",
|
|
113
|
+
"Rewind to: ": "Rebobinar a: ",
|
|
114
|
+
"Restore code and conversation": "Restaura el codi i la conversa",
|
|
115
|
+
"Restore conversation only": "Restaura nom\xE9s la conversa",
|
|
116
|
+
"Restore code only": "Restaura nom\xE9s el codi",
|
|
117
|
+
"Never mind": "Tant \xE9s",
|
|
118
|
+
"Computing file changes...": "S'estan calculant els canvis als fitxers...",
|
|
119
|
+
"Restoring...": "S'est\xE0 restaurant...",
|
|
120
|
+
"Restored {{count}} file(s).": "S'han restaurat {{count}} fitxer(s).",
|
|
121
|
+
"Failed to restore files: {{error}}": "Error en restaurar els fitxers: {{error}}",
|
|
122
|
+
"Rewind failed: {{error}}": "Error en retrocedir: {{error}}",
|
|
123
|
+
"Cannot rewind conversation: no active model client.": "No es pot retrocedir la conversa: cap client de model actiu.",
|
|
124
|
+
"Code restored, but conversation could not be rewound (no active client).": "Codi restaurat, per\xF2 la conversa no s\u2019ha pogut retrocedir (cap client actiu).",
|
|
125
|
+
"Conversation rewound. Edit your prompt and press Enter to continue.": "Conversa retrocedida. Edita la teva indicaci\xF3 i prem Retorn per continuar.",
|
|
126
|
+
"Rewinding does not affect files edited manually or via shell commands.": "El retroc\xE9s no afecta els fitxers editats manualment o mitjan\xE7ant comandes de shell.",
|
|
127
|
+
"Cannot rewind to a turn that was compressed. Try a more recent turn.": "No es pot retrocedir a un torn que ha estat comprimit. Prova amb un torn m\xE9s recent.",
|
|
128
|
+
"File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).": "La restauraci\xF3 de fitxers no est\xE0 disponible per a aquest torn (no s\u2019han capturat canvis, o aquest torn \xE9s anterior a la sessi\xF3 actual).",
|
|
129
|
+
"(+{{insertions}} -{{deletions}} in {{count}} file)": "(+{{insertions}} -{{deletions}} en {{count}} fitxer)",
|
|
130
|
+
"(+{{insertions}} -{{deletions}} in {{count}} files)": "(+{{insertions}} -{{deletions}} en {{count}} fitxers)",
|
|
131
|
+
"Failed to restore {{count}} file(s): {{files}}": "Error en restaurar {{count}} fitxer(s): {{files}}",
|
|
132
|
+
"Cannot restore files: this turn was created before file checkpointing was enabled.": "No es poden restaurar els fitxers: aquest torn es va crear abans que el punt de control de fitxers estigu\xE9s habilitat.",
|
|
133
|
+
"No files needed to be restored.": "Cap fitxer necessitava restauraci\xF3.",
|
|
134
|
+
"\u2191\u2193 to navigate \xB7 Enter to select \xB7 Esc to go back": "\u2191\u2193 per navegar \xB7 Enter per seleccionar \xB7 Esc per tornar",
|
|
135
|
+
"\u2191\u2193 to navigate \xB7 Enter to select \xB7 Esc to cancel": "\u2191\u2193 per navegar \xB7 Enter per seleccionar \xB7 Esc per cancel\xB7lar",
|
|
136
|
+
"Enter/Y to confirm \xB7 Esc/N to go back": "Enter/Y per confirmar \xB7 Esc/N per tornar",
|
|
111
137
|
"change the theme": "canviar el tema",
|
|
112
138
|
"Select Theme": "Seleccionar tema",
|
|
113
139
|
Preview: "Previsualitzaci\xF3",
|