OpenViking
volcengine
Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:SiriLee/dsh-rewind
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
In-place conversation rewind for DeepSeek Harness: the Claude Code /rewind semantics inside the same session window — cut the model context back to an earlier user message, and optionally restore workspace files from disk-persisted before-backups.
Status: published to npm (
dsh-rewind-plugin, v0.2.7) via GitHub Actions Trusted Publishing + Sigstore provenance. Targets the web profile (dsh --profile web). Interaction mirrors Claude Code's rewind, adapted to dsh's real web UI.v0.2.7 highlights: composer refill is event-driven (reopening a session never resurrects withdrawn text); subagent edits are not tracked (Claude Code alignment); concurrent rewinds are guarded; the code-restore option appears only when tracked changes exist (mixed host/client versions safe).
| Feature | Description |
|---|---|
| In-place rewind | Rewind to any user message from a per-message ↶ button: the target message and everything after it (agent replies, tool calls) are withdrawn from the model context and the rendered transcript — no new session, no window switch |
| Time-travel semantics | Rewinding to a message withdraws that message too; its text is offered back in the composer so you can edit and re-send it |
| Claude-Code-style file restore | Write-class edits are backed up before they happen and persisted on disk; "conversation and code" restores files to their pre-edit content and deletes files created after the target |
| Impact preview | "Conversation and code" first shows the exact restore / delete list for confirmation (the option is hidden when there are no tracked changes — like Claude Code's code-restore visibility) |
| Approval-plugin coexistence | Capture runs at the tools/execute around-dispatch stage, so another plugin's pre-execute approval short-circuit (e.g. dsh-edit-approval) cannot skip the backup, and a denied call never records |
| Paths resolved by session cwd | Relative paths are backed up and restored against the real file using the fs-tools session-cwd rule; the resolved display path is what gets recorded |
| Restores write real files | Restore goes through plain node:fs directly to the filesystem; symbolic and hard links are skipped with a warning (no clobber through a shared inode) |
| Survives host restart | Backups live on disk under ~/.dsh/rewind-snapshots/<session>/<anchor seq>/, newest 100 message groups per session |
| Localized | zh / en copy registered into the dsh locale system |
![]() Per-message ↶ rewind button |
![]() Mode-selection popover |
![]() "Conversation and code" impact list |
![]() Manual /rewind guard hint |
Two halves work together: the conversation rewind (in-place, same window) and the checkpoint file restore (Claude-Code-style before-backups).
The plugin appends an empty-content marker assistant/message into the session log whose surfaceOp: { op: 'replace', start, end } replaces every surface node after the target message with the marker:
sourceEventSeqs covering every shadowed node, and the Session.append surface rules validate the cut (only a contiguous range on the current surface).null — it never enters the model context and never renders as conversation content. The agent and the user both see the conversation exactly as it was at the target.markerTurnOf), never lastTurn + 1: the harness's agent loop numbers its next real turn exactly last turn/start + 1, so a marker numbered the same way would leave an assistant/message BEFORE the turn/start of the same turn — the client conversation-context builder rejects that ordering with conversation Context …:turn-tail… received an update before its start Match, history load fails, and the whole conversation disappears from the UI (the real defect in ≤ 0.2.4, fixed in 0.2.5). Reusing an already-consumed turn makes the marker a harmless trailing update on the previous completed turn's tail — it can never collide with a future turn.A running turn (LLM thinking / streaming) is force-stopped first (cancel({ kind: 'user' })) and the rewind waits for quiescence; if it can't stop, the rewind is aborted with an error.
The plugin tracks the write-class tools — write, edit, str_replace_editor (mutating commands create / str_replace / insert):
tools/execute (the around-dispatch stage): the target file is read and the resolved path + content are held in a pending map. This stage only runs after any pre-execute approval gate let the call through — so an ask short-circuit (dsh-edit-approval) cannot skip the backup, and a denied call never records.tools/post-execute: the before-backup is written under the turn's anchor message seq (~/.dsh/rewind-snapshots/<session>/<anchor seq>/<callId>.json)./rewind @<seq> both): every backup anchored at or after the target applies — modified files are written back to their earliest captured before-state, files created after the target are deleted, symbolic / hard links are skipped. Writes go through plain node:fs, independent of the fs service.tools/post-execute; a tools/result safety net clears the pending capture so nothing leaks in memory.Backups persist across host restarts, bounded to the newest 100 anchor groups per session.
…turn-tail… received an update before its start Match)Versions ≤ 0.2.4 corrupted client replay when a rewind was followed by further
conversation: the marker's turn number collided with the next real turn's
turn/start, so reopening the session showed
Failed to load history: conversation Context …:turn-tail… received an update before its start Match (internal)
and the history vanished. Rewinds created from 0.2.5 on no longer produce the
collision, but already-corrupted sessions need an offline repair (the log is
append-only — it cannot be rewritten in memory).
The repair tool ships inside the npm package (dsh-rewind-repair) — no
source checkout needed:
# 1. Fully quit dsh web / host first (while a session is resident in memory,
# a disk repair is overwritten by the next checkpoint)
# 2. Run the offline repair (scans every session under ~/.dsh/sessions,
# rewriting each marker's turn back to the last started turn)
npm exec --yes --package=dsh-rewind-plugin -- dsh-rewind-repair
npm exec --yes --package=dsh-rewind-plugin -- dsh-rewind-repair -- --dry-run # preview only
# 3. Restart dsh web — the repaired sessions load their history again
Or install it globally once (npm i -g dsh-rewind-plugin) and run
dsh-rewind-repair directly; from a source checkout the same tool is
node scripts/repair-markers.mjs (identical flags).
The tool only rewrites the data.turn of dsh-rewind empty-marker events
(keeping seqs, order, and the zstd frame structure intact), backs up the original
file to session.jsonl.zstd.bak-<timestamp> before writing, and never touches
any other event — safe to run repeatedly.
Published to npm — the registry path is the recommended one. Restart dsh web (--profile web) after installing.
⚠️ Note: the npm name
dsh-rewindbelongs to another author's package — install withdsh-rewind-plugin.
dsh plugin --profile web add dsh-rewind-plugin
cd dsh-rewind
npm install # devDeps come from the npm registry; no harness checkout needed
npm run build # full build: lib/ (host ESM + client bundle + .d.ts)
dsh plugin --profile web add /path/to/dsh-rewind # link install
dsh plugin --profile web add github:SiriLee/dsh-rewind#<commit-sha>
First run fails: pnpm blocks git dependencies from running build scripts. Follow
the CLI hint to add an allowBuilds key to the profile's pnpm-workspace.yaml
(e.g. $DSH_HOME/profiles/web/pnpm-workspace.yaml), then retry. pnpm then runs
the plugin's prepare (full build) and installs it into the profile.
Rewinding to a message withdraws it and everything after it — the transcript and the agent's context both return to before the message. The command result says so, and the message's text is offered back in the composer.
/rewind is blocked/rewind exists only as the button's internal channel. Typing /rewind (bare or with arguments) into the composer is intercepted — submitting shows a transient hint pointing at the ↶ button.
write / edit / str_replace_editor). Changes made by bash, other tools, or external programs are not backed up and cannot be restored — the same limitation as Claude Code, which also defers such rollbacks to the user's git.both rewind cannot restore it — the plugin logs a warning but does not block the write./compact — provided by the harness.^22.19.0 || >=24.0.0.dsh --profile web); peer @deepseek-ai/* packages are resolved by the harness at runtime.[!WARNING] This project and DeepSeek Harness are both in developer preview. Pin exact versions in reproducible environments and review the behavior notes above.
npm install # devDeps from the npm registry
npm run typecheck # tsc on both compilation surfaces (host + client)
npm test # vitest: rewind / snapshot / hidden / session-cwd / integration (46 cases)
npm run build # esbuild: lib/index.js (host ESM) + lib/client.js (loader closure) + .d.ts
node scripts/verify-host.mjs # boot the BUILT host artifact end-to-end (18 checks)
prepare runs the full build, so git installs and npm pack / npm publish
always produce a complete lib/ and the LICENSE.
Maintainers: see docs/harness-reference.md for the DeepSeek Harness interface reference (subsystem docs + key source index).
Releases go out through GitHub Actions Trusted Publishing (OIDC, no stored
NPM_TOKEN):
npm version patch && git push origin main --tags # triggers .github/workflows/publish.yml
package.json, runs typecheck + tests +
a full build + artifact verification, publishes with --provenance
(Sigstore), and creates a GitHub Release. It is idempotent — an already
published version is skipped. CI (.github/workflows/ci.yml) runs the same
checks on every push / PR, plus a npm pack --dry-run sanity check that the
tarball carries lib/ and LICENSE.SiriLee · Repository dsh-rewind (the GitHub
repo, not the npm name) · Workflow filename publish.yml · Environment
empty · Allowed actions npm publish. Once configured, pushes of
v<version> tags publish automatically.src/index.ts host plugin: /rewind command + checkpoint pipeline (tools/execute|post-execute)
src/rewind.ts pure planning: target resolution, surface range, candidate listing
src/snapshot.ts checkpoint store (disk before-backups, restore/preview, bounded prune)
src/session-cwd.ts session-cwd resolution (fs-tools rule)
src/client/index.ts client plugin: per-message ↶ button + manual /rewind guard
src/client/popover.ts mode-selection popover (both-mode impact confirm)
src/client/hidden.ts withdrawn-span computation (hiddenSeqsOf), pure
src/client/locales.ts zh / en copy (LocaleNamespaceMap)
src/client/styles.ts injected styles (dsh design tokens)
scripts/build.mjs esbuild: lib/index.js (host ESM) + lib/client.js (loader closure) + .d.ts
scripts/verify-host.mjs end-to-end host verification (18 checks)
tests/ vitest suites (rewind / snapshot / hidden / session-cwd / integration, 46 cases)
docs/harness-reference.md maintainer docs: DeepSeek Harness interface reference
assets/screenshots/ UI screenshots
cordis.patch.yml bundle patch (mounts the dual-face plugin row)
package.json dsh.bundle + dsh.client manifests, optional peerDependencies
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: rewind、session。