dsh-session-toolbox 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/cordis.patch.yml +2 -2
- package/lib/{chunk-4UQB3MPY.js → chunk-QXW2NIKH.js} +3 -1
- package/lib/{chunk-4UQB3MPY.js.map → chunk-QXW2NIKH.js.map} +2 -2
- package/lib/cli.js +1 -1
- package/lib/client.js +107 -12
- package/lib/client.js.map +2 -2
- package/lib/{host-v0.1.7.js → host-v0.1.9.js} +25 -2
- package/lib/host.js +25 -2
- package/lib/index.js +25 -2
- package/lib/index.js.map +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。版本号从 `0.1` 起;DSH 宿主接口(`workspaceRegistry` / `sessionPersistence` / `webServer` 服务面与 `~/.dsh/sessions` 布局)在 0.x 期间按 `0.2.0-rc.2` 基线验证,每次官方升级会重验并在此记录。
|
|
6
6
|
|
|
7
|
+
## 0.1.9
|
|
8
|
+
|
|
9
|
+
- **修复右键菜单里的迁移对话框没有项目选择**:0.1.8 只给设置页的迁移表单加了项目下拉,而会话行 `⋯` → 「切换到其它项目…」打开的是 `MoveDialog`,那里仍只能手填绝对路径。现在对话框与面板一致:显示当前项目、提供项目下拉(标注会话数与「当前项目」),并可继续手填路径。
|
|
10
|
+
|
|
11
|
+
## 0.1.8
|
|
12
|
+
|
|
13
|
+
- **回收站改名并明确语义**:会话的「删除」在 DSH 里本质就是官方归档,插件只是额外记录了入池时的项目归属、列表位置与置顶状态,因此可以还原到原位。界面统一改为「归档池」:菜单项「归档到归档池」、面板标题「归档池」、列名「入池时间」,并在面板里说明它同时出现在官方归档视图中。
|
|
14
|
+
- **切换项目支持按名字选择**:迁移表单新增项目下拉(显示项目名与会话数),并**标出当前项目**且禁用它作为目标;选中后自动填入路径。输入会话 ID 后会显示它当前所属的项目(名称 + 路径)。宿主新增 `project.of` 动作与 `state.projects` 列表。
|
|
15
|
+
|
|
7
16
|
## 0.1.7
|
|
8
17
|
|
|
9
18
|
- **修复插件页报错 `cannot get property "locale" without inject`**:客户端 `inject` 只声明了 `slots`,却直接读取 `ctx.locale`。cordis 的 reflect 代理对未注入的服务属性访问会抛错(而非返回 undefined),因此插件页无法完成同步。现已在 `inject` 中声明 `locale`,并按官方客户端插件的方式用 `ctx.effect` 包裹字典注册。
|
package/cordis.patch.yml
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
- insert:
|
|
2
|
-
- id: session-toolbox-v1-0.1.
|
|
3
|
-
name: ./lib/host-v0.1.
|
|
2
|
+
- id: session-toolbox-v1-0.1.9
|
|
3
|
+
name: ./lib/host-v0.1.9.js
|
|
@@ -795,6 +795,8 @@ async function dispatch(kit, input) {
|
|
|
795
795
|
return await kit.trash.purge(String(input.itemId ?? ""));
|
|
796
796
|
case "trash.sweep":
|
|
797
797
|
return await kit.trash.sweep();
|
|
798
|
+
case "project.of":
|
|
799
|
+
return { project: await kit.projectOf(String(input.sessionId ?? "")) };
|
|
798
800
|
case "settings.update":
|
|
799
801
|
return { settings: await kit.updateSettings(input.patch ?? {}) };
|
|
800
802
|
case "vault.sync":
|
|
@@ -825,4 +827,4 @@ export {
|
|
|
825
827
|
apiHandler,
|
|
826
828
|
dispatch
|
|
827
829
|
};
|
|
828
|
-
//# sourceMappingURL=chunk-
|
|
830
|
+
//# sourceMappingURL=chunk-QXW2NIKH.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/store.mjs", "../src/move.mjs", "../src/paths.mjs", "../src/session-log.mjs", "../src/trash.mjs", "../src/api.mjs"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin-owned durable documents under `<DSH_HOME>/session-toolbox/`. All writes go\n * through `@deepseek-ai/dsh-atomic-write` (`writeFileAtomic` inside `withFileLock`)\n * with owner-only modes, mirroring the host's durability discipline. Corrupt\n * files are never auto-reset: they fail loud and surface in status.\n */\nimport { mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { writeFileAtomic, withFileLock } from '@deepseek-ai/dsh-atomic-write';\n\nexport const DEFAULT_SETTINGS = Object.freeze({\n\tversion: 1,\n\tdraftVault: { enabled: true, maxSizeBytes: 200 * 1024 * 1024, ttlDays: 7 },\n\ttrash: { ttlDays: 30, autoPurge: false },\n\tmove: { enabled: true },\n});\n\nconst OWNED = { mode: 0o600, dirMode: 0o700 };\n\nfunction mergeSettings(raw) {\n\treturn {\n\t\tversion: 1,\n\t\tdraftVault: { ...DEFAULT_SETTINGS.draftVault, ...(raw.draftVault ?? {}) },\n\t\ttrash: { ...DEFAULT_SETTINGS.trash, ...(raw.trash ?? {}) },\n\t\tmove: { ...DEFAULT_SETTINGS.move, ...(raw.move ?? {}) },\n\t};\n}const positiveInt = value => Number.isSafeInteger(value) && value > 0;\n\n/** One durable JSON document: locked read-modify-write + schema guard. */\nexport class JsonDocument {\n\tfile;\n\t#fallback;\n\t#guard;\n\tconstructor(root, name, fallback, guard) {\n\t\tthis.file = join(root, name);\n\t\tthis.#fallback = fallback;\n\t\tthis.#guard = guard;\n\t}\n\tasync read() {\n\t\tlet value;\n\t\ttry {\n\t\t\tvalue = JSON.parse(await readFile(this.file, 'utf8'));\n\t\t} catch (error) {\n\t\t\tif (error.code === 'ENOENT') value = structuredClone(this.#fallback);\n\t\t\telse if (error instanceof SyntaxError) throw new Error(`session-toolbox: corrupt JSON in ${this.file}: ${error.message}`, { cause: error });\n\t\t\telse throw error;\n\t\t}\n\t\tif (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error(`session-toolbox: ${this.file} is not a JSON object`);\n\t\treturn this.#guard === undefined ? value : this.#guard(value, this.file);\n\t}\n\tasync write(value) {\n\t\tthis.#guard?.(value, this.file);\n\t\t// The lock sibling is created before writeFileAtomic's own mkdir, so the\n\t\t// parent directory must already exist for withFileLock.\n\t\tawait mkdir(dirname(this.file), { recursive: true, mode: 0o700 });\n\t\tawait withFileLock(this.file, () => writeFileAtomic(this.file, JSON.stringify(value, null, 2), OWNED));\n\t\treturn value;\n\t}\n\t/** Serialized read-modify-write; `fn` returning undefined aborts without writing. */\n\tasync update(fn) {\n\t\tawait mkdir(dirname(this.file), { recursive: true, mode: 0o700 });\n\t\treturn withFileLock(this.file, async () => {\n\t\t\tconst current = await this.read();\n\t\t\tconst next = fn(current);\n\t\t\tif (next === undefined) return current;\n\t\t\tthis.#guard?.(next, this.file);\n\t\t\tawait writeFileAtomic(this.file, JSON.stringify(next, null, 2), OWNED);\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport function guardSettings(value, file) {\n\tif (value.version !== undefined && value.version !== 1) throw new Error(`session-toolbox: unsupported settings version in ${file}: ${String(value.version)}`);\n\tconst draft = value.draftVault ?? {};\n\tif (draft.enabled !== undefined && typeof draft.enabled !== 'boolean') throw new Error(`session-toolbox: settings.draftVault.enabled must be boolean (${file})`);\n\tif (draft.maxSizeBytes !== undefined && !positiveInt(draft.maxSizeBytes)) throw new Error(`session-toolbox: settings.draftVault.maxSizeBytes must be a positive safe integer (${file})`);\n\tif (draft.ttlDays !== undefined && !positiveInt(draft.ttlDays)) throw new Error(`session-toolbox: settings.draftVault.ttlDays must be a positive integer (${file})`);\n\tconst trash = value.trash ?? {};\n\tif (trash.ttlDays !== undefined && !positiveInt(trash.ttlDays)) throw new Error(`session-toolbox: settings.trash.ttlDays must be a positive integer (${file})`);\n\tif (trash.autoPurge !== undefined && typeof trash.autoPurge !== 'boolean') throw new Error(`session-toolbox: settings.trash.autoPurge must be boolean (${file})`);\n\treturn mergeSettings(value);\n}\n\nexport function guardJournal(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported journal version in ${file}: ${String(value.version)}`);\n\tconst entry = value.active;\n\tif (entry === null || entry === undefined) return value;\n\tif (typeof entry.sessionId !== 'string' || typeof entry.fromCwd !== 'string' && entry.fromCwd !== null || typeof entry.toCwd !== 'string') {\n\t\tthrow new Error(`session-toolbox: malformed move journal (${file})`);\n\t}\n\tif (!Array.isArray(entry.done) || typeof entry.startedAt !== 'string') throw new Error(`session-toolbox: move journal lacks done/startedAt (${file})`);\n\treturn value;\n}\n\nexport function guardLedger(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported ledger version in ${file}: ${String(value.version)}`);\n\tif (!Array.isArray(value.items)) throw new Error(`session-toolbox: trash ledger has no items array (${file})`);\n\tfor (const item of value.items) {\n\t\tif ((item.kind !== 'session' && item.kind !== 'workspace') || typeof item.id !== 'string') throw new Error(`session-toolbox: malformed trash item (${file})`);\n\t\tif (item.snapshot === null || typeof item.snapshot !== 'object') throw new Error(`session-toolbox: trash item lacks snapshot (${file})`);\n\t}\n\treturn value;\n}\n\nexport function guardManifest(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported vault manifest version in ${file}: ${String(value.version)}`);\n\tif (!Array.isArray(value.records)) throw new Error(`session-toolbox: vault manifest has no records array (${file})`);\n\tfor (const record of value.records) {\n\t\tif (typeof record.sessionId !== 'string' || typeof record.attachmentId !== 'string') throw new Error(`session-toolbox: malformed vault record (${file})`);\n\t}\n\treturn value;\n}\n\nexport { mergeSettings, OWNED };\n", "/**\n * Session-to-project move (\u00A710). The engine is capability-injected: the host\n * wires it to `workspaceRegistry` / `sessionPersistence` / `sessionQuery`, the\n * CLI wires an offline ledger over `workspace.json`. Phases are journaled so an\n * interrupted move is detected on startup and rolled back or completed\n * deterministically (\u00A710 MR2/MR3, MN1).\n *\n * Critical-section ordering (\u00A710.6): backup \u2192 stage new artifact (header\n * rewritten + fsynced) \u2192 commit placement \u2192 ledger \u2192 caches. The store never\n * exposes a window where one id exists in two project directories, and the\n * ledger runs only after placement is consistent, so `attachSession`'s\n * header-cwd validation holds by construction.\n */\nimport { createHash } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport { mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { encodeSegment, findLogFile, projectKey, verifyEncoders } from './paths.mjs';\nimport { readHeader, rewriteHeaderFrame } from './session-log.mjs';\n\nexport const PHASES = ['backup', 'rewrite', 'commit', 'ledger', 'projcache', 'index'];\n\nexport class MovePreflightError extends Error {\n\tcode;\n\tdetails;\n\tconstructor(code, message, details = {}) {\n\t\tsuper(message);\n\t\tthis.name = 'MovePreflightError';\n\t\tthis.code = code;\n\t\tthis.details = details;\n\t}\n}\n\nconst sha256 = buffer => createHash('sha256').update(buffer).digest('hex');\n\nasync function fsyncFile(path) {\n\tconst handle = await open(path, constants.O_WRONLY);\n\ttry { await handle.sync(); } finally { await handle.close(); }\n}\n\nexport async function writeOwned(file, data, mode = 0o600) {\n\tawait mkdir(dirname(file), { recursive: true, mode: 0o700 });\n\tconst temp = `${file}.${process.pid}.${Date.now()}.tmp`;\n\tawait writeFile(temp, data, { mode, flag: 'wx' });\n\tawait rename(temp, file);\n\treturn file;\n}\n\n/**\n * Move a directory between the sessions store and the kit working areas.\n * `rename` is the atomic same-volume path; a cross-device layout (unusual, but\n * possible when DSH_HOME points at a separate mount) falls back to a\n * copy-then-remove so a move never dead-ends half-published.\n */\nexport async function relocate(source, target) {\n\tawait mkdir(dirname(target), { recursive: true, mode: 0o700 });\n\ttry {\n\t\tawait rename(source, target);\n\t\treturn;\n\t} catch (error) {\n\t\tif (error.code !== 'EXDEV') throw error;\n\t}\n\tconst { cp } = await import('node:fs/promises');\n\tawait cp(source, target, { recursive: true, errorOnExist: true, force: false });\n\tawait rm(source, { recursive: true, force: true });\n}\n\n/**\n * @param deps - {root (kit dir), sessionsRoot, projcacheRoot, journal: JsonDocument,\n * capabilities: {sessionLive, listHeaders, moveLedger, resyncIndex, refreshHeaderCache}, now}\n */\nexport class MoveEngine {\n\tconstructor(deps) {\n\t\tthis.root = deps.root;\n\t\tthis.sessionsRoot = deps.sessionsRoot;\n\t\tthis.projcacheRoot = deps.projcacheRoot;\n\t\tthis.journal = deps.journal;\n\t\tthis.caps = deps.capabilities ?? {};\n\t\tthis.now = deps.now ?? (() => Date.now());\n\t}\n\n\tasync readJournal() { return (await this.journal.read()).active ?? null; }\n\tasync writeJournal(entry) { await this.journal.write({ version: 1, active: entry }); }\n\n\t/** List every journaled placement hazard for status surfaces. */\n\tasync recoverable() { return await this.readJournal() !== null; }\n\n\t/**\n\t * Fail-closed feasibility check (\u00A710 MR1). Returns the plan or throws\n\t * MovePreflightError with a stable code; never touches anything.\n\t */\n\tasync preflight({ sessionId, toCwd, createTarget = false }) {\n\t\tif (typeof sessionId !== 'string' || !sessionId.startsWith('session-')) throw new MovePreflightError('bad-request', 'sessionId must look like session-<uuid>');\n\t\tif (typeof toCwd !== 'string' || (!toCwd.startsWith('/') && !/^[A-Za-z]:[\\\\/]/.test(toCwd))) throw new MovePreflightError('bad-request', 'toCwd must be an absolute path');\n\t\tif (await this.readJournal() !== null) throw new MovePreflightError('journal-active', 'another move is journaled; complete or roll it back first');\n\t\tif (this.caps.sessionLive?.(sessionId)) throw new MovePreflightError('session-busy', `session ${sessionId} is live; stop its work before moving`);\n\t\tconst headers = await this.caps.listHeaders();\n\t\tconst header = headers.find(row => row.id === sessionId);\n\t\tif (header === undefined) throw new MovePreflightError('session-unknown', `no stored session ${sessionId}`);\n\t\tif (typeof header.version === 'number' && header.version < 4) throw new MovePreflightError('format-legacy', `stored log is format v${header.version}; open the session once in DSH so the host migrates it, then retry`);\n\n\t\t// Locate the authoritative directory by scanning project dirs \u2014 never trust a computed path alone.\n\t\tconst encoded = encodeSegment(sessionId);\n\t\tconst entries = await readdir(this.sessionsRoot, { withFileTypes: true }).catch(error => {\n\t\t\tif (error.code === 'ENOENT') return [];\n\t\t\tthrow error;\n\t\t});\n\t\tconst projects = entries.filter(entry => entry.isDirectory() && !entry.name.startsWith('.')).map(entry => entry.name);\n\t\tconst found = [];\n\t\tfor (const project of projects) {\n\t\t\ttry { if ((await stat(join(this.sessionsRoot, project, encoded))).isDirectory()) found.push(project); } catch {}\n\t\t}\n\t\tif (found.length > 1) throw new MovePreflightError('duplicate-artifact', `session ${sessionId} lives in ${found.length} project directories; refusing to guess`);\n\t\tif (found.length === 0) throw new MovePreflightError('artifact-missing', `session ${sessionId} has no session directory under any project`);\n\t\tconst fromProject = found[0];\n\t\tconst logName = await findLogFile(join(this.sessionsRoot, fromProject, encoded));\n\t\tif (logName === undefined) throw new MovePreflightError('artifact-missing', `session directory for ${sessionId} holds no session log`);\n\t\tconst logPath = join(this.sessionsRoot, fromProject, encoded, logName);\n\t\t// \u00A710 MR1 belt-and-braces (CLI/offline path): a freshly-written log means an\n\t\t// appender is active; moving it now would orphan their writes.\n\t\tconst logStat = await stat(logPath);\n\t\tif (this.now() - logStat.mtimeMs < 10_000) throw new MovePreflightError('session-churning', `session log was written ${Math.round((this.now() - logStat.mtimeMs) / 1000)}s ago; make sure DSH has stopped using it, then retry`);\n\t\tif (header.cwd !== undefined && fromProject !== projectKey(header.cwd)) {\n\t\t\t// \u00A710 MN3: the layout changed in a way this build cannot follow.\n\t\t\tthrow new MovePreflightError('unknown-layout', `cwd '${header.cwd}' should live at '${projectKey(header.cwd)}' but the artifact was observed at '${fromProject}'`);\n\t\t}\n\t\tconst fromCwd = header.cwd;\n\t\tlet canonicalTo;\n\t\ttry { canonicalTo = await realpath(toCwd.replace(/[/\\\\]+$/, '') || toCwd); } catch { canonicalTo = undefined; }\n\t\tif (canonicalTo === undefined) {\n\t\t\tif (!createTarget) throw new MovePreflightError('target-missing', `target directory ${toCwd} does not exist (choose create to make it)`);\n\t\t\tawait mkdir(toCwd, { recursive: true });\n\t\t\tcanonicalTo = await realpath(toCwd);\n\t\t}\n\t\tif (fromCwd !== undefined && canonicalTo === fromCwd) throw new MovePreflightError('same-target', 'the session already belongs to that project');\n\t\tconst samples = headers.filter(row => row.cwd !== undefined).slice(0, 5)\n\t\t\t.map(row => ({ cwd: row.cwd, id: row.id, project: projectKey(row.cwd), dir: encodeSegment(row.id) }));\n\t\tif (samples.length > 0 && !verifyEncoders(samples, this.sessionsRoot)) {\n\t\t\tthrow new MovePreflightError('unknown-layout', 'project-key / segment encoders disagree with the shipped layout; refusing to write');\n\t\t}\n\t\treturn {\n\t\t\tsessionId, fromCwd: fromCwd ?? null, toCwd: canonicalTo,\n\t\t\tfromProject, toProject: projectKey(canonicalTo),\n\t\t\tdir: join(this.sessionsRoot, fromProject, encoded),\n\t\t\tnewDir: join(this.sessionsRoot, projectKey(canonicalTo), encoded),\n\t\t\tlogName,\n\t\t\tstartedAt: new Date(this.now()).toISOString(),\n\t\t};\n\t}\n\n\tasync #stage(entry, phase) {\n\t\tif (!entry.done.includes(phase)) { entry.done = [...entry.done, phase]; await this.writeJournal(entry); }\n\t}\n\n\t/** Execute the whole move; on failure the journal survives for rollback/complete. */\n\tasync move(plan) {\n\t\tconst entry = { ...plan, done: [], deferredLedger: false,\n\t\t\tbackup: join(this.root, 'backups', `${plan.sessionId}.orig`),\n\t\t\tstagedNew: join(this.root, 'backups', `${plan.sessionId}.new`),\n\t\t\tretired: join(this.root, 'pending-purge', `${plan.sessionId}__${this.now()}`) };\n\t\tawait this.writeJournal(entry);\n\t\ttry {\n\t\t\tawait this.phaseBackup(entry);\n\t\t\tawait this.phaseRewrite(entry);\n\t\t\tawait this.phaseCommit(entry);\n\t\t\tawait this.phaseLedger(entry);\n\t\t\tawait this.phaseProjcache(entry);\n\t\t\tawait this.phaseIndex(entry);\n\t\t} catch (error) {\n\t\t\terror.journal = await this.readJournal();\n\t\t\tthrow error;\n\t\t}\n\t\t// A deferred ledger (same-process stale header cache) keeps the journal alive\n\t\t// as the retry marker: the artifact is already moved, and the next process \u2014\n\t\t// or move.complete \u2014 converges the accounting (\u00A710 MR3).\n\t\tif (entry.deferredLedger === true) {\n\t\t\tawait this.writeJournal(entry);\n\t\t\treturn { ok: true, deferred: true, sessionId: entry.sessionId, toCwd: entry.toCwd,\n\t\t\t\tnote: '\u6587\u4EF6\u5DF2\u8FC1\u79FB\uFF1BDSH \u8D26\u672C\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u6216 move.complete \u65F6\u6536\u655B' };\n\t\t}\n\t\tawait this.#finish(entry);\n\t\treturn { ok: true, sessionId: entry.sessionId, toCwd: entry.toCwd, deferredLedger: entry.deferredLedger === true };\n\t}\n\n\tasync #finish(entry) {\n\t\tawait this.writeJournal(null);\n\t\tawait rm(entry.backup, { force: true });\n\t\tawait rm(entry.stagedNew, { force: true });\n\t\tif (entry.retired !== undefined) await rm(entry.retired, { recursive: true, force: true });\n\t}\n\n\tasync phaseBackup(entry) {\n\t\tconst source = await readFile(join(entry.dir, entry.logName));\n\t\tawait writeOwned(entry.backup, source);\n\t\tentry.sourceHash = sha256(source);\n\t\tawait this.#stage(entry, 'backup');\n\t}\n\n\tasync phaseRewrite(entry) {\n\t\tconst source = await readFile(entry.backup);\n\t\tif (sha256(source) !== entry.sourceHash) throw new MovePreflightError('source-changed', 'the session log changed between backup and rewrite');\n\t\tconst current = readHeader(source);\n\t\tif (current.header.id !== entry.sessionId) throw new MovePreflightError('artifact-mismatch', `log header id '${current.header.id}' does not name ${entry.sessionId}`);\n\t\tconst rewritten = rewriteHeaderFrame(source, entry.toCwd);\n\t\treadHeader(rewritten); // parse + walk validation of our own output before staging\n\t\tif (sha256(rewritten) === entry.sourceHash) throw new MovePreflightError('rewrite-noop', 'header rewrite produced identical bytes');\n\t\tawait writeOwned(entry.stagedNew, rewritten);\n\t\tawait fsyncFile(entry.stagedNew);\n\t\tawait this.#stage(entry, 'rewrite');\n\t}\n\n\tasync phaseCommit(entry) {\n\t\t// Retire first, then publish: the id is never simultaneously discoverable in two project dirs.\n\t\tawait relocate(entry.dir, entry.retired);\n\t\tawait mkdir(entry.newDir, { recursive: true, mode: 0o700 });\n\t\tawait writeOwned(join(entry.newDir, entry.logName), await readFile(entry.stagedNew));\n\t\tawait fsyncFile(join(entry.newDir, entry.logName));\n\t\t// Carry non-log artifacts (session-local files); never resurrect a stale lock.\n\t\tfor (const name of await readdir(entry.retired).catch(() => [])) {\n\t\t\tif (name === entry.logName || name === 'session.lock') continue;\n\t\t\tawait rename(join(entry.retired, name), join(entry.newDir, name)).catch(() => {});\n\t\t}\n\t\tawait rm(join(entry.newDir, 'session.lock'), { force: true });\n\t\tawait this.#stage(entry, 'commit');\n\t}\n\n\tasync phaseLedger(entry) {\n\t\tif (this.caps.moveLedger === undefined) { entry.deferredLedger = true; await this.#stage(entry, 'ledger'); return; }\n\t\ttry {\n\t\t\tawait this.caps.refreshHeaderCache?.();\n\t\t\tawait this.caps.moveLedger(entry.sessionId, entry.fromCwd ?? undefined, entry.toCwd);\n\t\t\tentry.deferredLedger = false;\n\t\t} catch (error) {\n\t\t\t// The registry's header/pin caches can lag a same-process move. Leaving the\n\t\t\t// journal's ledger phase undone lets startup recovery re-run it in a fresh\n\t\t\t// process where the caches are cold (\u00A710 MR3/MR4).\n\t\t\tentry.deferredLedger = true;\n\t\t\tentry.ledgerError = String(error?.message ?? error);\n\t\t}\n\t\tawait this.#stage(entry, 'ledger');\n\t}\n\n\tasync phaseProjcache(entry) {\n\t\tif (this.projcacheRoot !== undefined) await rm(join(this.projcacheRoot, `${entry.sessionId}.json`), { force: true });\n\t\tawait this.#stage(entry, 'projcache');\n\t}\n\n\tasync phaseIndex(entry) {\n\t\tawait this.caps.resyncIndex?.();\n\t\tawait this.#stage(entry, 'index');\n\t}\n\n\t/** Undo completed phases in reverse (\u00A710 MR3). */\n\tasync rollback() {\n\t\tconst entry = await this.readJournal();\n\t\tif (entry === null) throw new MovePreflightError('no-journal', 'no journaled move to roll back');\n\t\tif (entry.done.includes('commit')) {\n\t\t\tawait rm(entry.newDir, { recursive: true, force: true });\n\t\t\tawait mkdir(dirname(entry.dir), { recursive: true, mode: 0o700 });\n\t\t\tif (entry.retired !== undefined) await relocate(entry.retired, entry.dir);\n\t\t\telse throw new MovePreflightError('journal-order', 'committed journal lost its retired directory');\n\t\t}\n\t\tif (entry.deferredLedger !== true && entry.done.includes('ledger') && this.caps.moveLedger !== undefined) {\n\t\t\tawait this.caps.moveLedger(entry.sessionId, entry.toCwd, entry.fromCwd ?? undefined).catch(() => {});\n\t\t\tawait this.caps.refreshHeaderCache?.().catch(() => {});\n\t\t}\n\t\tif (this.projcacheRoot !== undefined) await rm(join(this.projcacheRoot, `${entry.sessionId}.json`), { force: true });\n\t\tawait this.caps.resyncIndex?.().catch(() => {});\n\t\tawait this.#finish({ ...entry, retired: entry.done.includes('commit') ? undefined : entry.retired });\n\t\treturn { ok: true, rolledBack: entry.done };\n\t}\n\n\t/** Resume a journaled move from its first missing phase (post-crash forward roll). */\n\tasync complete() {\n\t\tconst entry = await this.readJournal();\n\t\tif (entry === null) throw new MovePreflightError('no-journal', 'no journaled move to complete');\n\t\tconst runs = { backup: e => this.phaseBackup(e), rewrite: e => this.phaseRewrite(e), commit: e => this.phaseCommit(e),\n\t\t\tledger: e => this.phaseLedger(e), projcache: e => this.phaseProjcache(e), index: e => this.phaseIndex(e) };\n\t\tfor (const phase of PHASES) {\n\t\t\tif (entry.done.includes(phase)) {\n\t\t\t\t// A deferred ledger from a previous attempt deserves another try in\n\t\t\t\t// this (fresh) process where the registry caches are cold.\n\t\t\t\tif (phase === 'ledger' && entry.deferredLedger === true) await runs.ledger(entry);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (phase !== 'backup' && !entry.done.includes('backup')) throw new MovePreflightError('journal-order', `journal skipped '${phase}' before completing 'backup'`);\n\t\t\tawait runs[phase](entry);\n\t\t}\n\t\t// Still-deferred accounting keeps the journal (and every backup) alive as\n\t\t// the convergence pointer; rollback remains available (\u00A710 MR3).\n\t\tif (entry.deferredLedger === true) {\n\t\t\tawait this.writeJournal(entry);\n\t\t\treturn { ok: true, deferred: true, sessionId: entry.sessionId, toCwd: entry.toCwd, ledgerError: entry.ledgerError,\n\t\t\t\tnote: '\u6587\u4EF6\u5DF2\u8FC1\u79FB\u4F46 DSH \u8D26\u672C\u4ECD\u672A\u6536\u655B\uFF1B\u91CD\u542F DSH \u540E\u518D\u6B21\u70B9\u5B8C\u6210\uFF0C\u6216\u9009\u62E9\u56DE\u6EDA' };\n\t\t}\n\t\tawait this.#finish(entry);\n\t\treturn { ok: true, sessionId: entry.sessionId, toCwd: entry.toCwd };\n\t}\n}\n", "/**\n * DSH session-storage path algebra. Mirrors `projectKey` / `encodeSegment` /\n * `projectDir` / `sessionDir` from `@deepseek-ai/dsh-session-persistence-jsonl`\n * (which does not export them). Every implementation is verified against the\n * live layout by `verifyEncoders` before any mutation runs, so a future official\n * change to the encoding rules fails closed (\u00A710 MN3) instead of corrupting data.\n */\nimport { readdir, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\n\n/** The `undefined` cwd bucket: sessions whose stored header carries no cwd. */\nexport const NO_CWD_DIR = '_no-cwd';\n\n/** Encode one id/path segment: safe code units stay literal, everything else becomes `~XXXX`. */\nexport function encodeSegment(raw) {\n\tif (raw.length === 0) throw new Error('cannot encode an empty path segment');\n\tif (raw === '.') return '~002E';\n\tif (raw === '..') return '~002E~002E';\n\tlet out = '';\n\tfor (let i = 0; i < raw.length; i++) {\n\t\tconst code = raw.charCodeAt(i);\n\t\tconst ch = String.fromCharCode(code);\n\t\tif (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) out += ch;\n\t\telse out += '~' + code.toString(16).toUpperCase().padStart(4, '0');\n\t}\n\treturn out;\n}\n\n/**\n * Build the readable project directory key for a canonical cwd, exactly like the\n * official backend: separators collapse to one `-`, unsafe units escape as `~XXXX`,\n * the whole key is wrapped in `--\u2026--` and bounded to 251 readable characters.\n */\nexport function projectKey(cwd) {\n\tif (cwd.length === 0) throw new Error('cannot encode an empty project path');\n\tlet readable = '';\n\tlet separatorRun = false;\n\tfor (let i = 0; i < cwd.length; i++) {\n\t\tconst code = cwd.charCodeAt(i);\n\t\tconst ch = String.fromCharCode(code);\n\t\tif (ch === '/' || ch === '\\\\' || ch === ':') {\n\t\t\tif (!separatorRun) readable += '-';\n\t\t\tseparatorRun = true;\n\t\t} else if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) {\n\t\t\treadable += ch;\n\t\t\tseparatorRun = false;\n\t\t} else {\n\t\t\treadable += '~' + code.toString(16).toUpperCase().padStart(4, '0');\n\t\t\tseparatorRun = false;\n\t\t}\n\t}\n\treturn `--${(readable.replace(/^-+/, '') || 'root').slice(0, 251)}--`;\n}\n\nexport function projectDir(root, cwd) {\n\treturn cwd === undefined ? join(root, NO_CWD_DIR) : join(root, projectKey(cwd));\n}\n\nexport function sessionDir(root, cwd, id) {\n\treturn join(projectDir(root, cwd), encodeSegment(id));\n}\n\nconst LOG_BASENAMES = ['session.jsonl', 'session.v1.jsonl', 'session.v2.jsonl', 'session.v3.jsonl', 'session.v4.jsonl',\n\t'session.jsonl.zstd', 'session.v1.jsonl.zstd', 'session.v2.jsonl.zstd', 'session.v3.jsonl.zstd', 'session.v4.jsonl.zstd'];\n\n/** Locate the authoritative session log inside one session directory (highest generation wins). */\nexport async function findLogFile(dir) {\n\tconst entries = await readdir(dir);\n\tconst present = LOG_BASENAMES.filter(name => entries.includes(name));\n\tif (present.length === 0) return undefined;\n\t// Compression-suffixed generations outrank the bare same-generation name; then highest version.\n\tconst zstd = present.filter(name => name.endsWith('.zstd'));\n\tconst pool = zstd.length > 0 ? zstd : present;\n\treturn pool.sort((left, right) => right.length - left.length || right.localeCompare(left))[0];\n}\n\n/** One candidate location for a session id, checked cheaply (directory stat only). */\nexport async function sessionDirExists(root, cwd, id) {\n\ttry { return (await stat(join(sessionDir(root, cwd, id)))).isDirectory(); } catch { return false; }\n}\n\n/**\n * Prove our local encoders agree with the shipped layout before anything writes:\n * for every provided {cwd, id, observedProjectDir, observedSessionDir} sample\n * (taken from headers the host itself enumerated), the directory derived by\n * projectKey/encodeSegment must match the observed path relative to the root.\n * @param samples - observed placement of stored sessions.\n * @param root - absolute sessions root; samples carry root-relative dirs.\n * @returns whether every sample reproduces.\n */\nexport function verifyEncoders(samples, root) {\n\tif (samples.length === 0) return false;\n\treturn samples.every(({ cwd, id, project, dir }) =>\n\t\tjoin(root, project, dir) === sessionDir(root, cwd, id) && join(root, project) === projectDir(root, cwd));\n}\n", "/**\n * Session log zstd artifact surgery. The shipped format is a concatenation of\n * independent zstd frames: frame 0 is the header line, every event is its own\n * frame (verified against live v4 logs and against `scanZstdFrames` in\n * `@deepseek-ai/dsh-session-persistence-jsonl`). Rewriting the header therefore\n * only rebuilds frame 0; every event frame is carried over byte-for-byte, which\n * keeps the operation cheap and reversible for arbitrarily large logs.\n */\nimport { constants, zstdCompressSync, zstdDecompressSync } from 'node:zlib';\n\nexport const ZSTD_MAGIC = 0xfd2fb528;\nconst SKIPPABLE_MAGIC_MIN = 0x184d2a50, SKIPPABLE_MAGIC_MAX = 0x184d2a5f;\n// The shipped writer puts an XXH64 content checksum on every frame; match it so\n// the rewritten header is indistinguishable in style from the original.\nconst CHECKSUM = { [constants.ZSTD_c_checksumFlag]: 1 };\n\n/**\n * Walk a frame sequence exactly like the official scanner (including skippable\n * frames). Throws on any malformed byte \u2014 the walk IS the post-write validation.\n * @param buffer - complete artifact bytes.\n * @returns ordered frames with byte ranges.\n */\nexport function scanFrames(buffer) {\n\tconst frames = [];\n\tlet offset = 0;\n\twhile (offset < buffer.length) {\n\t\tconst start = offset;\n\t\tif (buffer.length - offset < 4) throw new Error(`truncated zstd artifact: fewer than 4 bytes at ${offset}`);\n\t\tconst magic = buffer.readUInt32LE(offset);\n\t\tif (magic >= SKIPPABLE_MAGIC_MIN && magic <= SKIPPABLE_MAGIC_MAX) {\n\t\t\tconst size = buffer.readUInt32LE(offset + 4);\n\t\t\toffset += 8 + size;\n\t\t\tif (offset > buffer.length) throw new Error(`truncated skippable frame at ${start}`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (magic !== ZSTD_MAGIC) throw new Error(`invalid frame magic at byte ${offset}`);\n\t\toffset += 4;\n\t\tif (offset === buffer.length) throw new Error(`frame header missing at byte ${start}`);\n\t\tconst descriptor = buffer.readUInt8(offset);\n\t\toffset += 1;\n\t\tif ((descriptor & 24) !== 0) throw new Error(`reserved frame-header bit at byte ${offset - 1}`);\n\t\tconst contentSizeFlag = descriptor >>> 6;\n\t\tconst singleSegment = (descriptor & 32) !== 0;\n\t\tconst checksum = (descriptor & 4) !== 0;\n\t\tconst dictionaryFlag = descriptor & 3;\n\t\tconst dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;\n\t\tconst contentSizeBytes = contentSizeFlag === 0 ? (singleSegment ? 1 : 0) : 1 << contentSizeFlag;\n\t\tconst remaining = (singleSegment ? 0 : 1) + dictionaryBytes + contentSizeBytes;\n\t\tif (buffer.length - offset < remaining) throw new Error(`truncated frame header at byte ${start}`);\n\t\toffset += remaining;\n\t\tfor (;;) {\n\t\t\tif (buffer.length - offset < 3) throw new Error(`truncated block header at byte ${offset}`);\n\t\t\tconst blockHeader = buffer.readUIntLE(offset, 3);\n\t\t\toffset += 3;\n\t\t\tconst lastBlock = (blockHeader & 1) !== 0;\n\t\t\tconst blockType = blockHeader >>> 1 & 3;\n\t\t\tconst blockSize = blockHeader >>> 3;\n\t\t\tif (blockType === 3) throw new Error(`reserved block type at byte ${offset - 3}`);\n\t\t\tconst payloadBytes = blockType === 1 ? 1 : blockSize;\n\t\t\tif (buffer.length - offset < payloadBytes) throw new Error(`truncated block payload at byte ${offset}`);\n\t\t\toffset += payloadBytes;\n\t\t\tif (lastBlock) break;\n\t\t}\n\t\tif (checksum) {\n\t\t\tif (buffer.length - offset < 4) throw new Error(`truncated frame checksum at byte ${offset}`);\n\t\t\toffset += 4;\n\t\t}\n\t\tframes.push({ start, end: offset });\n\t}\n\treturn frames;\n}\n\nexport function decodeFrame(buffer, frame) {\n\treturn zstdDecompressSync(buffer.subarray(frame.start, frame.end));\n}\n\n/** Parse the header line of a session artifact (first non-skippable frame). */\nexport function readHeader(buffer) {\n\tconst frames = scanFrames(buffer);\n\tif (frames.length === 0) throw new Error('empty zstd artifact');\n\tconst text = decodeFrame(buffer, frames[0]).toString('utf8').trim();\n\tconst header = JSON.parse(text);\n\tif (header.type !== 'session' || typeof header.id !== 'string') throw new Error('malformed session header frame');\n\treturn { header, frames };\n}\n\n/**\n * Produce a complete artifact whose header frame carries a replaced cwd. The\n * header object keeps its original key order; only the `cwd` value changes\n * (`undefined` removes the field). All remaining frames are copied verbatim.\n * @param buffer - original artifact bytes.\n * @param nextCwd - canonical project directory for the moved session, or undefined.\n * @returns rewritten bytes.\n */\nexport function rewriteHeaderFrame(buffer, nextCwd) {\n\tconst { header, frames } = readHeader(buffer);\n\tconst updated = { ...header };\n\tif (nextCwd === undefined) delete updated.cwd;\n\telse updated.cwd = nextCwd;\n\tif (JSON.stringify(updated) === JSON.stringify(header)) return Buffer.from(buffer);\n\tconst frame0 = zstdCompressSync(Buffer.from(`${JSON.stringify(updated)}\\n`, 'utf8'), { params: CHECKSUM });\n\tscanFrames(frame0); // re-verify our own output before it ever touches the store\n\treturn Buffer.concat([frame0, buffer.subarray(frames[0].end)]);\n}\n", "/**\n * Trash bin for sessions and projects (\u00A711). Semantics pinned by the shipped\n * build: archiving is the reversible hide (slot kept, unarchive restores the\n * position), workspace deletion keeps every session log, and startup bootstrap\n * only re-claims sessions that are NOT archived \u2014 so \"archive all sessions +\n * delete the registration\" keeps a trashed project invisible until this ledger\n * restores it. All official effects run through a narrow registry adapter\n * (implemented in the host, faked in tests); the plugin-owned ledger snapshots\n * the placement, archive and pin state needed to restore them (\u00A711 TB1/TB5).\n *\n * `purge` is the hard-delete path the official surface has no command for\n * (\u00A711.1-1): it moves the session artifact into `pending-purge/` (same volume,\n * atomic placement, undoable until the last step), drops the projection-cache\n * record and vault manifest entries, and only then removes the ledger item.\n */\nimport { readdir, rm, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { encodeSegment } from './paths.mjs';\nimport { relocate } from './move.mjs';\n\nexport class TrashError extends Error {\n\tcode;\n\tconstructor(code, message) { super(message); this.name = 'TrashError'; this.code = code; }\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\nexport class TrashEngine {\n\t/**\n\t * @param deps - {adapter: RegistryAdapter, sessions?: () => liveSessionIds,\n\t * sessionsRoot, projcacheRoot, kitRoot, ledger: JsonDocument, vault?,\n\t * journal?: () => activeJournalEntry|null, settings?: () => trashSettings, now}\n\t */\n\tconstructor(deps) {\n\t\tthis.deps = deps;\n\t\tthis.ledger = deps.ledger;\n\t\tthis.now = deps.now ?? (() => Date.now());\n\t}\n\n\tasync items() { return (await this.ledger.read()).items.map(publicItem); }\n\n\t#guardFree(id) {\n\t\tif (typeof this.deps.journal === 'function' && this.deps.journal() !== null) {\n\t\t\tthrow new TrashError('journal-active', 'a journaled move is unresolved; finish or roll it back first');\n\t\t}\n\t\tconst live = this.deps.sessions?.() ?? [];\n\t\tif (live.includes(id)) throw new TrashError('session-busy', `session ${id} is live; open it and stop its work first`);\n\t}\n\n\t#find(state, predicate) { return state.items.find(predicate); }\n\n\t/** \u00A711 TB3: trash one session (archive + ledger; already-archived sessions only enter the bin). */\n\tasync trashSession(sessionId, { force = false } = {}) {\n\t\tthis.#guardFree(sessionId);\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tif (this.#find(state, item => item.kind === 'session' && item.id2 === sessionId)) throw new TrashError('already-trashed', 'this session is already in the trash bin');\n\t\tif (!await adapter.sessionKnown(sessionId)) throw new TrashError('session-unknown', `session ${sessionId} is unknown to the registry`);\n\t\tconst archived = await adapter.archivedSet();\n\t\tconst pinned = await adapter.pinnedSet();\n\t\tconst { workspaceId, beforeId, title } = await adapter.locateSession(sessionId);\n\t\tif (!archived.has(sessionId)) await adapter.archiveSession(sessionId, force ? { stopActivity: true } : {});\n\t\tconst item = {\n\t\t\tid: randomUUID(), kind: 'session', id2: sessionId, trashedAt: new Date(this.now()).toISOString(),\n\t\t\tsnapshot: { sessionId, workspaceId: workspaceId ?? null, beforeId: beforeId ?? null,\n\t\t\t\tpreviouslyArchived: archived.has(sessionId), previouslyPinned: pinned.has(sessionId), title: title ?? null },\n\t\t};\n\t\tstate.items.push(item);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true, itemId: item.id };\n\t}\n\n\t/** \u00A711 TB4: trash a project (archive all its sessions, snapshot order/state, delete registration). */\n\tasync trashWorkspace(workspaceId, { force = false } = {}) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tif (this.#find(state, item => item.kind === 'workspace' && item.id2 === workspaceId)) throw new TrashError('already-trashed', 'this project is already in the trash bin');\n\t\tconst snapshot = await adapter.workspaceSnapshot(workspaceId);\n\t\tif (snapshot === undefined) throw new TrashError('workspace-unknown', `workspace ${workspaceId} not found`);\n\t\tconst live = new Set(this.deps.sessions?.() ?? []);\n\t\tif (!force && snapshot.sessions.some(row => live.has(row.sessionId))) throw new TrashError('workspace-busy', 'the project has live sessions; use force to stop and trash them');\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (row.previouslyArchived) continue;\n\t\t\tawait adapter.archiveSession(row.sessionId, live.has(row.sessionId) ? { stopActivity: true } : {});\n\t\t}\n\t\tconst item = { id: randomUUID(), kind: 'workspace', id2: workspaceId, trashedAt: new Date(this.now()).toISOString(), snapshot };\n\t\tstate.items.push(item);\n\t\tawait this.ledger.write(state);\n\t\tawait adapter.deleteWorkspace(workspaceId);\n\t\treturn { ok: true, itemId: item.id };\n\t}\n\n\t/** \u00A711 TB5 idempotent restore: converge to the snapshot; failures propagate so the item survives for retry. */\n\tasync restore(itemId) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tconst item = this.#find(state, row => row.id === itemId);\n\t\tif (item === undefined) throw new TrashError('item-unknown', `no trash item ${itemId}`);\n\t\tif (item.kind === 'session') await this.#restoreSession(adapter, item.snapshot);\n\t\telse await this.#restoreWorkspace(adapter, item.snapshot);\n\t\tstate.items = state.items.filter(row => row.id !== itemId);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true };\n\t}\n\n\tasync #restoreSession(adapter, snapshot) {\n\t\tconst { sessionId, workspaceId, beforeId, previouslyArchived, previouslyPinned } = snapshot;\n\t\tif (!previouslyArchived) await adapter.unarchiveSession(sessionId);\n\t\tif (workspaceId !== null) await adapter.repairSlot(sessionId, workspaceId, beforeId);\n\t\tif (previouslyPinned) await adapter.pinSession(sessionId);\n\t}\n\n\tasync #restoreWorkspace(adapter, snapshot) {\n\t\tawait adapter.restoreWorkspace(snapshot);\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (!row.previouslyArchived) await adapter.unarchiveSession(row.sessionId);\n\t\t}\n\t\t// Pins are dropped by archiving (official rule); restore them for sessions\n\t\t// that were pinned before entering the bin.\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (row.previouslyPinned && !row.previouslyArchived) await adapter.pinSession(row.sessionId).catch(() => {});\n\t\t}\n\t}\n\n\t/** \u00A711 TB6: hard-delete with staging so a crash never yields a half-deleted state. */\n\tasync purge(itemId) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tconst item = this.#find(state, row => row.id === itemId);\n\t\tif (item === undefined) throw new TrashError('item-unknown', `no trash item ${itemId}`);\n\t\tconst sessionIds = item.kind === 'session' ? [item.snapshot.sessionId] : item.snapshot.sessions.map(row => row.sessionId);\n\t\tfor (const sessionId of sessionIds) this.#guardFree(sessionId);\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tawait this.#stageArtifact(sessionId);\n\t\t\tif (adapter.purgeSession) await adapter.purgeSession(sessionId);\n\t\t}\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tawait adapter.unpinSession(sessionId).catch(() => {});\n\t\t\tawait adapter.unarchiveSession(sessionId).catch(() => {});\n\t\t}\n\t\tif (item.kind === 'workspace') await adapter.deleteWorkspace(item.id2).catch(() => {});\n\t\tif (this.deps.vault?.dropSession) for (const sessionId of sessionIds) await this.deps.vault.dropSession(sessionId);\n\t\tstate.items = state.items.filter(row => row.id !== itemId);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true, purged: sessionIds };\n\t}\n\n\tasync #stageArtifact(sessionId) {\n\t\tconst encoded = encodeSegment(sessionId);\n\t\tconst root = this.deps.sessionsRoot;\n\t\tlet found;\n\t\tfor (const project of await readdir(root).catch(() => [])) {\n\t\t\tif (project.startsWith('.')) continue;\n\t\t\ttry { if ((await stat(join(root, project, encoded))).isDirectory()) { found = join(root, project, encoded); break; } } catch {}\n\t\t}\n\t\tif (found === undefined) return; // already staged away (idempotent)\n\t\tconst staged = join(this.deps.kitRoot, 'pending-purge', `${sessionId}__${this.now()}`);\n\t\tawait relocate(found, staged);\n\t\tif (this.deps.projcacheRoot) await rm(join(this.deps.projcacheRoot, `${sessionId}.json`), { force: true });\n\t\t// Durable placement done; only now drop the real bytes.\n\t\tawait rm(staged, { recursive: true, force: true });\n\t}\n\n\t/** TTL sweep (\u00A711 T5). With autoPurge, expired items are hard-deleted; otherwise reported. */\n\tasync sweep({ now = this.now() } = {}) {\n\t\tconst state = await this.ledger.read();\n\t\tconst settings = this.deps.settings?.() ?? {};\n\t\tconst ttlDays = settings.ttlDays ?? 30;\n\t\tconst auto = settings.autoPurge === true;\n\t\tconst report = { expired: [], purged: [], skipped: [] };\n\t\tfor (const item of state.items) {\n\t\t\tconst trashedAt = Date.parse(item.trashedAt);\n\t\t\tif (!Number.isFinite(trashedAt) || now - trashedAt < ttlDays * DAY) continue;\n\t\t\treport.expired.push({ itemId: item.id, kind: item.kind, targetId: item.id2 });\n\t\t\tif (!auto) continue;\n\t\t\ttry { await this.purge(item.id); report.purged.push(item.id); }\n\t\t\tcatch (error) { report.skipped.push({ itemId: item.id, reason: String(error?.message ?? error) }); }\n\t\t}\n\t\treturn report;\n\t}\n}\n\nfunction publicItem(item) {\n\treturn { itemId: item.id, kind: item.kind, targetId: item.id2, trashedAt: item.trashedAt, snapshot: item.snapshot };\n}\n", "/**\n * Loopback management endpoint, same trust model as dsh-multi-router: exact\n * `/.well-known` route, host-header + socket must be loopback, Origin/\n * Sec-Fetch-Site cross-site rejected, writes need the per-process random key\n * the GET hands out (timing-safe compare). The handler is framework-free so the\n * host wires it into `ctx.webServer.register` and the CLI can call it directly.\n */\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport const API_PATH = '/.well-known/dsh-session-toolbox';\nconst MAX_BODY = 4 * 1024 * 1024;\n\nclass ApiError extends Error {\n\tstatus;\n\tconstructor(status, message) { super(message); this.status = status; }\n}\n\nconst json = (res, status, value) => {\n\tres.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' });\n\tres.end(JSON.stringify(value));\n};\n\nconst hostIsLoopback = host => {\n\tconst name = String(host ?? '').split(':')[0];\n\treturn ['localhost', '127.0.0.1', '::1', '[::1]', ''].includes(name) || name.startsWith('127.');\n};\n\n/**\n * @param kit - {state(): snapshot, action(input): result, move, trash, settings, vaultManifest}\n */\nexport function apiHandler(kit) {\n\tconst key = randomBytes(32).toString('base64url');\n\treturn async (req, res) => {\n\t\ttry {\n\t\t\tconst remote = req.socket?.remoteAddress;\n\t\t\tif (!hostIsLoopback(req.headers.host) || (remote && !['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(remote))) throw new ApiError(403, '\u4EC5\u5141\u8BB8\u672C\u673A\u8BF7\u6C42');\n\t\t\tconst origin = req.headers.origin;\n\t\t\tif (origin && origin !== `http://${req.headers.host}` && origin !== `https://${req.headers.host}`) throw new ApiError(403, '\u6765\u6E90\u65E0\u6548');\n\t\t\tif (req.headers['sec-fetch-site'] === 'cross-site') throw new ApiError(403, '\u6765\u6E90\u65E0\u6548');\n\t\t\tif (req.method === 'GET') { json(res, 200, { ...await kit.state(), key }); return; }\n\t\t\tif (req.method !== 'POST') throw new ApiError(405, '\u65B9\u6CD5\u65E0\u6548');\n\t\t\tconst actual = Buffer.from(String(req.headers['x-session-toolbox-key'] ?? '')), expected = Buffer.from(key);\n\t\t\tif (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw new ApiError(401, '\u8BF7\u5237\u65B0\u9762\u677F\u540E\u91CD\u8BD5');\n\t\t\tif (!/^application\\/json(?:\\s*;|$)/i.test(String(req.headers['content-type'] ?? ''))) throw new ApiError(415, '\u9700\u8981 JSON');\n\t\t\tlet size = 0; const chunks = [];\n\t\t\tfor await (const chunk of req) { size += chunk.length; if (size > MAX_BODY) throw new ApiError(413, '\u8BF7\u6C42\u8FC7\u5927'); chunks.push(chunk); }\n\t\t\tlet input;\n\t\t\ttry { input = JSON.parse(Buffer.concat(chunks).toString('utf8')); } catch { throw new ApiError(400, 'JSON \u65E0\u6548'); }\n\t\t\tif (input === null || typeof input !== 'object' || typeof input.type !== 'string') throw new ApiError(400, '\u7F3A\u5C11\u64CD\u4F5C\u7C7B\u578B');\n\t\t\tjson(res, 200, { ...await kit.action(input), key });\n\t\t} catch (error) {\n\t\t\tjson(res, error instanceof ApiError ? error.status : 500, { error: error instanceof ApiError ? error.message : `\u64CD\u4F5C\u5931\u8D25\uFF1A${error?.message ?? error}` });\n\t\t}\n\t};\n}\n\n/** Shared dispatch so the host, the CLI and tests all speak one vocabulary. */\nexport async function dispatch(kit, input) {\n\tswitch (input.type) {\n\t\tcase 'preflight': return await kit.move.preflight({ sessionId: String(input.sessionId ?? ''), toCwd: String(input.toCwd ?? ''), createTarget: input.createTarget === true });\n\t\tcase 'move': return await kit.move.move(await kit.move.preflight({ sessionId: String(input.sessionId ?? ''), toCwd: String(input.toCwd ?? ''), createTarget: input.createTarget === true }));\n\t\tcase 'move.rollback': return await kit.move.rollback();\n\t\tcase 'move.complete': return await kit.move.complete();\n\t\tcase 'trash.list': return { items: await kit.trash.items() };\n\t\tcase 'trash.session': return await kit.trash.trashSession(String(input.sessionId ?? ''), { force: input.force === true });\n\t\tcase 'trash.workspace': return await kit.trash.trashWorkspace(String(input.workspaceId ?? ''), { force: input.force === true });\n\t\tcase 'trash.restore': return await kit.trash.restore(String(input.itemId ?? ''));\n\t\tcase 'trash.purge': return await kit.trash.purge(String(input.itemId ?? ''));\n\t\tcase 'trash.sweep': return await kit.trash.sweep();\n\t\tcase 'settings.update': return { settings: await kit.updateSettings(input.patch ?? {}) };\n\t\tcase 'vault.sync': return { records: (await kit.vaultSync(Array.isArray(input.records) ? input.records : [])).records.length };\n\t\tcase 'vault.sweep': {\n\t\t\tconst settings = await kit.settings.read();\n\t\t\tconst ttlMs = (settings.draftVault?.ttlDays ?? 7) * 24 * 60 * 60 * 1000;\n\t\t\tconst manifest = await kit.manifest.update(current => ({\n\t\t\t\tversion: 1,\n\t\t\t\trecords: current.records.filter(record => Date.now() - (record.createdAt ?? 0) <= ttlMs),\n\t\t\t}));\n\t\t\treturn { records: manifest.records.length };\n\t\t}\n\t\tdefault: throw new Error(`\u672A\u77E5\u7684\u64CD\u4F5C\u7C7B\u578B\uFF1A${input.type}`);\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Plugin-owned durable documents under `<DSH_HOME>/session-toolbox/`. All writes go\n * through `@deepseek-ai/dsh-atomic-write` (`writeFileAtomic` inside `withFileLock`)\n * with owner-only modes, mirroring the host's durability discipline. Corrupt\n * files are never auto-reset: they fail loud and surface in status.\n */\nimport { mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { writeFileAtomic, withFileLock } from '@deepseek-ai/dsh-atomic-write';\n\nexport const DEFAULT_SETTINGS = Object.freeze({\n\tversion: 1,\n\tdraftVault: { enabled: true, maxSizeBytes: 200 * 1024 * 1024, ttlDays: 7 },\n\ttrash: { ttlDays: 30, autoPurge: false },\n\tmove: { enabled: true },\n});\n\nconst OWNED = { mode: 0o600, dirMode: 0o700 };\n\nfunction mergeSettings(raw) {\n\treturn {\n\t\tversion: 1,\n\t\tdraftVault: { ...DEFAULT_SETTINGS.draftVault, ...(raw.draftVault ?? {}) },\n\t\ttrash: { ...DEFAULT_SETTINGS.trash, ...(raw.trash ?? {}) },\n\t\tmove: { ...DEFAULT_SETTINGS.move, ...(raw.move ?? {}) },\n\t};\n}const positiveInt = value => Number.isSafeInteger(value) && value > 0;\n\n/** One durable JSON document: locked read-modify-write + schema guard. */\nexport class JsonDocument {\n\tfile;\n\t#fallback;\n\t#guard;\n\tconstructor(root, name, fallback, guard) {\n\t\tthis.file = join(root, name);\n\t\tthis.#fallback = fallback;\n\t\tthis.#guard = guard;\n\t}\n\tasync read() {\n\t\tlet value;\n\t\ttry {\n\t\t\tvalue = JSON.parse(await readFile(this.file, 'utf8'));\n\t\t} catch (error) {\n\t\t\tif (error.code === 'ENOENT') value = structuredClone(this.#fallback);\n\t\t\telse if (error instanceof SyntaxError) throw new Error(`session-toolbox: corrupt JSON in ${this.file}: ${error.message}`, { cause: error });\n\t\t\telse throw error;\n\t\t}\n\t\tif (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error(`session-toolbox: ${this.file} is not a JSON object`);\n\t\treturn this.#guard === undefined ? value : this.#guard(value, this.file);\n\t}\n\tasync write(value) {\n\t\tthis.#guard?.(value, this.file);\n\t\t// The lock sibling is created before writeFileAtomic's own mkdir, so the\n\t\t// parent directory must already exist for withFileLock.\n\t\tawait mkdir(dirname(this.file), { recursive: true, mode: 0o700 });\n\t\tawait withFileLock(this.file, () => writeFileAtomic(this.file, JSON.stringify(value, null, 2), OWNED));\n\t\treturn value;\n\t}\n\t/** Serialized read-modify-write; `fn` returning undefined aborts without writing. */\n\tasync update(fn) {\n\t\tawait mkdir(dirname(this.file), { recursive: true, mode: 0o700 });\n\t\treturn withFileLock(this.file, async () => {\n\t\t\tconst current = await this.read();\n\t\t\tconst next = fn(current);\n\t\t\tif (next === undefined) return current;\n\t\t\tthis.#guard?.(next, this.file);\n\t\t\tawait writeFileAtomic(this.file, JSON.stringify(next, null, 2), OWNED);\n\t\t\treturn next;\n\t\t});\n\t}\n}\n\nexport function guardSettings(value, file) {\n\tif (value.version !== undefined && value.version !== 1) throw new Error(`session-toolbox: unsupported settings version in ${file}: ${String(value.version)}`);\n\tconst draft = value.draftVault ?? {};\n\tif (draft.enabled !== undefined && typeof draft.enabled !== 'boolean') throw new Error(`session-toolbox: settings.draftVault.enabled must be boolean (${file})`);\n\tif (draft.maxSizeBytes !== undefined && !positiveInt(draft.maxSizeBytes)) throw new Error(`session-toolbox: settings.draftVault.maxSizeBytes must be a positive safe integer (${file})`);\n\tif (draft.ttlDays !== undefined && !positiveInt(draft.ttlDays)) throw new Error(`session-toolbox: settings.draftVault.ttlDays must be a positive integer (${file})`);\n\tconst trash = value.trash ?? {};\n\tif (trash.ttlDays !== undefined && !positiveInt(trash.ttlDays)) throw new Error(`session-toolbox: settings.trash.ttlDays must be a positive integer (${file})`);\n\tif (trash.autoPurge !== undefined && typeof trash.autoPurge !== 'boolean') throw new Error(`session-toolbox: settings.trash.autoPurge must be boolean (${file})`);\n\treturn mergeSettings(value);\n}\n\nexport function guardJournal(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported journal version in ${file}: ${String(value.version)}`);\n\tconst entry = value.active;\n\tif (entry === null || entry === undefined) return value;\n\tif (typeof entry.sessionId !== 'string' || typeof entry.fromCwd !== 'string' && entry.fromCwd !== null || typeof entry.toCwd !== 'string') {\n\t\tthrow new Error(`session-toolbox: malformed move journal (${file})`);\n\t}\n\tif (!Array.isArray(entry.done) || typeof entry.startedAt !== 'string') throw new Error(`session-toolbox: move journal lacks done/startedAt (${file})`);\n\treturn value;\n}\n\nexport function guardLedger(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported ledger version in ${file}: ${String(value.version)}`);\n\tif (!Array.isArray(value.items)) throw new Error(`session-toolbox: trash ledger has no items array (${file})`);\n\tfor (const item of value.items) {\n\t\tif ((item.kind !== 'session' && item.kind !== 'workspace') || typeof item.id !== 'string') throw new Error(`session-toolbox: malformed trash item (${file})`);\n\t\tif (item.snapshot === null || typeof item.snapshot !== 'object') throw new Error(`session-toolbox: trash item lacks snapshot (${file})`);\n\t}\n\treturn value;\n}\n\nexport function guardManifest(value, file) {\n\tif (value.version !== 1) throw new Error(`session-toolbox: unsupported vault manifest version in ${file}: ${String(value.version)}`);\n\tif (!Array.isArray(value.records)) throw new Error(`session-toolbox: vault manifest has no records array (${file})`);\n\tfor (const record of value.records) {\n\t\tif (typeof record.sessionId !== 'string' || typeof record.attachmentId !== 'string') throw new Error(`session-toolbox: malformed vault record (${file})`);\n\t}\n\treturn value;\n}\n\nexport { mergeSettings, OWNED };\n", "/**\n * Session-to-project move (\u00A710). The engine is capability-injected: the host\n * wires it to `workspaceRegistry` / `sessionPersistence` / `sessionQuery`, the\n * CLI wires an offline ledger over `workspace.json`. Phases are journaled so an\n * interrupted move is detected on startup and rolled back or completed\n * deterministically (\u00A710 MR2/MR3, MN1).\n *\n * Critical-section ordering (\u00A710.6): backup \u2192 stage new artifact (header\n * rewritten + fsynced) \u2192 commit placement \u2192 ledger \u2192 caches. The store never\n * exposes a window where one id exists in two project directories, and the\n * ledger runs only after placement is consistent, so `attachSession`'s\n * header-cwd validation holds by construction.\n */\nimport { createHash } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport { mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { encodeSegment, findLogFile, projectKey, verifyEncoders } from './paths.mjs';\nimport { readHeader, rewriteHeaderFrame } from './session-log.mjs';\n\nexport const PHASES = ['backup', 'rewrite', 'commit', 'ledger', 'projcache', 'index'];\n\nexport class MovePreflightError extends Error {\n\tcode;\n\tdetails;\n\tconstructor(code, message, details = {}) {\n\t\tsuper(message);\n\t\tthis.name = 'MovePreflightError';\n\t\tthis.code = code;\n\t\tthis.details = details;\n\t}\n}\n\nconst sha256 = buffer => createHash('sha256').update(buffer).digest('hex');\n\nasync function fsyncFile(path) {\n\tconst handle = await open(path, constants.O_WRONLY);\n\ttry { await handle.sync(); } finally { await handle.close(); }\n}\n\nexport async function writeOwned(file, data, mode = 0o600) {\n\tawait mkdir(dirname(file), { recursive: true, mode: 0o700 });\n\tconst temp = `${file}.${process.pid}.${Date.now()}.tmp`;\n\tawait writeFile(temp, data, { mode, flag: 'wx' });\n\tawait rename(temp, file);\n\treturn file;\n}\n\n/**\n * Move a directory between the sessions store and the kit working areas.\n * `rename` is the atomic same-volume path; a cross-device layout (unusual, but\n * possible when DSH_HOME points at a separate mount) falls back to a\n * copy-then-remove so a move never dead-ends half-published.\n */\nexport async function relocate(source, target) {\n\tawait mkdir(dirname(target), { recursive: true, mode: 0o700 });\n\ttry {\n\t\tawait rename(source, target);\n\t\treturn;\n\t} catch (error) {\n\t\tif (error.code !== 'EXDEV') throw error;\n\t}\n\tconst { cp } = await import('node:fs/promises');\n\tawait cp(source, target, { recursive: true, errorOnExist: true, force: false });\n\tawait rm(source, { recursive: true, force: true });\n}\n\n/**\n * @param deps - {root (kit dir), sessionsRoot, projcacheRoot, journal: JsonDocument,\n * capabilities: {sessionLive, listHeaders, moveLedger, resyncIndex, refreshHeaderCache}, now}\n */\nexport class MoveEngine {\n\tconstructor(deps) {\n\t\tthis.root = deps.root;\n\t\tthis.sessionsRoot = deps.sessionsRoot;\n\t\tthis.projcacheRoot = deps.projcacheRoot;\n\t\tthis.journal = deps.journal;\n\t\tthis.caps = deps.capabilities ?? {};\n\t\tthis.now = deps.now ?? (() => Date.now());\n\t}\n\n\tasync readJournal() { return (await this.journal.read()).active ?? null; }\n\tasync writeJournal(entry) { await this.journal.write({ version: 1, active: entry }); }\n\n\t/** List every journaled placement hazard for status surfaces. */\n\tasync recoverable() { return await this.readJournal() !== null; }\n\n\t/**\n\t * Fail-closed feasibility check (\u00A710 MR1). Returns the plan or throws\n\t * MovePreflightError with a stable code; never touches anything.\n\t */\n\tasync preflight({ sessionId, toCwd, createTarget = false }) {\n\t\tif (typeof sessionId !== 'string' || !sessionId.startsWith('session-')) throw new MovePreflightError('bad-request', 'sessionId must look like session-<uuid>');\n\t\tif (typeof toCwd !== 'string' || (!toCwd.startsWith('/') && !/^[A-Za-z]:[\\\\/]/.test(toCwd))) throw new MovePreflightError('bad-request', 'toCwd must be an absolute path');\n\t\tif (await this.readJournal() !== null) throw new MovePreflightError('journal-active', 'another move is journaled; complete or roll it back first');\n\t\tif (this.caps.sessionLive?.(sessionId)) throw new MovePreflightError('session-busy', `session ${sessionId} is live; stop its work before moving`);\n\t\tconst headers = await this.caps.listHeaders();\n\t\tconst header = headers.find(row => row.id === sessionId);\n\t\tif (header === undefined) throw new MovePreflightError('session-unknown', `no stored session ${sessionId}`);\n\t\tif (typeof header.version === 'number' && header.version < 4) throw new MovePreflightError('format-legacy', `stored log is format v${header.version}; open the session once in DSH so the host migrates it, then retry`);\n\n\t\t// Locate the authoritative directory by scanning project dirs \u2014 never trust a computed path alone.\n\t\tconst encoded = encodeSegment(sessionId);\n\t\tconst entries = await readdir(this.sessionsRoot, { withFileTypes: true }).catch(error => {\n\t\t\tif (error.code === 'ENOENT') return [];\n\t\t\tthrow error;\n\t\t});\n\t\tconst projects = entries.filter(entry => entry.isDirectory() && !entry.name.startsWith('.')).map(entry => entry.name);\n\t\tconst found = [];\n\t\tfor (const project of projects) {\n\t\t\ttry { if ((await stat(join(this.sessionsRoot, project, encoded))).isDirectory()) found.push(project); } catch {}\n\t\t}\n\t\tif (found.length > 1) throw new MovePreflightError('duplicate-artifact', `session ${sessionId} lives in ${found.length} project directories; refusing to guess`);\n\t\tif (found.length === 0) throw new MovePreflightError('artifact-missing', `session ${sessionId} has no session directory under any project`);\n\t\tconst fromProject = found[0];\n\t\tconst logName = await findLogFile(join(this.sessionsRoot, fromProject, encoded));\n\t\tif (logName === undefined) throw new MovePreflightError('artifact-missing', `session directory for ${sessionId} holds no session log`);\n\t\tconst logPath = join(this.sessionsRoot, fromProject, encoded, logName);\n\t\t// \u00A710 MR1 belt-and-braces (CLI/offline path): a freshly-written log means an\n\t\t// appender is active; moving it now would orphan their writes.\n\t\tconst logStat = await stat(logPath);\n\t\tif (this.now() - logStat.mtimeMs < 10_000) throw new MovePreflightError('session-churning', `session log was written ${Math.round((this.now() - logStat.mtimeMs) / 1000)}s ago; make sure DSH has stopped using it, then retry`);\n\t\tif (header.cwd !== undefined && fromProject !== projectKey(header.cwd)) {\n\t\t\t// \u00A710 MN3: the layout changed in a way this build cannot follow.\n\t\t\tthrow new MovePreflightError('unknown-layout', `cwd '${header.cwd}' should live at '${projectKey(header.cwd)}' but the artifact was observed at '${fromProject}'`);\n\t\t}\n\t\tconst fromCwd = header.cwd;\n\t\tlet canonicalTo;\n\t\ttry { canonicalTo = await realpath(toCwd.replace(/[/\\\\]+$/, '') || toCwd); } catch { canonicalTo = undefined; }\n\t\tif (canonicalTo === undefined) {\n\t\t\tif (!createTarget) throw new MovePreflightError('target-missing', `target directory ${toCwd} does not exist (choose create to make it)`);\n\t\t\tawait mkdir(toCwd, { recursive: true });\n\t\t\tcanonicalTo = await realpath(toCwd);\n\t\t}\n\t\tif (fromCwd !== undefined && canonicalTo === fromCwd) throw new MovePreflightError('same-target', 'the session already belongs to that project');\n\t\tconst samples = headers.filter(row => row.cwd !== undefined).slice(0, 5)\n\t\t\t.map(row => ({ cwd: row.cwd, id: row.id, project: projectKey(row.cwd), dir: encodeSegment(row.id) }));\n\t\tif (samples.length > 0 && !verifyEncoders(samples, this.sessionsRoot)) {\n\t\t\tthrow new MovePreflightError('unknown-layout', 'project-key / segment encoders disagree with the shipped layout; refusing to write');\n\t\t}\n\t\treturn {\n\t\t\tsessionId, fromCwd: fromCwd ?? null, toCwd: canonicalTo,\n\t\t\tfromProject, toProject: projectKey(canonicalTo),\n\t\t\tdir: join(this.sessionsRoot, fromProject, encoded),\n\t\t\tnewDir: join(this.sessionsRoot, projectKey(canonicalTo), encoded),\n\t\t\tlogName,\n\t\t\tstartedAt: new Date(this.now()).toISOString(),\n\t\t};\n\t}\n\n\tasync #stage(entry, phase) {\n\t\tif (!entry.done.includes(phase)) { entry.done = [...entry.done, phase]; await this.writeJournal(entry); }\n\t}\n\n\t/** Execute the whole move; on failure the journal survives for rollback/complete. */\n\tasync move(plan) {\n\t\tconst entry = { ...plan, done: [], deferredLedger: false,\n\t\t\tbackup: join(this.root, 'backups', `${plan.sessionId}.orig`),\n\t\t\tstagedNew: join(this.root, 'backups', `${plan.sessionId}.new`),\n\t\t\tretired: join(this.root, 'pending-purge', `${plan.sessionId}__${this.now()}`) };\n\t\tawait this.writeJournal(entry);\n\t\ttry {\n\t\t\tawait this.phaseBackup(entry);\n\t\t\tawait this.phaseRewrite(entry);\n\t\t\tawait this.phaseCommit(entry);\n\t\t\tawait this.phaseLedger(entry);\n\t\t\tawait this.phaseProjcache(entry);\n\t\t\tawait this.phaseIndex(entry);\n\t\t} catch (error) {\n\t\t\terror.journal = await this.readJournal();\n\t\t\tthrow error;\n\t\t}\n\t\t// A deferred ledger (same-process stale header cache) keeps the journal alive\n\t\t// as the retry marker: the artifact is already moved, and the next process \u2014\n\t\t// or move.complete \u2014 converges the accounting (\u00A710 MR3).\n\t\tif (entry.deferredLedger === true) {\n\t\t\tawait this.writeJournal(entry);\n\t\t\treturn { ok: true, deferred: true, sessionId: entry.sessionId, toCwd: entry.toCwd,\n\t\t\t\tnote: '\u6587\u4EF6\u5DF2\u8FC1\u79FB\uFF1BDSH \u8D26\u672C\u5C06\u5728\u4E0B\u6B21\u542F\u52A8\u6216 move.complete \u65F6\u6536\u655B' };\n\t\t}\n\t\tawait this.#finish(entry);\n\t\treturn { ok: true, sessionId: entry.sessionId, toCwd: entry.toCwd, deferredLedger: entry.deferredLedger === true };\n\t}\n\n\tasync #finish(entry) {\n\t\tawait this.writeJournal(null);\n\t\tawait rm(entry.backup, { force: true });\n\t\tawait rm(entry.stagedNew, { force: true });\n\t\tif (entry.retired !== undefined) await rm(entry.retired, { recursive: true, force: true });\n\t}\n\n\tasync phaseBackup(entry) {\n\t\tconst source = await readFile(join(entry.dir, entry.logName));\n\t\tawait writeOwned(entry.backup, source);\n\t\tentry.sourceHash = sha256(source);\n\t\tawait this.#stage(entry, 'backup');\n\t}\n\n\tasync phaseRewrite(entry) {\n\t\tconst source = await readFile(entry.backup);\n\t\tif (sha256(source) !== entry.sourceHash) throw new MovePreflightError('source-changed', 'the session log changed between backup and rewrite');\n\t\tconst current = readHeader(source);\n\t\tif (current.header.id !== entry.sessionId) throw new MovePreflightError('artifact-mismatch', `log header id '${current.header.id}' does not name ${entry.sessionId}`);\n\t\tconst rewritten = rewriteHeaderFrame(source, entry.toCwd);\n\t\treadHeader(rewritten); // parse + walk validation of our own output before staging\n\t\tif (sha256(rewritten) === entry.sourceHash) throw new MovePreflightError('rewrite-noop', 'header rewrite produced identical bytes');\n\t\tawait writeOwned(entry.stagedNew, rewritten);\n\t\tawait fsyncFile(entry.stagedNew);\n\t\tawait this.#stage(entry, 'rewrite');\n\t}\n\n\tasync phaseCommit(entry) {\n\t\t// Retire first, then publish: the id is never simultaneously discoverable in two project dirs.\n\t\tawait relocate(entry.dir, entry.retired);\n\t\tawait mkdir(entry.newDir, { recursive: true, mode: 0o700 });\n\t\tawait writeOwned(join(entry.newDir, entry.logName), await readFile(entry.stagedNew));\n\t\tawait fsyncFile(join(entry.newDir, entry.logName));\n\t\t// Carry non-log artifacts (session-local files); never resurrect a stale lock.\n\t\tfor (const name of await readdir(entry.retired).catch(() => [])) {\n\t\t\tif (name === entry.logName || name === 'session.lock') continue;\n\t\t\tawait rename(join(entry.retired, name), join(entry.newDir, name)).catch(() => {});\n\t\t}\n\t\tawait rm(join(entry.newDir, 'session.lock'), { force: true });\n\t\tawait this.#stage(entry, 'commit');\n\t}\n\n\tasync phaseLedger(entry) {\n\t\tif (this.caps.moveLedger === undefined) { entry.deferredLedger = true; await this.#stage(entry, 'ledger'); return; }\n\t\ttry {\n\t\t\tawait this.caps.refreshHeaderCache?.();\n\t\t\tawait this.caps.moveLedger(entry.sessionId, entry.fromCwd ?? undefined, entry.toCwd);\n\t\t\tentry.deferredLedger = false;\n\t\t} catch (error) {\n\t\t\t// The registry's header/pin caches can lag a same-process move. Leaving the\n\t\t\t// journal's ledger phase undone lets startup recovery re-run it in a fresh\n\t\t\t// process where the caches are cold (\u00A710 MR3/MR4).\n\t\t\tentry.deferredLedger = true;\n\t\t\tentry.ledgerError = String(error?.message ?? error);\n\t\t}\n\t\tawait this.#stage(entry, 'ledger');\n\t}\n\n\tasync phaseProjcache(entry) {\n\t\tif (this.projcacheRoot !== undefined) await rm(join(this.projcacheRoot, `${entry.sessionId}.json`), { force: true });\n\t\tawait this.#stage(entry, 'projcache');\n\t}\n\n\tasync phaseIndex(entry) {\n\t\tawait this.caps.resyncIndex?.();\n\t\tawait this.#stage(entry, 'index');\n\t}\n\n\t/** Undo completed phases in reverse (\u00A710 MR3). */\n\tasync rollback() {\n\t\tconst entry = await this.readJournal();\n\t\tif (entry === null) throw new MovePreflightError('no-journal', 'no journaled move to roll back');\n\t\tif (entry.done.includes('commit')) {\n\t\t\tawait rm(entry.newDir, { recursive: true, force: true });\n\t\t\tawait mkdir(dirname(entry.dir), { recursive: true, mode: 0o700 });\n\t\t\tif (entry.retired !== undefined) await relocate(entry.retired, entry.dir);\n\t\t\telse throw new MovePreflightError('journal-order', 'committed journal lost its retired directory');\n\t\t}\n\t\tif (entry.deferredLedger !== true && entry.done.includes('ledger') && this.caps.moveLedger !== undefined) {\n\t\t\tawait this.caps.moveLedger(entry.sessionId, entry.toCwd, entry.fromCwd ?? undefined).catch(() => {});\n\t\t\tawait this.caps.refreshHeaderCache?.().catch(() => {});\n\t\t}\n\t\tif (this.projcacheRoot !== undefined) await rm(join(this.projcacheRoot, `${entry.sessionId}.json`), { force: true });\n\t\tawait this.caps.resyncIndex?.().catch(() => {});\n\t\tawait this.#finish({ ...entry, retired: entry.done.includes('commit') ? undefined : entry.retired });\n\t\treturn { ok: true, rolledBack: entry.done };\n\t}\n\n\t/** Resume a journaled move from its first missing phase (post-crash forward roll). */\n\tasync complete() {\n\t\tconst entry = await this.readJournal();\n\t\tif (entry === null) throw new MovePreflightError('no-journal', 'no journaled move to complete');\n\t\tconst runs = { backup: e => this.phaseBackup(e), rewrite: e => this.phaseRewrite(e), commit: e => this.phaseCommit(e),\n\t\t\tledger: e => this.phaseLedger(e), projcache: e => this.phaseProjcache(e), index: e => this.phaseIndex(e) };\n\t\tfor (const phase of PHASES) {\n\t\t\tif (entry.done.includes(phase)) {\n\t\t\t\t// A deferred ledger from a previous attempt deserves another try in\n\t\t\t\t// this (fresh) process where the registry caches are cold.\n\t\t\t\tif (phase === 'ledger' && entry.deferredLedger === true) await runs.ledger(entry);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (phase !== 'backup' && !entry.done.includes('backup')) throw new MovePreflightError('journal-order', `journal skipped '${phase}' before completing 'backup'`);\n\t\t\tawait runs[phase](entry);\n\t\t}\n\t\t// Still-deferred accounting keeps the journal (and every backup) alive as\n\t\t// the convergence pointer; rollback remains available (\u00A710 MR3).\n\t\tif (entry.deferredLedger === true) {\n\t\t\tawait this.writeJournal(entry);\n\t\t\treturn { ok: true, deferred: true, sessionId: entry.sessionId, toCwd: entry.toCwd, ledgerError: entry.ledgerError,\n\t\t\t\tnote: '\u6587\u4EF6\u5DF2\u8FC1\u79FB\u4F46 DSH \u8D26\u672C\u4ECD\u672A\u6536\u655B\uFF1B\u91CD\u542F DSH \u540E\u518D\u6B21\u70B9\u5B8C\u6210\uFF0C\u6216\u9009\u62E9\u56DE\u6EDA' };\n\t\t}\n\t\tawait this.#finish(entry);\n\t\treturn { ok: true, sessionId: entry.sessionId, toCwd: entry.toCwd };\n\t}\n}\n", "/**\n * DSH session-storage path algebra. Mirrors `projectKey` / `encodeSegment` /\n * `projectDir` / `sessionDir` from `@deepseek-ai/dsh-session-persistence-jsonl`\n * (which does not export them). Every implementation is verified against the\n * live layout by `verifyEncoders` before any mutation runs, so a future official\n * change to the encoding rules fails closed (\u00A710 MN3) instead of corrupting data.\n */\nimport { readdir, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\n\n/** The `undefined` cwd bucket: sessions whose stored header carries no cwd. */\nexport const NO_CWD_DIR = '_no-cwd';\n\n/** Encode one id/path segment: safe code units stay literal, everything else becomes `~XXXX`. */\nexport function encodeSegment(raw) {\n\tif (raw.length === 0) throw new Error('cannot encode an empty path segment');\n\tif (raw === '.') return '~002E';\n\tif (raw === '..') return '~002E~002E';\n\tlet out = '';\n\tfor (let i = 0; i < raw.length; i++) {\n\t\tconst code = raw.charCodeAt(i);\n\t\tconst ch = String.fromCharCode(code);\n\t\tif (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) out += ch;\n\t\telse out += '~' + code.toString(16).toUpperCase().padStart(4, '0');\n\t}\n\treturn out;\n}\n\n/**\n * Build the readable project directory key for a canonical cwd, exactly like the\n * official backend: separators collapse to one `-`, unsafe units escape as `~XXXX`,\n * the whole key is wrapped in `--\u2026--` and bounded to 251 readable characters.\n */\nexport function projectKey(cwd) {\n\tif (cwd.length === 0) throw new Error('cannot encode an empty project path');\n\tlet readable = '';\n\tlet separatorRun = false;\n\tfor (let i = 0; i < cwd.length; i++) {\n\t\tconst code = cwd.charCodeAt(i);\n\t\tconst ch = String.fromCharCode(code);\n\t\tif (ch === '/' || ch === '\\\\' || ch === ':') {\n\t\t\tif (!separatorRun) readable += '-';\n\t\t\tseparatorRun = true;\n\t\t} else if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) {\n\t\t\treadable += ch;\n\t\t\tseparatorRun = false;\n\t\t} else {\n\t\t\treadable += '~' + code.toString(16).toUpperCase().padStart(4, '0');\n\t\t\tseparatorRun = false;\n\t\t}\n\t}\n\treturn `--${(readable.replace(/^-+/, '') || 'root').slice(0, 251)}--`;\n}\n\nexport function projectDir(root, cwd) {\n\treturn cwd === undefined ? join(root, NO_CWD_DIR) : join(root, projectKey(cwd));\n}\n\nexport function sessionDir(root, cwd, id) {\n\treturn join(projectDir(root, cwd), encodeSegment(id));\n}\n\nconst LOG_BASENAMES = ['session.jsonl', 'session.v1.jsonl', 'session.v2.jsonl', 'session.v3.jsonl', 'session.v4.jsonl',\n\t'session.jsonl.zstd', 'session.v1.jsonl.zstd', 'session.v2.jsonl.zstd', 'session.v3.jsonl.zstd', 'session.v4.jsonl.zstd'];\n\n/** Locate the authoritative session log inside one session directory (highest generation wins). */\nexport async function findLogFile(dir) {\n\tconst entries = await readdir(dir);\n\tconst present = LOG_BASENAMES.filter(name => entries.includes(name));\n\tif (present.length === 0) return undefined;\n\t// Compression-suffixed generations outrank the bare same-generation name; then highest version.\n\tconst zstd = present.filter(name => name.endsWith('.zstd'));\n\tconst pool = zstd.length > 0 ? zstd : present;\n\treturn pool.sort((left, right) => right.length - left.length || right.localeCompare(left))[0];\n}\n\n/** One candidate location for a session id, checked cheaply (directory stat only). */\nexport async function sessionDirExists(root, cwd, id) {\n\ttry { return (await stat(join(sessionDir(root, cwd, id)))).isDirectory(); } catch { return false; }\n}\n\n/**\n * Prove our local encoders agree with the shipped layout before anything writes:\n * for every provided {cwd, id, observedProjectDir, observedSessionDir} sample\n * (taken from headers the host itself enumerated), the directory derived by\n * projectKey/encodeSegment must match the observed path relative to the root.\n * @param samples - observed placement of stored sessions.\n * @param root - absolute sessions root; samples carry root-relative dirs.\n * @returns whether every sample reproduces.\n */\nexport function verifyEncoders(samples, root) {\n\tif (samples.length === 0) return false;\n\treturn samples.every(({ cwd, id, project, dir }) =>\n\t\tjoin(root, project, dir) === sessionDir(root, cwd, id) && join(root, project) === projectDir(root, cwd));\n}\n", "/**\n * Session log zstd artifact surgery. The shipped format is a concatenation of\n * independent zstd frames: frame 0 is the header line, every event is its own\n * frame (verified against live v4 logs and against `scanZstdFrames` in\n * `@deepseek-ai/dsh-session-persistence-jsonl`). Rewriting the header therefore\n * only rebuilds frame 0; every event frame is carried over byte-for-byte, which\n * keeps the operation cheap and reversible for arbitrarily large logs.\n */\nimport { constants, zstdCompressSync, zstdDecompressSync } from 'node:zlib';\n\nexport const ZSTD_MAGIC = 0xfd2fb528;\nconst SKIPPABLE_MAGIC_MIN = 0x184d2a50, SKIPPABLE_MAGIC_MAX = 0x184d2a5f;\n// The shipped writer puts an XXH64 content checksum on every frame; match it so\n// the rewritten header is indistinguishable in style from the original.\nconst CHECKSUM = { [constants.ZSTD_c_checksumFlag]: 1 };\n\n/**\n * Walk a frame sequence exactly like the official scanner (including skippable\n * frames). Throws on any malformed byte \u2014 the walk IS the post-write validation.\n * @param buffer - complete artifact bytes.\n * @returns ordered frames with byte ranges.\n */\nexport function scanFrames(buffer) {\n\tconst frames = [];\n\tlet offset = 0;\n\twhile (offset < buffer.length) {\n\t\tconst start = offset;\n\t\tif (buffer.length - offset < 4) throw new Error(`truncated zstd artifact: fewer than 4 bytes at ${offset}`);\n\t\tconst magic = buffer.readUInt32LE(offset);\n\t\tif (magic >= SKIPPABLE_MAGIC_MIN && magic <= SKIPPABLE_MAGIC_MAX) {\n\t\t\tconst size = buffer.readUInt32LE(offset + 4);\n\t\t\toffset += 8 + size;\n\t\t\tif (offset > buffer.length) throw new Error(`truncated skippable frame at ${start}`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (magic !== ZSTD_MAGIC) throw new Error(`invalid frame magic at byte ${offset}`);\n\t\toffset += 4;\n\t\tif (offset === buffer.length) throw new Error(`frame header missing at byte ${start}`);\n\t\tconst descriptor = buffer.readUInt8(offset);\n\t\toffset += 1;\n\t\tif ((descriptor & 24) !== 0) throw new Error(`reserved frame-header bit at byte ${offset - 1}`);\n\t\tconst contentSizeFlag = descriptor >>> 6;\n\t\tconst singleSegment = (descriptor & 32) !== 0;\n\t\tconst checksum = (descriptor & 4) !== 0;\n\t\tconst dictionaryFlag = descriptor & 3;\n\t\tconst dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;\n\t\tconst contentSizeBytes = contentSizeFlag === 0 ? (singleSegment ? 1 : 0) : 1 << contentSizeFlag;\n\t\tconst remaining = (singleSegment ? 0 : 1) + dictionaryBytes + contentSizeBytes;\n\t\tif (buffer.length - offset < remaining) throw new Error(`truncated frame header at byte ${start}`);\n\t\toffset += remaining;\n\t\tfor (;;) {\n\t\t\tif (buffer.length - offset < 3) throw new Error(`truncated block header at byte ${offset}`);\n\t\t\tconst blockHeader = buffer.readUIntLE(offset, 3);\n\t\t\toffset += 3;\n\t\t\tconst lastBlock = (blockHeader & 1) !== 0;\n\t\t\tconst blockType = blockHeader >>> 1 & 3;\n\t\t\tconst blockSize = blockHeader >>> 3;\n\t\t\tif (blockType === 3) throw new Error(`reserved block type at byte ${offset - 3}`);\n\t\t\tconst payloadBytes = blockType === 1 ? 1 : blockSize;\n\t\t\tif (buffer.length - offset < payloadBytes) throw new Error(`truncated block payload at byte ${offset}`);\n\t\t\toffset += payloadBytes;\n\t\t\tif (lastBlock) break;\n\t\t}\n\t\tif (checksum) {\n\t\t\tif (buffer.length - offset < 4) throw new Error(`truncated frame checksum at byte ${offset}`);\n\t\t\toffset += 4;\n\t\t}\n\t\tframes.push({ start, end: offset });\n\t}\n\treturn frames;\n}\n\nexport function decodeFrame(buffer, frame) {\n\treturn zstdDecompressSync(buffer.subarray(frame.start, frame.end));\n}\n\n/** Parse the header line of a session artifact (first non-skippable frame). */\nexport function readHeader(buffer) {\n\tconst frames = scanFrames(buffer);\n\tif (frames.length === 0) throw new Error('empty zstd artifact');\n\tconst text = decodeFrame(buffer, frames[0]).toString('utf8').trim();\n\tconst header = JSON.parse(text);\n\tif (header.type !== 'session' || typeof header.id !== 'string') throw new Error('malformed session header frame');\n\treturn { header, frames };\n}\n\n/**\n * Produce a complete artifact whose header frame carries a replaced cwd. The\n * header object keeps its original key order; only the `cwd` value changes\n * (`undefined` removes the field). All remaining frames are copied verbatim.\n * @param buffer - original artifact bytes.\n * @param nextCwd - canonical project directory for the moved session, or undefined.\n * @returns rewritten bytes.\n */\nexport function rewriteHeaderFrame(buffer, nextCwd) {\n\tconst { header, frames } = readHeader(buffer);\n\tconst updated = { ...header };\n\tif (nextCwd === undefined) delete updated.cwd;\n\telse updated.cwd = nextCwd;\n\tif (JSON.stringify(updated) === JSON.stringify(header)) return Buffer.from(buffer);\n\tconst frame0 = zstdCompressSync(Buffer.from(`${JSON.stringify(updated)}\\n`, 'utf8'), { params: CHECKSUM });\n\tscanFrames(frame0); // re-verify our own output before it ever touches the store\n\treturn Buffer.concat([frame0, buffer.subarray(frames[0].end)]);\n}\n", "/**\n * Trash bin for sessions and projects (\u00A711). Semantics pinned by the shipped\n * build: archiving is the reversible hide (slot kept, unarchive restores the\n * position), workspace deletion keeps every session log, and startup bootstrap\n * only re-claims sessions that are NOT archived \u2014 so \"archive all sessions +\n * delete the registration\" keeps a trashed project invisible until this ledger\n * restores it. All official effects run through a narrow registry adapter\n * (implemented in the host, faked in tests); the plugin-owned ledger snapshots\n * the placement, archive and pin state needed to restore them (\u00A711 TB1/TB5).\n *\n * `purge` is the hard-delete path the official surface has no command for\n * (\u00A711.1-1): it moves the session artifact into `pending-purge/` (same volume,\n * atomic placement, undoable until the last step), drops the projection-cache\n * record and vault manifest entries, and only then removes the ledger item.\n */\nimport { readdir, rm, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { encodeSegment } from './paths.mjs';\nimport { relocate } from './move.mjs';\n\nexport class TrashError extends Error {\n\tcode;\n\tconstructor(code, message) { super(message); this.name = 'TrashError'; this.code = code; }\n}\n\nconst DAY = 24 * 60 * 60 * 1000;\n\nexport class TrashEngine {\n\t/**\n\t * @param deps - {adapter: RegistryAdapter, sessions?: () => liveSessionIds,\n\t * sessionsRoot, projcacheRoot, kitRoot, ledger: JsonDocument, vault?,\n\t * journal?: () => activeJournalEntry|null, settings?: () => trashSettings, now}\n\t */\n\tconstructor(deps) {\n\t\tthis.deps = deps;\n\t\tthis.ledger = deps.ledger;\n\t\tthis.now = deps.now ?? (() => Date.now());\n\t}\n\n\tasync items() { return (await this.ledger.read()).items.map(publicItem); }\n\n\t#guardFree(id) {\n\t\tif (typeof this.deps.journal === 'function' && this.deps.journal() !== null) {\n\t\t\tthrow new TrashError('journal-active', 'a journaled move is unresolved; finish or roll it back first');\n\t\t}\n\t\tconst live = this.deps.sessions?.() ?? [];\n\t\tif (live.includes(id)) throw new TrashError('session-busy', `session ${id} is live; open it and stop its work first`);\n\t}\n\n\t#find(state, predicate) { return state.items.find(predicate); }\n\n\t/** \u00A711 TB3: trash one session (archive + ledger; already-archived sessions only enter the bin). */\n\tasync trashSession(sessionId, { force = false } = {}) {\n\t\tthis.#guardFree(sessionId);\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tif (this.#find(state, item => item.kind === 'session' && item.id2 === sessionId)) throw new TrashError('already-trashed', 'this session is already in the trash bin');\n\t\tif (!await adapter.sessionKnown(sessionId)) throw new TrashError('session-unknown', `session ${sessionId} is unknown to the registry`);\n\t\tconst archived = await adapter.archivedSet();\n\t\tconst pinned = await adapter.pinnedSet();\n\t\tconst { workspaceId, beforeId, title } = await adapter.locateSession(sessionId);\n\t\tif (!archived.has(sessionId)) await adapter.archiveSession(sessionId, force ? { stopActivity: true } : {});\n\t\tconst item = {\n\t\t\tid: randomUUID(), kind: 'session', id2: sessionId, trashedAt: new Date(this.now()).toISOString(),\n\t\t\tsnapshot: { sessionId, workspaceId: workspaceId ?? null, beforeId: beforeId ?? null,\n\t\t\t\tpreviouslyArchived: archived.has(sessionId), previouslyPinned: pinned.has(sessionId), title: title ?? null },\n\t\t};\n\t\tstate.items.push(item);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true, itemId: item.id };\n\t}\n\n\t/** \u00A711 TB4: trash a project (archive all its sessions, snapshot order/state, delete registration). */\n\tasync trashWorkspace(workspaceId, { force = false } = {}) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tif (this.#find(state, item => item.kind === 'workspace' && item.id2 === workspaceId)) throw new TrashError('already-trashed', 'this project is already in the trash bin');\n\t\tconst snapshot = await adapter.workspaceSnapshot(workspaceId);\n\t\tif (snapshot === undefined) throw new TrashError('workspace-unknown', `workspace ${workspaceId} not found`);\n\t\tconst live = new Set(this.deps.sessions?.() ?? []);\n\t\tif (!force && snapshot.sessions.some(row => live.has(row.sessionId))) throw new TrashError('workspace-busy', 'the project has live sessions; use force to stop and trash them');\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (row.previouslyArchived) continue;\n\t\t\tawait adapter.archiveSession(row.sessionId, live.has(row.sessionId) ? { stopActivity: true } : {});\n\t\t}\n\t\tconst item = { id: randomUUID(), kind: 'workspace', id2: workspaceId, trashedAt: new Date(this.now()).toISOString(), snapshot };\n\t\tstate.items.push(item);\n\t\tawait this.ledger.write(state);\n\t\tawait adapter.deleteWorkspace(workspaceId);\n\t\treturn { ok: true, itemId: item.id };\n\t}\n\n\t/** \u00A711 TB5 idempotent restore: converge to the snapshot; failures propagate so the item survives for retry. */\n\tasync restore(itemId) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tconst item = this.#find(state, row => row.id === itemId);\n\t\tif (item === undefined) throw new TrashError('item-unknown', `no trash item ${itemId}`);\n\t\tif (item.kind === 'session') await this.#restoreSession(adapter, item.snapshot);\n\t\telse await this.#restoreWorkspace(adapter, item.snapshot);\n\t\tstate.items = state.items.filter(row => row.id !== itemId);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true };\n\t}\n\n\tasync #restoreSession(adapter, snapshot) {\n\t\tconst { sessionId, workspaceId, beforeId, previouslyArchived, previouslyPinned } = snapshot;\n\t\tif (!previouslyArchived) await adapter.unarchiveSession(sessionId);\n\t\tif (workspaceId !== null) await adapter.repairSlot(sessionId, workspaceId, beforeId);\n\t\tif (previouslyPinned) await adapter.pinSession(sessionId);\n\t}\n\n\tasync #restoreWorkspace(adapter, snapshot) {\n\t\tawait adapter.restoreWorkspace(snapshot);\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (!row.previouslyArchived) await adapter.unarchiveSession(row.sessionId);\n\t\t}\n\t\t// Pins are dropped by archiving (official rule); restore them for sessions\n\t\t// that were pinned before entering the bin.\n\t\tfor (const row of snapshot.sessions) {\n\t\t\tif (row.previouslyPinned && !row.previouslyArchived) await adapter.pinSession(row.sessionId).catch(() => {});\n\t\t}\n\t}\n\n\t/** \u00A711 TB6: hard-delete with staging so a crash never yields a half-deleted state. */\n\tasync purge(itemId) {\n\t\tconst adapter = this.deps.adapter;\n\t\tconst state = await this.ledger.read();\n\t\tconst item = this.#find(state, row => row.id === itemId);\n\t\tif (item === undefined) throw new TrashError('item-unknown', `no trash item ${itemId}`);\n\t\tconst sessionIds = item.kind === 'session' ? [item.snapshot.sessionId] : item.snapshot.sessions.map(row => row.sessionId);\n\t\tfor (const sessionId of sessionIds) this.#guardFree(sessionId);\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tawait this.#stageArtifact(sessionId);\n\t\t\tif (adapter.purgeSession) await adapter.purgeSession(sessionId);\n\t\t}\n\t\tfor (const sessionId of sessionIds) {\n\t\t\tawait adapter.unpinSession(sessionId).catch(() => {});\n\t\t\tawait adapter.unarchiveSession(sessionId).catch(() => {});\n\t\t}\n\t\tif (item.kind === 'workspace') await adapter.deleteWorkspace(item.id2).catch(() => {});\n\t\tif (this.deps.vault?.dropSession) for (const sessionId of sessionIds) await this.deps.vault.dropSession(sessionId);\n\t\tstate.items = state.items.filter(row => row.id !== itemId);\n\t\tawait this.ledger.write(state);\n\t\treturn { ok: true, purged: sessionIds };\n\t}\n\n\tasync #stageArtifact(sessionId) {\n\t\tconst encoded = encodeSegment(sessionId);\n\t\tconst root = this.deps.sessionsRoot;\n\t\tlet found;\n\t\tfor (const project of await readdir(root).catch(() => [])) {\n\t\t\tif (project.startsWith('.')) continue;\n\t\t\ttry { if ((await stat(join(root, project, encoded))).isDirectory()) { found = join(root, project, encoded); break; } } catch {}\n\t\t}\n\t\tif (found === undefined) return; // already staged away (idempotent)\n\t\tconst staged = join(this.deps.kitRoot, 'pending-purge', `${sessionId}__${this.now()}`);\n\t\tawait relocate(found, staged);\n\t\tif (this.deps.projcacheRoot) await rm(join(this.deps.projcacheRoot, `${sessionId}.json`), { force: true });\n\t\t// Durable placement done; only now drop the real bytes.\n\t\tawait rm(staged, { recursive: true, force: true });\n\t}\n\n\t/** TTL sweep (\u00A711 T5). With autoPurge, expired items are hard-deleted; otherwise reported. */\n\tasync sweep({ now = this.now() } = {}) {\n\t\tconst state = await this.ledger.read();\n\t\tconst settings = this.deps.settings?.() ?? {};\n\t\tconst ttlDays = settings.ttlDays ?? 30;\n\t\tconst auto = settings.autoPurge === true;\n\t\tconst report = { expired: [], purged: [], skipped: [] };\n\t\tfor (const item of state.items) {\n\t\t\tconst trashedAt = Date.parse(item.trashedAt);\n\t\t\tif (!Number.isFinite(trashedAt) || now - trashedAt < ttlDays * DAY) continue;\n\t\t\treport.expired.push({ itemId: item.id, kind: item.kind, targetId: item.id2 });\n\t\t\tif (!auto) continue;\n\t\t\ttry { await this.purge(item.id); report.purged.push(item.id); }\n\t\t\tcatch (error) { report.skipped.push({ itemId: item.id, reason: String(error?.message ?? error) }); }\n\t\t}\n\t\treturn report;\n\t}\n}\n\nfunction publicItem(item) {\n\treturn { itemId: item.id, kind: item.kind, targetId: item.id2, trashedAt: item.trashedAt, snapshot: item.snapshot };\n}\n", "/**\n * Loopback management endpoint, same trust model as dsh-multi-router: exact\n * `/.well-known` route, host-header + socket must be loopback, Origin/\n * Sec-Fetch-Site cross-site rejected, writes need the per-process random key\n * the GET hands out (timing-safe compare). The handler is framework-free so the\n * host wires it into `ctx.webServer.register` and the CLI can call it directly.\n */\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\n\nexport const API_PATH = '/.well-known/dsh-session-toolbox';\nconst MAX_BODY = 4 * 1024 * 1024;\n\nclass ApiError extends Error {\n\tstatus;\n\tconstructor(status, message) { super(message); this.status = status; }\n}\n\nconst json = (res, status, value) => {\n\tres.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' });\n\tres.end(JSON.stringify(value));\n};\n\nconst hostIsLoopback = host => {\n\tconst name = String(host ?? '').split(':')[0];\n\treturn ['localhost', '127.0.0.1', '::1', '[::1]', ''].includes(name) || name.startsWith('127.');\n};\n\n/**\n * @param kit - {state(): snapshot, action(input): result, move, trash, settings, vaultManifest}\n */\nexport function apiHandler(kit) {\n\tconst key = randomBytes(32).toString('base64url');\n\treturn async (req, res) => {\n\t\ttry {\n\t\t\tconst remote = req.socket?.remoteAddress;\n\t\t\tif (!hostIsLoopback(req.headers.host) || (remote && !['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(remote))) throw new ApiError(403, '\u4EC5\u5141\u8BB8\u672C\u673A\u8BF7\u6C42');\n\t\t\tconst origin = req.headers.origin;\n\t\t\tif (origin && origin !== `http://${req.headers.host}` && origin !== `https://${req.headers.host}`) throw new ApiError(403, '\u6765\u6E90\u65E0\u6548');\n\t\t\tif (req.headers['sec-fetch-site'] === 'cross-site') throw new ApiError(403, '\u6765\u6E90\u65E0\u6548');\n\t\t\tif (req.method === 'GET') { json(res, 200, { ...await kit.state(), key }); return; }\n\t\t\tif (req.method !== 'POST') throw new ApiError(405, '\u65B9\u6CD5\u65E0\u6548');\n\t\t\tconst actual = Buffer.from(String(req.headers['x-session-toolbox-key'] ?? '')), expected = Buffer.from(key);\n\t\t\tif (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw new ApiError(401, '\u8BF7\u5237\u65B0\u9762\u677F\u540E\u91CD\u8BD5');\n\t\t\tif (!/^application\\/json(?:\\s*;|$)/i.test(String(req.headers['content-type'] ?? ''))) throw new ApiError(415, '\u9700\u8981 JSON');\n\t\t\tlet size = 0; const chunks = [];\n\t\t\tfor await (const chunk of req) { size += chunk.length; if (size > MAX_BODY) throw new ApiError(413, '\u8BF7\u6C42\u8FC7\u5927'); chunks.push(chunk); }\n\t\t\tlet input;\n\t\t\ttry { input = JSON.parse(Buffer.concat(chunks).toString('utf8')); } catch { throw new ApiError(400, 'JSON \u65E0\u6548'); }\n\t\t\tif (input === null || typeof input !== 'object' || typeof input.type !== 'string') throw new ApiError(400, '\u7F3A\u5C11\u64CD\u4F5C\u7C7B\u578B');\n\t\t\tjson(res, 200, { ...await kit.action(input), key });\n\t\t} catch (error) {\n\t\t\tjson(res, error instanceof ApiError ? error.status : 500, { error: error instanceof ApiError ? error.message : `\u64CD\u4F5C\u5931\u8D25\uFF1A${error?.message ?? error}` });\n\t\t}\n\t};\n}\n\n/** Shared dispatch so the host, the CLI and tests all speak one vocabulary. */\nexport async function dispatch(kit, input) {\n\tswitch (input.type) {\n\t\tcase 'preflight': return await kit.move.preflight({ sessionId: String(input.sessionId ?? ''), toCwd: String(input.toCwd ?? ''), createTarget: input.createTarget === true });\n\t\tcase 'move': return await kit.move.move(await kit.move.preflight({ sessionId: String(input.sessionId ?? ''), toCwd: String(input.toCwd ?? ''), createTarget: input.createTarget === true }));\n\t\tcase 'move.rollback': return await kit.move.rollback();\n\t\tcase 'move.complete': return await kit.move.complete();\n\t\tcase 'trash.list': return { items: await kit.trash.items() };\n\t\tcase 'trash.session': return await kit.trash.trashSession(String(input.sessionId ?? ''), { force: input.force === true });\n\t\tcase 'trash.workspace': return await kit.trash.trashWorkspace(String(input.workspaceId ?? ''), { force: input.force === true });\n\t\tcase 'trash.restore': return await kit.trash.restore(String(input.itemId ?? ''));\n\t\tcase 'trash.purge': return await kit.trash.purge(String(input.itemId ?? ''));\n\t\tcase 'trash.sweep': return await kit.trash.sweep();\n\t\tcase 'project.of': return { project: await kit.projectOf(String(input.sessionId ?? '')) };\n\t\tcase 'settings.update': return { settings: await kit.updateSettings(input.patch ?? {}) };\n\t\tcase 'vault.sync': return { records: (await kit.vaultSync(Array.isArray(input.records) ? input.records : [])).records.length };\n\t\tcase 'vault.sweep': {\n\t\t\tconst settings = await kit.settings.read();\n\t\t\tconst ttlMs = (settings.draftVault?.ttlDays ?? 7) * 24 * 60 * 60 * 1000;\n\t\t\tconst manifest = await kit.manifest.update(current => ({\n\t\t\t\tversion: 1,\n\t\t\t\trecords: current.records.filter(record => Date.now() - (record.createdAt ?? 0) <= ttlMs),\n\t\t\t}));\n\t\t\treturn { records: manifest.records.length };\n\t\t}\n\t\tdefault: throw new Error(`\u672A\u77E5\u7684\u64CD\u4F5C\u7C7B\u578B\uFF1A${input.type}`);\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["constants", "mkdir", "readFile", "readdir", "stat", "dirname", "join", "join", "join", "constants", "mkdir", "dirname", "readdir", "stat", "join", "readFile", "readdir", "rm", "stat", "join", "item", "readdir", "stat", "join", "rm"]
|
|
7
7
|
}
|