eminiar 0.6.1 → 0.7.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/.claude-plugin/plugin.json +1 -1
- package/dist/cli.js +666 -226
- package/dist/server.js +404 -244
- package/dist/ui/app.global.js +55 -54
- package/dist/ui/styles.css +25 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -26524,9 +26524,9 @@ var require_parse2 = __commonJS({
|
|
|
26524
26524
|
const idx = prev.value.lastIndexOf("[");
|
|
26525
26525
|
const pre = prev.value.slice(0, idx);
|
|
26526
26526
|
const rest3 = prev.value.slice(idx + 2);
|
|
26527
|
-
const
|
|
26528
|
-
if (
|
|
26529
|
-
prev.value = pre +
|
|
26527
|
+
const posix2 = POSIX_REGEX_SOURCE[rest3];
|
|
26528
|
+
if (posix2) {
|
|
26529
|
+
prev.value = pre + posix2;
|
|
26530
26530
|
state.backtrack = true;
|
|
26531
26531
|
advance();
|
|
26532
26532
|
if (!bos.output && tokens.indexOf(prev) === 1) {
|
|
@@ -27048,7 +27048,7 @@ var require_picomatch = __commonJS({
|
|
|
27048
27048
|
throw new TypeError("Expected pattern to be a non-empty string");
|
|
27049
27049
|
}
|
|
27050
27050
|
const opts = options || {};
|
|
27051
|
-
const
|
|
27051
|
+
const posix2 = utils.isWindows(options);
|
|
27052
27052
|
const regex = isState ? picomatch.compileRe(glob2, options) : picomatch.makeRe(glob2, options, false, true);
|
|
27053
27053
|
const state = regex.state;
|
|
27054
27054
|
delete regex.state;
|
|
@@ -27058,8 +27058,8 @@ var require_picomatch = __commonJS({
|
|
|
27058
27058
|
isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
|
|
27059
27059
|
}
|
|
27060
27060
|
const matcher = (input2, returnObject = false) => {
|
|
27061
|
-
const { isMatch, match, output: output2 } = picomatch.test(input2, regex, options, { glob: glob2, posix });
|
|
27062
|
-
const result = { glob: glob2, state, regex, posix, input: input2, output: output2, match, isMatch };
|
|
27061
|
+
const { isMatch, match, output: output2 } = picomatch.test(input2, regex, options, { glob: glob2, posix: posix2 });
|
|
27062
|
+
const result = { glob: glob2, state, regex, posix: posix2, input: input2, output: output2, match, isMatch };
|
|
27063
27063
|
if (typeof opts.onResult === "function") {
|
|
27064
27064
|
opts.onResult(result);
|
|
27065
27065
|
}
|
|
@@ -27084,7 +27084,7 @@ var require_picomatch = __commonJS({
|
|
|
27084
27084
|
}
|
|
27085
27085
|
return matcher;
|
|
27086
27086
|
};
|
|
27087
|
-
picomatch.test = (input2, regex, options, { glob: glob2, posix } = {}) => {
|
|
27087
|
+
picomatch.test = (input2, regex, options, { glob: glob2, posix: posix2 } = {}) => {
|
|
27088
27088
|
if (typeof input2 !== "string") {
|
|
27089
27089
|
throw new TypeError("Expected input to be a string");
|
|
27090
27090
|
}
|
|
@@ -27092,7 +27092,7 @@ var require_picomatch = __commonJS({
|
|
|
27092
27092
|
return { isMatch: false, output: "" };
|
|
27093
27093
|
}
|
|
27094
27094
|
const opts = options || {};
|
|
27095
|
-
const format = opts.format || (
|
|
27095
|
+
const format = opts.format || (posix2 ? utils.toPosixSlashes : null);
|
|
27096
27096
|
let match = input2 === glob2;
|
|
27097
27097
|
let output2 = match && format ? format(input2) : input2;
|
|
27098
27098
|
if (match === false) {
|
|
@@ -27101,14 +27101,14 @@ var require_picomatch = __commonJS({
|
|
|
27101
27101
|
}
|
|
27102
27102
|
if (match === false || opts.capture === true) {
|
|
27103
27103
|
if (opts.matchBase === true || opts.basename === true) {
|
|
27104
|
-
match = picomatch.matchBase(input2, regex, options,
|
|
27104
|
+
match = picomatch.matchBase(input2, regex, options, posix2);
|
|
27105
27105
|
} else {
|
|
27106
27106
|
match = regex.exec(output2);
|
|
27107
27107
|
}
|
|
27108
27108
|
}
|
|
27109
27109
|
return { isMatch: Boolean(match), match, output: output2 };
|
|
27110
27110
|
};
|
|
27111
|
-
picomatch.matchBase = (input2, glob2, options,
|
|
27111
|
+
picomatch.matchBase = (input2, glob2, options, posix2 = utils.isWindows(options)) => {
|
|
27112
27112
|
const regex = glob2 instanceof RegExp ? glob2 : picomatch.makeRe(glob2, options);
|
|
27113
27113
|
return regex.test(path3.basename(input2));
|
|
27114
27114
|
};
|
|
@@ -27299,9 +27299,9 @@ var require_micromatch = __commonJS({
|
|
|
27299
27299
|
return [].concat(patterns).every((p) => picomatch(p, options)(str2));
|
|
27300
27300
|
};
|
|
27301
27301
|
micromatch.capture = (glob2, input2, options) => {
|
|
27302
|
-
let
|
|
27302
|
+
let posix2 = utils.isWindows(options);
|
|
27303
27303
|
let regex = picomatch.makeRe(String(glob2), { ...options, capture: true });
|
|
27304
|
-
let match = regex.exec(
|
|
27304
|
+
let match = regex.exec(posix2 ? utils.toPosixSlashes(input2) : input2);
|
|
27305
27305
|
if (match) {
|
|
27306
27306
|
return match.slice(1).map((v) => v === void 0 ? "" : v);
|
|
27307
27307
|
}
|
|
@@ -27481,15 +27481,15 @@ var require_pattern = __commonJS({
|
|
|
27481
27481
|
exports.removeDuplicateSlashes = removeDuplicateSlashes;
|
|
27482
27482
|
function partitionAbsoluteAndRelative(patterns) {
|
|
27483
27483
|
const absolute = [];
|
|
27484
|
-
const
|
|
27484
|
+
const relative11 = [];
|
|
27485
27485
|
for (const pattern2 of patterns) {
|
|
27486
27486
|
if (isAbsolute(pattern2)) {
|
|
27487
27487
|
absolute.push(pattern2);
|
|
27488
27488
|
} else {
|
|
27489
|
-
|
|
27489
|
+
relative11.push(pattern2);
|
|
27490
27490
|
}
|
|
27491
27491
|
}
|
|
27492
|
-
return [absolute,
|
|
27492
|
+
return [absolute, relative11];
|
|
27493
27493
|
}
|
|
27494
27494
|
exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
|
|
27495
27495
|
function isAbsolute(pattern2) {
|
|
@@ -27920,11 +27920,11 @@ var require_out = __commonJS({
|
|
|
27920
27920
|
async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
|
|
27921
27921
|
}
|
|
27922
27922
|
exports.stat = stat;
|
|
27923
|
-
function
|
|
27923
|
+
function statSync12(path3, optionsOrSettings) {
|
|
27924
27924
|
const settings = getSettings(optionsOrSettings);
|
|
27925
27925
|
return sync.read(path3, settings);
|
|
27926
27926
|
}
|
|
27927
|
-
exports.statSync =
|
|
27927
|
+
exports.statSync = statSync12;
|
|
27928
27928
|
function getSettings(settingsOrOptions = {}) {
|
|
27929
27929
|
if (settingsOrOptions instanceof settings_1.default) {
|
|
27930
27930
|
return settingsOrOptions;
|
|
@@ -29804,19 +29804,19 @@ var require_out4 = __commonJS({
|
|
|
29804
29804
|
return utils.path.convertPathToPattern(source);
|
|
29805
29805
|
}
|
|
29806
29806
|
FastGlob2.convertPathToPattern = convertPathToPattern;
|
|
29807
|
-
let
|
|
29808
|
-
(function(
|
|
29807
|
+
let posix2;
|
|
29808
|
+
(function(posix3) {
|
|
29809
29809
|
function escapePath2(source) {
|
|
29810
29810
|
assertPatternsInput(source);
|
|
29811
29811
|
return utils.path.escapePosixPath(source);
|
|
29812
29812
|
}
|
|
29813
|
-
|
|
29813
|
+
posix3.escapePath = escapePath2;
|
|
29814
29814
|
function convertPathToPattern2(source) {
|
|
29815
29815
|
assertPatternsInput(source);
|
|
29816
29816
|
return utils.path.convertPosixPathToPattern(source);
|
|
29817
29817
|
}
|
|
29818
|
-
|
|
29819
|
-
})(
|
|
29818
|
+
posix3.convertPathToPattern = convertPathToPattern2;
|
|
29819
|
+
})(posix2 = FastGlob2.posix || (FastGlob2.posix = {}));
|
|
29820
29820
|
let win32;
|
|
29821
29821
|
(function(win322) {
|
|
29822
29822
|
function escapePath2(source) {
|
|
@@ -30776,13 +30776,14 @@ function fileOf(id) {
|
|
|
30776
30776
|
if (kind === "sym") return rest2.split("#")[0];
|
|
30777
30777
|
return void 0;
|
|
30778
30778
|
}
|
|
30779
|
-
var fileId, memoryId, symId, pkgId, personId, conceptId;
|
|
30779
|
+
var fileId, memoryId, docId, symId, pkgId, personId, conceptId;
|
|
30780
30780
|
var init_ids = __esm({
|
|
30781
30781
|
"src/graph/ids.ts"() {
|
|
30782
30782
|
"use strict";
|
|
30783
30783
|
init_esm_shims();
|
|
30784
30784
|
fileId = (rel) => `file:${rel}`;
|
|
30785
30785
|
memoryId = (name) => `memory:${name}`;
|
|
30786
|
+
docId = (name) => `doc:${name}`;
|
|
30786
30787
|
symId = (rel, name) => `sym:${rel}#${name}`;
|
|
30787
30788
|
pkgId = (name) => `pkg:${name}`;
|
|
30788
30789
|
personId = (name) => `person:${name}`;
|
|
@@ -31152,9 +31153,10 @@ function impact(db, ref, opts = {}) {
|
|
|
31152
31153
|
frontier = next;
|
|
31153
31154
|
if (!frontier.length) break;
|
|
31154
31155
|
}
|
|
31155
|
-
for (const e of db.graphEdgesTo(start, ["mentions"])) {
|
|
31156
|
+
for (const e of db.graphEdgesTo(start, ["mentions", "documents"])) {
|
|
31156
31157
|
const via = e.dst === root.id ? root.name : e.dst.replace(/^sym:[^#]*#/, "");
|
|
31157
|
-
|
|
31158
|
+
const who = e.kind === "documents" ? "doc documents" : "memory mentions";
|
|
31159
|
+
add(e.src, 0.5 * e.confidence, 1, `${who} ${via}`);
|
|
31158
31160
|
}
|
|
31159
31161
|
if (opts.includeGit !== false) {
|
|
31160
31162
|
const file3 = toFile(root.id);
|
|
@@ -35514,10 +35516,12 @@ __export(store_exports, {
|
|
|
35514
35516
|
isValidName: () => isValidName,
|
|
35515
35517
|
list: () => list,
|
|
35516
35518
|
memoriesDir: () => memoriesDir,
|
|
35519
|
+
memoryLinks: () => memoryLinks,
|
|
35517
35520
|
normalizeRelated: () => normalizeRelated,
|
|
35518
35521
|
read: () => read,
|
|
35519
35522
|
reconcile: () => reconcile,
|
|
35520
35523
|
relOf: () => relOf,
|
|
35524
|
+
relatedTarget: () => relatedTarget,
|
|
35521
35525
|
remove: () => remove,
|
|
35522
35526
|
rename: () => rename,
|
|
35523
35527
|
setMeta: () => setMeta,
|
|
@@ -35593,6 +35597,17 @@ function normalizeRelated(ids) {
|
|
|
35593
35597
|
}
|
|
35594
35598
|
return [...out];
|
|
35595
35599
|
}
|
|
35600
|
+
function relatedTarget(id) {
|
|
35601
|
+
return id.startsWith("mem:") ? memoryId(id.slice(4)) : id;
|
|
35602
|
+
}
|
|
35603
|
+
function memoryLinks(body, self) {
|
|
35604
|
+
const out = /* @__PURE__ */ new Set();
|
|
35605
|
+
for (const m of body.matchAll(MEM_LINK_RE)) {
|
|
35606
|
+
const name = m[1].replace(/[.-]+$/, "");
|
|
35607
|
+
if (name && name !== self && isValidName(name)) out.add(name);
|
|
35608
|
+
}
|
|
35609
|
+
return [...out];
|
|
35610
|
+
}
|
|
35596
35611
|
function writeMemoryFile(ctx, name, meta4, body) {
|
|
35597
35612
|
const abs = absOf(ctx, name);
|
|
35598
35613
|
mkdirSync7(dirname8(abs), { recursive: true });
|
|
@@ -35600,36 +35615,30 @@ function writeMemoryFile(ctx, name, meta4, body) {
|
|
|
35600
35615
|
${body.trim()}
|
|
35601
35616
|
`));
|
|
35602
35617
|
}
|
|
35603
|
-
function syncGraph(db, name, rel,
|
|
35618
|
+
function syncGraph(db, name, rel, g) {
|
|
35619
|
+
const self = memoryId(name);
|
|
35604
35620
|
db.graphDeleteForPath("curated", rel);
|
|
35605
35621
|
db.graphUpsertNodes([
|
|
35606
35622
|
{
|
|
35607
|
-
id:
|
|
35623
|
+
id: self,
|
|
35608
35624
|
kind: "memory",
|
|
35609
35625
|
name,
|
|
35610
35626
|
path: rel,
|
|
35611
35627
|
source: "curated",
|
|
35612
|
-
meta: { kind, tags }
|
|
35628
|
+
meta: { kind: g.kind, tags: g.tags, ...g.status ? { status: g.status } : {} }
|
|
35613
35629
|
}
|
|
35614
35630
|
]);
|
|
35615
|
-
const edges =
|
|
35616
|
-
|
|
35617
|
-
|
|
35618
|
-
kind
|
|
35619
|
-
|
|
35620
|
-
|
|
35621
|
-
weight: 1
|
|
35622
|
-
}
|
|
35623
|
-
|
|
35624
|
-
|
|
35625
|
-
|
|
35626
|
-
dst: memoryId(supersedes),
|
|
35627
|
-
kind: "supersedes",
|
|
35628
|
-
source: "curated",
|
|
35629
|
-
confidence: 1,
|
|
35630
|
-
weight: 1
|
|
35631
|
-
});
|
|
35632
|
-
}
|
|
35631
|
+
const edges = [];
|
|
35632
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35633
|
+
const push = (dst, kind) => {
|
|
35634
|
+
const key = `${kind}|${dst}`;
|
|
35635
|
+
if (dst === self || seen.has(key)) return;
|
|
35636
|
+
seen.add(key);
|
|
35637
|
+
edges.push({ src: self, dst, kind, source: "curated", confidence: 1, weight: 1 });
|
|
35638
|
+
};
|
|
35639
|
+
for (const id of g.related) push(relatedTarget(id), "mentions");
|
|
35640
|
+
for (const other of memoryLinks(g.body, name)) push(memoryId(other), "links");
|
|
35641
|
+
if (g.supersedes) push(memoryId(g.supersedes.replace(/^mem(?:ory)?:/, "")), "supersedes");
|
|
35633
35642
|
if (edges.length) db.graphUpsertEdges(edges);
|
|
35634
35643
|
}
|
|
35635
35644
|
function forgetInDb(db, name, rel) {
|
|
@@ -35716,7 +35725,7 @@ tags: ${tags.join(", ")}` : ""}`,
|
|
|
35716
35725
|
status,
|
|
35717
35726
|
supersedes
|
|
35718
35727
|
});
|
|
35719
|
-
syncGraph(db, name, rel, kind, tags, related, supersedes);
|
|
35728
|
+
syncGraph(db, name, rel, { kind, tags, related, status, supersedes, body });
|
|
35720
35729
|
return { changed: true, row: db.memoryGetByName(name) };
|
|
35721
35730
|
}
|
|
35722
35731
|
function setMeta(ctx, db, name, patch) {
|
|
@@ -35919,7 +35928,7 @@ function gitignoreHint(ctx) {
|
|
|
35919
35928
|
const ignored = readFileSync16(file3, "utf8").split(/\r?\n/).map((l) => l.trim().replace(/^\//, "").replace(/\/$/, "")).some((l) => l === top || l === dir || l === `${top}/**` || l === `${dir}/**`);
|
|
35920
35929
|
return ignored ? `note: .gitignore ignores ${dir}, so memories stay local to this machine (remove that line to share them with the team)` : void 0;
|
|
35921
35930
|
}
|
|
35922
|
-
var import_fast_glob3, MEMORY_KINDS, SEGMENT, NAME_RE, hinted;
|
|
35931
|
+
var import_fast_glob3, MEMORY_KINDS, SEGMENT, NAME_RE, MEM_LINK_RE, hinted;
|
|
35923
35932
|
var init_store = __esm({
|
|
35924
35933
|
"src/memory/store.ts"() {
|
|
35925
35934
|
"use strict";
|
|
@@ -35941,6 +35950,7 @@ var init_store = __esm({
|
|
|
35941
35950
|
];
|
|
35942
35951
|
SEGMENT = "[a-z0-9][a-z0-9._-]*";
|
|
35943
35952
|
NAME_RE = new RegExp(`^(?:${SEGMENT}/)?${SEGMENT}$`);
|
|
35953
|
+
MEM_LINK_RE = /(?<![A-Za-z0-9_./-])mem:([a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)?)/g;
|
|
35944
35954
|
hinted = /* @__PURE__ */ new Set();
|
|
35945
35955
|
}
|
|
35946
35956
|
});
|
|
@@ -36626,7 +36636,7 @@ function architecture(ctx, db, aspects = ASPECTS) {
|
|
|
36626
36636
|
for (const l of languages2.values()) langCounts[l] = (langCounts[l] ?? 0) + 1;
|
|
36627
36637
|
const counts = db.graphCounts();
|
|
36628
36638
|
const nodeCounts = db.graphNodeCounts();
|
|
36629
|
-
const symbols = Object.entries(nodeCounts).filter(([k]) => !["file", "package", "person", "concept", "memory"].includes(k)).reduce((a, [, n]) => a + n, 0);
|
|
36639
|
+
const symbols = Object.entries(nodeCounts).filter(([k]) => !["file", "package", "person", "concept", "memory", "doc"].includes(k)).reduce((a, [, n]) => a + n, 0);
|
|
36630
36640
|
const out = {
|
|
36631
36641
|
project: {
|
|
36632
36642
|
name: typeof pkg.name === "string" ? pkg.name : void 0,
|
|
@@ -39030,6 +39040,341 @@ var init_discover = __esm({
|
|
|
39030
39040
|
}
|
|
39031
39041
|
});
|
|
39032
39042
|
|
|
39043
|
+
// src/docs/category.ts
|
|
39044
|
+
function categoryInfo(id) {
|
|
39045
|
+
return BY_ID.get(id) ?? BY_ID.get("local");
|
|
39046
|
+
}
|
|
39047
|
+
function localCategory(s) {
|
|
39048
|
+
const title = s.title ?? "";
|
|
39049
|
+
for (const [re, cat] of TITLE_RULES) if (re.test(title)) return cat;
|
|
39050
|
+
for (const [re, cat] of NAME_RULES) if (re.test(s.name)) return cat;
|
|
39051
|
+
const path3 = s.path ?? "";
|
|
39052
|
+
if (/(^|\/)(adrs?|decisions)$/i.test(path3)) return "adr";
|
|
39053
|
+
const globs = s.glob ?? [];
|
|
39054
|
+
const hits = /* @__PURE__ */ new Map();
|
|
39055
|
+
for (const g of globs)
|
|
39056
|
+
for (const [re, cat] of GLOB_RULES)
|
|
39057
|
+
if (re.test(g)) {
|
|
39058
|
+
hits.set(cat, (hits.get(cat) ?? 0) + 1);
|
|
39059
|
+
break;
|
|
39060
|
+
}
|
|
39061
|
+
if (hits.size) return [...hits.entries()].sort((a, b) => b[1] - a[1])[0][0];
|
|
39062
|
+
if (/(^|\/)(docs?|documentation)$/i.test(path3)) return "guides";
|
|
39063
|
+
if (/README|CONTRIBUTING|CHANGELOG/i.test(path3)) return "readme";
|
|
39064
|
+
return "local";
|
|
39065
|
+
}
|
|
39066
|
+
function docCategory(s, entry) {
|
|
39067
|
+
if (s.kind === "path") return localCategory(s);
|
|
39068
|
+
if (entry) {
|
|
39069
|
+
const tier = entry.tier ?? "library";
|
|
39070
|
+
return tier === "service" ? "service" : tier === "infra" ? "infra" : "library";
|
|
39071
|
+
}
|
|
39072
|
+
const provider = s.provider ?? "";
|
|
39073
|
+
const i = provider.indexOf(":");
|
|
39074
|
+
const kind = i === -1 ? provider : provider.slice(0, i);
|
|
39075
|
+
switch (kind) {
|
|
39076
|
+
case "api":
|
|
39077
|
+
return "api";
|
|
39078
|
+
case "env":
|
|
39079
|
+
return "service";
|
|
39080
|
+
case "image":
|
|
39081
|
+
case "files":
|
|
39082
|
+
return "infra";
|
|
39083
|
+
case "npm":
|
|
39084
|
+
case "pypi":
|
|
39085
|
+
case "go":
|
|
39086
|
+
return "library";
|
|
39087
|
+
default:
|
|
39088
|
+
return "web";
|
|
39089
|
+
}
|
|
39090
|
+
}
|
|
39091
|
+
function categoryRank(id) {
|
|
39092
|
+
const i = DOC_CATEGORIES.findIndex((c) => c.id === id);
|
|
39093
|
+
return i === -1 ? DOC_CATEGORIES.length : i;
|
|
39094
|
+
}
|
|
39095
|
+
var DOC_CATEGORIES, BY_ID, GROUP_LABELS, TITLE_RULES, NAME_RULES, GLOB_RULES;
|
|
39096
|
+
var init_category = __esm({
|
|
39097
|
+
"src/docs/category.ts"() {
|
|
39098
|
+
"use strict";
|
|
39099
|
+
init_esm_shims();
|
|
39100
|
+
DOC_CATEGORIES = [
|
|
39101
|
+
{
|
|
39102
|
+
id: "readme",
|
|
39103
|
+
group: "project",
|
|
39104
|
+
label: "Readme & guides",
|
|
39105
|
+
blurb: "README, CONTRIBUTING, CHANGELOG and other top-level guides"
|
|
39106
|
+
},
|
|
39107
|
+
{
|
|
39108
|
+
id: "guides",
|
|
39109
|
+
group: "project",
|
|
39110
|
+
label: "Docs folders",
|
|
39111
|
+
blurb: "docs/ directories: handbooks, how-tos, references"
|
|
39112
|
+
},
|
|
39113
|
+
{
|
|
39114
|
+
id: "adr",
|
|
39115
|
+
group: "project",
|
|
39116
|
+
label: "Decision records",
|
|
39117
|
+
blurb: "architecture decision records"
|
|
39118
|
+
},
|
|
39119
|
+
{
|
|
39120
|
+
id: "agent-instructions",
|
|
39121
|
+
group: "project",
|
|
39122
|
+
label: "Agent instructions",
|
|
39123
|
+
blurb: "Copilot, Claude and Cursor instructions, agents and skills"
|
|
39124
|
+
},
|
|
39125
|
+
{
|
|
39126
|
+
id: "api-specs",
|
|
39127
|
+
group: "project",
|
|
39128
|
+
label: "API specs",
|
|
39129
|
+
blurb: "OpenAPI, Postman, GraphQL and protobuf definitions"
|
|
39130
|
+
},
|
|
39131
|
+
{
|
|
39132
|
+
id: "env-reference",
|
|
39133
|
+
group: "project",
|
|
39134
|
+
label: "Environment reference",
|
|
39135
|
+
blurb: ".env examples: every variable the project reads"
|
|
39136
|
+
},
|
|
39137
|
+
{
|
|
39138
|
+
id: "deploy-config",
|
|
39139
|
+
group: "project",
|
|
39140
|
+
label: "Deploy config",
|
|
39141
|
+
blurb: "Terraform, Kubernetes, Helm, Compose and CI workflows"
|
|
39142
|
+
},
|
|
39143
|
+
{ id: "local", group: "project", label: "Other local files", blurb: "hand-registered paths" },
|
|
39144
|
+
{
|
|
39145
|
+
id: "service",
|
|
39146
|
+
group: "external",
|
|
39147
|
+
label: "Services",
|
|
39148
|
+
blurb: "third-party products and APIs the project integrates"
|
|
39149
|
+
},
|
|
39150
|
+
{
|
|
39151
|
+
id: "api",
|
|
39152
|
+
group: "external",
|
|
39153
|
+
label: "External APIs",
|
|
39154
|
+
blurb: "hosts the code calls, found by probing their docs"
|
|
39155
|
+
},
|
|
39156
|
+
{
|
|
39157
|
+
id: "infra",
|
|
39158
|
+
group: "external",
|
|
39159
|
+
label: "Infrastructure",
|
|
39160
|
+
blurb: "platforms the project runs on"
|
|
39161
|
+
},
|
|
39162
|
+
{ id: "library", group: "external", label: "Libraries", blurb: "frameworks and packages" },
|
|
39163
|
+
{ id: "web", group: "external", label: "Web pages", blurb: "hand-registered URLs" }
|
|
39164
|
+
];
|
|
39165
|
+
BY_ID = new Map(DOC_CATEGORIES.map((c) => [c.id, c]));
|
|
39166
|
+
GROUP_LABELS = {
|
|
39167
|
+
project: "Project documentation",
|
|
39168
|
+
external: "External documentation"
|
|
39169
|
+
};
|
|
39170
|
+
TITLE_RULES = [
|
|
39171
|
+
[/^project readme/i, "readme"],
|
|
39172
|
+
[/^(docs|doc|documentation)\/ directory$/i, "guides"],
|
|
39173
|
+
[/decision records/i, "adr"],
|
|
39174
|
+
[/copilot|claude|cursor/i, "agent-instructions"],
|
|
39175
|
+
[/openapi|postman|graphql|protobuf/i, "api-specs"],
|
|
39176
|
+
[/environment variable/i, "env-reference"],
|
|
39177
|
+
[/terraform|kubernetes|helm|compose|workflow/i, "deploy-config"]
|
|
39178
|
+
];
|
|
39179
|
+
NAME_RULES = [
|
|
39180
|
+
[/(^|-)readme$/, "readme"],
|
|
39181
|
+
[/(^|-)docs$/, "guides"],
|
|
39182
|
+
[/(^|-)adrs?$/, "adr"],
|
|
39183
|
+
[/(^|-)agent-instructions$/, "agent-instructions"],
|
|
39184
|
+
[/(^|-)api-specs$/, "api-specs"],
|
|
39185
|
+
[/(^|-)env-example$/, "env-reference"],
|
|
39186
|
+
[/(^|-)deploy-config$/, "deploy-config"]
|
|
39187
|
+
];
|
|
39188
|
+
GLOB_RULES = [
|
|
39189
|
+
[/openapi|swagger|postman_collection|asyncapi|\.graphql$|\.proto$/i, "api-specs"],
|
|
39190
|
+
[/^\.env\./, "env-reference"],
|
|
39191
|
+
[
|
|
39192
|
+
/\.tf$|tfvars|^k8s\/|^helm\/|^charts\/|^manifests\/|compose.*\.ya?ml|\.github\/workflows/i,
|
|
39193
|
+
"deploy-config"
|
|
39194
|
+
],
|
|
39195
|
+
[
|
|
39196
|
+
/copilot-instructions|\.github\/(instructions|agents|skills)|\.claude\/(agents|skills)|\.cursor\/rules|^(AGENTS|CLAUDE)\.md$/i,
|
|
39197
|
+
"agent-instructions"
|
|
39198
|
+
],
|
|
39199
|
+
[/^(README|CONTRIBUTING|CHANGELOG|SECURITY)(\.md)?$/i, "readme"],
|
|
39200
|
+
[/^\*\*\/\*\.(md|mdx|rst|txt)$/i, "guides"]
|
|
39201
|
+
];
|
|
39202
|
+
}
|
|
39203
|
+
});
|
|
39204
|
+
|
|
39205
|
+
// src/docs/graph.ts
|
|
39206
|
+
import { existsSync as existsSync21, statSync as statSync9 } from "fs";
|
|
39207
|
+
import { dirname as dirname10, posix, relative as relative8, sep as sep2 } from "path";
|
|
39208
|
+
function manifestRel(ctx) {
|
|
39209
|
+
return relative8(ctx.root, manifestPath(ctx)).split(sep2).join("/");
|
|
39210
|
+
}
|
|
39211
|
+
function packageCandidates(provider) {
|
|
39212
|
+
if (!provider) return [];
|
|
39213
|
+
const i = provider.indexOf(":");
|
|
39214
|
+
if (i === -1) return [];
|
|
39215
|
+
const kind = provider.slice(0, i);
|
|
39216
|
+
const name = provider.slice(i + 1).trim();
|
|
39217
|
+
if (!name) return [];
|
|
39218
|
+
if (kind === "npm" || kind === "go") return [pkgId(name)];
|
|
39219
|
+
if (kind === "pypi") {
|
|
39220
|
+
const lower = name.toLowerCase();
|
|
39221
|
+
return [.../* @__PURE__ */ new Set([pkgId(lower.replace(/-/g, "_")), pkgId(lower), pkgId(name)])];
|
|
39222
|
+
}
|
|
39223
|
+
return [];
|
|
39224
|
+
}
|
|
39225
|
+
function pathsIn(text3, pageRel, files) {
|
|
39226
|
+
const out = /* @__PURE__ */ new Set();
|
|
39227
|
+
for (const m of text3.matchAll(PATH_RE)) {
|
|
39228
|
+
const raw = m[1];
|
|
39229
|
+
const tries = [raw.replace(/^(\.\/)+/, "")];
|
|
39230
|
+
if (pageRel && raw.startsWith("."))
|
|
39231
|
+
tries.unshift(posix.normalize(posix.join(dirname10(pageRel), raw)));
|
|
39232
|
+
for (const t of tries) {
|
|
39233
|
+
if (files.has(t)) {
|
|
39234
|
+
out.add(t);
|
|
39235
|
+
break;
|
|
39236
|
+
}
|
|
39237
|
+
}
|
|
39238
|
+
}
|
|
39239
|
+
return [...out];
|
|
39240
|
+
}
|
|
39241
|
+
function pageRelOf(ctx, uri) {
|
|
39242
|
+
if (!uri?.startsWith("file://")) return void 0;
|
|
39243
|
+
const rel = relative8(ctx.root, uri.slice("file://".length)).split(sep2).join("/");
|
|
39244
|
+
return rel.startsWith("..") ? void 0 : rel;
|
|
39245
|
+
}
|
|
39246
|
+
function localEdges(ctx, db, src, files) {
|
|
39247
|
+
const id = docId(src.name);
|
|
39248
|
+
const hits = /* @__PURE__ */ new Map();
|
|
39249
|
+
for (const page of db.documentsBySource(docsTag(src.name), MAX_PAGES)) {
|
|
39250
|
+
const rel = pageRelOf(ctx, page.uri);
|
|
39251
|
+
if (rel && files.has(rel)) hits.set(rel, { via: "covers", count: 1 });
|
|
39252
|
+
const text3 = db.chunksOfDocument(page.id).map((c) => c.body).join("\n");
|
|
39253
|
+
for (const f of pathsIn(text3, rel, files)) {
|
|
39254
|
+
const h = hits.get(f);
|
|
39255
|
+
if (h) h.count++;
|
|
39256
|
+
else hits.set(f, { via: "mentions", count: 1 });
|
|
39257
|
+
}
|
|
39258
|
+
if (hits.size >= MAX_EDGES) break;
|
|
39259
|
+
}
|
|
39260
|
+
return [...hits].sort((a, b) => b[1].count - a[1].count).slice(0, MAX_EDGES).map(([rel, h]) => ({
|
|
39261
|
+
src: id,
|
|
39262
|
+
dst: `file:${rel}`,
|
|
39263
|
+
kind: DOCUMENTS_EDGE,
|
|
39264
|
+
source: "curated",
|
|
39265
|
+
confidence: h.via === "covers" ? 1 : 0.8,
|
|
39266
|
+
weight: Math.min(1, 0.5 + h.count / 10),
|
|
39267
|
+
meta: { via: h.via, count: h.count }
|
|
39268
|
+
}));
|
|
39269
|
+
}
|
|
39270
|
+
function packageEdges(src, packages) {
|
|
39271
|
+
const id = docId(src.name);
|
|
39272
|
+
const cands = packageCandidates(src.provider);
|
|
39273
|
+
if (!cands.length) return [];
|
|
39274
|
+
let targets = cands.filter((c) => packages.has(c));
|
|
39275
|
+
if (src.provider?.startsWith("go:"))
|
|
39276
|
+
targets = [...targets, ...[...packages].filter((p) => p.startsWith(`${cands[0]}/`))];
|
|
39277
|
+
if (!targets.length) targets = [cands[0]];
|
|
39278
|
+
return [...new Set(targets)].map((dst) => ({
|
|
39279
|
+
src: id,
|
|
39280
|
+
dst,
|
|
39281
|
+
kind: DOCUMENTS_EDGE,
|
|
39282
|
+
source: "curated",
|
|
39283
|
+
confidence: 1,
|
|
39284
|
+
weight: 1,
|
|
39285
|
+
meta: { via: "provider" }
|
|
39286
|
+
}));
|
|
39287
|
+
}
|
|
39288
|
+
function localDocPages(ctx, db) {
|
|
39289
|
+
const out = /* @__PURE__ */ new Map();
|
|
39290
|
+
for (const s of readManifest(ctx).sources) {
|
|
39291
|
+
if (s.kind !== "path") continue;
|
|
39292
|
+
for (const page of db.documentsBySource(docsTag(s.name), MAX_PAGES)) {
|
|
39293
|
+
const rel = pageRelOf(ctx, page.uri);
|
|
39294
|
+
if (!rel) continue;
|
|
39295
|
+
const names = out.get(rel) ?? [];
|
|
39296
|
+
if (!names.includes(s.name)) names.push(s.name);
|
|
39297
|
+
out.set(rel, names);
|
|
39298
|
+
}
|
|
39299
|
+
}
|
|
39300
|
+
return out;
|
|
39301
|
+
}
|
|
39302
|
+
function stampOf(ctx, db) {
|
|
39303
|
+
const file3 = manifestPath(ctx);
|
|
39304
|
+
const st = existsSync21(file3) ? statSync9(file3) : void 0;
|
|
39305
|
+
const counts = db.graphNodeCounts();
|
|
39306
|
+
const syncs = readManifest(ctx).sources.map((s) => syncState(db, s.name)?.at ?? 0).join(",");
|
|
39307
|
+
return `${st ? `${Math.floor(st.mtimeMs)}:${st.size}` : "none"}|${counts.file ?? 0}|${counts.package ?? 0}|${syncs}`;
|
|
39308
|
+
}
|
|
39309
|
+
function syncDocsGraph(ctx, db) {
|
|
39310
|
+
const rel = manifestRel(ctx);
|
|
39311
|
+
const m = readManifest(ctx);
|
|
39312
|
+
const catalog = mergedCatalog(ctx.config.docs.catalog);
|
|
39313
|
+
const files = new Set(
|
|
39314
|
+
db.graphFileNodes().filter((n) => n.source === "tree-sitter" && n.path).map((n) => n.path)
|
|
39315
|
+
);
|
|
39316
|
+
const packages = new Set(db.graphNodesByKind(["package"]).map((n) => n.id));
|
|
39317
|
+
const nodes = [];
|
|
39318
|
+
const edges = [];
|
|
39319
|
+
for (const s of m.sources) {
|
|
39320
|
+
const category = docCategory(
|
|
39321
|
+
s,
|
|
39322
|
+
s.provider ? catalogForProvider(s.provider, catalog) : void 0
|
|
39323
|
+
);
|
|
39324
|
+
nodes.push({
|
|
39325
|
+
id: docId(s.name),
|
|
39326
|
+
kind: "doc",
|
|
39327
|
+
name: s.name,
|
|
39328
|
+
path: rel,
|
|
39329
|
+
source: "curated",
|
|
39330
|
+
meta: {
|
|
39331
|
+
category,
|
|
39332
|
+
group: categoryInfo(category).group,
|
|
39333
|
+
sourceKind: s.kind,
|
|
39334
|
+
...s.provider ? { provider: s.provider } : {},
|
|
39335
|
+
...s.title ? { title: s.title } : {},
|
|
39336
|
+
...s.tags?.length ? { tags: s.tags } : {},
|
|
39337
|
+
...s.kind === "path" ? { target: s.path } : { url: s.urls?.[0] },
|
|
39338
|
+
documents: db.countDocuments(docsTag(s.name))
|
|
39339
|
+
}
|
|
39340
|
+
});
|
|
39341
|
+
edges.push(...packageEdges(s, packages));
|
|
39342
|
+
if (s.kind === "path") edges.push(...localEdges(ctx, db, s, files));
|
|
39343
|
+
}
|
|
39344
|
+
db.graphDeleteForPath("curated", rel, { keepFile: true });
|
|
39345
|
+
if (nodes.length) db.graphUpsertNodes(nodes);
|
|
39346
|
+
if (edges.length) db.graphUpsertEdges(edges);
|
|
39347
|
+
db.metaSet(STAMP_KEY, stampOf(ctx, db));
|
|
39348
|
+
return { sources: nodes.length, edges: edges.length };
|
|
39349
|
+
}
|
|
39350
|
+
function ensureDocsGraph(ctx, db) {
|
|
39351
|
+
if (db.metaGet(STAMP_KEY) === stampOf(ctx, db)) return false;
|
|
39352
|
+
syncDocsGraph(ctx, db);
|
|
39353
|
+
return true;
|
|
39354
|
+
}
|
|
39355
|
+
function syncDocsGraphQuietly(ctx, db) {
|
|
39356
|
+
try {
|
|
39357
|
+
syncDocsGraph(ctx, db);
|
|
39358
|
+
} catch {
|
|
39359
|
+
}
|
|
39360
|
+
}
|
|
39361
|
+
var DOCUMENTS_EDGE, MAX_PAGES, MAX_EDGES, PATH_RE, STAMP_KEY;
|
|
39362
|
+
var init_graph = __esm({
|
|
39363
|
+
"src/docs/graph.ts"() {
|
|
39364
|
+
"use strict";
|
|
39365
|
+
init_esm_shims();
|
|
39366
|
+
init_ids();
|
|
39367
|
+
init_catalog();
|
|
39368
|
+
init_category();
|
|
39369
|
+
init_manifest();
|
|
39370
|
+
DOCUMENTS_EDGE = "documents";
|
|
39371
|
+
MAX_PAGES = 500;
|
|
39372
|
+
MAX_EDGES = 400;
|
|
39373
|
+
PATH_RE = /(?:^|[\s(`'"[<])((?:\.{1,2}\/)*(?:[\w@.-]+\/)+[\w@.-]+\.[A-Za-z0-9]{1,8})(?=$|[\s)`'"\]>:#,;!?]|\.(?:\s|$))/gm;
|
|
39374
|
+
STAMP_KEY = "docs.graph.stamp";
|
|
39375
|
+
}
|
|
39376
|
+
});
|
|
39377
|
+
|
|
39033
39378
|
// src/docs/resolve.ts
|
|
39034
39379
|
async function getJson(url2, opts) {
|
|
39035
39380
|
const f = opts.fetchImpl ?? fetch;
|
|
@@ -39914,6 +40259,7 @@ async function syncSources(ctx, db, names, opts = {}) {
|
|
|
39914
40259
|
});
|
|
39915
40260
|
}
|
|
39916
40261
|
for (const src of wanted) out.push(await syncSource(ctx, db, src, opts));
|
|
40262
|
+
syncDocsGraphQuietly(ctx, db);
|
|
39917
40263
|
return out;
|
|
39918
40264
|
}
|
|
39919
40265
|
function formatSync(results) {
|
|
@@ -39943,6 +40289,7 @@ var init_sync = __esm({
|
|
|
39943
40289
|
init_queue();
|
|
39944
40290
|
init_fetcher();
|
|
39945
40291
|
init_indexer();
|
|
40292
|
+
init_graph();
|
|
39946
40293
|
init_manifest();
|
|
39947
40294
|
init_specs();
|
|
39948
40295
|
SKIP_EXT2 = /\.(png|jpe?g|gif|svg|webp|ico|css|js|mjs|map|zip|gz|tgz|tar|pdf|woff2?|ttf|otf|eot|mp4|mp3|webm|xml|rss|atom|wasm)$/i;
|
|
@@ -40086,12 +40433,14 @@ async function addDocSources(ctx, db, inputs, opts = {}) {
|
|
|
40086
40433
|
const names = [...out.added, ...out.updated];
|
|
40087
40434
|
if (opts.sync !== false && names.length)
|
|
40088
40435
|
out.sync = await syncSources(ctx, db, names, { force: opts.force });
|
|
40436
|
+
else if (names.length) syncDocsGraphQuietly(ctx, db);
|
|
40089
40437
|
return out;
|
|
40090
40438
|
}
|
|
40091
40439
|
function removeDocSource(ctx, db, name) {
|
|
40092
40440
|
const removed = removeSource(ctx, name);
|
|
40093
40441
|
const documents = db.deleteDocumentsBySource(docsTag(name));
|
|
40094
40442
|
clearSyncState(db, name);
|
|
40443
|
+
if (removed) syncDocsGraphQuietly(ctx, db);
|
|
40095
40444
|
return { removed, documents };
|
|
40096
40445
|
}
|
|
40097
40446
|
function formatAdd(o) {
|
|
@@ -40125,6 +40474,7 @@ var init_add = __esm({
|
|
|
40125
40474
|
init_esm_shims();
|
|
40126
40475
|
init_catalog();
|
|
40127
40476
|
init_discover();
|
|
40477
|
+
init_graph();
|
|
40128
40478
|
init_manifest();
|
|
40129
40479
|
init_resolve2();
|
|
40130
40480
|
init_sync();
|
|
@@ -40141,168 +40491,6 @@ var init_add = __esm({
|
|
|
40141
40491
|
}
|
|
40142
40492
|
});
|
|
40143
40493
|
|
|
40144
|
-
// src/docs/category.ts
|
|
40145
|
-
function categoryInfo(id) {
|
|
40146
|
-
return BY_ID.get(id) ?? BY_ID.get("local");
|
|
40147
|
-
}
|
|
40148
|
-
function localCategory(s) {
|
|
40149
|
-
const title = s.title ?? "";
|
|
40150
|
-
for (const [re, cat] of TITLE_RULES) if (re.test(title)) return cat;
|
|
40151
|
-
for (const [re, cat] of NAME_RULES) if (re.test(s.name)) return cat;
|
|
40152
|
-
const path3 = s.path ?? "";
|
|
40153
|
-
if (/(^|\/)(adrs?|decisions)$/i.test(path3)) return "adr";
|
|
40154
|
-
const globs = s.glob ?? [];
|
|
40155
|
-
const hits = /* @__PURE__ */ new Map();
|
|
40156
|
-
for (const g of globs)
|
|
40157
|
-
for (const [re, cat] of GLOB_RULES)
|
|
40158
|
-
if (re.test(g)) {
|
|
40159
|
-
hits.set(cat, (hits.get(cat) ?? 0) + 1);
|
|
40160
|
-
break;
|
|
40161
|
-
}
|
|
40162
|
-
if (hits.size) return [...hits.entries()].sort((a, b) => b[1] - a[1])[0][0];
|
|
40163
|
-
if (/(^|\/)(docs?|documentation)$/i.test(path3)) return "guides";
|
|
40164
|
-
if (/README|CONTRIBUTING|CHANGELOG/i.test(path3)) return "readme";
|
|
40165
|
-
return "local";
|
|
40166
|
-
}
|
|
40167
|
-
function docCategory(s, entry) {
|
|
40168
|
-
if (s.kind === "path") return localCategory(s);
|
|
40169
|
-
if (entry) {
|
|
40170
|
-
const tier = entry.tier ?? "library";
|
|
40171
|
-
return tier === "service" ? "service" : tier === "infra" ? "infra" : "library";
|
|
40172
|
-
}
|
|
40173
|
-
const provider = s.provider ?? "";
|
|
40174
|
-
const i = provider.indexOf(":");
|
|
40175
|
-
const kind = i === -1 ? provider : provider.slice(0, i);
|
|
40176
|
-
switch (kind) {
|
|
40177
|
-
case "api":
|
|
40178
|
-
return "api";
|
|
40179
|
-
case "env":
|
|
40180
|
-
return "service";
|
|
40181
|
-
case "image":
|
|
40182
|
-
case "files":
|
|
40183
|
-
return "infra";
|
|
40184
|
-
case "npm":
|
|
40185
|
-
case "pypi":
|
|
40186
|
-
case "go":
|
|
40187
|
-
return "library";
|
|
40188
|
-
default:
|
|
40189
|
-
return "web";
|
|
40190
|
-
}
|
|
40191
|
-
}
|
|
40192
|
-
function categoryRank(id) {
|
|
40193
|
-
const i = DOC_CATEGORIES.findIndex((c) => c.id === id);
|
|
40194
|
-
return i === -1 ? DOC_CATEGORIES.length : i;
|
|
40195
|
-
}
|
|
40196
|
-
var DOC_CATEGORIES, BY_ID, GROUP_LABELS, TITLE_RULES, NAME_RULES, GLOB_RULES;
|
|
40197
|
-
var init_category = __esm({
|
|
40198
|
-
"src/docs/category.ts"() {
|
|
40199
|
-
"use strict";
|
|
40200
|
-
init_esm_shims();
|
|
40201
|
-
DOC_CATEGORIES = [
|
|
40202
|
-
{
|
|
40203
|
-
id: "readme",
|
|
40204
|
-
group: "project",
|
|
40205
|
-
label: "Readme & guides",
|
|
40206
|
-
blurb: "README, CONTRIBUTING, CHANGELOG and other top-level guides"
|
|
40207
|
-
},
|
|
40208
|
-
{
|
|
40209
|
-
id: "guides",
|
|
40210
|
-
group: "project",
|
|
40211
|
-
label: "Docs folders",
|
|
40212
|
-
blurb: "docs/ directories: handbooks, how-tos, references"
|
|
40213
|
-
},
|
|
40214
|
-
{
|
|
40215
|
-
id: "adr",
|
|
40216
|
-
group: "project",
|
|
40217
|
-
label: "Decision records",
|
|
40218
|
-
blurb: "architecture decision records"
|
|
40219
|
-
},
|
|
40220
|
-
{
|
|
40221
|
-
id: "agent-instructions",
|
|
40222
|
-
group: "project",
|
|
40223
|
-
label: "Agent instructions",
|
|
40224
|
-
blurb: "Copilot, Claude and Cursor instructions, agents and skills"
|
|
40225
|
-
},
|
|
40226
|
-
{
|
|
40227
|
-
id: "api-specs",
|
|
40228
|
-
group: "project",
|
|
40229
|
-
label: "API specs",
|
|
40230
|
-
blurb: "OpenAPI, Postman, GraphQL and protobuf definitions"
|
|
40231
|
-
},
|
|
40232
|
-
{
|
|
40233
|
-
id: "env-reference",
|
|
40234
|
-
group: "project",
|
|
40235
|
-
label: "Environment reference",
|
|
40236
|
-
blurb: ".env examples: every variable the project reads"
|
|
40237
|
-
},
|
|
40238
|
-
{
|
|
40239
|
-
id: "deploy-config",
|
|
40240
|
-
group: "project",
|
|
40241
|
-
label: "Deploy config",
|
|
40242
|
-
blurb: "Terraform, Kubernetes, Helm, Compose and CI workflows"
|
|
40243
|
-
},
|
|
40244
|
-
{ id: "local", group: "project", label: "Other local files", blurb: "hand-registered paths" },
|
|
40245
|
-
{
|
|
40246
|
-
id: "service",
|
|
40247
|
-
group: "external",
|
|
40248
|
-
label: "Services",
|
|
40249
|
-
blurb: "third-party products and APIs the project integrates"
|
|
40250
|
-
},
|
|
40251
|
-
{
|
|
40252
|
-
id: "api",
|
|
40253
|
-
group: "external",
|
|
40254
|
-
label: "External APIs",
|
|
40255
|
-
blurb: "hosts the code calls, found by probing their docs"
|
|
40256
|
-
},
|
|
40257
|
-
{
|
|
40258
|
-
id: "infra",
|
|
40259
|
-
group: "external",
|
|
40260
|
-
label: "Infrastructure",
|
|
40261
|
-
blurb: "platforms the project runs on"
|
|
40262
|
-
},
|
|
40263
|
-
{ id: "library", group: "external", label: "Libraries", blurb: "frameworks and packages" },
|
|
40264
|
-
{ id: "web", group: "external", label: "Web pages", blurb: "hand-registered URLs" }
|
|
40265
|
-
];
|
|
40266
|
-
BY_ID = new Map(DOC_CATEGORIES.map((c) => [c.id, c]));
|
|
40267
|
-
GROUP_LABELS = {
|
|
40268
|
-
project: "Project documentation",
|
|
40269
|
-
external: "External documentation"
|
|
40270
|
-
};
|
|
40271
|
-
TITLE_RULES = [
|
|
40272
|
-
[/^project readme/i, "readme"],
|
|
40273
|
-
[/^(docs|doc|documentation)\/ directory$/i, "guides"],
|
|
40274
|
-
[/decision records/i, "adr"],
|
|
40275
|
-
[/copilot|claude|cursor/i, "agent-instructions"],
|
|
40276
|
-
[/openapi|postman|graphql|protobuf/i, "api-specs"],
|
|
40277
|
-
[/environment variable/i, "env-reference"],
|
|
40278
|
-
[/terraform|kubernetes|helm|compose|workflow/i, "deploy-config"]
|
|
40279
|
-
];
|
|
40280
|
-
NAME_RULES = [
|
|
40281
|
-
[/(^|-)readme$/, "readme"],
|
|
40282
|
-
[/(^|-)docs$/, "guides"],
|
|
40283
|
-
[/(^|-)adrs?$/, "adr"],
|
|
40284
|
-
[/(^|-)agent-instructions$/, "agent-instructions"],
|
|
40285
|
-
[/(^|-)api-specs$/, "api-specs"],
|
|
40286
|
-
[/(^|-)env-example$/, "env-reference"],
|
|
40287
|
-
[/(^|-)deploy-config$/, "deploy-config"]
|
|
40288
|
-
];
|
|
40289
|
-
GLOB_RULES = [
|
|
40290
|
-
[/openapi|swagger|postman_collection|asyncapi|\.graphql$|\.proto$/i, "api-specs"],
|
|
40291
|
-
[/^\.env\./, "env-reference"],
|
|
40292
|
-
[
|
|
40293
|
-
/\.tf$|tfvars|^k8s\/|^helm\/|^charts\/|^manifests\/|compose.*\.ya?ml|\.github\/workflows/i,
|
|
40294
|
-
"deploy-config"
|
|
40295
|
-
],
|
|
40296
|
-
[
|
|
40297
|
-
/copilot-instructions|\.github\/(instructions|agents|skills)|\.claude\/(agents|skills)|\.cursor\/rules|^(AGENTS|CLAUDE)\.md$/i,
|
|
40298
|
-
"agent-instructions"
|
|
40299
|
-
],
|
|
40300
|
-
[/^(README|CONTRIBUTING|CHANGELOG|SECURITY)(\.md)?$/i, "readme"],
|
|
40301
|
-
[/^\*\*\/\*\.(md|mdx|rst|txt)$/i, "guides"]
|
|
40302
|
-
];
|
|
40303
|
-
}
|
|
40304
|
-
});
|
|
40305
|
-
|
|
40306
40494
|
// src/tools/em_docs.ts
|
|
40307
40495
|
var em_docs_exports = {};
|
|
40308
40496
|
__export(em_docs_exports, {
|
|
@@ -41003,8 +41191,8 @@ var init_em_search = __esm({
|
|
|
41003
41191
|
});
|
|
41004
41192
|
|
|
41005
41193
|
// src/ui/api.ts
|
|
41006
|
-
import { existsSync as
|
|
41007
|
-
import { join as join26, relative as
|
|
41194
|
+
import { existsSync as existsSync22, readdirSync as readdirSync8 } from "fs";
|
|
41195
|
+
import { join as join26, relative as relative9 } from "path";
|
|
41008
41196
|
function listProjects() {
|
|
41009
41197
|
const dir = paths().projects;
|
|
41010
41198
|
const out = [];
|
|
@@ -41037,7 +41225,7 @@ function statsPayload(ctx) {
|
|
|
41037
41225
|
const sessionId = getCurrentSession(ctx);
|
|
41038
41226
|
const g = globalDb();
|
|
41039
41227
|
const onboardingDir = join26(memoriesDir(ctx), "onboarding");
|
|
41040
|
-
const onboarding =
|
|
41228
|
+
const onboarding = existsSync22(onboardingDir) ? readdirSync8(onboardingDir).filter((f) => f.endsWith(".md")).map((f) => f.slice(0, -3)) : [];
|
|
41041
41229
|
return {
|
|
41042
41230
|
project: ctx.root,
|
|
41043
41231
|
projectId: ctx.id,
|
|
@@ -41229,7 +41417,7 @@ function docsPayload(ctx) {
|
|
|
41229
41417
|
const known = new Set(m.sources.map((s) => docsTag(s.name)));
|
|
41230
41418
|
const orphans2 = [...stats.values()].filter((s) => !known.has(s.source)).map((s) => ({ source: s.source, documents: s.documents, chunks: s.chunks }));
|
|
41231
41419
|
return {
|
|
41232
|
-
manifest:
|
|
41420
|
+
manifest: relative9(ctx.root, manifestPath(ctx)),
|
|
41233
41421
|
sources,
|
|
41234
41422
|
orphans: orphans2,
|
|
41235
41423
|
totals: {
|
|
@@ -41575,7 +41763,7 @@ var init_namepath = __esm({
|
|
|
41575
41763
|
});
|
|
41576
41764
|
|
|
41577
41765
|
// src/code/symbols.ts
|
|
41578
|
-
import { existsSync as
|
|
41766
|
+
import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
|
|
41579
41767
|
import { join as join27 } from "path";
|
|
41580
41768
|
function isExported2(n) {
|
|
41581
41769
|
if (!n.meta) return false;
|
|
@@ -41612,8 +41800,8 @@ var init_symbols2 = __esm({
|
|
|
41612
41800
|
});
|
|
41613
41801
|
|
|
41614
41802
|
// src/ui/graph-api.ts
|
|
41615
|
-
import { readFileSync as readFileSync21, realpathSync as realpathSync2, statSync as
|
|
41616
|
-
import { relative as
|
|
41803
|
+
import { readFileSync as readFileSync21, realpathSync as realpathSync2, statSync as statSync10 } from "fs";
|
|
41804
|
+
import { relative as relative10, resolve as resolve7 } from "path";
|
|
41617
41805
|
function metaOf2(row) {
|
|
41618
41806
|
if (!row?.meta) return {};
|
|
41619
41807
|
try {
|
|
@@ -41675,16 +41863,16 @@ function treePayload(ctx) {
|
|
|
41675
41863
|
function filePayload(ctx, rel) {
|
|
41676
41864
|
const clean = rel.replace(/^\.\//, "");
|
|
41677
41865
|
const abs = resolve7(ctx.root, clean);
|
|
41678
|
-
if (
|
|
41866
|
+
if (relative10(ctx.root, abs).startsWith("..")) throw new Error("path outside the project");
|
|
41679
41867
|
let real = abs;
|
|
41680
41868
|
try {
|
|
41681
41869
|
real = realpathSync2(abs);
|
|
41682
41870
|
} catch {
|
|
41683
41871
|
return { error: "not found", path: clean };
|
|
41684
41872
|
}
|
|
41685
|
-
if (
|
|
41873
|
+
if (relative10(realpathSync2(ctx.root), real).startsWith(".."))
|
|
41686
41874
|
throw new Error("path outside the project");
|
|
41687
|
-
const st =
|
|
41875
|
+
const st = statSync10(real);
|
|
41688
41876
|
if (!st.isFile()) return { error: "not a file", path: clean };
|
|
41689
41877
|
const db = getStorage(ctx);
|
|
41690
41878
|
const row = db.fileIndexGet(clean);
|
|
@@ -43269,6 +43457,247 @@ var init_history_api = __esm({
|
|
|
43269
43457
|
}
|
|
43270
43458
|
});
|
|
43271
43459
|
|
|
43460
|
+
// src/ui/knowledge-api.ts
|
|
43461
|
+
function metaOf3(row) {
|
|
43462
|
+
if (!row?.meta) return {};
|
|
43463
|
+
try {
|
|
43464
|
+
return JSON.parse(row.meta);
|
|
43465
|
+
} catch {
|
|
43466
|
+
return {};
|
|
43467
|
+
}
|
|
43468
|
+
}
|
|
43469
|
+
function kindOfMissing(id) {
|
|
43470
|
+
const k = parseId(id).kind;
|
|
43471
|
+
return k === "pkg" ? "package" : k === "sym" ? "symbol" : k === "doc" ? "doc" : k;
|
|
43472
|
+
}
|
|
43473
|
+
function scopeOf2(raw) {
|
|
43474
|
+
return raw === "memory" || raw === "docs" ? raw : "all";
|
|
43475
|
+
}
|
|
43476
|
+
function knowledgePayload(ctx, opts = {}) {
|
|
43477
|
+
const db = getStorage(ctx);
|
|
43478
|
+
reconcile(ctx, db);
|
|
43479
|
+
try {
|
|
43480
|
+
ensureDocsGraph(ctx, db);
|
|
43481
|
+
} catch {
|
|
43482
|
+
}
|
|
43483
|
+
return buildKnowledge(ctx, db, opts);
|
|
43484
|
+
}
|
|
43485
|
+
function buildKnowledge(ctx, db, opts = {}) {
|
|
43486
|
+
const scope = opts.scope ?? "all";
|
|
43487
|
+
const limit = Math.max(10, Math.min(2e3, opts.limit ?? 300));
|
|
43488
|
+
const focus = opts.focus?.trim() || null;
|
|
43489
|
+
const memRows = new Map(
|
|
43490
|
+
db.memoryList({ limit: 1e5 }).filter((r) => r.name).map((r) => [r.name, r])
|
|
43491
|
+
);
|
|
43492
|
+
const memNodes = db.graphNodesByKind(["memory"]);
|
|
43493
|
+
const docNodes = db.graphNodesByKind(["doc"]);
|
|
43494
|
+
const rows = /* @__PURE__ */ new Map();
|
|
43495
|
+
for (const n of [...memNodes, ...docNodes]) rows.set(n.id, n);
|
|
43496
|
+
const hubsOf = (id) => {
|
|
43497
|
+
const n = rows.get(id);
|
|
43498
|
+
if (!n) return [];
|
|
43499
|
+
const m = metaOf3(n);
|
|
43500
|
+
const out = [];
|
|
43501
|
+
if (n.kind === "memory") {
|
|
43502
|
+
const row = memRows.get(n.name);
|
|
43503
|
+
const tags = row?.tags ? JSON.parse(row.tags) : m.tags ?? [];
|
|
43504
|
+
for (const t of tags) out.push({ id: tagId(t), kind: "tag", label: `#${t}` });
|
|
43505
|
+
if (n.name.includes("/")) {
|
|
43506
|
+
const topic = n.name.split("/")[0];
|
|
43507
|
+
out.push({ id: topicId(topic), kind: "topic", label: `${topic}/` });
|
|
43508
|
+
}
|
|
43509
|
+
} else if (n.kind === "doc") {
|
|
43510
|
+
for (const t of m.tags ?? [])
|
|
43511
|
+
out.push({ id: tagId(t), kind: "tag", label: `#${t}` });
|
|
43512
|
+
const cat = typeof m.category === "string" ? m.category : "local";
|
|
43513
|
+
out.push({ id: topicId(`docs/${cat}`), kind: "topic", label: categoryInfo(cat).label });
|
|
43514
|
+
}
|
|
43515
|
+
return out;
|
|
43516
|
+
};
|
|
43517
|
+
const scoped = [
|
|
43518
|
+
...scope !== "docs" ? memNodes : [],
|
|
43519
|
+
...scope !== "memory" ? docNodes : []
|
|
43520
|
+
].map((n) => n.id);
|
|
43521
|
+
let seeds;
|
|
43522
|
+
if (!focus) seeds = scoped;
|
|
43523
|
+
else if (focus.startsWith("tag:") || focus.startsWith("topic:"))
|
|
43524
|
+
seeds = [...memNodes, ...docNodes].map((n) => n.id).filter((id) => hubsOf(id).some((h) => h.id === focus));
|
|
43525
|
+
else seeds = [focus];
|
|
43526
|
+
const edges = /* @__PURE__ */ new Map();
|
|
43527
|
+
const addEdge = (e) => {
|
|
43528
|
+
if (e.src === e.dst) return;
|
|
43529
|
+
const key = `${e.src}|${e.dst}|${e.kind}`;
|
|
43530
|
+
if (!edges.has(key)) edges.set(key, e);
|
|
43531
|
+
};
|
|
43532
|
+
const stored = (e) => addEdge({ src: e.src, dst: e.dst, kind: e.kind, weight: e.weight });
|
|
43533
|
+
const hop = (ids2) => {
|
|
43534
|
+
if (!ids2.length) return [];
|
|
43535
|
+
const found = /* @__PURE__ */ new Set();
|
|
43536
|
+
for (const e of db.graphEdgesFrom(ids2, ALL_KINDS)) {
|
|
43537
|
+
stored(e);
|
|
43538
|
+
found.add(e.dst);
|
|
43539
|
+
}
|
|
43540
|
+
for (const e of db.graphEdgesTo(ids2, ALL_KINDS)) {
|
|
43541
|
+
stored(e);
|
|
43542
|
+
found.add(e.src);
|
|
43543
|
+
}
|
|
43544
|
+
return [...found];
|
|
43545
|
+
};
|
|
43546
|
+
const first = hop(seeds);
|
|
43547
|
+
if (focus && !focus.startsWith("tag:") && !focus.startsWith("topic:")) {
|
|
43548
|
+
const fresh = first.filter((id) => !seeds.includes(id));
|
|
43549
|
+
hop(fresh);
|
|
43550
|
+
}
|
|
43551
|
+
const pages = localDocPages(ctx, db);
|
|
43552
|
+
const knowledgeIds = () => new Set([...edges.values()].flatMap((e) => [e.src, e.dst]).concat(seeds));
|
|
43553
|
+
if (pages.size) {
|
|
43554
|
+
for (const id of knowledgeIds()) {
|
|
43555
|
+
if (!id.startsWith("memory:")) continue;
|
|
43556
|
+
const row = memRows.get(id.slice("memory:".length));
|
|
43557
|
+
const related = row?.node_ids ? JSON.parse(row.node_ids) : [];
|
|
43558
|
+
for (const r of related) {
|
|
43559
|
+
const f = fileOf(r);
|
|
43560
|
+
for (const name of f && pages.get(f) || [])
|
|
43561
|
+
addEdge({ src: id, dst: docId(name), kind: "about", weight: 1, derived: true });
|
|
43562
|
+
}
|
|
43563
|
+
}
|
|
43564
|
+
const docsInView = [...knowledgeIds()].filter((id) => id.startsWith("doc:"));
|
|
43565
|
+
if (docsInView.length) {
|
|
43566
|
+
for (const [name, row] of memRows) {
|
|
43567
|
+
const related = row.node_ids ? JSON.parse(row.node_ids) : [];
|
|
43568
|
+
for (const r of related) {
|
|
43569
|
+
const f = fileOf(r);
|
|
43570
|
+
for (const doc of f && pages.get(f) || [])
|
|
43571
|
+
if (docsInView.includes(docId(doc)))
|
|
43572
|
+
addEdge({
|
|
43573
|
+
src: memoryId(name),
|
|
43574
|
+
dst: docId(doc),
|
|
43575
|
+
kind: "about",
|
|
43576
|
+
weight: 1,
|
|
43577
|
+
derived: true
|
|
43578
|
+
});
|
|
43579
|
+
}
|
|
43580
|
+
}
|
|
43581
|
+
}
|
|
43582
|
+
}
|
|
43583
|
+
const hubNodes = /* @__PURE__ */ new Map();
|
|
43584
|
+
for (const id of knowledgeIds()) {
|
|
43585
|
+
for (const h of hubsOf(id)) {
|
|
43586
|
+
if (!hubNodes.has(h.id))
|
|
43587
|
+
hubNodes.set(h.id, {
|
|
43588
|
+
id: h.id,
|
|
43589
|
+
label: h.label,
|
|
43590
|
+
kind: h.kind,
|
|
43591
|
+
path: null,
|
|
43592
|
+
line: null,
|
|
43593
|
+
group: "hub"
|
|
43594
|
+
});
|
|
43595
|
+
addEdge({
|
|
43596
|
+
src: id,
|
|
43597
|
+
dst: h.id,
|
|
43598
|
+
kind: h.kind === "tag" ? "tagged" : "in_topic",
|
|
43599
|
+
weight: 0.5,
|
|
43600
|
+
derived: true
|
|
43601
|
+
});
|
|
43602
|
+
}
|
|
43603
|
+
}
|
|
43604
|
+
if (focus && (focus.startsWith("tag:") || focus.startsWith("topic:")) && !hubNodes.has(focus))
|
|
43605
|
+
hubNodes.set(focus, {
|
|
43606
|
+
id: focus,
|
|
43607
|
+
label: focus.startsWith("tag:") ? `#${focus.slice(4)}` : `${focus.slice(6)}/`,
|
|
43608
|
+
kind: focus.startsWith("tag:") ? "tag" : "topic",
|
|
43609
|
+
path: null,
|
|
43610
|
+
line: null,
|
|
43611
|
+
group: "hub"
|
|
43612
|
+
});
|
|
43613
|
+
const ids = knowledgeIds();
|
|
43614
|
+
for (const h of hubNodes.keys()) ids.add(h);
|
|
43615
|
+
const graphRows = new Map(
|
|
43616
|
+
db.graphGetNodes([...ids].filter((id) => !hubNodes.has(id))).map((n) => [n.id, n])
|
|
43617
|
+
);
|
|
43618
|
+
const seedSet = new Set(seeds);
|
|
43619
|
+
if (focus) seedSet.add(focus);
|
|
43620
|
+
const nodes = [];
|
|
43621
|
+
for (const id of ids) {
|
|
43622
|
+
const hub = hubNodes.get(id);
|
|
43623
|
+
if (hub) {
|
|
43624
|
+
nodes.push({ ...hub, seed: seedSet.has(id) || void 0, root: id === focus });
|
|
43625
|
+
continue;
|
|
43626
|
+
}
|
|
43627
|
+
const row = graphRows.get(id);
|
|
43628
|
+
const base = vis(row, id, id === focus);
|
|
43629
|
+
const m = metaOf3(row);
|
|
43630
|
+
const node2 = {
|
|
43631
|
+
...base,
|
|
43632
|
+
kind: row ? row.kind : kindOfMissing(id),
|
|
43633
|
+
group: "code",
|
|
43634
|
+
seed: seedSet.has(id) || void 0,
|
|
43635
|
+
missing: row ? void 0 : true
|
|
43636
|
+
};
|
|
43637
|
+
if (node2.kind === "memory") {
|
|
43638
|
+
const name = row?.name ?? id.slice("memory:".length);
|
|
43639
|
+
const mr = memRows.get(name);
|
|
43640
|
+
node2.group = "memory";
|
|
43641
|
+
node2.label = name;
|
|
43642
|
+
node2.sub = mr?.kind ?? m.kind;
|
|
43643
|
+
node2.status = mr?.status ?? m.status ?? (node2.sub === "decision" ? "accepted" : void 0);
|
|
43644
|
+
node2.tags = mr?.tags ? JSON.parse(mr.tags) : m.tags;
|
|
43645
|
+
node2.detail = name.includes("/") ? `${name.split("/")[0]}/` : void 0;
|
|
43646
|
+
} else if (node2.kind === "doc") {
|
|
43647
|
+
node2.group = "doc";
|
|
43648
|
+
node2.label = row?.name ?? id.slice("doc:".length);
|
|
43649
|
+
node2.sub = typeof m.category === "string" ? m.category : void 0;
|
|
43650
|
+
node2.detail = node2.sub ? categoryInfo(node2.sub).label : void 0;
|
|
43651
|
+
node2.provider = typeof m.provider === "string" ? m.provider : void 0;
|
|
43652
|
+
node2.tags = m.tags;
|
|
43653
|
+
}
|
|
43654
|
+
nodes.push(node2);
|
|
43655
|
+
}
|
|
43656
|
+
const deg = /* @__PURE__ */ new Map();
|
|
43657
|
+
for (const e of edges.values()) {
|
|
43658
|
+
deg.set(e.src, (deg.get(e.src) ?? 0) + 1);
|
|
43659
|
+
deg.set(e.dst, (deg.get(e.dst) ?? 0) + 1);
|
|
43660
|
+
}
|
|
43661
|
+
const updated = (n) => n.kind === "memory" ? memRows.get(n.label)?.updated_at ?? 0 : 0;
|
|
43662
|
+
const rank = (n) => n.root ? 0 : n.seed ? 1 : n.group === "memory" || n.group === "doc" ? 2 : n.group === "hub" ? 3 : 4;
|
|
43663
|
+
nodes.sort(
|
|
43664
|
+
(a, b) => rank(a) - rank(b) || updated(b) - updated(a) || (deg.get(b.id) ?? 0) - (deg.get(a.id) ?? 0) || a.id.localeCompare(b.id)
|
|
43665
|
+
);
|
|
43666
|
+
const total = nodes.length;
|
|
43667
|
+
const kept = nodes.slice(0, limit);
|
|
43668
|
+
const keep = new Set(kept.map((n) => n.id));
|
|
43669
|
+
const keptEdges = [...edges.values()].filter((e) => keep.has(e.src) && keep.has(e.dst));
|
|
43670
|
+
const counts = { nodes: {}, edges: {} };
|
|
43671
|
+
for (const n of kept) counts.nodes[n.kind] = (counts.nodes[n.kind] ?? 0) + 1;
|
|
43672
|
+
for (const e of keptEdges) counts.edges[e.kind] = (counts.edges[e.kind] ?? 0) + 1;
|
|
43673
|
+
return {
|
|
43674
|
+
scope,
|
|
43675
|
+
focus,
|
|
43676
|
+
nodes: kept,
|
|
43677
|
+
edges: keptEdges,
|
|
43678
|
+
truncated: total > kept.length,
|
|
43679
|
+
total,
|
|
43680
|
+
counts
|
|
43681
|
+
};
|
|
43682
|
+
}
|
|
43683
|
+
var KNOWLEDGE_EDGES, ALL_KINDS, tagId, topicId;
|
|
43684
|
+
var init_knowledge_api = __esm({
|
|
43685
|
+
"src/ui/knowledge-api.ts"() {
|
|
43686
|
+
"use strict";
|
|
43687
|
+
init_esm_shims();
|
|
43688
|
+
init_category();
|
|
43689
|
+
init_graph();
|
|
43690
|
+
init_ids();
|
|
43691
|
+
init_store();
|
|
43692
|
+
init_storage();
|
|
43693
|
+
init_graph_api();
|
|
43694
|
+
KNOWLEDGE_EDGES = ["mentions", "links", "supersedes", "documents"];
|
|
43695
|
+
ALL_KINDS = [...KNOWLEDGE_EDGES];
|
|
43696
|
+
tagId = (t) => `tag:${t}`;
|
|
43697
|
+
topicId = (t) => `topic:${t}`;
|
|
43698
|
+
}
|
|
43699
|
+
});
|
|
43700
|
+
|
|
43272
43701
|
// src/ui/server.ts
|
|
43273
43702
|
var server_exports = {};
|
|
43274
43703
|
__export(server_exports, {
|
|
@@ -43276,7 +43705,7 @@ __export(server_exports, {
|
|
|
43276
43705
|
uiDir: () => uiDir
|
|
43277
43706
|
});
|
|
43278
43707
|
import { spawn as spawn2 } from "child_process";
|
|
43279
|
-
import { existsSync as
|
|
43708
|
+
import { existsSync as existsSync24, readFileSync as readFileSync22, statSync as statSync11 } from "fs";
|
|
43280
43709
|
import { createServer } from "http";
|
|
43281
43710
|
import { extname as extname3, join as join28, normalize as normalize6 } from "path";
|
|
43282
43711
|
import { URL as URL2 } from "url";
|
|
@@ -43326,12 +43755,12 @@ function serveStatic(res, p) {
|
|
|
43326
43755
|
const rel = p === "/" ? "index.html" : p.replace(/^\/+/, "");
|
|
43327
43756
|
const file3 = normalize6(join28(dir, rel));
|
|
43328
43757
|
if (!file3.startsWith(normalize6(dir))) return false;
|
|
43329
|
-
if (!
|
|
43758
|
+
if (!existsSync24(file3) || !statSync11(file3).isFile()) return false;
|
|
43330
43759
|
const type = MIME[extname3(file3).toLowerCase()] ?? "application/octet-stream";
|
|
43331
43760
|
if (rel === "index.html") {
|
|
43332
43761
|
const stamp = (name) => {
|
|
43333
43762
|
try {
|
|
43334
|
-
return `/${name}?v=${Math.floor(
|
|
43763
|
+
return `/${name}?v=${Math.floor(statSync11(join28(dir, name)).mtimeMs)}`;
|
|
43335
43764
|
} catch {
|
|
43336
43765
|
return `/${name}`;
|
|
43337
43766
|
}
|
|
@@ -43495,6 +43924,16 @@ async function serve(opts) {
|
|
|
43495
43924
|
if (!provider) return json2(res, 400, { error: "provider required" });
|
|
43496
43925
|
return json2(res, 200, await docsResolvePayload(ctx(), provider));
|
|
43497
43926
|
}
|
|
43927
|
+
if (p === "/api/knowledge")
|
|
43928
|
+
return json2(
|
|
43929
|
+
res,
|
|
43930
|
+
200,
|
|
43931
|
+
knowledgePayload(ctx(), {
|
|
43932
|
+
scope: scopeOf2(q.get("scope")),
|
|
43933
|
+
focus: str2("focus"),
|
|
43934
|
+
limit: num2("limit", 300)
|
|
43935
|
+
})
|
|
43936
|
+
);
|
|
43498
43937
|
if (p === "/api/graph") {
|
|
43499
43938
|
const mode = q.get("mode") ?? "impact";
|
|
43500
43939
|
const node2 = q.get("node") ?? "";
|
|
@@ -43705,6 +44144,7 @@ var init_server = __esm({
|
|
|
43705
44144
|
init_api2();
|
|
43706
44145
|
init_graph_api();
|
|
43707
44146
|
init_history_api();
|
|
44147
|
+
init_knowledge_api();
|
|
43708
44148
|
MIME = {
|
|
43709
44149
|
".html": "text/html; charset=utf-8",
|
|
43710
44150
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -43727,7 +44167,7 @@ var statusline_exports = {};
|
|
|
43727
44167
|
__export(statusline_exports, {
|
|
43728
44168
|
renderStatusline: () => renderStatusline
|
|
43729
44169
|
});
|
|
43730
|
-
import { existsSync as
|
|
44170
|
+
import { existsSync as existsSync25, readFileSync as readFileSync23, writeFileSync as writeFileSync9 } from "fs";
|
|
43731
44171
|
function renderStatusline(raw) {
|
|
43732
44172
|
let input2 = {};
|
|
43733
44173
|
try {
|
|
@@ -43736,7 +44176,7 @@ function renderStatusline(raw) {
|
|
|
43736
44176
|
}
|
|
43737
44177
|
const cache3 = paths().statuslineCache;
|
|
43738
44178
|
try {
|
|
43739
|
-
if (
|
|
44179
|
+
if (existsSync25(cache3)) {
|
|
43740
44180
|
const c = JSON.parse(readFileSync23(cache3, "utf8"));
|
|
43741
44181
|
if (Date.now() - c.at < 5e3 && c.key === (input2.session_id ?? "")) return c.line;
|
|
43742
44182
|
}
|