ygl-trees 0.70.0 → 0.71.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.
@@ -9156,6 +9156,61 @@ function gatherData(env) {
9156
9156
  }));
9157
9157
  }
9158
9158
  }
9159
+ const kgEdges = [];
9160
+ const kgMap = /* @__PURE__ */ new Map();
9161
+ try {
9162
+ const rels = db.all("SELECT src_type, src_id, dst_type, dst_id, rel FROM relations LIMIT 200");
9163
+ const colors = {
9164
+ node: "#7c9885",
9165
+ claim: "#6a994e",
9166
+ kb: "#8b7355",
9167
+ evidence: "#daa520",
9168
+ artifact: "#5b8db8",
9169
+ skill: "#9b7cb8"
9170
+ };
9171
+ for (const r of rels) {
9172
+ for (const side of ["src", "dst"]) {
9173
+ const type = r[`${side}_type`];
9174
+ const id = r[`${side}_id`];
9175
+ const key = `${type}:${id}`;
9176
+ if (kgMap.has(key)) continue;
9177
+ let label = id;
9178
+ try {
9179
+ if (type === "node") {
9180
+ const n = db.get("SELECT name FROM nodes WHERE id=?", [id]);
9181
+ if (n) label = n.name;
9182
+ } else if (type === "claim") {
9183
+ const c = db.get("SELECT substr(text,1,40) AS t FROM claims WHERE id=?", [id]);
9184
+ if (c) label = c.t;
9185
+ } else if (type === "kb") {
9186
+ const k = db.get("SELECT title FROM kb_notes WHERE id=?", [id]);
9187
+ if (k) label = k.title.slice(0, 40);
9188
+ } else if (type === "evidence") {
9189
+ const e = db.get("SELECT substr(quote,1,40) AS q FROM evidence WHERE id=?", [id]);
9190
+ if (e) label = e.q;
9191
+ } else if (type === "artifact") {
9192
+ const a = db.get("SELECT title FROM artifacts WHERE id=?", [id]);
9193
+ if (a) label = a.title;
9194
+ }
9195
+ } catch {}
9196
+ kgMap.set(key, {
9197
+ id: key,
9198
+ label,
9199
+ type,
9200
+ color: colors[type] || "#999"
9201
+ });
9202
+ }
9203
+ kgEdges.push({
9204
+ source: `${r.src_type}:${r.src_id}`,
9205
+ target: `${r.dst_type}:${r.dst_id}`,
9206
+ label: r.rel
9207
+ });
9208
+ }
9209
+ } catch {}
9210
+ data.knowledge_graph = {
9211
+ nodes: Array.from(kgMap.values()),
9212
+ edges: kgEdges
9213
+ };
9159
9214
  return data;
9160
9215
  }
9161
9216
  /** Single-file dashboard HTML. `live` adds a fetch bootstrap + auto-refresh. */
@@ -145,6 +145,59 @@ function gatherData(env) {
145
145
  .map((r) => ({ id: r.id, kind: r.kind, title: r.title, version: r.version, created: r.created }));
146
146
  }
147
147
  }
148
+ // R19: knowledge graph — entities and relations from the rel fabric
149
+ const kgNodes = [];
150
+ const kgEdges = [];
151
+ const kgMap = new Map();
152
+ try {
153
+ const rels = db.all("SELECT src_type, src_id, dst_type, dst_id, rel FROM relations LIMIT 200");
154
+ const colors = {
155
+ node: "#7c9885", claim: "#6a994e", kb: "#8b7355",
156
+ evidence: "#daa520", artifact: "#5b8db8", skill: "#9b7cb8",
157
+ };
158
+ for (const r of rels) {
159
+ for (const side of ["src", "dst"]) {
160
+ const type = r[`${side}_type`];
161
+ const id = r[`${side}_id`];
162
+ const key = `${type}:${id}`;
163
+ if (kgMap.has(key))
164
+ continue;
165
+ let label = id;
166
+ try {
167
+ if (type === "node") {
168
+ const n = db.get("SELECT name FROM nodes WHERE id=?", [id]);
169
+ if (n)
170
+ label = n.name;
171
+ }
172
+ else if (type === "claim") {
173
+ const c = db.get("SELECT substr(text,1,40) AS t FROM claims WHERE id=?", [id]);
174
+ if (c)
175
+ label = c.t;
176
+ }
177
+ else if (type === "kb") {
178
+ const k = db.get("SELECT title FROM kb_notes WHERE id=?", [id]);
179
+ if (k)
180
+ label = k.title.slice(0, 40);
181
+ }
182
+ else if (type === "evidence") {
183
+ const e = db.get("SELECT substr(quote,1,40) AS q FROM evidence WHERE id=?", [id]);
184
+ if (e)
185
+ label = e.q;
186
+ }
187
+ else if (type === "artifact") {
188
+ const a = db.get("SELECT title FROM artifacts WHERE id=?", [id]);
189
+ if (a)
190
+ label = a.title;
191
+ }
192
+ }
193
+ catch { /* best-effort */ }
194
+ kgMap.set(key, { id: key, label, type, color: colors[type] || "#999" });
195
+ }
196
+ kgEdges.push({ source: `${r.src_type}:${r.src_id}`, target: `${r.dst_type}:${r.dst_id}`, label: r.rel });
197
+ }
198
+ }
199
+ catch { /* graph data best-effort */ }
200
+ data.knowledge_graph = { nodes: Array.from(kgMap.values()), edges: kgEdges };
148
201
  return data;
149
202
  }
150
203
  /** Single-file dashboard HTML. `live` adds a fetch bootstrap + auto-refresh. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ygl-trees",
3
- "version": "0.70.0",
3
+ "version": "0.71.0",
4
4
  "description": "猿光 · 科技树 — database-centric CLI for research → production → knowledge reuse, built for AI agents.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/apps/cli/index.js",
@@ -25,9 +25,9 @@
25
25
  "reflect-metadata": "^0.2.2",
26
26
  "typeorm": "^1.1.2",
27
27
  "@deepseek-ai/cordis": "~4.0.5-alpha.2",
28
- "@deepseek-ai/schemastery": "~3.18.5-alpha.2",
29
28
  "@deepseek-ai/cosmokit": "~1.8.6-alpha.2",
30
- "@deepseek-ai/cordis-plugin-timer": "~1.1.7-alpha.2"
29
+ "@deepseek-ai/cordis-plugin-timer": "~1.1.7-alpha.2",
30
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^20.0.0",