Skip to content

feat(ai-vault): surface Qwen Code sessions in AI Vault - #11419

Open
pythonstrup wants to merge 5 commits into
stablyai:mainfrom
pythonstrup:feat/qwen-ai-vault-sessions
Open

pythonstrup wants to merge 5 commits into
stablyai:mainfrom
pythonstrup:feat/qwen-ai-vault-sessions

Conversation

@pythonstrup

@pythonstrup pythonstrup commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Qwen Code could be launched in Orca but its sessions never appeared in the AI Vault (Agent Session History). qwen-code was missing from AI_VAULT_AGENTS, so the scanner never discovered or parsed Qwen transcripts. This wires Qwen Code into the vault the same way other agents (e.g. Kimi, #5376) are wired.

Closes #11418

Changes

  • Register qwen-code in AI_VAULT_AGENTS / AI_VAULT_AGENT_LABELS and the resume invocation (qwen --resume <id>, verified against qwen --help).
  • Discover ~/.qwen/projects/<encoded-cwd>/chats/*.jsonl (new session-scanner-qwen-sources.ts), pruning subagents/ subtrees and ignoring non-chats files.
  • Add session-scanner-qwen-parser.ts: parses the Gemini-shaped append-only transcript, reads cwd/gitBranch from each record (no sidecar index needed, unlike Kimi), and drops thought: true parts so previews/titles show only real replies.
  • Enable incremental append parsing via the shared accumulator fold (createQwenSessionResumeState).
  • Route qwen-code in the agent parser and parse-cache; add a qwenProjectsDir scan option.
  • Tests: new parser unit tests (real Qwen 0.21.0 record shapes) plus all-agents scanner coverage; sandbox the new dir in shared fixtures.

Out of scope: live agent-status hooks for Qwen (a separate hook installer), matching the scope note in #11186.

Screenshots

The AI Vault now lists Qwen Code sessions with title, preview, model, and a working resume command. Verified locally by running the dev app against real ~/.qwen/projects data.

image

Testing

  • pnpm lint
  • pnpm typecheck
  • pnpm test
  • pnpm build (build:electron-vite desktop bundle)
  • Added high-quality tests that would catch regressions: parser unit tests + all-agents scanner coverage; sandboxed the new dir in shared fixtures so tests never read the real ~/.qwen.

pnpm test: 39957 passed. The only 2 failures are pre-existing and environmental in src/relay/agent-exec-handler.test.ts — the local shell exports GIT_CONFIG_COUNT=2 (credential keys), which the spawned-command env snapshot double-counts to 4. Unrelated to this change (no relay files touched) and passes in a clean CI environment.

AI Review Report

AI-assisted review explicitly checked:

  • Cross-platform (macOS/Linux/Windows): discovery uses path.join/homedir() and the shared sessionRootDirs (WSL-home aware); resume commands use the existing platform-aware quoting (quoteShellArg / cmd). No hardcoded path separators.
  • SSH/remote/local: follows the same local-host + WSL discovery pattern as grok/hermes/kimi; no new local-only assumptions beyond what those agents already make.
  • Agent/integration compatibility: Qwen logic is fully isolated behind its own parser/discovery and the qwen-code agent id; no changes to other agents' parsing or routing behavior.
  • Performance: incremental append parsing (only newly appended lines are re-read on subsequent scans), same as the other append-only JSONL agents; discovery prunes the subagents/ subtree up front.
  • UI quality: no component/CSS changes; the renderer picks up the new agent automatically via AI_VAULT_AGENTS (label + existing Qwen favicon). docs/STYLEGUIDE.md is not applicable to this backend change.

Security Audit

  • Input handling: transcript lines are parsed with the shared parseJsonObject/asRecord guards; malformed/partial JSON is skipped, never thrown. Text extraction reuses the existing normalization that strips injected <system-reminder>/hidden blocks from titles and previews.
  • Path handling: discovery roots derive from homedir()/path.join; the chats/subagents predicates only filter within the discovered root. No user-supplied paths are executed.
  • Command execution: the resume command is built solely from the existing buildAiVaultResumeCommand quoting helpers and the agent's configured detectCmd; session ids are shell-quoted. No new shell spawning.
  • IPC/secrets/dependencies: no new IPC channels, no secrets read, no new dependencies.

Notes

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

We couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting @coderabbitai full review.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

  • Last reviewed commit: ed2130333cfecbfcbf24cb2d2ab83d8bc83dd441
  • Latest commit, not reviewed: 539c0f9

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 56acb647-1e9f-4eae-bcf9-0efea629cdd4

📥 Commits

Reviewing files that changed from the base of the PR and between 212c0e4 and ed2130333cfecbfcbf24cb2d2ab83d8bc83dd441.

📒 Files selected for processing (11)
  • src/main/ai-vault/session-scanner-agent-parser.ts
  • src/main/ai-vault/session-scanner-agent-sources.ts
  • src/main/ai-vault/session-scanner-codex-workers.test.ts
  • src/main/ai-vault/session-scanner-parse-cache.ts
  • src/main/ai-vault/session-scanner-qwen-parser.test.ts
  • src/main/ai-vault/session-scanner-qwen-parser.ts
  • src/main/ai-vault/session-scanner-test-fixtures.ts
  • src/main/ai-vault/session-scanner-types.ts
  • src/main/ai-vault/session-scanner.test.ts
  • src/shared/ai-vault-resume-command.ts
  • src/shared/ai-vault-types.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/shared/ai-vault-resume-command.ts
  • src/main/ai-vault/session-scanner-codex-workers.test.ts
  • src/main/ai-vault/session-scanner-parse-cache.ts
  • src/main/ai-vault/session-scanner.test.ts
  • src/main/ai-vault/session-scanner-agent-parser.ts
  • src/main/ai-vault/session-scanner-qwen-parser.test.ts
  • src/main/ai-vault/session-scanner-test-fixtures.ts
  • src/main/ai-vault/session-scanner-qwen-parser.ts
  • src/shared/ai-vault-types.ts
  • src/main/ai-vault/session-scanner-types.ts
  • src/main/ai-vault/session-scanner-agent-sources.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Walkthrough

Adds Qwen Code to the supported AI Vault agents. The scanner discovers Qwen JSONL chat transcripts from configured or default project paths. A resumable parser extracts session metadata, messages, previews, titles, and models. Resume commands use Qwen’s --resume format. Tests cover parsing behavior, fixture discovery, indexing, resume commands, and scan configuration.

Merge Risk: Minimal · up to ed213

This PR adds localized Qwen Code session discovery, parsing, and resume support with no actionable merge-blocking risk remaining after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 13 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: adding Qwen Code sessions to AI Vault.
Description check ✅ Passed The description explains the problem, implementation, scope, visual result, linked issue, testing, security, compatibility, and performance considerations. It does not reproduce every template heading…
Linked Issues check ✅ Passed The changes satisfy issue #11418 by registering Qwen Code, discovering and parsing its JSONL sessions, supporting incremental parsing, exposing metadata and previews, and generating a functional resum…
Out of Scope Changes check ✅ Passed The changes remain focused on Qwen Code session discovery, parsing, resume support, integration, and related tests and fixtures. No unrelated code changes are identified.
Full details: Description check

Explanation

The description explains the problem, implementation, scope, visual result, linked issue, testing, security, compatibility, and performance considerations. It does not reproduce every template heading or checklist item, but it contains the required information and is mostly complete.

Full details: Linked Issues check

Explanation

The changes satisfy issue #11418 by registering Qwen Code, discovering and parsing its JSONL sessions, supporting incremental parsing, exposing metadata and previews, and generating a functional resume command. Live agent-status hooks are correctly excluded as separate scope.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e2509c10-2753-4249-bc20-6c0f41081c61

📥 Commits

Reviewing files that changed from the base of the PR and between b21f978 and d5563a9384ef007dccab62593e15fd53666a257b.

📒 Files selected for processing (11)
  • src/main/ai-vault/session-scanner-agent-parser.ts
  • src/main/ai-vault/session-scanner-codex-workers.test.ts
  • src/main/ai-vault/session-scanner-parse-cache.ts
  • src/main/ai-vault/session-scanner-qwen-parser.test.ts
  • src/main/ai-vault/session-scanner-qwen-parser.ts
  • src/main/ai-vault/session-scanner-qwen-sources.ts
  • src/main/ai-vault/session-scanner-source-discovery.ts
  • src/main/ai-vault/session-scanner-test-fixtures.ts
  • src/main/ai-vault/session-scanner-types.ts
  • src/main/ai-vault/session-scanner.test.ts
  • src/shared/ai-vault-types.ts

@greptile-apps

greptile-apps Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR wires Qwen Code into the AI Vault by registering it in AI_VAULT_AGENTS, adding a discovery source pointing at ~/.qwen/projects/<encoded-cwd>/chats/*.jsonl, and implementing a new Gemini-shaped append-only JSONL parser with incremental resume support.

  • session-scanner-qwen-parser.ts parses transcripts, filtering out thought: true parts and reading cwd/gitBranch from each record (no sidecar index required). Incremental append parsing is wired through createQwenSessionResumeState.
  • session-scanner-agent-sources.ts adds the qwen-code source with directoryPredicate pruning subagents/ and a filePredicate matching files under chats/ — consistent with the Cursor/OpenClaw convention.
  • Resume uses qwen --resume <id> via a fall-through in buildAgentResumeInvocation, and tests cover parser correctness, thought-part exclusion, system-reminder stripping, and all-agents scanner coverage.

Confidence Score: 4/5

  • The PR is safe to merge after fixing the missing stream teardown in the Qwen parser.
  • The Qwen parser opens a gated transcript stream via openTranscriptReadStream but never saves a reference to it, so neither lines.close() nor input.destroy() can be called on error. Every other parser doing the same thing (antigravity, droid, graph-parsers, grok, kimi, claude-subagents) has a finally teardown block to prevent the handle from being stranded until the gate's deadline. The codebase even has a dedicated test file (session-scanner-parser-stream-cleanup.test.ts) that validates this contract for those parsers — qwen-code is absent because the cleanup code is missing. Outside that one issue, the implementation is thorough and consistent with existing patterns.
  • src/main/ai-vault/session-scanner-qwen-parser.ts — the parseQwenSessionFile function needs an explicit finally { lines.close(); input.destroy() } block, and a corresponding case should be added to session-scanner-parser-stream-cleanup.test.ts.

Important Files Changed

Filename Overview
src/main/ai-vault/session-scanner-qwen-parser.ts New Qwen Code parser following the Gemini-shaped transcript format. The parsing logic, model extraction, thought-part filtering, and incremental resume state are all correct, but parseQwenSessionFile is missing the finally { lines.close(); input.destroy() } teardown that every other gated-stream parser in the codebase requires to prevent handle leaks on error.
src/main/ai-vault/session-scanner-agent-sources.ts Adds qwen-code source entry pointing to ~/.qwen/projects, filtering .jsonl files inside chats/ directories and pruning subagents/ trees. Follows the same conventions as Cursor and other append-only JSONL agents.
src/shared/ai-vault-resume-command.ts Adds qwen-code to the --resume <id> fall-through case in buildAgentResumeInvocation. Placement and comment are clear.
src/main/ai-vault/session-scanner-parse-cache.ts Routes qwen-code to createQwenSessionResumeState in the resumable-state factory, enabling incremental append parsing. Correct placement and consistent with all other JSONL-fold parsers.
src/main/ai-vault/session-scanner-qwen-parser.test.ts Thorough unit tests covering full parse, thought-part exclusion, resume command, system-reminder stripping, empty transcript, preview truncation, and thought-only turns. The one gap is that session-scanner-parser-stream-cleanup.test.ts does not include qwen-code, which is a consequence of the missing teardown in the parser.
src/shared/ai-vault-types.ts Adds qwen-code to AI_VAULT_AGENTS and AI_VAULT_AGENT_LABELS with the label 'Qwen Code'. Clean addition.

Sequence Diagram

sequenceDiagram
    participant Scanner as scanAiVaultSessions
    participant Sources as AI_VAULT_AGENT_SOURCES['qwen-code']
    participant Cache as parseAgentSessionFileCached
    participant Parser as parseQwenSessionFile
    participant Resume as createQwenSessionResumeState
    participant FS as openTranscriptReadStream

    Scanner->>Sources: "rootDirs → ~/.qwen/projects/<project>/chats/*.jsonl"
    Sources-->>Scanner: candidate files (filePredicate: includes('chats'))
    Scanner->>Cache: parseAgentSessionFileCached(candidate)
    Cache->>Resume: resumableStateFactoryFor → createQwenSessionResumeState
    Cache->>FS: consumeCompleteJsonlLines (incremental from byteOffset)
    FS-->>Cache: new lines only
    Cache->>Resume: state.consumeLine(line) for each record
    Note over Resume: updateTimeline, updateLatestLocation,<br/>qwenMessagePartsText (excludeThought=true for assistant)
    Cache->>Resume: state.finalize(platform)
    Resume-->>Cache: AiVaultSession (sessionId, title, cwd, branch, model, resumeCommand)
    Cache-->>Scanner: "session with resumeCommand = "cd '<cwd>' && qwen --resume '<id>'""
Loading

Reviews (3): Last reviewed commit: "fix(ai-vault): route Qwen transcript rea..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5d21c31-0895-4477-9c54-3409cec165c4

📥 Commits

Reviewing files that changed from the base of the PR and between 56b6d84 and c5c14cfeb36304c4a1abba91195d2362d5c143c6.

📒 Files selected for processing (11)
  • src/main/ai-vault/session-scanner-agent-parser.ts
  • src/main/ai-vault/session-scanner-agent-sources.ts
  • src/main/ai-vault/session-scanner-codex-workers.test.ts
  • src/main/ai-vault/session-scanner-parse-cache.ts
  • src/main/ai-vault/session-scanner-qwen-parser.test.ts
  • src/main/ai-vault/session-scanner-qwen-parser.ts
  • src/main/ai-vault/session-scanner-test-fixtures.ts
  • src/main/ai-vault/session-scanner-types.ts
  • src/main/ai-vault/session-scanner.test.ts
  • src/shared/ai-vault-resume-command.ts
  • src/shared/ai-vault-types.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/main/ai-vault/session-scanner-types.ts
  • src/main/ai-vault/session-scanner-agent-parser.ts
  • src/main/ai-vault/session-scanner-codex-workers.test.ts
  • src/shared/ai-vault-types.ts
  • src/main/ai-vault/session-scanner-test-fixtures.ts
  • src/main/ai-vault/session-scanner-qwen-parser.test.ts
  • src/main/ai-vault/session-scanner-qwen-parser.ts
  • src/main/ai-vault/session-scanner.test.ts
  • src/main/ai-vault/session-scanner-parse-cache.ts

@nwparker nwparker removed the P2 label Aug 19, 2026
@pythonstrup
pythonstrup force-pushed the feat/qwen-ai-vault-sessions branch from c5c14cf to d156dae Compare August 20, 2026 00:56
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@pythonstrup
pythonstrup force-pushed the feat/qwen-ai-vault-sessions branch from d156dae to ed21303 Compare August 31, 2026 14:30
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

pythonstrup added a commit to pythonstrup/orca that referenced this pull request Sep 15, 2026
A thought-only or tool-only assistant turn carries record.model but no
visible reply text, so the model was dropped by the early return on empty
text. Capture the model first; the turn still adds no preview/message.

Addresses CodeRabbit review feedback on stablyai#11419.
@pythonstrup
pythonstrup force-pushed the feat/qwen-ai-vault-sessions branch from ed21303 to 2aa3d97 Compare September 15, 2026 12:26
@ChoshimWy

Copy link
Copy Markdown

Confirming this is still missing on the latest release and that the on-disk layout this PR targets still matches current Qwen Code.

  • Orca 1.4.242 (macOS, Apple Silicon) with Qwen Code 0.26.1: Agent Session History / session search shows no Qwen Code sessions. The Qwen hook status and terminal resume both work, so only the session scanner is missing qwen-code.
  • Qwen Code 0.26.1 still writes transcripts to ~/.qwen/projects/<encoded-cwd>/chats/<uuid>.jsonl, the path this PR scans.
  • One small thing worth double-checking: each chats/ directory also holds a sibling <uuid>.runtime.json next to every <uuid>.jsonl, so discovery should filter on the .jsonl extension and not treat the runtime files as transcripts.

Qoder session history landed in #24614, and this PR looks like the same shape of change for Qwen Code. It has had no maintainer review since it was opened. Could a maintainer take a look when there is time? Happy to test a build against real Qwen Code data if that helps.

pythonstrup and others added 3 commits October 28, 2026 21:11
Qwen Code launched and ran in Orca but its sessions never appeared in the
AI Vault (Agent Session History): qwen-code was absent from AI_VAULT_AGENTS,
so the scanner never discovered or parsed its transcripts.

Wire Qwen Code into the vault the same way other agents are wired:
- register qwen-code in AI_VAULT_AGENTS / labels and the resume invocation
  (`qwen --resume <id>`)
- discover ~/.qwen/projects/<cwd>/chats/*.jsonl, pruning subagent transcripts
- parse the Gemini-shaped append-only transcript, dropping `thought` parts
  from previews and reading cwd/gitBranch from each record
- enable incremental append parsing via the shared accumulator fold

Live agent-status hooks for Qwen remain out of scope (separate installer).
A thought-only or tool-only assistant turn carries record.model but no
visible reply text, so the model was dropped by the early return on empty
text. Capture the model first; the turn still adds no preview/message.

Addresses CodeRabbit review feedback on stablyai#11419.
The STA-4049 import guard on main forbids raw node:fs reads in scanner
parsers; read via openTranscriptReadStream and rethrow gate refusals so
a partial session is never cached, matching the sibling JSONL parsers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pythonstrup and others added 2 commits October 28, 2026 21:11
readline.close() leaves its input open, so a mid-read throw stranded the
gated transcript handle until the gate deadline and delayed later scans.
Mirror the other JSONL parsers: keep the stream reference and destroy it
in a finally block. Pinned by the shared stream-cleanup regression test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rebasing onto main surfaced per-agent contracts the branch predates:

- Port the parser from addPreviewMessage to addSessionText (stablyai#32086).
- Pass the transcript sink to the Qwen resume state so cached parses
  publish messages like every other agent.
- Read scope cwd from the first record, matching the parser's
  first-cwd rule.
- Mark Qwen transcripts self-contained for the search index.
- Expect qwen-code to stay out of legacy-host search projections; old
  hosts only see it through their supportedAgents catalog.
- Resolve the Qwen roots in the Qwen module, as Kimi and Muse do, so
  the shared source table stays within max-lines.
- Pin the parser test's mtime instead of reading the wall clock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pythonstrup
pythonstrup force-pushed the feat/qwen-ai-vault-sessions branch from 52ceb81 to 539c0f9 Compare October 28, 2026 13:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Qwen Code sessions are not indexed in the AI Vault (Agent Session History)

5 participants