dsh-trivium 0.2.0 → 0.4.0

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/settings.js CHANGED
@@ -59,10 +59,36 @@ export function writeUiSettings(patch) {
59
59
  if (typeof patch.embeddingApiKey === "string" && patch.embeddingApiKey.trim()) {
60
60
  next.embeddingApiKey = patch.embeddingApiKey.trim();
61
61
  }
62
+ if (patch.pinsBySession && typeof patch.pinsBySession === "object") {
63
+ next.pinsBySession = patch.pinsBySession;
64
+ } else if (prev.pinsBySession && typeof prev.pinsBySession === "object") {
65
+ next.pinsBySession = prev.pinsBySession;
66
+ }
62
67
  writeFileSync(SETTINGS_FILE, JSON.stringify(next, null, 2), "utf8");
63
68
  return next;
64
69
  }
65
70
 
71
+ export function pinsOf(sessionId) {
72
+ const raw = readUiSettings().pinsBySession;
73
+ if (!raw || typeof raw !== "object") return [];
74
+ const ids = raw[String(sessionId || "")];
75
+ if (!Array.isArray(ids)) return [];
76
+ return [...new Set(ids.map(Number).filter((id) => Number.isFinite(id)))];
77
+ }
78
+
79
+ export function writePins(sessionId, ids) {
80
+ const key = String(sessionId || "");
81
+ const prev = readUiSettings();
82
+ const pinsBySession = { ...(prev.pinsBySession && typeof prev.pinsBySession === "object" ? prev.pinsBySession : {}) };
83
+ const nextIds = [...new Set((ids || []).map(Number).filter((id) => Number.isFinite(id)))];
84
+ if (!key) return nextIds;
85
+ if (!nextIds.length) delete pinsBySession[key];
86
+ else pinsBySession[key] = nextIds;
87
+ mkdirSync(join(homedir(), ".dsh"), { recursive: true });
88
+ writeFileSync(SETTINGS_FILE, JSON.stringify({ ...prev, pinsBySession }, null, 2), "utf8");
89
+ return nextIds;
90
+ }
91
+
66
92
  export function settingsFileExists() {
67
93
  return existsSync(SETTINGS_FILE);
68
94
  }
package/lib/store.js CHANGED
@@ -163,7 +163,7 @@ function rebuildTextIndex(db) {
163
163
 
164
164
  export function findMergeTarget(db, candidate) {
165
165
  const type = candidate?.type;
166
- if (!type) return null;
166
+ if (!type || type === "episode") return null;
167
167
  const name = String(candidate.name || "").trim().toLowerCase();
168
168
  const text = String(candidate.text || "").trim().toLowerCase();
169
169
  for (const n of findByType(db, type)) {
@@ -227,7 +227,7 @@ export function mergeInto(db, id, incoming) {
227
227
 
228
228
  export function listNodes(
229
229
  db,
230
- { type, q, includeArchived = false, includeStale = false, aboutId } = {},
230
+ { type, q, includeArchived = false, includeStale = false, aboutId, includeEpisodes = false } = {},
231
231
  ) {
232
232
  const rows = [];
233
233
  const needle = String(q || "").trim().toLowerCase();
@@ -241,6 +241,7 @@ export function listNodes(
241
241
  if (!node) continue;
242
242
  const payload = node.payload || {};
243
243
  if (!includeArchived && payload.status === "archived") continue;
244
+ if (payload.type === "episode" && !includeEpisodes && type !== "episode") continue;
244
245
  if (type && payload.type !== type) continue;
245
246
  if (around && !around.has(Number(id))) continue;
246
247
  const stale = isStalePayload(payload);
@@ -418,7 +419,7 @@ export function exportGraph(db, cwd = "") {
418
419
  };
419
420
  }
420
421
 
421
- function findByUri(db, uri) {
422
+ export function findByUri(db, uri) {
422
423
  const needle = String(uri || "").trim();
423
424
  if (!needle) return null;
424
425
  for (const id of db.allNodeIds?.() || []) {
@@ -542,6 +543,7 @@ function persistVector(db, id, vec) {
542
543
  }
543
544
 
544
545
  function queueEmbed(db, id, payload) {
546
+ if (payload?.type === "episode") return;
545
547
  if (!embeddingEnabled()) return;
546
548
  const text = indexTextFor(payload);
547
549
  if (!text) return;
@@ -564,7 +566,7 @@ export async function backfillEmbeddings(db, { log } = {}) {
564
566
  for (const id of db.allNodeIds?.() || []) {
565
567
  const node = db.get(id);
566
568
  const payload = node?.payload;
567
- if (!payload || payload.status === "archived") continue;
569
+ if (!payload || payload.status === "archived" || payload.type === "episode") continue;
568
570
  const text = indexTextFor(payload);
569
571
  if (!text) continue;
570
572
  const vec = await embedText(text);
@@ -705,7 +707,14 @@ function rankBoost(db, hit, query, now) {
705
707
 
706
708
  function hitRecord(db, id) {
707
709
  const node = db.get(Number(id));
708
- if (!node || node.payload?.status === "archived" || node.payload?.type === "workspace") return null;
710
+ if (
711
+ !node ||
712
+ node.payload?.status === "archived" ||
713
+ node.payload?.type === "workspace" ||
714
+ node.payload?.type === "episode"
715
+ ) {
716
+ return null;
717
+ }
709
718
  return {
710
719
  id: Number(id),
711
720
  score: 0,
@@ -749,7 +758,7 @@ function entityAnchorIds(db, query) {
749
758
  const ids = [];
750
759
  for (const id of db.allNodeIds?.() || []) {
751
760
  const node = db.get(id);
752
- if (node?.payload?.status === "archived") continue;
761
+ if (node?.payload?.status === "archived" || node?.payload?.type === "episode") continue;
753
762
  if (entityAnchorScore(node?.payload, q) > 0) ids.push(Number(id));
754
763
  }
755
764
  return ids;
@@ -795,7 +804,7 @@ function scanBusinessNeighbors(db, id) {
795
804
  return ids;
796
805
  }
797
806
 
798
- function businessNeighborIds(db, id) {
807
+ export function businessNeighborIds(db, id) {
799
808
  const ids = scanBusinessNeighbors(db, id);
800
809
  const viaTql = tqlBusinessNeighbors(db, id);
801
810
  if (viaTql) {
@@ -804,6 +813,17 @@ function businessNeighborIds(db, id) {
804
813
  return [...ids].filter((n) => Number.isFinite(n));
805
814
  }
806
815
 
816
+ /** Chip suggestions: business-edge neighbors of entities named in `text`. Not written to pins. */
817
+ export function suggestedNeighborIds(db, text) {
818
+ const ids = new Set();
819
+ for (const eid of entityAnchorIds(db, text)) {
820
+ for (const nid of businessNeighborIds(db, eid)) {
821
+ if (Number(nid) !== Number(eid)) ids.add(Number(nid));
822
+ }
823
+ }
824
+ return [...ids];
825
+ }
826
+
807
827
  function tqlBusinessNeighbors(db, id) {
808
828
  if (typeof db.tql !== "function") return null;
809
829
  const nid = Number(id);
@@ -828,7 +848,14 @@ function keywordFallback(db, text, topK) {
828
848
  const hits = [];
829
849
  for (const id of ids) {
830
850
  const node = db.get(id);
831
- if (!node || node.payload?.status === "archived" || node.payload?.type === "workspace") continue;
851
+ if (
852
+ !node ||
853
+ node.payload?.status === "archived" ||
854
+ node.payload?.type === "workspace" ||
855
+ node.payload?.type === "episode"
856
+ ) {
857
+ continue;
858
+ }
832
859
  const hay = indexTextFor(node.payload || {}).toLowerCase();
833
860
  if (!hay.includes(q)) continue;
834
861
  hits.push({
@@ -1000,6 +1027,7 @@ export function buildShortMapReport(db, budgetTokens = 400) {
1000
1027
  const nodes = findByType(db, type);
1001
1028
  counts[type] = nodes.length;
1002
1029
  for (const n of nodes) {
1030
+ if (n.payload?.type === "episode") continue;
1003
1031
  if (type === "decision" && isStalePayload(n.payload)) continue;
1004
1032
  let label = n.payload?.name || n.payload?.text;
1005
1033
  if (!label) continue;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-trivium",
3
- "version": "0.2.0",
4
- "description": "In-process graph memory kernel for DeepSeek Harness, backed by TriviumDB.",
3
+ "version": "0.4.0",
4
+ "description": "In-process graph memory and session map for DeepSeek Harness, backed by TriviumDB.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
@@ -23,7 +23,8 @@
23
23
  "client": {
24
24
  "inject": [
25
25
  "@deepseek-ai/dsh-client-runtime",
26
- "@deepseek-ai/dsh-client-ui-settings"
26
+ "@deepseek-ai/dsh-client-ui-settings",
27
+ "@deepseek-ai/dsh-client-ui-conversation"
27
28
  ],
28
29
  "platform": "web"
29
30
  }
@@ -36,6 +37,10 @@
36
37
  "smoke-p3": "node scripts/smoke-p3.mjs",
37
38
  "smoke-p4": "node scripts/smoke-p4.mjs",
38
39
  "smoke-p5": "node scripts/smoke-p5.mjs",
40
+ "smoke-p6": "node scripts/smoke-p6.mjs",
41
+ "smoke-p7": "node scripts/smoke-p7.mjs",
42
+ "smoke-p8": "node scripts/smoke-p8.mjs",
43
+ "smoke-p9": "node scripts/smoke-p9.mjs",
39
44
  "verify-live-p2": "node scripts/verify-live-p2.mjs"
40
45
  },
41
46
  "engines": {