@artenx/dshb 0.1.37 → 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-CQWx3lW9.js → session-sync-BBCm_ou2.js} +25 -9
- 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-CQWx3lW9.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({
|
|
@@ -1745,7 +1745,9 @@ var SyncSessionService = class SyncSessionService {
|
|
|
1745
1745
|
manifestPayloadCacheBytes = 0;
|
|
1746
1746
|
/** 带外对象收件箱:对象流 RPC 的落盘暂存区,apply 水合后删除。 */
|
|
1747
1747
|
objectInbox;
|
|
1748
|
-
|
|
1748
|
+
/** 工作区级指令存储:导入采纳写入,驱动该工作区新会话的指令注入。 */
|
|
1749
|
+
workspaceInstructions;
|
|
1750
|
+
constructor(state, nodes, registry, bindings, getWorkspaces, getPersistence, getAttachments, getSpills, instructions, journal = new SyncSessionJournalStore(), now = Date.now, home, workspaceInstructions) {
|
|
1749
1751
|
this.state = state;
|
|
1750
1752
|
this.nodes = nodes;
|
|
1751
1753
|
this.registry = registry;
|
|
@@ -1759,6 +1761,7 @@ var SyncSessionService = class SyncSessionService {
|
|
|
1759
1761
|
this.now = now;
|
|
1760
1762
|
this.exportCacheStore = new SyncSessionExportCacheStore(home);
|
|
1761
1763
|
this.objectInbox = new SyncSessionObjectInbox(home);
|
|
1764
|
+
this.workspaceInstructions = workspaceInstructions ?? sharedWorkspaceInstructionStore();
|
|
1762
1765
|
for (const [key, entry] of this.exportCacheStore.entries()) if (!this.exportCache.has(key)) this.exportCache.set(key, entry);
|
|
1763
1766
|
}
|
|
1764
1767
|
exportBundle() {
|
|
@@ -2629,7 +2632,20 @@ var SyncSessionService = class SyncSessionService {
|
|
|
2629
2632
|
async applyPrepared(prepared) {
|
|
2630
2633
|
const sessionId = prepared.localSessionId;
|
|
2631
2634
|
const existed = await this.writeSession(prepared);
|
|
2632
|
-
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
|
+
}
|
|
2633
2649
|
const registry = this.getWorkspaces();
|
|
2634
2650
|
const workspace = registry?.get(prepared.workspaceId);
|
|
2635
2651
|
if (!registry || !workspace || normalize(workspace.path) !== normalize(prepared.workspacePath)) throw new SyncSessionError("workspace-unmapped", "导入 session 的目标工作区不可用");
|
|
@@ -3397,4 +3413,4 @@ var SyncSessionService = class SyncSessionService {
|
|
|
3397
3413
|
//#endregion
|
|
3398
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 };
|
|
3399
3415
|
|
|
3400
|
-
//# sourceMappingURL=session-sync-
|
|
3416
|
+
//# sourceMappingURL=session-sync-BBCm_ou2.js.map
|