@artenx/dshb 0.1.36 → 0.1.38
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/lib/core/index.js +1 -1
- package/lib/core/sync/coordinator.d.ts +2 -2
- package/lib/core/sync/coordinator.js +1 -1
- package/lib/core/sync/internal-routes.d.ts +1 -1
- package/lib/core/sync/internal-routes.js +1 -1
- package/lib/core/sync/offline-archive.d.ts +1 -1
- package/lib/core/sync/offline-archive.js +1 -1
- package/lib/core/sync/offline-routes.js +1 -1
- package/lib/core/sync/routes.d.ts +1 -1
- package/lib/core/sync/session-routes.d.ts +1 -1
- package/lib/core/sync/session-routes.js +1 -1
- package/lib/core/sync/session-sync.d.ts +1 -1
- package/lib/core/sync/session-sync.js +1 -1
- package/lib/core/sync/ssh-transport.d.ts +1 -1
- package/lib/core/workspace-instruction-context.d.ts +1 -1
- package/lib/core/workspace-instruction-routes.d.ts +1 -1
- package/lib/core/workspace-instructions.d.ts +1 -1
- package/lib/core/workspace-instructions.js +33 -1
- package/lib/core/workspace-instructions.js.map +1 -1
- package/lib/{session-sync-DLr_BdvN.js → session-sync-BBCm_ou2.js} +26 -11
- package/lib/session-sync-BBCm_ou2.js.map +1 -0
- package/lib/{session-sync-DrKShc5c.d.ts → session-sync-Bw0cZ4oa.d.ts} +5 -3
- package/lib/{ssh-transport-BxPWfu9X.d.ts → ssh-transport-COZe0BDr.d.ts} +2 -2
- package/lib/{workspace-instructions-DirYYiku.d.ts → workspace-instructions-C_ViytzA.d.ts} +19 -1
- package/package.json +1 -1
- package/lib/session-sync-DLr_BdvN.js.map +0 -1
package/lib/core/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { registerWorkspaceInstructionRoutes } from "./workspace-instruction-rout
|
|
|
11
11
|
import { WorkspaceBindingsStore } from "./workspace-bindings.js";
|
|
12
12
|
import { registerWorkspaceInstructionInjector } from "./workspace-instruction-context.js";
|
|
13
13
|
import { SyncPeerManager } from "./sync/peer-manager.js";
|
|
14
|
-
import { i as SyncSessionService } from "../session-sync-
|
|
14
|
+
import { i as SyncSessionService } from "../session-sync-BBCm_ou2.js";
|
|
15
15
|
import { registerSyncInternalRoutes } from "./sync/internal-routes.js";
|
|
16
16
|
import { SyncSshTransport } from "./sync/ssh-transport.js";
|
|
17
17
|
import { SyncCoordinator } from "./sync/coordinator.js";
|
|
@@ -2,8 +2,8 @@ import { a as SyncPeer } from "../../model-CKTBf-Pl.js";
|
|
|
2
2
|
import { n as SyncStateStore } from "../../stores-puyTC075.js";
|
|
3
3
|
import { n as SyncNodeEntry, s as SyncNodeService } from "../../node-sync-C3Ym-HDu.js";
|
|
4
4
|
import { SyncPeerManager } from "./peer-manager.js";
|
|
5
|
-
import { h as SyncSessionService } from "../../session-sync-
|
|
6
|
-
import { m as SyncSshTransport } from "../../ssh-transport-
|
|
5
|
+
import { h as SyncSessionService } from "../../session-sync-Bw0cZ4oa.js";
|
|
6
|
+
import { m as SyncSshTransport } from "../../ssh-transport-COZe0BDr.js";
|
|
7
7
|
//#region src/core/sync/coordinator.d.ts
|
|
8
8
|
interface NodeTransferPlan {
|
|
9
9
|
toLocal: SyncNodeEntry[];
|
|
@@ -3,7 +3,7 @@ import { syncRecordKey } from "./model.js";
|
|
|
3
3
|
import { SyncNodeManifestError } from "./node-sync.js";
|
|
4
4
|
import { SyncPeerNotFoundError } from "./peer-manager.js";
|
|
5
5
|
import { SYNC_SESSION_BUNDLE_OBJECTS_CAPABILITY, SYNC_SESSION_EVENT_TAIL_CAPABILITY, SYNC_SESSION_OBJECT_STREAM_CAPABILITY } from "./protocol.js";
|
|
6
|
-
import { c as planSessionTransfers, f as validateSyncSessionBundle, l as sessionEventListDigest, n as SyncSessionError, o as makeSyncSessionBundle, p as validateSyncSessionManifest, u as syncSessionEntryKey } from "../../session-sync-
|
|
6
|
+
import { c as planSessionTransfers, f as validateSyncSessionBundle, l as sessionEventListDigest, n as SyncSessionError, o as makeSyncSessionBundle, p as validateSyncSessionManifest, u as syncSessionEntryKey } from "../../session-sync-BBCm_ou2.js";
|
|
7
7
|
import { SyncHostKeyChallengeError } from "./host-key.js";
|
|
8
8
|
import { SyncSessionDeltaPrefixError, SyncSshProbeError } from "./ssh-transport.js";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as SyncStateStore } from "../../stores-puyTC075.js";
|
|
2
2
|
import { s as SyncNodeService } from "../../node-sync-C3Ym-HDu.js";
|
|
3
|
-
import { h as SyncSessionService } from "../../session-sync-
|
|
3
|
+
import { h as SyncSessionService } from "../../session-sync-Bw0cZ4oa.js";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
5
5
|
//#region src/core/sync/internal-routes.d.ts
|
|
6
6
|
declare function registerSyncInternalRoutes(ctx: Context, state: SyncStateStore, nodeSync?: SyncNodeService, sessionSync?: SyncSessionService): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isLoopbackRequest } from "../../auth/loopback.js";
|
|
2
2
|
import { SyncNodeManifestError } from "./node-sync.js";
|
|
3
3
|
import { SYNC_SESSION_BUNDLE_OBJECTS_CAPABILITY, SYNC_SESSION_EVENT_TAIL_CAPABILITY, SYNC_SESSION_MANIFEST_CAPABILITY, SYNC_SESSION_OBJECT_STREAM_CAPABILITY } from "./protocol.js";
|
|
4
|
-
import { d as validateObjectPayload, n as SyncSessionError } from "../../session-sync-
|
|
4
|
+
import { d as validateObjectPayload, n as SyncSessionError } from "../../session-sync-BBCm_ou2.js";
|
|
5
5
|
//#region src/core/sync/internal-routes.ts
|
|
6
6
|
const MAX_APPLY_BODY_BYTES = 134217728;
|
|
7
7
|
function sendJson(res, status, body) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as SyncStateStore } from "../../stores-puyTC075.js";
|
|
2
2
|
import { s as SyncNodeService } from "../../node-sync-C3Ym-HDu.js";
|
|
3
|
-
import { h as SyncSessionService } from "../../session-sync-
|
|
3
|
+
import { h as SyncSessionService } from "../../session-sync-Bw0cZ4oa.js";
|
|
4
4
|
//#region src/core/sync/offline-archive.d.ts
|
|
5
5
|
declare const MAX_OFFLINE_ARCHIVE_BYTES: number;
|
|
6
6
|
declare class SyncOfflineArchiveError extends Error {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as validateSyncSessionBundle, n as SyncSessionError } from "../../session-sync-
|
|
1
|
+
import { f as validateSyncSessionBundle, n as SyncSessionError } from "../../session-sync-BBCm_ou2.js";
|
|
2
2
|
import { SyncOfflineArchiveJournalStore } from "./offline-journal.js";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { appendFileSync, chmodSync, closeSync, createReadStream, createWriteStream, mkdirSync, mkdtempSync, openSync, readSync, readdirSync, rmSync, statSync, statfsSync, writeFileSync } from "node:fs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as SyncSessionError } from "../../session-sync-
|
|
1
|
+
import { n as SyncSessionError } from "../../session-sync-BBCm_ou2.js";
|
|
2
2
|
import { SyncOfflineArchiveError } from "./offline-archive.js";
|
|
3
3
|
import { createReadStream } from "node:fs";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SyncPeerManager } from "./peer-manager.js";
|
|
2
|
-
import { m as SyncSshTransport } from "../../ssh-transport-
|
|
2
|
+
import { m as SyncSshTransport } from "../../ssh-transport-COZe0BDr.js";
|
|
3
3
|
import { SyncCoordinator } from "./coordinator.js";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
5
5
|
//#region src/core/sync/routes.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h as SyncSessionService } from "../../session-sync-
|
|
1
|
+
import { h as SyncSessionService } from "../../session-sync-Bw0cZ4oa.js";
|
|
2
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
//#region src/core/sync/session-routes.d.ts
|
|
4
4
|
declare function registerSyncSessionRoutes(ctx: Context, sessions: SyncSessionService): void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as sessionEventListDigest, D as validateSyncSessionManifest, E as validateSyncSessionBundle, S as planSessionTransfers, T as validateObjectPayload, _ as SyncSessionWorkspace, a as SyncSessionBundle, b as makeSyncSessionBundle, c as SyncSessionEventDelta, d as SyncSessionManifest, f as SyncSessionManifestEntry, g as SyncSessionTransferPlan, h as SyncSessionService, i as SyncSessionApplyResult, l as SyncSessionEventPrefix, m as SyncSessionObjectInbox, n as SyncObjectInboxWriter, o as SyncSessionEntry, p as SyncSessionObject, r as SyncSessionApplyOptions, s as SyncSessionError, t as ExportObjectCache, u as SyncSessionInstructionSnapshot, v as WorkspaceRegistryLike, w as syncSessionEntryKey, x as makeSyncSessionManifest, y as estimateJsonBytes } from "../../session-sync-
|
|
1
|
+
import { C as sessionEventListDigest, D as validateSyncSessionManifest, E as validateSyncSessionBundle, S as planSessionTransfers, T as validateObjectPayload, _ as SyncSessionWorkspace, a as SyncSessionBundle, b as makeSyncSessionBundle, c as SyncSessionEventDelta, d as SyncSessionManifest, f as SyncSessionManifestEntry, g as SyncSessionTransferPlan, h as SyncSessionService, i as SyncSessionApplyResult, l as SyncSessionEventPrefix, m as SyncSessionObjectInbox, n as SyncObjectInboxWriter, o as SyncSessionEntry, p as SyncSessionObject, r as SyncSessionApplyOptions, s as SyncSessionError, t as ExportObjectCache, u as SyncSessionInstructionSnapshot, v as WorkspaceRegistryLike, w as syncSessionEntryKey, x as makeSyncSessionManifest, y as estimateJsonBytes } from "../../session-sync-Bw0cZ4oa.js";
|
|
2
2
|
export { ExportObjectCache, SyncObjectInboxWriter, SyncSessionApplyOptions, SyncSessionApplyResult, SyncSessionBundle, SyncSessionEntry, SyncSessionError, SyncSessionEventDelta, SyncSessionEventPrefix, SyncSessionInstructionSnapshot, SyncSessionManifest, SyncSessionManifestEntry, SyncSessionObject, SyncSessionObjectInbox, SyncSessionService, SyncSessionTransferPlan, SyncSessionWorkspace, WorkspaceRegistryLike, estimateJsonBytes, makeSyncSessionBundle, makeSyncSessionManifest, planSessionTransfers, sessionEventListDigest, syncSessionEntryKey, validateObjectPayload, validateSyncSessionBundle, validateSyncSessionManifest };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as estimateJsonBytes, c as planSessionTransfers, d as validateObjectPayload, f as validateSyncSessionBundle, i as SyncSessionService, l as sessionEventListDigest, n as SyncSessionError, o as makeSyncSessionBundle, p as validateSyncSessionManifest, r as SyncSessionObjectInbox, s as makeSyncSessionManifest, t as ExportObjectCache, u as syncSessionEntryKey } from "../../session-sync-
|
|
1
|
+
import { a as estimateJsonBytes, c as planSessionTransfers, d as validateObjectPayload, f as validateSyncSessionBundle, i as SyncSessionService, l as sessionEventListDigest, n as SyncSessionError, o as makeSyncSessionBundle, p as validateSyncSessionManifest, r as SyncSessionObjectInbox, s as makeSyncSessionManifest, t as ExportObjectCache, u as syncSessionEntryKey } from "../../session-sync-BBCm_ou2.js";
|
|
2
2
|
export { ExportObjectCache, SyncSessionError, SyncSessionObjectInbox, SyncSessionService, estimateJsonBytes, makeSyncSessionBundle, makeSyncSessionManifest, planSessionTransfers, sessionEventListDigest, syncSessionEntryKey, validateObjectPayload, validateSyncSessionBundle, validateSyncSessionManifest };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as parseRemoteProbeOutput, a as SyncRemoteProbe, c as SyncRemoteProbeProfile, d as SyncSshErrorCategory, f as SyncSshProbeError, g as buildSyncSshConnectConfig, h as buildRemoteProbeScript, i as SyncRemoteNodeManifest, l as SyncRemoteProbeResult, m as SyncSshTransport, n as REMOTE_PROBE_END_MARKER, o as SyncRemoteProbeDraft, p as SyncSshSession, r as SyncRemoteHandshake, s as SyncRemoteProbeHandshake, t as REMOTE_PROBE_BEGIN_MARKER, u as SyncSessionDeltaPrefixError } from "../../ssh-transport-
|
|
1
|
+
import { _ as parseRemoteProbeOutput, a as SyncRemoteProbe, c as SyncRemoteProbeProfile, d as SyncSshErrorCategory, f as SyncSshProbeError, g as buildSyncSshConnectConfig, h as buildRemoteProbeScript, i as SyncRemoteNodeManifest, l as SyncRemoteProbeResult, m as SyncSshTransport, n as REMOTE_PROBE_END_MARKER, o as SyncRemoteProbeDraft, p as SyncSshSession, r as SyncRemoteHandshake, s as SyncRemoteProbeHandshake, t as REMOTE_PROBE_BEGIN_MARKER, u as SyncSessionDeltaPrefixError } from "../../ssh-transport-COZe0BDr.js";
|
|
2
2
|
export { REMOTE_PROBE_BEGIN_MARKER, REMOTE_PROBE_END_MARKER, SyncRemoteHandshake, SyncRemoteNodeManifest, SyncRemoteProbe, SyncRemoteProbeDraft, SyncRemoteProbeHandshake, SyncRemoteProbeProfile, SyncRemoteProbeResult, SyncSessionDeltaPrefixError, SyncSshErrorCategory, SyncSshProbeError, SyncSshSession, SyncSshTransport, buildRemoteProbeScript, buildSyncSshConnectConfig, parseRemoteProbeOutput };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h as createUserMessage } from "../index-VF8bcBeX.js";
|
|
2
|
-
import { a as SessionInstructionSnapshotStore, i as SessionInstructionSnapshot, s as WorkspaceInstructionStore } from "../workspace-instructions-
|
|
2
|
+
import { a as SessionInstructionSnapshotStore, i as SessionInstructionSnapshot, s as WorkspaceInstructionStore } from "../workspace-instructions-C_ViytzA.js";
|
|
3
3
|
import { Context } from "@deepseek-ai/cordis";
|
|
4
4
|
//#region src/core/workspace-instruction-context.d.ts
|
|
5
5
|
interface InstructionSnapshotResult {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as WorkspaceInstructionStore } from "../workspace-instructions-
|
|
1
|
+
import { s as WorkspaceInstructionStore } from "../workspace-instructions-C_ViytzA.js";
|
|
2
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
//#region src/core/workspace-instruction-routes.d.ts
|
|
4
4
|
declare function registerWorkspaceInstructionRoutes(ctx: Context, store: WorkspaceInstructionStore): void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SessionInstructionSnapshotStore, c as sharedSessionInstructionSnapshotStore, i as SessionInstructionSnapshot, l as sharedWorkspaceInstructionStore, n as InstructionConflictError, o as WorkspaceInstructionRecord, r as InstructionSizeError, s as WorkspaceInstructionStore, t as INSTRUCTION_MAX_BYTES } from "../workspace-instructions-
|
|
1
|
+
import { a as SessionInstructionSnapshotStore, c as sharedSessionInstructionSnapshotStore, i as SessionInstructionSnapshot, l as sharedWorkspaceInstructionStore, n as InstructionConflictError, o as WorkspaceInstructionRecord, r as InstructionSizeError, s as WorkspaceInstructionStore, t as INSTRUCTION_MAX_BYTES } from "../workspace-instructions-C_ViytzA.js";
|
|
2
2
|
export { INSTRUCTION_MAX_BYTES, InstructionConflictError, InstructionSizeError, SessionInstructionSnapshot, SessionInstructionSnapshotStore, WorkspaceInstructionRecord, WorkspaceInstructionStore, sharedSessionInstructionSnapshotStore, sharedWorkspaceInstructionStore };
|
|
@@ -34,8 +34,12 @@ function computeDigest(text) {
|
|
|
34
34
|
var WorkspaceInstructionStore = class {
|
|
35
35
|
data = { records: {} };
|
|
36
36
|
loaded = false;
|
|
37
|
+
home;
|
|
38
|
+
constructor(home) {
|
|
39
|
+
this.home = home;
|
|
40
|
+
}
|
|
37
41
|
file() {
|
|
38
|
-
return join(dshHome(), "dshb", "workspace-instructions.json");
|
|
42
|
+
return join(this.home ?? dshHome(), "dshb", "workspace-instructions.json");
|
|
39
43
|
}
|
|
40
44
|
load() {
|
|
41
45
|
if (this.loaded) return;
|
|
@@ -92,6 +96,29 @@ var WorkspaceInstructionStore = class {
|
|
|
92
96
|
delete this.data.records[workspaceId];
|
|
93
97
|
this.save();
|
|
94
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* 同步导入采纳:以对端快照的修订恢复工作区指令。
|
|
101
|
+
* 本地缺失或本地修订更低(对端编辑过)时采纳;本地同版或更新时保留本地。
|
|
102
|
+
* revision 直接采用对端计数,使两端的指令修订序列保持同一根。
|
|
103
|
+
*/
|
|
104
|
+
restoreWorkspace(input) {
|
|
105
|
+
this.load();
|
|
106
|
+
if (utf8Bytes(input.text) > 32768) throw new InstructionSizeError(utf8Bytes(input.text));
|
|
107
|
+
const existing = this.data.records[input.workspaceId];
|
|
108
|
+
if (existing && existing.revision >= input.revision) return { ...existing };
|
|
109
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
110
|
+
const record = {
|
|
111
|
+
workspaceId: input.workspaceId,
|
|
112
|
+
text: input.text,
|
|
113
|
+
revision: input.revision,
|
|
114
|
+
digest: computeDigest(input.text),
|
|
115
|
+
createdAt: existing?.createdAt ?? input.capturedAt ?? now,
|
|
116
|
+
updatedAt: now
|
|
117
|
+
};
|
|
118
|
+
this.data.records[input.workspaceId] = record;
|
|
119
|
+
this.save();
|
|
120
|
+
return { ...record };
|
|
121
|
+
}
|
|
95
122
|
removeByWorkspace(workspaceId) {
|
|
96
123
|
this.load();
|
|
97
124
|
if (!this.data.records[workspaceId]) return;
|
|
@@ -181,6 +208,11 @@ var SessionInstructionSnapshotStore = class {
|
|
|
181
208
|
this.save();
|
|
182
209
|
return { ...snapshot };
|
|
183
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* 同步导入采纳:以对端快照的修订恢复工作区指令。
|
|
213
|
+
* 本地缺失或本地修订更低(对端编辑过)时采纳;本地同版或更新时保留本地。
|
|
214
|
+
* revision 直接采用对端计数,使两端的指令修订序列保持同一根。
|
|
215
|
+
*/
|
|
184
216
|
remove(sessionId) {
|
|
185
217
|
this.load();
|
|
186
218
|
if (!this.data.records[sessionId]) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-instructions.js","names":[],"sources":["../../src/core/workspace-instructions.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const INSTRUCTION_MAX_BYTES = 32768\n\nexport interface WorkspaceInstructionRecord {\n workspaceId: string\n text: string\n revision: number\n digest: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface SessionInstructionSnapshot {\n sessionId: string\n workspaceId?: string\n workspaceRevision?: number\n digest?: string\n text: string\n capturedAt: string\n inheritedFromSessionId?: string\n}\n\nexport class InstructionConflictError extends Error {\n readonly expected: number\n readonly actual: number\n constructor(expected: number, actual: number) {\n super(`revision conflict: expected ${expected}, current ${actual}`)\n this.name = 'InstructionConflictError'\n this.expected = expected\n this.actual = actual\n }\n}\n\nexport class InstructionSizeError extends Error {\n readonly bytes: number\n constructor(bytes: number) {\n super(`instruction exceeds ${INSTRUCTION_MAX_BYTES} bytes (got ${bytes})`)\n this.name = 'InstructionSizeError'\n this.bytes = bytes\n }\n}\n\nfunction dshHome(): string {\n return process.env.DSH_HOME ?? join(homedir(), '.dsh')\n}\n\nfunction utf8Bytes(text: string): number {\n return Buffer.byteLength(text, 'utf8')\n}\n\nfunction computeDigest(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex')\n}\n\ninterface WorkspaceStoreData {\n records: Record<string, WorkspaceInstructionRecord>\n}\n\ninterface SnapshotStoreData {\n records: Record<string, SessionInstructionSnapshot>\n}\n\nexport class WorkspaceInstructionStore {\n private data: WorkspaceStoreData = { records: {} }\n private loaded = false\n\n private file(): string {\n return join(dshHome(), 'dshb', 'workspace-instructions.json')\n }\n\n private load(): void {\n if (this.loaded) return\n this.loaded = true\n try {\n const raw = readFileSync(this.file(), 'utf8')\n this.data = JSON.parse(raw) as WorkspaceStoreData\n if (!this.data.records || typeof this.data.records !== 'object') {\n this.data = { records: {} }\n }\n } catch {\n this.data = { records: {} }\n }\n }\n\n private save(): void {\n this.load()\n const file = this.file()\n mkdirSync(join(file, '..'), { recursive: true, mode: 0o700 })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 0o600 })\n renameSync(tmp, file)\n chmodSync(file, 0o600)\n }\n\n get(workspaceId: string): WorkspaceInstructionRecord | undefined {\n this.load()\n const r = this.data.records[workspaceId]\n return r ? { ...r } : undefined\n }\n\n update(input: {\n workspaceId: string\n text: string\n expectedRevision: number\n }): WorkspaceInstructionRecord {\n this.load()\n const bytes = utf8Bytes(input.text)\n if (bytes > INSTRUCTION_MAX_BYTES) throw new InstructionSizeError(bytes)\n const existing = this.data.records[input.workspaceId]\n if (existing && existing.revision !== input.expectedRevision) {\n throw new InstructionConflictError(input.expectedRevision, existing.revision)\n }\n const now = new Date().toISOString()\n const record: WorkspaceInstructionRecord = {\n workspaceId: input.workspaceId,\n text: input.text,\n revision: (existing?.revision ?? 0) + 1,\n digest: computeDigest(input.text),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n this.data.records[input.workspaceId] = record\n this.save()\n return { ...record }\n }\n\n clear(workspaceId: string, expectedRevision: number): void {\n this.load()\n const existing = this.data.records[workspaceId]\n if (existing && existing.revision !== expectedRevision) {\n throw new InstructionConflictError(expectedRevision, existing.revision)\n }\n if (!existing) return\n delete this.data.records[workspaceId]\n this.save()\n }\n\n removeByWorkspace(workspaceId: string): void {\n this.load()\n if (!this.data.records[workspaceId]) return\n delete this.data.records[workspaceId]\n this.save()\n }\n}\n\nexport class SessionInstructionSnapshotStore {\n private data: SnapshotStoreData = { records: {} }\n private loaded = false\n\n private file(): string {\n return join(dshHome(), 'dshb', 'session-instruction-snapshots.json')\n }\n\n private load(): void {\n if (this.loaded) return\n this.loaded = true\n try {\n const raw = readFileSync(this.file(), 'utf8')\n this.data = JSON.parse(raw) as SnapshotStoreData\n if (!this.data.records || typeof this.data.records !== 'object') {\n this.data = { records: {} }\n }\n } catch {\n this.data = { records: {} }\n }\n }\n\n private save(): void {\n this.load()\n const file = this.file()\n mkdirSync(join(file, '..'), { recursive: true, mode: 0o700 })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 0o600 })\n renameSync(tmp, file)\n chmodSync(file, 0o600)\n }\n\n get(sessionId: string): SessionInstructionSnapshot | undefined {\n this.load()\n const r = this.data.records[sessionId]\n return r ? { ...r } : undefined\n }\n\n createIfAbsent(\n sessionId: string,\n source:\n | { kind: 'workspace'; record: WorkspaceInstructionRecord; workspaceId: string }\n | { kind: 'empty'; workspaceId?: string }\n | { kind: 'inherit'; parentSnapshot: SessionInstructionSnapshot },\n ): SessionInstructionSnapshot {\n this.load()\n const existing = this.data.records[sessionId]\n if (existing) return { ...existing }\n let snapshot: SessionInstructionSnapshot\n const now = new Date().toISOString()\n if (source.kind === 'workspace') {\n snapshot = {\n sessionId,\n workspaceId: source.workspaceId,\n workspaceRevision: source.record.revision,\n digest: source.record.digest,\n text: source.record.text,\n capturedAt: now,\n }\n } else if (source.kind === 'inherit') {\n const parent = source.parentSnapshot\n snapshot = {\n sessionId,\n workspaceId: parent.workspaceId,\n workspaceRevision: parent.workspaceRevision,\n digest: parent.digest,\n text: parent.text,\n capturedAt: now,\n inheritedFromSessionId: parent.sessionId,\n }\n } else {\n snapshot = {\n sessionId,\n workspaceId: source.workspaceId,\n text: '',\n capturedAt: now,\n }\n }\n this.data.records[sessionId] = snapshot\n this.save()\n return { ...snapshot }\n }\n\n restore(snapshot: SessionInstructionSnapshot): SessionInstructionSnapshot {\n this.load()\n if (utf8Bytes(snapshot.text) > INSTRUCTION_MAX_BYTES) throw new InstructionSizeError(utf8Bytes(snapshot.text))\n if (snapshot.digest !== undefined && snapshot.digest !== computeDigest(snapshot.text)) {\n throw new Error('session instruction snapshot digest mismatch')\n }\n const existing = this.data.records[snapshot.sessionId]\n if (existing) {\n if (JSON.stringify(existing) !== JSON.stringify(snapshot)) throw new Error('session instruction snapshot already differs')\n return { ...existing }\n }\n this.data.records[snapshot.sessionId] = { ...snapshot }\n this.save()\n return { ...snapshot }\n }\n\n remove(sessionId: string): void {\n this.load()\n if (!this.data.records[sessionId]) return\n delete this.data.records[sessionId]\n this.save()\n }\n}\n\nlet sharedWorkspaceStore: WorkspaceInstructionStore | null = null\nlet sharedSnapshotStore: SessionInstructionSnapshotStore | null = null\n\nexport function sharedWorkspaceInstructionStore(): WorkspaceInstructionStore {\n if (!sharedWorkspaceStore) sharedWorkspaceStore = new WorkspaceInstructionStore()\n return sharedWorkspaceStore\n}\n\nexport function sharedSessionInstructionSnapshotStore(): SessionInstructionSnapshotStore {\n if (!sharedSnapshotStore) sharedSnapshotStore = new SessionInstructionSnapshotStore()\n return sharedSnapshotStore\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workspace-instructions.js","names":[],"sources":["../../src/core/workspace-instructions.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const INSTRUCTION_MAX_BYTES = 32768\n\nexport interface WorkspaceInstructionRecord {\n workspaceId: string\n text: string\n revision: number\n digest: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface SessionInstructionSnapshot {\n sessionId: string\n workspaceId?: string\n workspaceRevision?: number\n digest?: string\n text: string\n capturedAt: string\n inheritedFromSessionId?: string\n}\n\nexport class InstructionConflictError extends Error {\n readonly expected: number\n readonly actual: number\n constructor(expected: number, actual: number) {\n super(`revision conflict: expected ${expected}, current ${actual}`)\n this.name = 'InstructionConflictError'\n this.expected = expected\n this.actual = actual\n }\n}\n\nexport class InstructionSizeError extends Error {\n readonly bytes: number\n constructor(bytes: number) {\n super(`instruction exceeds ${INSTRUCTION_MAX_BYTES} bytes (got ${bytes})`)\n this.name = 'InstructionSizeError'\n this.bytes = bytes\n }\n}\n\nfunction dshHome(): string {\n return process.env.DSH_HOME ?? join(homedir(), '.dsh')\n}\n\nfunction utf8Bytes(text: string): number {\n return Buffer.byteLength(text, 'utf8')\n}\n\nfunction computeDigest(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex')\n}\n\ninterface WorkspaceStoreData {\n records: Record<string, WorkspaceInstructionRecord>\n}\n\ninterface SnapshotStoreData {\n records: Record<string, SessionInstructionSnapshot>\n}\n\nexport class WorkspaceInstructionStore {\n private data: WorkspaceStoreData = { records: {} }\n private loaded = false\n private readonly home: string | undefined\n\n constructor(home?: string) {\n this.home = home\n }\n\n private file(): string {\n return join(this.home ?? dshHome(), 'dshb', 'workspace-instructions.json')\n }\n\n private load(): void {\n if (this.loaded) return\n this.loaded = true\n try {\n const raw = readFileSync(this.file(), 'utf8')\n this.data = JSON.parse(raw) as WorkspaceStoreData\n if (!this.data.records || typeof this.data.records !== 'object') {\n this.data = { records: {} }\n }\n } catch {\n this.data = { records: {} }\n }\n }\n\n private save(): void {\n this.load()\n const file = this.file()\n mkdirSync(join(file, '..'), { recursive: true, mode: 0o700 })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 0o600 })\n renameSync(tmp, file)\n chmodSync(file, 0o600)\n }\n\n get(workspaceId: string): WorkspaceInstructionRecord | undefined {\n this.load()\n const r = this.data.records[workspaceId]\n return r ? { ...r } : undefined\n }\n\n update(input: {\n workspaceId: string\n text: string\n expectedRevision: number\n }): WorkspaceInstructionRecord {\n this.load()\n const bytes = utf8Bytes(input.text)\n if (bytes > INSTRUCTION_MAX_BYTES) throw new InstructionSizeError(bytes)\n const existing = this.data.records[input.workspaceId]\n if (existing && existing.revision !== input.expectedRevision) {\n throw new InstructionConflictError(input.expectedRevision, existing.revision)\n }\n const now = new Date().toISOString()\n const record: WorkspaceInstructionRecord = {\n workspaceId: input.workspaceId,\n text: input.text,\n revision: (existing?.revision ?? 0) + 1,\n digest: computeDigest(input.text),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n this.data.records[input.workspaceId] = record\n this.save()\n return { ...record }\n }\n\n clear(workspaceId: string, expectedRevision: number): void {\n this.load()\n const existing = this.data.records[workspaceId]\n if (existing && existing.revision !== expectedRevision) {\n throw new InstructionConflictError(expectedRevision, existing.revision)\n }\n if (!existing) return\n delete this.data.records[workspaceId]\n this.save()\n }\n\n /**\n * 同步导入采纳:以对端快照的修订恢复工作区指令。\n * 本地缺失或本地修订更低(对端编辑过)时采纳;本地同版或更新时保留本地。\n * revision 直接采用对端计数,使两端的指令修订序列保持同一根。\n */\n restoreWorkspace(input: { workspaceId: string; text: string; revision: number; capturedAt?: string }): WorkspaceInstructionRecord | undefined {\n this.load()\n if (utf8Bytes(input.text) > INSTRUCTION_MAX_BYTES) throw new InstructionSizeError(utf8Bytes(input.text))\n const existing = this.data.records[input.workspaceId]\n if (existing && existing.revision >= input.revision) return { ...existing }\n const now = new Date().toISOString()\n const record: WorkspaceInstructionRecord = {\n workspaceId: input.workspaceId,\n text: input.text,\n revision: input.revision,\n digest: computeDigest(input.text),\n createdAt: existing?.createdAt ?? (input.capturedAt ?? now),\n updatedAt: now,\n }\n this.data.records[input.workspaceId] = record\n this.save()\n return { ...record }\n }\n\n removeByWorkspace(workspaceId: string): void {\n this.load()\n if (!this.data.records[workspaceId]) return\n delete this.data.records[workspaceId]\n this.save()\n }\n}\n\nexport class SessionInstructionSnapshotStore {\n private data: SnapshotStoreData = { records: {} }\n private loaded = false\n\n private file(): string {\n return join(dshHome(), 'dshb', 'session-instruction-snapshots.json')\n }\n\n private load(): void {\n if (this.loaded) return\n this.loaded = true\n try {\n const raw = readFileSync(this.file(), 'utf8')\n this.data = JSON.parse(raw) as SnapshotStoreData\n if (!this.data.records || typeof this.data.records !== 'object') {\n this.data = { records: {} }\n }\n } catch {\n this.data = { records: {} }\n }\n }\n\n private save(): void {\n this.load()\n const file = this.file()\n mkdirSync(join(file, '..'), { recursive: true, mode: 0o700 })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 0o600 })\n renameSync(tmp, file)\n chmodSync(file, 0o600)\n }\n\n get(sessionId: string): SessionInstructionSnapshot | undefined {\n this.load()\n const r = this.data.records[sessionId]\n return r ? { ...r } : undefined\n }\n\n createIfAbsent(\n sessionId: string,\n source:\n | { kind: 'workspace'; record: WorkspaceInstructionRecord; workspaceId: string }\n | { kind: 'empty'; workspaceId?: string }\n | { kind: 'inherit'; parentSnapshot: SessionInstructionSnapshot },\n ): SessionInstructionSnapshot {\n this.load()\n const existing = this.data.records[sessionId]\n if (existing) return { ...existing }\n let snapshot: SessionInstructionSnapshot\n const now = new Date().toISOString()\n if (source.kind === 'workspace') {\n snapshot = {\n sessionId,\n workspaceId: source.workspaceId,\n workspaceRevision: source.record.revision,\n digest: source.record.digest,\n text: source.record.text,\n capturedAt: now,\n }\n } else if (source.kind === 'inherit') {\n const parent = source.parentSnapshot\n snapshot = {\n sessionId,\n workspaceId: parent.workspaceId,\n workspaceRevision: parent.workspaceRevision,\n digest: parent.digest,\n text: parent.text,\n capturedAt: now,\n inheritedFromSessionId: parent.sessionId,\n }\n } else {\n snapshot = {\n sessionId,\n workspaceId: source.workspaceId,\n text: '',\n capturedAt: now,\n }\n }\n this.data.records[sessionId] = snapshot\n this.save()\n return { ...snapshot }\n }\n\n restore(snapshot: SessionInstructionSnapshot): SessionInstructionSnapshot {\n this.load()\n if (utf8Bytes(snapshot.text) > INSTRUCTION_MAX_BYTES) throw new InstructionSizeError(utf8Bytes(snapshot.text))\n if (snapshot.digest !== undefined && snapshot.digest !== computeDigest(snapshot.text)) {\n throw new Error('session instruction snapshot digest mismatch')\n }\n const existing = this.data.records[snapshot.sessionId]\n if (existing) {\n if (JSON.stringify(existing) !== JSON.stringify(snapshot)) throw new Error('session instruction snapshot already differs')\n return { ...existing }\n }\n this.data.records[snapshot.sessionId] = { ...snapshot }\n this.save()\n return { ...snapshot }\n }\n\n /**\n * 同步导入采纳:以对端快照的修订恢复工作区指令。\n * 本地缺失或本地修订更低(对端编辑过)时采纳;本地同版或更新时保留本地。\n * revision 直接采用对端计数,使两端的指令修订序列保持同一根。\n */\n remove(sessionId: string): void {\n this.load()\n if (!this.data.records[sessionId]) return\n delete this.data.records[sessionId]\n this.save()\n }\n}\n\nlet sharedWorkspaceStore: WorkspaceInstructionStore | null = null\nlet sharedSnapshotStore: SessionInstructionSnapshotStore | null = null\n\nexport function sharedWorkspaceInstructionStore(): WorkspaceInstructionStore {\n if (!sharedWorkspaceStore) sharedWorkspaceStore = new WorkspaceInstructionStore()\n return sharedWorkspaceStore\n}\n\nexport function sharedSessionInstructionSnapshotStore(): SessionInstructionSnapshotStore {\n if (!sharedSnapshotStore) sharedSnapshotStore = new SessionInstructionSnapshotStore()\n return sharedSnapshotStore\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { compareSyncRevision } from "./core/sync/revision.js";
|
|
2
2
|
import { isNonNegativeSafeInteger, isRecord as isRecord$1, syncRecordKey, syncWorkspaceKey } from "./core/sync/model.js";
|
|
3
|
-
import "./core/workspace-instructions.js";
|
|
3
|
+
import { InstructionSizeError, sharedWorkspaceInstructionStore } from "./core/workspace-instructions.js";
|
|
4
4
|
import { i as deepFreeze, r as brandString } from "./lib-gdtU_WKT.js";
|
|
5
5
|
import { MAX_SESSION_OBJECT_INLINE_BYTES, MAX_SESSION_OBJECT_STREAM_BYTES, MAX_SYNC_TRANSFER_BYTES } from "./core/sync/protocol.js";
|
|
6
6
|
import { SyncSessionJournalStore } from "./core/sync/session-journal.js";
|
|
@@ -1042,11 +1042,11 @@ function sessionEventDigest(header, inheritedEventCount, events, workspace, inst
|
|
|
1042
1042
|
hash.update(`,"instructionSnapshot":${instructionSnapshot ? canonicalJson({
|
|
1043
1043
|
text: instructionSnapshot.text,
|
|
1044
1044
|
capturedAt: instructionSnapshot.capturedAt,
|
|
1045
|
-
workspaceOrigin: instructionSnapshot.workspaceOrigin,
|
|
1046
|
-
workspaceRemotePath: instructionSnapshot.workspaceRemotePath,
|
|
1047
|
-
workspaceRevision: instructionSnapshot.workspaceRevision,
|
|
1048
|
-
digest: instructionSnapshot.digest,
|
|
1049
|
-
inheritedFromOrigin: instructionSnapshot.inheritedFromOrigin
|
|
1045
|
+
...instructionSnapshot.workspaceOrigin === void 0 ? {} : { workspaceOrigin: instructionSnapshot.workspaceOrigin },
|
|
1046
|
+
...instructionSnapshot.workspaceRemotePath === void 0 ? {} : { workspaceRemotePath: instructionSnapshot.workspaceRemotePath },
|
|
1047
|
+
...instructionSnapshot.workspaceRevision === void 0 ? {} : { workspaceRevision: instructionSnapshot.workspaceRevision },
|
|
1048
|
+
...instructionSnapshot.digest === void 0 ? {} : { digest: instructionSnapshot.digest },
|
|
1049
|
+
...instructionSnapshot.inheritedFromOrigin === void 0 ? {} : { inheritedFromOrigin: instructionSnapshot.inheritedFromOrigin }
|
|
1050
1050
|
}) : "undefined"}`);
|
|
1051
1051
|
hash.update(`,"parentOrigin":${parentOrigin ? canonicalJson(parentOrigin) : "undefined"}`);
|
|
1052
1052
|
hash.update(`,"workspace":${canonicalJson({
|
|
@@ -1079,7 +1079,6 @@ function sessionStateDigest(workspace, workspacePosition, archived, pinned) {
|
|
|
1079
1079
|
revision: workspace.revision,
|
|
1080
1080
|
contentDigest: workspace.contentDigest
|
|
1081
1081
|
},
|
|
1082
|
-
workspacePosition,
|
|
1083
1082
|
archived,
|
|
1084
1083
|
pinned
|
|
1085
1084
|
}));
|
|
@@ -1746,7 +1745,9 @@ var SyncSessionService = class SyncSessionService {
|
|
|
1746
1745
|
manifestPayloadCacheBytes = 0;
|
|
1747
1746
|
/** 带外对象收件箱:对象流 RPC 的落盘暂存区,apply 水合后删除。 */
|
|
1748
1747
|
objectInbox;
|
|
1749
|
-
|
|
1748
|
+
/** 工作区级指令存储:导入采纳写入,驱动该工作区新会话的指令注入。 */
|
|
1749
|
+
workspaceInstructions;
|
|
1750
|
+
constructor(state, nodes, registry, bindings, getWorkspaces, getPersistence, getAttachments, getSpills, instructions, journal = new SyncSessionJournalStore(), now = Date.now, home, workspaceInstructions) {
|
|
1750
1751
|
this.state = state;
|
|
1751
1752
|
this.nodes = nodes;
|
|
1752
1753
|
this.registry = registry;
|
|
@@ -1760,6 +1761,7 @@ var SyncSessionService = class SyncSessionService {
|
|
|
1760
1761
|
this.now = now;
|
|
1761
1762
|
this.exportCacheStore = new SyncSessionExportCacheStore(home);
|
|
1762
1763
|
this.objectInbox = new SyncSessionObjectInbox(home);
|
|
1764
|
+
this.workspaceInstructions = workspaceInstructions ?? sharedWorkspaceInstructionStore();
|
|
1763
1765
|
for (const [key, entry] of this.exportCacheStore.entries()) if (!this.exportCache.has(key)) this.exportCache.set(key, entry);
|
|
1764
1766
|
}
|
|
1765
1767
|
exportBundle() {
|
|
@@ -2630,7 +2632,20 @@ var SyncSessionService = class SyncSessionService {
|
|
|
2630
2632
|
async applyPrepared(prepared) {
|
|
2631
2633
|
const sessionId = prepared.localSessionId;
|
|
2632
2634
|
const existed = await this.writeSession(prepared);
|
|
2633
|
-
if (prepared.instructionSnapshot)
|
|
2635
|
+
if (prepared.instructionSnapshot) {
|
|
2636
|
+
this.instructions.restore(prepared.instructionSnapshot);
|
|
2637
|
+
const snapshot = prepared.instructionSnapshot;
|
|
2638
|
+
if (snapshot.workspaceId && snapshot.workspaceRevision !== void 0) try {
|
|
2639
|
+
this.workspaceInstructions.restoreWorkspace({
|
|
2640
|
+
workspaceId: snapshot.workspaceId,
|
|
2641
|
+
text: snapshot.text,
|
|
2642
|
+
revision: snapshot.workspaceRevision,
|
|
2643
|
+
capturedAt: snapshot.capturedAt
|
|
2644
|
+
});
|
|
2645
|
+
} catch (error) {
|
|
2646
|
+
if (!(error instanceof InstructionSizeError)) throw error;
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2634
2649
|
const registry = this.getWorkspaces();
|
|
2635
2650
|
const workspace = registry?.get(prepared.workspaceId);
|
|
2636
2651
|
if (!registry || !workspace || normalize(workspace.path) !== normalize(prepared.workspacePath)) throw new SyncSessionError("workspace-unmapped", "导入 session 的目标工作区不可用");
|
|
@@ -2985,7 +3000,7 @@ var SyncSessionService = class SyncSessionService {
|
|
|
2985
3000
|
let contentDigest = digest;
|
|
2986
3001
|
let outputBranchId = archive?.branchId;
|
|
2987
3002
|
if (archive) {
|
|
2988
|
-
if (archive.contentDigest !== digest || archive.stateDigest !== stateDigest
|
|
3003
|
+
if (archive.contentDigest !== digest || archive.stateDigest !== stateDigest) {
|
|
2989
3004
|
const nextRevision = this.state.nextRevision(this.now());
|
|
2990
3005
|
revision = nextRevision;
|
|
2991
3006
|
const branchId = archive.contentDigest !== digest ? branchIdFor({
|
|
@@ -3398,4 +3413,4 @@ var SyncSessionService = class SyncSessionService {
|
|
|
3398
3413
|
//#endregion
|
|
3399
3414
|
export { estimateJsonBytes as a, planSessionTransfers as c, validateObjectPayload as d, validateSyncSessionBundle as f, SyncSessionService as i, sessionEventListDigest as l, SyncSessionError as n, makeSyncSessionBundle as o, validateSyncSessionManifest as p, SyncSessionObjectInbox as r, makeSyncSessionManifest as s, ExportObjectCache as t, syncSessionEntryKey as u };
|
|
3400
3415
|
|
|
3401
|
-
//# sourceMappingURL=session-sync-
|
|
3416
|
+
//# sourceMappingURL=session-sync-BBCm_ou2.js.map
|