mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-26 09:04:37 +00:00
* fix(serve): keep skill slash commands available after the ACP child is reaped `GET /workspace/skills` is answered exclusively by the ACP child — the daemon has no local SkillManager. `requestWorkspaceStatus` only checks for an already-live channel (`liveChannelInfo()`, never `ensureChannel()`), so when no child is running it returns the idle placeholder (`initialized: false`, empty `skills`). That is the norm before the first session, and — crucially — again after the child is reaped on session close, which happens immediately by default (`--channel-idle-timeout-ms` defaults to 0 = immediate kill). Unlike `/workspace/providers`, skills have no daemon-local status provider to fall back on. So once a user has created and closed a session, every subsequent pre-first-prompt `/workspace/skills` query returns empty, the Web Shell's slash-command list falls back to the hardcoded built-ins (which omit skills), and `/rev` stops autocompleting `/review`. Retain the last skills status a live child produced and replay it while no channel is live, so skill-backed slash commands keep autocompleting; the next live query refreshes the cache. `initialized` cleanly separates a real child answer (always `true`) from the idle placeholder (always `false`). Completes #6153, which wired the Web Shell to fetch `/workspace/skills` in the deferred-connect path but could not surface skills the daemon was unable to answer without a live child. * fix(serve): enumerate workspace skills locally when the ACP child is unavailable The cache from the previous commit keeps the last child answer alive across a reap, but it never warms when the child never answers at all — most visibly under `npm run dev`, where the on-demand-transpiled child's `initialize` handshake routinely exceeds the 10s preheat budget, so preheat times out and no channel ever comes up. `/workspace/skills` then stays empty until the first prompt, dropping `/review` and every other skill from the Web Shell's pre-first-prompt autocomplete even though the skills exist on disk (typing `/review` in full still runs it, since submitting spawns a session — hence "not in the list, but usable"). Add a daemon-local skills provider that enumerates skills straight from the filesystem via SkillManager (a lightweight Config shim — no child, no MCP init), mirroring the existing daemon-local providers-status provider. The facade falls back to it only after both a live child answer and the cached last answer are unavailable, so the live child stays authoritative (and keeps extension-provided skills) while a never-preheated child still yields the on-disk skills — `/review` included. * fix(serve): fall back to cached/local skills when the child query throws mid-flight Addresses review feedback on #6169: the channel can die after `liveChannelInfo()` returns a valid channel but before the RPC completes, so `queryWorkspaceStatus` rejects. Previously that exception propagated even though the cache or the daemon-local provider could still answer. Wrap the query in try/catch (logging via writeStderrLine, matching getWorkspaceEnvStatus / getWorkspacePreflightStatus) and treat a mid-flight failure as "no live child", so the request degrades to the cached last answer or daemon-local enumeration instead of failing. * refactor(serve): address review feedback on daemon-local skills provider - Extract the SkillConfig → ServeWorkspaceSkillStatus mapping into a shared workspace-skills-mapping module used by both the ACP child's buildWorkspaceSkillsStatus and the daemon-local provider, so the two skill listings can't drift; cover it (including the disable-model-invocation branch) with a unit test. - Memoize the SkillManager per workspace so repeat queries reuse its in-memory cache instead of re-scanning every skill level on each call. - Honor the safe-mode env (isSafeModeEnv, as Config does) instead of hardcoding isSafeMode to false; keep bareMode off (the daemon never runs `--bare`). - Log daemon-local enumeration failures via writeStderrLine, matching the rest of the workspace-service error handling. * test(serve): cover daemon-local skills error path; guard the facade provider call - Test the previously-uncovered `buildWorkspaceSkillsStatus` catch branch: when enumeration fails it returns `{ initialized: false, skills: [], errors: [{ kind: 'skills', status: 'error', error }] }` and logs to stderr. Also cover the per-workspace SkillManager memoization. - Wrap the facade's `workspaceSkillsStatusProvider` call in try/catch so a throwing injected provider degrades to the idle placeholder instead of failing the request (matching getWorkspaceEnvStatus / getWorkspacePreflightStatus), with a facade test for the throw path. |
||
|---|---|---|
| .. | ||
| src | ||
| index.ts | ||
| package.json | ||
| test-setup.ts | ||
| tsconfig.json | ||
| vitest.config.ts | ||