mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-09-12 03:57:07 +00:00
* feat(qwen-live): interactive init command with agent detection
`qwen-live init` walks a new user through setup:
- Scans PATH for supported coding agents (qodercli, qwen, gemini,
claude, codex) via `--version` probe, resolving each to an absolute
path. Native agents (qodercli/qwen/gemini) use their resolved binary
directly; adapter-based agents (claude/codex) configure npx to run
the ACP adapter, passing the detected binary via env (CODEX_PATH).
- Interactive prompts (prompts library) let the user pick a default
backend, add additional backends, enter their DashScope API key
(with env-var reuse option), and set a working directory.
- macOS: checks the Live Host app via LiveHostInstaller.refresh();
offers to install if missing. Non-macOS: informs the user the Host
is required.
- Writes ~/.qwen-live/config.json atomically (tmp + rename) with
user-only permissions (0o600).
Subcommand dispatch in index.ts: `qwen-live init` runs the wizard,
everything else starts the daemon.
* feat(qwen-live,live-host): protocol v7 playback receipts
The injector's playback window no longer guesses from byte counts;
the Host app sends real playback_started/completed events.
Protocol:
- LIVE_HOST_PROTOCOL_VERSION 6 → 7 (types.ts both copies +
live-host shared/protocol.ts)
- New Host → Daemon messages: host.playback_started, host.playback_completed
(both carry epoch for call-scoping)
- CLI coordinator copy accepts the new messages (v7 Host connecting to
built-in serve is not rejected as invalid)
- FakeHost in e2e harness bumped to v7
Daemon side (packages/qwen-live):
- Injector: replaces playbackDeadline (byte ÷ 48kB/s estimation) with
playbackInProgress boolean + playbackCompletedAt timestamp.
notePlaybackStarted/notePlaybackCompleted replace noteOutputAudio.
windowClosedForMs returns -1 while playback is active, waits
completedAt + quietGapMs after completion, returns 0 if no playback
or cleared.
- v6 forward compatibility: onOutputAudioDelta calls notePlaybackStarted
as a fallback (v6 Host never sends receipts; v7 Host does). The
fallback preserves the existing "speech after audio triggers
clearOutput" behavior without the byte-estimation wait.
- live-session: onPlaybackStarted/onPlaybackCompleted wired from
coordinator handlers to injector signals
- Coordinator: parseHostMessage + handleTextFrame dispatch the new
messages; LiveCallHandlers gains optional onPlaybackStarted/
onPlaybackCompleted; epoch-scoped (stale receipts ignored)
Host app (packages/live-host):
- audio-engine.ts: constructor gains onPlaybackStarted/
onPlaybackCompleted callbacks; play() fires started on 0→1 source
transition; source.onended fires completed on 1→0 transition
(generation-guarded so clearOutput's stop() doesn't false-fire)
- preload/index.ts: callbacks → IPC live:audio:playback-started/
playback-completed with the current epoch; play IPC payload changes
from bare Uint8Array to { audio, epoch }
- main/index.ts: IPC handlers validate epoch === daemon.getEpoch(),
call daemon.sendPlaybackStarted/sendPlaybackCompleted
- daemon-connection.ts: sendPlaybackStarted/sendPlaybackCompleted
via sendControl
Tests: injector tests rewritten for receipt-based timing (started
holds, completed + gap delivers); e2e discovery assertion bumped to v7.
* test(qwen-live): v7 parity test and playback receipt coverage
- live-host parity test: version assertion bumped 6→7, 13/13 pass
- injector tests rewritten: playback_started holds window,
playback_completed + quiet gap delivers, clearOutput reopens
immediately, speech-started returns playbackInProgress
- e2e: FakeHost protocol version v7, discovery record assertion v7
* docs(qwen-live): rewrite README with quick start, init wizard, v7, and backend table
* fix(live-host): prefix unused IPC event parameters
* fix(live-host): gate playback IPC handlers with isTrustedSender
The playback-started/completed IPC channels skipped the sender
validation every sibling channel applies — an untrusted renderer
could forge playback receipts. Added isTrustedSender(event) as the
first guard, matching the pattern in live:set-output-muted etc.
* fix(qwen-live): wire playback receipts to injector + publish qwen-live with Host release
Two fixes in one commit:
1. Playback receipt wiring (qqqys's blocking review):
- daemon.ts setHandlers now passes onPlaybackStarted/
onPlaybackCompleted to the session
- LiveSession gains notePlaybackStarted/notePlaybackCompleted
methods that resolve the active context by epoch and forward
to the injector
- The per-delta notePlaybackStarted fallback in onOutputAudioDelta
is removed — it latched playbackInProgress closed with no matching
completion, blocking all queued injections until the user spoke
- v7 Host receipts now flow end-to-end: Host audio engine →
IPC → daemon-connection → WS frame → coordinator → session →
injector
- Test updated to call session.notePlaybackStarted directly
(matching the production coordinator→session path)
2. qwen-live npm publish in live-host-release.yml:
- Added checkout + install + build + npm publish steps to the
Host release publish job
- Version aligned with the Host release version via npm version
- Published as @qwen-code/qwen-live with --provenance
- Tag: "preview" for prereleases, "latest" for stable
- Skips if the version is already published
* fix(live-host-release): omit --provenance on first npm publish
@qwen-code/qwen-live does not exist on npm yet; provenance requires
an existing package. The workflow now checks if the package exists
and omits --provenance on the first publish, adds it on subsequent
ones.
* fix(live-host-release): use single quotes in NPM_TAG expression
GitHub Actions expressions require single quotes for string literals;
double quotes cause actionlint to fail.
---------
Co-authored-by: Claude <noreply@anthropic.com>
148 lines
3.6 KiB
Text
148 lines
3.6 KiB
Text
# API keys and secrets
|
|
.env
|
|
.env~
|
|
|
|
# gemini-cli settings
|
|
# We want to keep the .gemini in the root of the repo and ignore any .gemini
|
|
# in subdirectories. In our root .gemini we want to allow for version control
|
|
# for subcommands.
|
|
**/.gemini/
|
|
!/.gemini/
|
|
.gemini/*
|
|
!.gemini/config.yaml
|
|
!.gemini/commands/
|
|
|
|
# Note: .qwen-clipboard/ is NOT in gitignore so Gemini can access pasted images
|
|
|
|
# Dependency directory
|
|
node_modules
|
|
bower_components
|
|
|
|
# Editors
|
|
.idea
|
|
*.iml
|
|
.cursor
|
|
.qoder
|
|
.claude
|
|
.codex
|
|
.worktrees/
|
|
.atlarix/
|
|
|
|
# Qwen Code Configs
|
|
.qwen/*
|
|
!.qwen/commands/
|
|
!.qwen/commands/**
|
|
!.qwen/skills/
|
|
!.qwen/skills/**
|
|
# Re-ignore auto-generated skills (created by the managed-skill-extractor
|
|
# agent with the mandatory `auto-skill-` directory prefix). Git's last-rule-
|
|
# wins semantics keep hand-authored project skills tracked while excluding
|
|
# these transient, session-specific directories. The `auto-skill-` prefix is
|
|
# reserved for auto-generated skills — do not hand-author a project skill with
|
|
# this prefix, or its directory will be ignored here.
|
|
.qwen/skills/auto-skill-*/
|
|
# Re-ignore learned skills (created by the /learn command with the mandatory
|
|
# `learned-skill-` directory prefix). Same rationale as auto-skill-*/.
|
|
.qwen/skills/learned-skill-*/
|
|
# Staging area for auto-skills awaiting confirmation (memory.autoSkillConfirm).
|
|
# Already covered by `.qwen/*` above since it's never re-included, but listed
|
|
# explicitly alongside auto-skill-*/ so the intent is obvious.
|
|
.qwen/pending-skills/
|
|
!.qwen/agents/
|
|
!.qwen/agents/**
|
|
# Team memory (memory.enableTeamMemory) is shared with collaborators THROUGH
|
|
# git, so it must be tracked despite the `.qwen/*` ignore above.
|
|
!.qwen/team-memory/
|
|
!.qwen/team-memory/**
|
|
# Repository review context is shared review metadata for `qwen review
|
|
# repo-context`, not session output, so it must be tracked too.
|
|
!.qwen/review-context.json
|
|
|
|
# Developer-local session identifier (auto-generated by qwen serve).
|
|
.qwen-session
|
|
|
|
# OS metadata
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# TypeScript build info files
|
|
*.tsbuildinfo
|
|
|
|
# Ignore built ts files
|
|
dist
|
|
packages/audio-capture/build/
|
|
packages/audio-capture/prebuilds/
|
|
|
|
# Docker folder to help skip auth refreshes
|
|
.docker
|
|
|
|
bundle
|
|
|
|
# Test report files
|
|
junit.xml
|
|
packages/*/coverage/
|
|
packages/web-shell/client/e2e/playwright-report/
|
|
packages/web-shell/client/e2e/test-results/
|
|
packages/web-shell/client/e2e/visuals/output/
|
|
packages/web-shell/client/e2e/visuals/.playwright/
|
|
|
|
# PR body draft
|
|
pr_body.md
|
|
|
|
# Generated files
|
|
packages/cli/src/generated/
|
|
packages/core/src/generated/
|
|
packages/web-templates/src/generated/
|
|
.integration-tests/
|
|
packages/vscode-ide-companion/*.vsix
|
|
|
|
logs/
|
|
.repro-runs/
|
|
# GHA credentials
|
|
gha-creds-*.json
|
|
|
|
# Log files
|
|
patch_output.log
|
|
|
|
# docs build
|
|
docs-site/.next
|
|
# content is a symlink to ../docs
|
|
docs-site/content
|
|
|
|
# python cache
|
|
__pycache__/
|
|
|
|
integration-tests/concurrent-runner/output/
|
|
integration-tests/concurrent-runner/task-*
|
|
|
|
integration-tests/terminal-capture/scenarios/screenshots/
|
|
|
|
# Test-built worker artifact (fzfWorkerHandle.test.ts builds this on-the-fly)
|
|
packages/core/src/utils/filesearch/fzfWorker.js
|
|
|
|
# storybook
|
|
*storybook.log
|
|
storybook-static
|
|
|
|
# test
|
|
coverage/
|
|
|
|
# Dev symlink: qc-helper bundled skill docs (created by scripts/dev.js)
|
|
packages/core/src/skills/bundled/qc-helper/docs
|
|
tmp/
|
|
.worktrees/
|
|
|
|
# code graph skills
|
|
.venv
|
|
.codegraph
|
|
.qwen/computer-use/installed.json
|
|
# Auto-generated computer-use marker can also appear under nested packages.
|
|
**/.qwen/computer-use/
|
|
.playwright-mcp/
|
|
|
|
# Tool state written to the repo root when $HOME is unset (e.g. gh CLI)
|
|
.local/
|
|
|
|
# Brand build workspaces (created by the desktop-brand-builder skill)
|
|
brand-builds/
|
|
workspace/
|