dsh-trivium 0.4.14 → 0.4.16

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/extract.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { writeFile } from "node:fs/promises";
2
3
  import { dirname, join } from "node:path";
3
4
  import { EDGE_LABELS, clip, looksSecret, nowIso } from "./schema.js";
4
5
  import { sanitizeForWrite } from "./hygiene.js";
@@ -73,10 +74,10 @@ export function loadPending(cwd) {
73
74
  }
74
75
  }
75
76
 
76
- export function savePending(cwd, payload) {
77
+ export async function savePending(cwd, payload) {
77
78
  const file = pendingPath(cwd);
78
79
  mkdirSync(dirname(file), { recursive: true });
79
- writeFileSync(
80
+ await writeFile(
80
81
  file,
81
82
  JSON.stringify(
82
83
  {
package/lib/index.js CHANGED
@@ -149,14 +149,14 @@ async function runExtract(ctx, { cwd, turns, sessionId, session, agent, log, opt
149
149
  llmFailed: result.llmFailed,
150
150
  };
151
151
  if (result.llmFailed) {
152
- savePending(cwd, { sessionId, turns, error: "llm failed" });
152
+ await savePending(cwd, { sessionId, turns, error: "llm failed" });
153
153
  } else {
154
154
  clearPending(cwd);
155
155
  }
156
156
  } catch (err) {
157
157
  log.warn?.(`[dsh-trivium] extract skipped: ${err.message}`);
158
158
  try {
159
- savePending(cwd, { sessionId, turns, error: String(err.message || err) });
159
+ await savePending(cwd, { sessionId, turns, error: String(err.message || err) });
160
160
  } catch {
161
161
  // ignore
162
162
  }
@@ -192,6 +192,7 @@ function onSessionEvent(session, event) {
192
192
  case "tool/result": {
193
193
  const callId = event.data?.message?.source?.callId || event.data?.callId;
194
194
  const name = buf.calls[callId] || "tool";
195
+ delete buf.calls[callId];
195
196
  const msg = event.data?.message || event.data;
196
197
  const content0 = Array.isArray(msg?.content) ? msg.content[0] : null;
197
198
  const err = event.data?.error || msg?.error;
@@ -213,7 +214,7 @@ function onSessionEvent(session, event) {
213
214
  }
214
215
  case "turn/end": {
215
216
  if (buf.dirty && buf.cwd && buf.turns.length) {
216
- savePending(buf.cwd, { sessionId: buf.sessionId, turns: buf.turns });
217
+ savePending(buf.cwd, { sessionId: buf.sessionId, turns: buf.turns }).catch(() => {});
217
218
  }
218
219
  buf.lastTurnEndSeq = event.seq;
219
220
  break;
@@ -342,7 +343,12 @@ export function apply(ctx, config = {}) {
342
343
  log,
343
344
  options: optionsOf(),
344
345
  reason: "compaction/end",
345
- }).catch((err) => log.warn?.(`[dsh-trivium] compaction extract: ${err.message}`));
346
+ })
347
+ .then(() => {
348
+ buf.dirty = false;
349
+ buf.turns = [];
350
+ })
351
+ .catch((err) => log.warn?.(`[dsh-trivium] compaction extract: ${err.message}`));
346
352
  const cwd = buf.cwd || session.header?.cwd;
347
353
  const sessionId = buf.sessionId || session.id;
348
354
  if (cwd && sessionId && sessionLayerEnabledOf(optionsOf())) {
@@ -404,6 +410,7 @@ export function apply(ctx, config = {}) {
404
410
  })
405
411
  .then(() => {
406
412
  buf.dirty = false;
413
+ buf.turns = [];
407
414
  })
408
415
  .catch((err) => log.warn?.(`[dsh-trivium] idle extract: ${err.message}`));
409
416
  }, 12000);
@@ -502,7 +509,7 @@ export function apply(ctx, config = {}) {
502
509
  clearIdle(sessionKey(session));
503
510
  const buf = bufOf(session);
504
511
  if (buf.dirty && buf.cwd && buf.turns.length) {
505
- savePending(buf.cwd, { sessionId: buf.sessionId, turns: buf.turns });
512
+ savePending(buf.cwd, { sessionId: buf.sessionId, turns: buf.turns }).catch(() => {});
506
513
  }
507
514
  buffers.delete(sessionKey(session));
508
515
  mapInjected.delete(sessionKey(session));
package/lib/server.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
2
3
  import {
3
4
  generateSidecarFromDb,
4
5
  archiveNode,
@@ -17,7 +18,7 @@ import {
17
18
  updateNode,
18
19
  } from "./store.js";
19
20
  import { embeddingPublicStatus } from "./embed.js";
20
- import { chipsEnabledOf, configPanelOpenOf, gitSidecarEnabledOf, pluginLocaleOf, recallModeOf, sessionLayerEnabledOf, writeUiSettings } from "./settings.js";
21
+ import { chipsEnabledOf, configPanelOpenOf, gitSidecarEnabledOf, listedWorkspaces, pluginLocaleOf, recallModeOf, sessionLayerEnabledOf, writeUiSettings } from "./settings.js";
21
22
  import { discoverWorkbuddyFiles, discoverExternalFiles, exportMarkdown, importWorkbuddy, importExternal } from "./markdown.js";
22
23
  import { checkNpmUpdate, installedVersion } from "./update.js";
23
24
  import { writeGateMessage } from "./hygiene.js";
@@ -31,6 +32,26 @@ function isLoopback(req) {
31
32
  return ra === "127.0.0.1" || ra === "::1" || ra === "::ffff:127.0.0.1";
32
33
  }
33
34
 
35
+ function isAllowedOrigin(req) {
36
+ const origin = req.headers?.origin;
37
+ if (!origin) return true;
38
+ try {
39
+ const u = new URL(origin);
40
+ const h = u.hostname;
41
+ return h === "127.0.0.1" || h === "localhost" || h === "::1";
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
47
+ function isKnownCwd(cwd) {
48
+ if (!cwd) return false;
49
+ const r = resolve(cwd);
50
+ if (listOpenWorkspaces().some((c) => resolve(c.cwd) === r)) return true;
51
+ if (listedWorkspaces().some((c) => resolve(c) === r)) return true;
52
+ return false;
53
+ }
54
+
34
55
  function sendText(res, status, body, contentType) {
35
56
  const data = Buffer.from(String(body || ""), "utf8");
36
57
  res.writeHead(status, {
@@ -61,8 +82,10 @@ function readBody(req) {
61
82
  }
62
83
 
63
84
  async function dbForRequest(url) {
64
- const cwd = url.searchParams.get("cwd") || getActiveCwd();
85
+ const paramCwd = url.searchParams.get("cwd");
86
+ const cwd = paramCwd || getActiveCwd();
65
87
  if (!cwd) return { cwd: null, db: null };
88
+ if (paramCwd && !isKnownCwd(cwd)) return { cwd: null, db: null };
66
89
  return { cwd, db: await openWorkspaceDb(cwd) };
67
90
  }
68
91
 
@@ -76,6 +99,12 @@ export function registerMemoryApi(ctx, { liveOptions, status }) {
76
99
  res.end("forbidden");
77
100
  return;
78
101
  }
102
+ const m = req.method || "GET";
103
+ if (m !== "GET" && m !== "HEAD" && !isAllowedOrigin(req)) {
104
+ res.writeHead(403);
105
+ res.end("forbidden origin");
106
+ return;
107
+ }
79
108
  try {
80
109
  await handle(req, res, { liveOptions, status });
81
110
  } catch (err) {
@@ -93,7 +122,8 @@ async function handle(req, res, { liveOptions, status }) {
93
122
 
94
123
  if (path === "/api/dsh-trivium/status" && method === "GET") {
95
124
  const opts = liveOptions();
96
- const cwd = url.searchParams.get("cwd") || getActiveCwd();
125
+ const paramCwd = url.searchParams.get("cwd");
126
+ const cwd = paramCwd ? (isKnownCwd(paramCwd) ? paramCwd : "") : getActiveCwd();
97
127
  let nodeCount = 0;
98
128
  let dbPath = cwd ? dbPathFor(cwd) : "";
99
129
  if (cwd) {
package/lib/store.js CHANGED
@@ -114,7 +114,7 @@ export async function openWorkspaceDb(cwd) {
114
114
  if (dbs.has(key)) return dbs.get(key);
115
115
  mkdirSync(join(key, ".dsh"), { recursive: true });
116
116
  const Engine = loadEngine();
117
- const db = new Engine(dbPathFor(key), DIM);
117
+ const db = new Engine(dbPathFor(key), { dim: DIM });
118
118
  try {
119
119
  db.createIndex("type");
120
120
  db.createIndex("status");
@@ -191,8 +191,10 @@ function normalizeTql(rows) {
191
191
  return rows
192
192
  .map((row) => {
193
193
  const node = row?._ || row?.["*"] || row?.a || Object.values(row || {})[0];
194
- if (!node || typeof node.id !== "number") return null;
195
- return { id: node.id, payload: node.payload || {} };
194
+ if (!node) return null;
195
+ const id = Number(node.id);
196
+ if (!Number.isFinite(id)) return null;
197
+ return { id, payload: node.payload || {} };
196
198
  })
197
199
  .filter(Boolean);
198
200
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-trivium",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "description": "In-process graph memory for DeepSeek Harness, backed by TriviumDB.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -55,7 +55,7 @@
55
55
  "@deepseek-ai/dsh-tools": ">=0.1.0-rc.8 <0.1.1 || >=0.1.1-rc.2 <0.2.0"
56
56
  },
57
57
  "dependencies": {
58
- "triviumdb": "^0.8.1"
58
+ "triviumdb": "^0.8.4"
59
59
  },
60
60
  "keywords": [
61
61
  "dsh-plugin",