dsh-trivium 0.4.3 → 0.4.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/README.md +4 -2
- package/lib/schema.js +1 -1
- package/lib/store.js +103 -30
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -155,6 +155,8 @@ dsh plugin --profile web add dsh-trivium
|
|
|
155
155
|
|
|
156
156
|
## 更新说明
|
|
157
157
|
|
|
158
|
+
**0.4.4** — 依赖 `triviumdb@0.7.5`:入边、按 label 扩邻、按 label 删边走引擎 API,不再全表扫边。find / 会话图行为不变。
|
|
159
|
+
|
|
158
160
|
**0.4.3** — 会话图「更新检查点」:把当前对话里 DSH 已有的压缩标记和侧边栏 fork 补进图,给装插件之前的旧会话用。没压过的会话仍然只有「后续」。
|
|
159
161
|
|
|
160
162
|
**0.4.2** — 会话图芯片条可新增(整段粘贴一条)、批量归档 / 删除。自动抽取仍偏严;芯片新增按你写的入库。
|
|
@@ -168,6 +170,6 @@ dsh plugin --profile web add dsh-trivium
|
|
|
168
170
|
## 发布信息
|
|
169
171
|
|
|
170
172
|
- GitHub: https://github.com/QWQcool/dsh-trivium
|
|
171
|
-
- npm: [`dsh-trivium@0.4.
|
|
173
|
+
- npm: [`dsh-trivium@0.4.4`](https://www.npmjs.com/package/dsh-trivium)
|
|
172
174
|
- 测试宿主:`@deepseek-ai/dsh@0.1.0-rc.8`
|
|
173
|
-
- License: MIT(依赖 [TriviumDB](https://github.com/TriviumDB
|
|
175
|
+
- License: MIT(依赖 [TriviumDB](https://github.com/YoKONCy/TriviumDB) 为 Apache-2.0)
|
package/lib/schema.js
CHANGED
|
@@ -25,7 +25,7 @@ export const EDGE_LABELS = Object.freeze({
|
|
|
25
25
|
|
|
26
26
|
export const BUSINESS_EDGES = Object.freeze(["about", "decided", "broke", "fixed"]);
|
|
27
27
|
|
|
28
|
-
/** Weights written on link(). Engine
|
|
28
|
+
/** Weights written on link(). Engine neighbors / expandLabels can whitelist labels; we still persist weights. */
|
|
29
29
|
export const EDGE_WEIGHTS = Object.freeze({
|
|
30
30
|
about: 1,
|
|
31
31
|
decided: 1,
|
package/lib/store.js
CHANGED
|
@@ -135,6 +135,42 @@ function normalizeTql(rows) {
|
|
|
135
135
|
.filter(Boolean);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
function edgeTarget(e) {
|
|
139
|
+
return Number(e?.targetId ?? e?.target_id);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function edgeSource(e) {
|
|
143
|
+
return Number(e?.sourceId ?? e?.source_id ?? e?.fromId);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Native incoming edges when triviumdb >= 0.7.5; otherwise null so callers can scan. */
|
|
147
|
+
function nativeIncoming(db, id, label) {
|
|
148
|
+
if (typeof db.getIncomingEdges !== "function") return null;
|
|
149
|
+
try {
|
|
150
|
+
const rows = label
|
|
151
|
+
? db.getIncomingEdges(Number(id), label)
|
|
152
|
+
: db.getIncomingEdges(Number(id));
|
|
153
|
+
return Array.isArray(rows) ? rows : [];
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function nativeLabeledNeighbors(db, id, labels) {
|
|
160
|
+
if (typeof db.neighbors !== "function") return null;
|
|
161
|
+
try {
|
|
162
|
+
const rows = db.neighbors(Number(id), 1, [...labels]);
|
|
163
|
+
return Array.isArray(rows) ? rows.map(Number).filter(Number.isFinite) : [];
|
|
164
|
+
} catch {
|
|
165
|
+
try {
|
|
166
|
+
const rows = db.neighbors(Number(id), 1);
|
|
167
|
+
return Array.isArray(rows) ? rows.map(Number).filter(Number.isFinite) : null;
|
|
168
|
+
} catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
138
174
|
function indexNode(db, id, payload) {
|
|
139
175
|
const text = indexTextFor(payload);
|
|
140
176
|
try {
|
|
@@ -364,12 +400,18 @@ export function mergeNodes(db, keepId, dropId) {
|
|
|
364
400
|
if (pa.status === "archived" || pb.status === "archived") {
|
|
365
401
|
return { ok: false, message: "archived" };
|
|
366
402
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
if (Number(
|
|
372
|
-
|
|
403
|
+
const inbound = nativeIncoming(db, drop);
|
|
404
|
+
if (inbound) {
|
|
405
|
+
for (const e of inbound) {
|
|
406
|
+
const from = edgeSource(e);
|
|
407
|
+
if (Number.isFinite(from) && from !== keep) ensureLink(db, from, keep, e.label);
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
for (const other of db.allNodeIds?.() || []) {
|
|
411
|
+
if (Number(other) === drop) continue;
|
|
412
|
+
const n = db.get(other);
|
|
413
|
+
for (const e of n?.edges || []) {
|
|
414
|
+
if (edgeTarget(e) === drop) ensureLink(db, other, keep, e.label);
|
|
373
415
|
}
|
|
374
416
|
}
|
|
375
417
|
}
|
|
@@ -402,7 +444,7 @@ export function exportGraph(db, cwd = "") {
|
|
|
402
444
|
for (const e of node.edges || []) {
|
|
403
445
|
edges.push({
|
|
404
446
|
from: Number(id),
|
|
405
|
-
to:
|
|
447
|
+
to: edgeTarget(e),
|
|
406
448
|
label: e.label || "",
|
|
407
449
|
weight: e.weight ?? null,
|
|
408
450
|
});
|
|
@@ -474,11 +516,11 @@ export function importGraph(db, graph) {
|
|
|
474
516
|
export function hasEdge(db, from, to, label) {
|
|
475
517
|
const node = db.get(Number(from));
|
|
476
518
|
return (node?.edges || []).some(
|
|
477
|
-
(e) =>
|
|
519
|
+
(e) => edgeTarget(e) === Number(to) && (!label || e.label === label),
|
|
478
520
|
);
|
|
479
521
|
}
|
|
480
522
|
|
|
481
|
-
/** Link once for a (from, to, label) triple.
|
|
523
|
+
/** Link once for a (from, to, label) triple. */
|
|
482
524
|
export function ensureLink(db, from, to, label) {
|
|
483
525
|
const src = Number(from);
|
|
484
526
|
const dst = Number(to);
|
|
@@ -489,6 +531,22 @@ export function ensureLink(db, from, to, label) {
|
|
|
489
531
|
return true;
|
|
490
532
|
}
|
|
491
533
|
|
|
534
|
+
/** Drop one labeled edge when the engine supports unlink(src, dst, label). */
|
|
535
|
+
export function dropLink(db, from, to, label) {
|
|
536
|
+
const src = Number(from);
|
|
537
|
+
const dst = Number(to);
|
|
538
|
+
if (!Number.isFinite(src) || !Number.isFinite(dst)) return false;
|
|
539
|
+
if (!hasEdge(db, src, dst, label)) return false;
|
|
540
|
+
try {
|
|
541
|
+
if (label) db.unlink(src, dst, label);
|
|
542
|
+
else db.unlink(src, dst);
|
|
543
|
+
db.flush();
|
|
544
|
+
return true;
|
|
545
|
+
} catch {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
492
550
|
function pickMergedText(oldText, incomingText) {
|
|
493
551
|
const a = String(oldText || "").trim();
|
|
494
552
|
const b = String(incomingText || "").trim();
|
|
@@ -756,10 +814,9 @@ function entityAnchorIds(db, query) {
|
|
|
756
814
|
const q = String(query || "").trim().toLowerCase();
|
|
757
815
|
if (!q) return [];
|
|
758
816
|
const ids = [];
|
|
759
|
-
for (const
|
|
760
|
-
|
|
761
|
-
if (
|
|
762
|
-
if (entityAnchorScore(node?.payload, q) > 0) ids.push(Number(id));
|
|
817
|
+
for (const n of findByType(db, "entity")) {
|
|
818
|
+
if (n.payload?.status === "archived") continue;
|
|
819
|
+
if (entityAnchorScore(n.payload, q) > 0) ids.push(Number(n.id));
|
|
763
820
|
}
|
|
764
821
|
return ids;
|
|
765
822
|
}
|
|
@@ -788,16 +845,27 @@ function primaryScore(payload, query, now) {
|
|
|
788
845
|
function scanBusinessNeighbors(db, id) {
|
|
789
846
|
const ids = new Set();
|
|
790
847
|
const want = new Set(BUSINESS_EDGES);
|
|
791
|
-
const
|
|
792
|
-
|
|
793
|
-
|
|
848
|
+
const nid = Number(id);
|
|
849
|
+
const labeled = nativeLabeledNeighbors(db, nid, BUSINESS_EDGES);
|
|
850
|
+
if (labeled) {
|
|
851
|
+
for (const other of labeled) ids.add(other);
|
|
852
|
+
} else {
|
|
853
|
+
const node = db.get(nid);
|
|
854
|
+
for (const e of node?.edges || []) {
|
|
855
|
+
if (want.has(e.label)) ids.add(edgeTarget(e));
|
|
856
|
+
}
|
|
794
857
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
858
|
+
const inbound = nativeIncoming(db, nid);
|
|
859
|
+
if (inbound) {
|
|
860
|
+
for (const e of inbound) {
|
|
861
|
+
if (want.has(e.label)) ids.add(edgeSource(e));
|
|
862
|
+
}
|
|
863
|
+
} else {
|
|
864
|
+
for (const other of db.allNodeIds?.() || []) {
|
|
865
|
+
if (Number(other) === nid) continue;
|
|
866
|
+
const n = db.get(other);
|
|
867
|
+
for (const e of n?.edges || []) {
|
|
868
|
+
if (want.has(e.label) && edgeTarget(e) === nid) ids.add(Number(other));
|
|
801
869
|
}
|
|
802
870
|
}
|
|
803
871
|
}
|
|
@@ -806,9 +874,11 @@ function scanBusinessNeighbors(db, id) {
|
|
|
806
874
|
|
|
807
875
|
export function businessNeighborIds(db, id) {
|
|
808
876
|
const ids = scanBusinessNeighbors(db, id);
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
877
|
+
if (typeof db.getIncomingEdges !== "function") {
|
|
878
|
+
const viaTql = tqlBusinessNeighbors(db, id);
|
|
879
|
+
if (viaTql) {
|
|
880
|
+
for (const nid of viaTql) ids.add(Number(nid));
|
|
881
|
+
}
|
|
812
882
|
}
|
|
813
883
|
return [...ids].filter((n) => Number.isFinite(n));
|
|
814
884
|
}
|
|
@@ -885,7 +955,7 @@ function nodeLabel(db, id) {
|
|
|
885
955
|
function sameAsTarget(db, id) {
|
|
886
956
|
const node = db.get(Number(id));
|
|
887
957
|
for (const e of node?.edges || []) {
|
|
888
|
-
if (e.label === EDGE_LABELS.sameAs) return
|
|
958
|
+
if (e.label === EDGE_LABELS.sameAs) return edgeTarget(e);
|
|
889
959
|
}
|
|
890
960
|
return null;
|
|
891
961
|
}
|
|
@@ -913,6 +983,11 @@ function incomingBusinessEdges(db, id, { query = "", now, hideStale = false } =
|
|
|
913
983
|
seen.add(key);
|
|
914
984
|
found.push({ fromId: src, label, payload: srcNode.payload });
|
|
915
985
|
};
|
|
986
|
+
const inbound = nativeIncoming(db, nid);
|
|
987
|
+
if (inbound) {
|
|
988
|
+
for (const e of inbound) add(edgeSource(e), e.label);
|
|
989
|
+
return found;
|
|
990
|
+
}
|
|
916
991
|
if (typeof db.tql === "function") {
|
|
917
992
|
try {
|
|
918
993
|
for (const label of BUSINESS_EDGES) {
|
|
@@ -928,9 +1003,7 @@ function incomingBusinessEdges(db, id, { query = "", now, hideStale = false } =
|
|
|
928
1003
|
const n = db.get(other);
|
|
929
1004
|
if (!n || n.payload?.status === "archived") continue;
|
|
930
1005
|
for (const e of n.edges || []) {
|
|
931
|
-
if (want.has(e.label) &&
|
|
932
|
-
add(other, e.label);
|
|
933
|
-
}
|
|
1006
|
+
if (want.has(e.label) && edgeTarget(e) === nid) add(other, e.label);
|
|
934
1007
|
}
|
|
935
1008
|
}
|
|
936
1009
|
return found;
|
|
@@ -976,7 +1049,7 @@ export function listOutgoingBusiness(db, id) {
|
|
|
976
1049
|
const seen = new Set();
|
|
977
1050
|
for (const e of node?.edges || []) {
|
|
978
1051
|
if (!want.has(e.label)) continue;
|
|
979
|
-
const tid =
|
|
1052
|
+
const tid = edgeTarget(e);
|
|
980
1053
|
if (!Number.isFinite(tid)) continue;
|
|
981
1054
|
const key = `${e.label}:${tid}`;
|
|
982
1055
|
if (seen.has(key)) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-trivium",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "In-process graph memory and session map for DeepSeek Harness, backed by TriviumDB.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@deepseek-ai/dsh-tools": "0.1.0-rc.8"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"triviumdb": "^0.7.
|
|
54
|
+
"triviumdb": "^0.7.5"
|
|
55
55
|
},
|
|
56
56
|
"keywords": [
|
|
57
57
|
"dsh-plugin",
|