@everme/qwenwork
v0.7.10
Published
Native EverMe memory hooks for QwenWork.
Readme
@everme/qwenwork
Native EverMe memory hooks for QwenWork.
What it does
QwenWork's desktop app bundles @qoder-ai/qoder-agent-sdk, whose worker
runtime implements a Claude Code-shaped hook contract: stdin carries the hook
input as JSON, stdout is parsed as hook output, exit code 2 blocks the
operation. evercli plugin install qwenwork wires three of its events:
| Event | Mode | What it does |
|---|---|---|
| SessionStart | sync | injects the durable Profile block once per session |
| UserPromptSubmit | sync | injects recall for the prompt as additionalContext |
| Stop | async | captures the finished turn and uploads it |
Install also stages this bundle at ~/.qwenworkcn/everme/, writes credentials
to ~/.qwenworkcn/everme.env (0600), and keeps the read-only everme-memory
MCP entry in ~/.qwenworkcn/mcp.json so the model can also call
mem_search / mem_context on demand mid-turn.
The app does not watch its config directory, so a fresh install is live only after QwenWork restarts.
Why Stop, and why async
Measured against the shipped app on 2026-09-03 with a probe registered on five events, across a two-prompt session:
SessionStart 2 · UserPromptSubmit 4 · PostToolUse 5 · Stop 4 · SessionEnd 0SessionEndnever fires while the app stays open, so it cannot be the capture boundary.Stopfires once per turn, so it is.- Because
Stopis per-turn, a synchronous upload would sit on every turn's critical path. QwenWork supportsasync: true(fire-and-forget: the host neither waits nor reads stdout), so capture takes it and the write never blocks a turn or reports a timeout it did not suffer. PostToolUseis deliberately not registered. It would spawn a process per tool call for data the transcript already carries verbatim.
Unlike MiniMax Code — whose host only fires tool-call events, so a conversation with zero tool calls is never captured — a QwenWork turn is captured whether or not it used tools.
How a turn is read
Every hook payload carries transcript_path, pointing into
~/.qwenworkcn/projects/<cwd-slug>/<session-uuid>.jsonl. Capture reads that
file rather than reassembling a turn from event fields. Capture retains
visible assistant text, tool calls, and actual results, but excludes native
internal thinking blocks.
The reader selects the latest native active-leaf ancestry, restoring sibling assistant blocks and parallel tool results in source order. Copied fork history and internal compaction summaries are excluded. Invalid active chains fail with a fixed reason instead of uploading unselected history. Missing, blank, or non-string native tool IDs are dropped with bounded counts; the reader does not generate IDs or infer pairs. Real empty results remain empty. Native result arrays contribute their text blocks in order, matching cold import; image-only and empty arrays retain an empty result rather than a fabricated caption. Calls with blank names or invalid JSON arguments are dropped, along with results uniquely identified by that native call ID. Duplicate IDs do not justify deleting another call's result. Diagnostics contain counts, not tool content.
Task batching preserves complete user tasks when they fit the request budget.
Only oversized tasks compress tool results, trying 4, 3, then 2 KiB per
result before falling back to semantic splitting. Native end_turn marks
final replies; this does not change Stop checkpoints or the non-flushing write.
The upload is a delta against a per-session checkpoint, so a Stop the host
never delivered (app killed mid-turn) is recovered by the next one instead of
being lost. A re-fired Stop over an unchanged transcript resolves to the
same turn key and is deduped.
New checkpoints select records by native UUID, role and native tool-result ID, not by message count. Regenerating an answer under the same user uploads only the new branch records; returning to an already handled branch uploads nothing. The first Stop still uploads only the latest turn: older active-path records are recorded as the excluded baseline, not replayed. Identity keys stay local. Existing count-only checkpoints remain unchanged, with no migration or backfill; their existing branch-switch limitation is deliberately retained.
Deploy Server support before this plugin. New checkpoints send
deduplication: "client-native-id" on hook writes, without baseTurn.
Server does not read or advance positional session watermarks for these writes,
which would otherwise discard replacements under an already uploaded user turn.
This does not provide cross-channel import/hook deduplication or exactly-once
delivery after an ambiguous HTTP failure. Old Server versions ignore this field
and can still trim replacements. No database migration is required.
Complete leading system-reminder envelopes are removed; quoted tags inside
user prose are preserved, matching cold-start conversion. An incomplete host
reminder is not treated as a complete envelope.
Two things are filtered out on the way in:
- Our own injected blocks.
<everme_recall>/<everme_profile>come back as leading context in the next user turn; re-uploading them would feed memory into memory. Tags quoted within user prose are preserved, including unclosed examples; they are not evidence of injected context. Cold-start conversion applies the same leading EverMe envelope rule only for QwenWork; sharing Claude's content reader does not change Claude's policy. - Sidechain records, which belong to a sub-agent run and would otherwise be absorbed into the parent session.
Configuration
Credentials are read from ~/.qwenworkcn/everme.env (written by evercli).
EVERME_ENV_FILE_PATH overrides the location; EVERCLI_QWENWORK_CONFIG_DIR
overrides the QwenWork home the default is derived from.
Without credentials the hooks are silent: no output, no error at the user, exit 0. Memory is never allowed to block a turn, so every failure path exits 0 with a one-line note on stderr.
Uninstall
evercli plugin uninstall qwenworkManually: drop the everme-named handlers from hooks in
~/.qwenworkcn/settings.json and the mcpServers["everme-memory"] entry from
~/.qwenworkcn/mcp.json (keeping every other hook and server), then
rm -rf ~/.qwenworkcn/everme ~/.qwenworkcn/everme.env and restart QwenWork.
Tests
npm test --workspace @everme/qwenworkLicense
Apache-2.0
