@artenx/dshb 0.1.2 → 0.1.4
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/cordis.patch.yml +2 -0
- package/lib/client.js +392 -29
- package/lib/client.js.map +1 -1
- package/lib/core/index.js +5 -0
- package/lib/core/index.js.map +1 -1
- package/lib/core/workspace-instruction-context.d.ts +1667 -0
- package/lib/core/workspace-instruction-context.js +3 -0
- package/lib/core/workspace-instruction-routes.d.ts +7 -0
- package/lib/core/workspace-instruction-routes.js +155 -0
- package/lib/core/workspace-instruction-routes.js.map +1 -0
- package/lib/core/workspace-instructions.d.ts +68 -0
- package/lib/core/workspace-instructions.js +191 -0
- package/lib/core/workspace-instructions.js.map +1 -0
- package/lib/router/router-fs.d.ts +1 -1
- package/lib/router/router-shell.d.ts +1 -1
- package/lib/router/router-subprocess.d.ts +1 -1
- package/lib/ui/picker.d.ts +1 -1
- package/lib/workspace-instruction-context-CxUldQkP.js +2241 -0
- package/lib/workspace-instruction-context-CxUldQkP.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import "./workspace-instructions.js";
|
|
2
|
+
import { a as registerWorkspaceInstructionInjector, i as name, n as escapeInstructionFrameBody, o as renderInstructionMessageText, r as inject, s as resolveSnapshotForSession, t as createInstructionMessage } from "../workspace-instruction-context-CxUldQkP.js";
|
|
3
|
+
export { createInstructionMessage, escapeInstructionFrameBody, inject, name, registerWorkspaceInstructionInjector, renderInstructionMessageText, resolveSnapshotForSession };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { WorkspaceInstructionStore } from "./workspace-instructions.js";
|
|
2
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
//#region src/core/workspace-instruction-routes.d.ts
|
|
4
|
+
declare function registerWorkspaceInstructionRoutes(ctx: Context, store: WorkspaceInstructionStore): void;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { registerWorkspaceInstructionRoutes };
|
|
7
|
+
//# sourceMappingURL=workspace-instruction-routes.d.ts.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { INSTRUCTION_MAX_BYTES, InstructionConflictError, InstructionSizeError } from "./workspace-instructions.js";
|
|
2
|
+
//#region src/core/workspace-instruction-routes.ts
|
|
3
|
+
const MAX_BODY = 65536;
|
|
4
|
+
function sendJson(res, status, body) {
|
|
5
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
6
|
+
res.end(JSON.stringify(body));
|
|
7
|
+
}
|
|
8
|
+
function readBody(req) {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
if ((req.headers["content-type"] ?? "") !== "application/json") {
|
|
11
|
+
resolve(null);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const chunks = [];
|
|
15
|
+
let size = 0;
|
|
16
|
+
req.on("data", (chunk) => {
|
|
17
|
+
size += chunk.length;
|
|
18
|
+
if (size > MAX_BODY) {
|
|
19
|
+
resolve(null);
|
|
20
|
+
req.destroy();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
chunks.push(chunk);
|
|
24
|
+
});
|
|
25
|
+
req.on("end", () => {
|
|
26
|
+
try {
|
|
27
|
+
resolve(JSON.parse(Buffer.concat(chunks).toString("utf8")));
|
|
28
|
+
} catch {
|
|
29
|
+
resolve(null);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
req.on("error", () => resolve(null));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function pathSegments(req) {
|
|
36
|
+
return new URL(req.url ?? "/", "http://x").pathname.split("/").filter(Boolean);
|
|
37
|
+
}
|
|
38
|
+
function registerWorkspaceInstructionRoutes(ctx, store) {
|
|
39
|
+
const webServer = ctx.webServer;
|
|
40
|
+
ctx.effect(() => webServer.register({
|
|
41
|
+
kind: "prefix",
|
|
42
|
+
path: "/api/dshb/instructions",
|
|
43
|
+
handler: async (req, res) => {
|
|
44
|
+
const workspaceId = pathSegments(req)[3];
|
|
45
|
+
if (!workspaceId) {
|
|
46
|
+
sendJson(res, 404, {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: "not found"
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const registry = ctx.get("workspaceRegistry");
|
|
53
|
+
if (registry) {
|
|
54
|
+
if (!registry.get(workspaceId)) {
|
|
55
|
+
sendJson(res, 404, {
|
|
56
|
+
ok: false,
|
|
57
|
+
error: "workspace not found"
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (req.method === "GET") {
|
|
63
|
+
const record = store.get(workspaceId);
|
|
64
|
+
if (!record) {
|
|
65
|
+
sendJson(res, 200, {
|
|
66
|
+
workspaceId,
|
|
67
|
+
text: "",
|
|
68
|
+
revision: 0,
|
|
69
|
+
updatedAt: null
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
sendJson(res, 200, {
|
|
74
|
+
workspaceId: record.workspaceId,
|
|
75
|
+
text: record.text,
|
|
76
|
+
revision: record.revision,
|
|
77
|
+
updatedAt: record.updatedAt
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (req.method === "PUT") {
|
|
82
|
+
const body = await readBody(req);
|
|
83
|
+
if (!body || typeof body.text !== "string" || typeof body.expectedRevision !== "number") {
|
|
84
|
+
sendJson(res, 400, {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: "需要 text 和 expectedRevision"
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const text = body.text;
|
|
91
|
+
const expectedRevision = body.expectedRevision;
|
|
92
|
+
try {
|
|
93
|
+
if (text.length === 0) {
|
|
94
|
+
store.clear(workspaceId, expectedRevision);
|
|
95
|
+
sendJson(res, 200, {
|
|
96
|
+
workspaceId,
|
|
97
|
+
text: "",
|
|
98
|
+
revision: expectedRevision,
|
|
99
|
+
updatedAt: null
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const record = store.update({
|
|
104
|
+
workspaceId,
|
|
105
|
+
text,
|
|
106
|
+
expectedRevision
|
|
107
|
+
});
|
|
108
|
+
sendJson(res, 200, {
|
|
109
|
+
workspaceId: record.workspaceId,
|
|
110
|
+
text: record.text,
|
|
111
|
+
revision: record.revision,
|
|
112
|
+
updatedAt: record.updatedAt
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
} catch (err) {
|
|
116
|
+
if (err instanceof InstructionConflictError) {
|
|
117
|
+
const current = store.get(workspaceId);
|
|
118
|
+
sendJson(res, 409, {
|
|
119
|
+
ok: false,
|
|
120
|
+
error: "revision conflict",
|
|
121
|
+
expected: err.expected,
|
|
122
|
+
actual: err.actual,
|
|
123
|
+
currentRevision: current?.revision ?? 0,
|
|
124
|
+
currentText: current?.text ?? "",
|
|
125
|
+
currentUpdatedAt: current?.updatedAt ?? null
|
|
126
|
+
});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (err instanceof InstructionSizeError) {
|
|
130
|
+
sendJson(res, 400, {
|
|
131
|
+
ok: false,
|
|
132
|
+
error: `instruction exceeds ${INSTRUCTION_MAX_BYTES} bytes`,
|
|
133
|
+
bytes: err.bytes,
|
|
134
|
+
limit: INSTRUCTION_MAX_BYTES
|
|
135
|
+
});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
sendJson(res, 500, {
|
|
139
|
+
ok: false,
|
|
140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
sendJson(res, 404, {
|
|
146
|
+
ok: false,
|
|
147
|
+
error: "not found"
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { registerWorkspaceInstructionRoutes };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=workspace-instruction-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-instruction-routes.js","names":[],"sources":["../../src/core/workspace-instruction-routes.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-host-webserver'\nimport {\n InstructionConflictError,\n InstructionSizeError,\n INSTRUCTION_MAX_BYTES,\n type WorkspaceInstructionStore,\n} from './workspace-instructions.js'\n\nconst MAX_BODY = 64 * 1024\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { 'content-type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: IncomingMessage): Promise<Record<string, unknown> | null> {\n return new Promise((resolve) => {\n if ((req.headers['content-type'] ?? '') !== 'application/json') {\n resolve(null)\n return\n }\n const chunks: Buffer[] = []\n let size = 0\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_BODY) {\n resolve(null)\n req.destroy()\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => {\n try {\n resolve(JSON.parse(Buffer.concat(chunks).toString('utf8')) as Record<string, unknown>)\n } catch {\n resolve(null)\n }\n })\n req.on('error', () => resolve(null))\n })\n}\n\nfunction pathSegments(req: IncomingMessage): string[] {\n return new URL(req.url ?? '/', 'http://x').pathname.split('/').filter(Boolean)\n}\n\ninterface WorkspaceRegistryLike {\n get(workspaceId: string): { id: string; path: string; title: string } | undefined\n}\n\nexport function registerWorkspaceInstructionRoutes(ctx: Context, store: WorkspaceInstructionStore): void {\n const webServer = ctx.webServer\n\n ctx.effect(() =>\n webServer.register({\n kind: 'prefix',\n path: '/api/dshb/instructions',\n handler: async (req, res) => {\n const segs = pathSegments(req)\n const workspaceId = segs[3]\n if (!workspaceId) {\n sendJson(res, 404, { ok: false, error: 'not found' })\n return\n }\n\n const registry = ctx.get('workspaceRegistry') as WorkspaceRegistryLike | undefined\n if (registry) {\n const ws = registry.get(workspaceId)\n if (!ws) {\n sendJson(res, 404, { ok: false, error: 'workspace not found' })\n return\n }\n }\n\n if (req.method === 'GET') {\n const record = store.get(workspaceId)\n if (!record) {\n sendJson(res, 200, {\n workspaceId,\n text: '',\n revision: 0,\n updatedAt: null,\n })\n return\n }\n sendJson(res, 200, {\n workspaceId: record.workspaceId,\n text: record.text,\n revision: record.revision,\n updatedAt: record.updatedAt,\n })\n return\n }\n\n if (req.method === 'PUT') {\n const body = await readBody(req)\n if (!body || typeof body.text !== 'string' || typeof body.expectedRevision !== 'number') {\n sendJson(res, 400, { ok: false, error: '需要 text 和 expectedRevision' })\n return\n }\n const text = body.text as string\n const expectedRevision = body.expectedRevision as number\n try {\n if (text.length === 0) {\n store.clear(workspaceId, expectedRevision)\n sendJson(res, 200, {\n workspaceId,\n text: '',\n revision: expectedRevision,\n updatedAt: null,\n })\n return\n }\n const record = store.update({ workspaceId, text, expectedRevision })\n sendJson(res, 200, {\n workspaceId: record.workspaceId,\n text: record.text,\n revision: record.revision,\n updatedAt: record.updatedAt,\n })\n return\n } catch (err) {\n if (err instanceof InstructionConflictError) {\n const current = store.get(workspaceId)\n sendJson(res, 409, {\n ok: false,\n error: 'revision conflict',\n expected: err.expected,\n actual: err.actual,\n currentRevision: current?.revision ?? 0,\n currentText: current?.text ?? '',\n currentUpdatedAt: current?.updatedAt ?? null,\n })\n return\n }\n if (err instanceof InstructionSizeError) {\n sendJson(res, 400, {\n ok: false,\n error: `instruction exceeds ${INSTRUCTION_MAX_BYTES} bytes`,\n bytes: err.bytes,\n limit: INSTRUCTION_MAX_BYTES,\n })\n return\n }\n sendJson(res, 500, { ok: false, error: err instanceof Error ? err.message : String(err) })\n return\n }\n }\n\n sendJson(res, 404, { ok: false, error: 'not found' })\n },\n }),\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//#region src/core/workspace-instructions.d.ts
|
|
2
|
+
declare const INSTRUCTION_MAX_BYTES = 32768;
|
|
3
|
+
interface WorkspaceInstructionRecord {
|
|
4
|
+
workspaceId: string;
|
|
5
|
+
text: string;
|
|
6
|
+
revision: number;
|
|
7
|
+
digest: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
updatedAt: string;
|
|
10
|
+
}
|
|
11
|
+
interface SessionInstructionSnapshot {
|
|
12
|
+
sessionId: string;
|
|
13
|
+
workspaceId?: string;
|
|
14
|
+
workspaceRevision?: number;
|
|
15
|
+
digest?: string;
|
|
16
|
+
text: string;
|
|
17
|
+
capturedAt: string;
|
|
18
|
+
inheritedFromSessionId?: string;
|
|
19
|
+
}
|
|
20
|
+
declare class InstructionConflictError extends Error {
|
|
21
|
+
readonly expected: number;
|
|
22
|
+
readonly actual: number;
|
|
23
|
+
constructor(expected: number, actual: number);
|
|
24
|
+
}
|
|
25
|
+
declare class InstructionSizeError extends Error {
|
|
26
|
+
readonly bytes: number;
|
|
27
|
+
constructor(bytes: number);
|
|
28
|
+
}
|
|
29
|
+
declare class WorkspaceInstructionStore {
|
|
30
|
+
private data;
|
|
31
|
+
private loaded;
|
|
32
|
+
private file;
|
|
33
|
+
private load;
|
|
34
|
+
private save;
|
|
35
|
+
get(workspaceId: string): WorkspaceInstructionRecord | undefined;
|
|
36
|
+
update(input: {
|
|
37
|
+
workspaceId: string;
|
|
38
|
+
text: string;
|
|
39
|
+
expectedRevision: number;
|
|
40
|
+
}): WorkspaceInstructionRecord;
|
|
41
|
+
clear(workspaceId: string, expectedRevision: number): void;
|
|
42
|
+
removeByWorkspace(workspaceId: string): void;
|
|
43
|
+
}
|
|
44
|
+
declare class SessionInstructionSnapshotStore {
|
|
45
|
+
private data;
|
|
46
|
+
private loaded;
|
|
47
|
+
private file;
|
|
48
|
+
private load;
|
|
49
|
+
private save;
|
|
50
|
+
get(sessionId: string): SessionInstructionSnapshot | undefined;
|
|
51
|
+
createIfAbsent(sessionId: string, source: {
|
|
52
|
+
kind: 'workspace';
|
|
53
|
+
record: WorkspaceInstructionRecord;
|
|
54
|
+
workspaceId: string;
|
|
55
|
+
} | {
|
|
56
|
+
kind: 'empty';
|
|
57
|
+
workspaceId?: string;
|
|
58
|
+
} | {
|
|
59
|
+
kind: 'inherit';
|
|
60
|
+
parentSnapshot: SessionInstructionSnapshot;
|
|
61
|
+
}): SessionInstructionSnapshot;
|
|
62
|
+
remove(sessionId: string): void;
|
|
63
|
+
}
|
|
64
|
+
declare function sharedWorkspaceInstructionStore(): WorkspaceInstructionStore;
|
|
65
|
+
declare function sharedSessionInstructionSnapshotStore(): SessionInstructionSnapshotStore;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { INSTRUCTION_MAX_BYTES, InstructionConflictError, InstructionSizeError, SessionInstructionSnapshot, SessionInstructionSnapshotStore, WorkspaceInstructionRecord, WorkspaceInstructionStore, sharedSessionInstructionSnapshotStore, sharedWorkspaceInstructionStore };
|
|
68
|
+
//# sourceMappingURL=workspace-instructions.d.ts.map
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
//#region src/core/workspace-instructions.ts
|
|
6
|
+
const INSTRUCTION_MAX_BYTES = 32768;
|
|
7
|
+
var InstructionConflictError = class extends Error {
|
|
8
|
+
expected;
|
|
9
|
+
actual;
|
|
10
|
+
constructor(expected, actual) {
|
|
11
|
+
super(`revision conflict: expected ${expected}, current ${actual}`);
|
|
12
|
+
this.name = "InstructionConflictError";
|
|
13
|
+
this.expected = expected;
|
|
14
|
+
this.actual = actual;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var InstructionSizeError = class extends Error {
|
|
18
|
+
bytes;
|
|
19
|
+
constructor(bytes) {
|
|
20
|
+
super(`instruction exceeds ${INSTRUCTION_MAX_BYTES} bytes (got ${bytes})`);
|
|
21
|
+
this.name = "InstructionSizeError";
|
|
22
|
+
this.bytes = bytes;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function dshHome() {
|
|
26
|
+
return process.env.DSH_HOME ?? join(homedir(), ".dsh");
|
|
27
|
+
}
|
|
28
|
+
function utf8Bytes(text) {
|
|
29
|
+
return Buffer.byteLength(text, "utf8");
|
|
30
|
+
}
|
|
31
|
+
function computeDigest(text) {
|
|
32
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
33
|
+
}
|
|
34
|
+
var WorkspaceInstructionStore = class {
|
|
35
|
+
data = { records: {} };
|
|
36
|
+
loaded = false;
|
|
37
|
+
file() {
|
|
38
|
+
return join(dshHome(), "dshb", "workspace-instructions.json");
|
|
39
|
+
}
|
|
40
|
+
load() {
|
|
41
|
+
if (this.loaded) return;
|
|
42
|
+
this.loaded = true;
|
|
43
|
+
try {
|
|
44
|
+
const raw = readFileSync(this.file(), "utf8");
|
|
45
|
+
this.data = JSON.parse(raw);
|
|
46
|
+
if (!this.data.records || typeof this.data.records !== "object") this.data = { records: {} };
|
|
47
|
+
} catch {
|
|
48
|
+
this.data = { records: {} };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
save() {
|
|
52
|
+
this.load();
|
|
53
|
+
const file = this.file();
|
|
54
|
+
mkdirSync(join(file, ".."), {
|
|
55
|
+
recursive: true,
|
|
56
|
+
mode: 448
|
|
57
|
+
});
|
|
58
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
59
|
+
writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 384 });
|
|
60
|
+
renameSync(tmp, file);
|
|
61
|
+
chmodSync(file, 384);
|
|
62
|
+
}
|
|
63
|
+
get(workspaceId) {
|
|
64
|
+
this.load();
|
|
65
|
+
const r = this.data.records[workspaceId];
|
|
66
|
+
return r ? { ...r } : void 0;
|
|
67
|
+
}
|
|
68
|
+
update(input) {
|
|
69
|
+
this.load();
|
|
70
|
+
const bytes = utf8Bytes(input.text);
|
|
71
|
+
if (bytes > 32768) throw new InstructionSizeError(bytes);
|
|
72
|
+
const existing = this.data.records[input.workspaceId];
|
|
73
|
+
if (existing && existing.revision !== input.expectedRevision) throw new InstructionConflictError(input.expectedRevision, existing.revision);
|
|
74
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
75
|
+
const record = {
|
|
76
|
+
workspaceId: input.workspaceId,
|
|
77
|
+
text: input.text,
|
|
78
|
+
revision: (existing?.revision ?? 0) + 1,
|
|
79
|
+
digest: computeDigest(input.text),
|
|
80
|
+
createdAt: existing?.createdAt ?? now,
|
|
81
|
+
updatedAt: now
|
|
82
|
+
};
|
|
83
|
+
this.data.records[input.workspaceId] = record;
|
|
84
|
+
this.save();
|
|
85
|
+
return { ...record };
|
|
86
|
+
}
|
|
87
|
+
clear(workspaceId, expectedRevision) {
|
|
88
|
+
this.load();
|
|
89
|
+
const existing = this.data.records[workspaceId];
|
|
90
|
+
if (existing && existing.revision !== expectedRevision) throw new InstructionConflictError(expectedRevision, existing.revision);
|
|
91
|
+
if (!existing) return;
|
|
92
|
+
delete this.data.records[workspaceId];
|
|
93
|
+
this.save();
|
|
94
|
+
}
|
|
95
|
+
removeByWorkspace(workspaceId) {
|
|
96
|
+
this.load();
|
|
97
|
+
if (!this.data.records[workspaceId]) return;
|
|
98
|
+
delete this.data.records[workspaceId];
|
|
99
|
+
this.save();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var SessionInstructionSnapshotStore = class {
|
|
103
|
+
data = { records: {} };
|
|
104
|
+
loaded = false;
|
|
105
|
+
file() {
|
|
106
|
+
return join(dshHome(), "dshb", "session-instruction-snapshots.json");
|
|
107
|
+
}
|
|
108
|
+
load() {
|
|
109
|
+
if (this.loaded) return;
|
|
110
|
+
this.loaded = true;
|
|
111
|
+
try {
|
|
112
|
+
const raw = readFileSync(this.file(), "utf8");
|
|
113
|
+
this.data = JSON.parse(raw);
|
|
114
|
+
if (!this.data.records || typeof this.data.records !== "object") this.data = { records: {} };
|
|
115
|
+
} catch {
|
|
116
|
+
this.data = { records: {} };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
save() {
|
|
120
|
+
this.load();
|
|
121
|
+
const file = this.file();
|
|
122
|
+
mkdirSync(join(file, ".."), {
|
|
123
|
+
recursive: true,
|
|
124
|
+
mode: 448
|
|
125
|
+
});
|
|
126
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
127
|
+
writeFileSync(tmp, JSON.stringify(this.data, null, 2), { mode: 384 });
|
|
128
|
+
renameSync(tmp, file);
|
|
129
|
+
chmodSync(file, 384);
|
|
130
|
+
}
|
|
131
|
+
get(sessionId) {
|
|
132
|
+
this.load();
|
|
133
|
+
const r = this.data.records[sessionId];
|
|
134
|
+
return r ? { ...r } : void 0;
|
|
135
|
+
}
|
|
136
|
+
createIfAbsent(sessionId, source) {
|
|
137
|
+
this.load();
|
|
138
|
+
const existing = this.data.records[sessionId];
|
|
139
|
+
if (existing) return { ...existing };
|
|
140
|
+
let snapshot;
|
|
141
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
142
|
+
if (source.kind === "workspace") snapshot = {
|
|
143
|
+
sessionId,
|
|
144
|
+
workspaceId: source.workspaceId,
|
|
145
|
+
workspaceRevision: source.record.revision,
|
|
146
|
+
digest: source.record.digest,
|
|
147
|
+
text: source.record.text,
|
|
148
|
+
capturedAt: now
|
|
149
|
+
};
|
|
150
|
+
else if (source.kind === "inherit") {
|
|
151
|
+
const parent = source.parentSnapshot;
|
|
152
|
+
snapshot = {
|
|
153
|
+
sessionId,
|
|
154
|
+
workspaceId: parent.workspaceId,
|
|
155
|
+
workspaceRevision: parent.workspaceRevision,
|
|
156
|
+
digest: parent.digest,
|
|
157
|
+
text: parent.text,
|
|
158
|
+
capturedAt: now,
|
|
159
|
+
inheritedFromSessionId: parent.sessionId
|
|
160
|
+
};
|
|
161
|
+
} else snapshot = {
|
|
162
|
+
sessionId,
|
|
163
|
+
workspaceId: source.workspaceId,
|
|
164
|
+
text: "",
|
|
165
|
+
capturedAt: now
|
|
166
|
+
};
|
|
167
|
+
this.data.records[sessionId] = snapshot;
|
|
168
|
+
this.save();
|
|
169
|
+
return { ...snapshot };
|
|
170
|
+
}
|
|
171
|
+
remove(sessionId) {
|
|
172
|
+
this.load();
|
|
173
|
+
if (!this.data.records[sessionId]) return;
|
|
174
|
+
delete this.data.records[sessionId];
|
|
175
|
+
this.save();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
let sharedWorkspaceStore = null;
|
|
179
|
+
let sharedSnapshotStore = null;
|
|
180
|
+
function sharedWorkspaceInstructionStore() {
|
|
181
|
+
if (!sharedWorkspaceStore) sharedWorkspaceStore = new WorkspaceInstructionStore();
|
|
182
|
+
return sharedWorkspaceStore;
|
|
183
|
+
}
|
|
184
|
+
function sharedSessionInstructionSnapshotStore() {
|
|
185
|
+
if (!sharedSnapshotStore) sharedSnapshotStore = new SessionInstructionSnapshotStore();
|
|
186
|
+
return sharedSnapshotStore;
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
export { INSTRUCTION_MAX_BYTES, InstructionConflictError, InstructionSizeError, SessionInstructionSnapshotStore, WorkspaceInstructionStore, sharedSessionInstructionSnapshotStore, sharedWorkspaceInstructionStore };
|
|
190
|
+
|
|
191
|
+
//# sourceMappingURL=workspace-instructions.js.map
|
|
@@ -0,0 +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 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,5 +1,5 @@
|
|
|
1
|
-
import SandboxedFileSystem from "@deepseek-ai/dsh-fs-sandbox";
|
|
2
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import SandboxedFileSystem from "@deepseek-ai/dsh-fs-sandbox";
|
|
3
3
|
import { FsDirEntry, FsEditOutcome, FsEditRequest, FsInfo, FsPathInfo, FsTarget, FsVersion, FsWriteIntent, FsWriteOutcome } from "@deepseek-ai/dsh-fs";
|
|
4
4
|
import { SandboxExecutionPolicy } from "@deepseek-ai/dsh-sandbox";
|
|
5
5
|
//#region src/router/router-fs.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import SandboxBashExecutor from "@deepseek-ai/dsh-bash-sandbox";
|
|
2
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import SandboxBashExecutor from "@deepseek-ai/dsh-bash-sandbox";
|
|
3
3
|
import { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from "@deepseek-ai/dsh-shell";
|
|
4
4
|
//#region src/router/router-shell.d.ts
|
|
5
5
|
declare class RouterShell extends SandboxBashExecutor {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import LocalSubprocessRuntime from "@deepseek-ai/dsh-subprocess-local";
|
|
2
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import LocalSubprocessRuntime from "@deepseek-ai/dsh-subprocess-local";
|
|
3
3
|
import { SubprocessHandle, SubprocessSpawnSpec, SubprocessTerminalHandle, SubprocessTerminalSpawnSpec } from "@deepseek-ai/dsh-subprocess";
|
|
4
4
|
//#region src/router/router-subprocess.d.ts
|
|
5
5
|
declare class RouterSubprocess extends LocalSubprocessRuntime {
|
package/lib/ui/picker.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import DirectoryPicker, { DirectoryPickerBrowseCapability } from "@deepseek-ai/dsh-host-directory-picker";
|
|
2
1
|
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import DirectoryPicker, { DirectoryPickerBrowseCapability } from "@deepseek-ai/dsh-host-directory-picker";
|
|
3
3
|
//#region src/ui/picker.d.ts
|
|
4
4
|
declare class DshbDirectoryPicker extends DirectoryPicker {
|
|
5
5
|
constructor(ctx: Context);
|