@agentskit/doc-bridge 1.2.6 → 1.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/CHANGELOG.md +19 -0
- package/README.md +32 -6
- package/action.yml +1 -1
- package/dist/cli/program.js +344 -130
- package/dist/cli/program.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/{index-DGI9TBLE.d.ts → index-DAeq_OIi.d.ts} +22 -22
- package/dist/index.d.ts +7 -4
- package/dist/index.js +320 -105
- package/dist/index.js.map +1 -1
- package/docs/MARKETPLACE.md +1 -1
- package/docs/POSITIONING.md +1 -1
- package/docs/examples.md +4 -0
- package/docs/getting-started.md +1 -1
- package/docs/guides/choose-context-layer.md +129 -0
- package/docs/guides/gate-ci.md +1 -1
- package/docs/guides/meta.json +1 -0
- package/docs/landing/index.html +2 -2
- package/docs/playbook/doc-bridge-pattern.md +1 -1
- package/docs/qa/vitepress-starlight-adapters.md +19 -0
- package/docs/recipes/index-pipeline.md +1 -1
- package/docs/spec/config-v1.md +33 -2
- package/examples/nextra-only.config.ts +17 -0
- package/examples/nx-monorepo.config.ts +11 -0
- package/examples/starlight-only.config.ts +17 -0
- package/examples/vitepress-only.config.ts +19 -0
- package/mcpb/manifest.json +1 -1
- package/package.json +15 -4
- package/skills/doc-bridge-handoff/SKILL.md +38 -0
- package/skills/doc-bridge-handoff/fixtures/synthetic-repo/doc-bridge.config.json +23 -0
- package/skills/doc-bridge-handoff/fixtures/synthetic-repo/docs/for-agents/packages/payments.md +5 -0
- package/skills/doc-bridge-handoff/fixtures/synthetic-repo/packages/payments/package.json +4 -0
- package/skills/doc-bridge-handoff/scripts/resolve-handoff.mjs +70 -0
- package/src/config/schema.ts +3 -1
- package/src/index-builder/build-handoffs.ts +2 -0
- package/src/index-builder/build-index.ts +7 -1
- package/src/index-builder/human-adapters/index.ts +6 -0
- package/src/index-builder/human-adapters/nextra.ts +43 -0
- package/src/index-builder/human-adapters/starlight.ts +40 -0
- package/src/index-builder/human-adapters/vitepress.ts +43 -0
- package/src/index-builder/plugins/nx.ts +161 -0
- package/src/index-builder/plugins/pnpm-monorepo.ts +1 -0
- package/src/index-builder/watch-index.ts +11 -2
- package/src/index.ts +1 -0
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -64,6 +64,8 @@ var HumanCorpusPluginIdSchema = z.enum([
|
|
|
64
64
|
"docusaurus",
|
|
65
65
|
"mkdocs",
|
|
66
66
|
"vitepress",
|
|
67
|
+
"starlight",
|
|
68
|
+
"nextra",
|
|
67
69
|
"custom"
|
|
68
70
|
]);
|
|
69
71
|
var AgentCorpusConfigSchema = z.object({
|
|
@@ -103,7 +105,7 @@ var OwnershipEntrySchema = z.object({
|
|
|
103
105
|
humanDoc: z.string().min(1).max(512).optional()
|
|
104
106
|
}).strict();
|
|
105
107
|
var RoutingConfigSchema = z.object({
|
|
106
|
-
plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "pattern-files", "custom"]).optional(),
|
|
108
|
+
plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "nx", "pattern-files", "custom"]).optional(),
|
|
107
109
|
options: z.object({
|
|
108
110
|
packages: z.array(z.string().min(1).max(256)).max(128).optional(),
|
|
109
111
|
/** Infer ownership from corpus paths/frontmatter (default true). */
|
|
@@ -1028,8 +1030,8 @@ ${zodIssues(result.error).map((i) => ` - ${i.path}: ${i.message}`).join("\n")}`
|
|
|
1028
1030
|
};
|
|
1029
1031
|
|
|
1030
1032
|
// src/index-builder/build-index.ts
|
|
1031
|
-
import { mkdirSync, readFileSync as
|
|
1032
|
-
import { dirname as
|
|
1033
|
+
import { mkdirSync, readFileSync as readFileSync7, writeFileSync } from "fs";
|
|
1034
|
+
import { dirname as dirname4, join as join7 } from "path";
|
|
1033
1035
|
|
|
1034
1036
|
// src/lib/paths.ts
|
|
1035
1037
|
import { existsSync as existsSync2, realpathSync } from "fs";
|
|
@@ -1298,17 +1300,17 @@ var scanAgentCorpus = (root, config) => {
|
|
|
1298
1300
|
};
|
|
1299
1301
|
});
|
|
1300
1302
|
};
|
|
1301
|
-
var guessAgentDocForPackage = (corpus,
|
|
1303
|
+
var guessAgentDocForPackage = (corpus, packageId2) => {
|
|
1302
1304
|
const candidates = [
|
|
1303
|
-
(doc) => frontmatterString(doc.frontmatter, "package") ===
|
|
1304
|
-
(doc) => doc.id ===
|
|
1305
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1306
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1307
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1308
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1309
|
-
(doc) => doc.relPath.endsWith(`/${
|
|
1310
|
-
(doc) => doc.relPath.endsWith(`/${
|
|
1311
|
-
(doc) => doc.relPath.includes(`/packages/${
|
|
1305
|
+
(doc) => frontmatterString(doc.frontmatter, "package") === packageId2,
|
|
1306
|
+
(doc) => doc.id === packageId2,
|
|
1307
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}.md`),
|
|
1308
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}.mdx`),
|
|
1309
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.md`),
|
|
1310
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.mdx`),
|
|
1311
|
+
(doc) => doc.relPath.endsWith(`/${packageId2}.md`),
|
|
1312
|
+
(doc) => doc.relPath.endsWith(`/${packageId2}.mdx`),
|
|
1313
|
+
(doc) => doc.relPath.includes(`/packages/${packageId2}/`)
|
|
1312
1314
|
];
|
|
1313
1315
|
for (const match of candidates) {
|
|
1314
1316
|
const hit = corpus.find(match);
|
|
@@ -1400,7 +1402,8 @@ var collectPackages = (config, discovered, corpus) => {
|
|
|
1400
1402
|
byId.set(pkg.id, {
|
|
1401
1403
|
id: pkg.id,
|
|
1402
1404
|
path: existing.path || pkg.path,
|
|
1403
|
-
...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {}
|
|
1405
|
+
...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {},
|
|
1406
|
+
...pkg.checks ? { checks: pkg.checks } : existing.checks ? { checks: existing.checks } : {}
|
|
1404
1407
|
});
|
|
1405
1408
|
}
|
|
1406
1409
|
const seeds = [
|
|
@@ -1419,24 +1422,24 @@ var collectPackages = (config, discovered, corpus) => {
|
|
|
1419
1422
|
}
|
|
1420
1423
|
return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
1421
1424
|
};
|
|
1422
|
-
var resolveHumanDoc = (
|
|
1425
|
+
var resolveHumanDoc = (packageId2, override, fmHuman, humanDocs = {}) => {
|
|
1423
1426
|
if (override) return override;
|
|
1424
1427
|
if (fmHuman) return fmHuman;
|
|
1425
|
-
if (humanDocs[
|
|
1428
|
+
if (humanDocs[packageId2]) return humanDocs[packageId2];
|
|
1426
1429
|
const aliases = [
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
`packages/${
|
|
1432
|
-
`reference/packages/${
|
|
1433
|
-
`packages/${
|
|
1430
|
+
packageId2,
|
|
1431
|
+
packageId2.replace(/^@[^/]+\//, ""),
|
|
1432
|
+
packageId2.replace(/^os-/, ""),
|
|
1433
|
+
packageId2.replace(/-pattern$/, ""),
|
|
1434
|
+
`packages/${packageId2}`,
|
|
1435
|
+
`reference/packages/${packageId2}`,
|
|
1436
|
+
`packages/${packageId2}/index`
|
|
1434
1437
|
];
|
|
1435
1438
|
for (const alias of aliases) {
|
|
1436
1439
|
if (humanDocs[alias]) return humanDocs[alias];
|
|
1437
1440
|
}
|
|
1438
1441
|
for (const [key, url] of Object.entries(humanDocs)) {
|
|
1439
|
-
if (key ===
|
|
1442
|
+
if (key === packageId2 || key.endsWith(`/${packageId2}`) || key.endsWith(`/${packageId2}/index`) || key.endsWith(`-${packageId2}`)) {
|
|
1440
1443
|
return url;
|
|
1441
1444
|
}
|
|
1442
1445
|
}
|
|
@@ -1460,7 +1463,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
|
|
|
1460
1463
|
const purpose = override?.purpose ?? fm?.purpose;
|
|
1461
1464
|
const path = override?.path ?? fm?.path ?? pkg.path;
|
|
1462
1465
|
const checks = [
|
|
1463
|
-
...override?.checks ?? fm?.checks ?? defaultChecksForTarget(root, {
|
|
1466
|
+
...override?.checks ?? fm?.checks ?? pkg.checks ?? defaultChecksForTarget(root, {
|
|
1464
1467
|
packageId: pkg.id,
|
|
1465
1468
|
packagePath: path,
|
|
1466
1469
|
...pkg.name ? { packageName: pkg.name } : {},
|
|
@@ -1534,7 +1537,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
|
|
|
1534
1537
|
};
|
|
1535
1538
|
|
|
1536
1539
|
// src/version.ts
|
|
1537
|
-
var PACKAGE_VERSION = "1.
|
|
1540
|
+
var PACKAGE_VERSION = "1.4.0";
|
|
1538
1541
|
|
|
1539
1542
|
// src/index-builder/capabilities.ts
|
|
1540
1543
|
var renderCapabilitiesJson = (config, index, paths) => {
|
|
@@ -1791,6 +1794,38 @@ var fumadocsAdapter = {
|
|
|
1791
1794
|
}
|
|
1792
1795
|
};
|
|
1793
1796
|
|
|
1797
|
+
// src/index-builder/human-adapters/nextra.ts
|
|
1798
|
+
var nextraRecordId = (relPath, raw) => {
|
|
1799
|
+
const frontmatter = parseFrontmatter2(raw);
|
|
1800
|
+
return frontmatter.package ?? frontmatter.module ?? frontmatter.id ?? (routeSlug(relPath) || "index");
|
|
1801
|
+
};
|
|
1802
|
+
var isIndexPage = (path) => /(^|[/\\])index\.mdx?$/i.test(path);
|
|
1803
|
+
var resolveRouteCollisions = (records) => {
|
|
1804
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
1805
|
+
for (const record of records) {
|
|
1806
|
+
const normalized = { ...record, url: record.url || "/" };
|
|
1807
|
+
const indexPage = isIndexPage(record.path);
|
|
1808
|
+
const existing = byUrl.get(normalized.url);
|
|
1809
|
+
if (!existing || indexPage || !existing.indexPage) {
|
|
1810
|
+
byUrl.set(normalized.url, { record: normalized, indexPage });
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
return [...byUrl.values()].map(({ record }) => record);
|
|
1814
|
+
};
|
|
1815
|
+
var nextraAdapter = {
|
|
1816
|
+
plugin: "nextra",
|
|
1817
|
+
scan: ({ root, config }) => {
|
|
1818
|
+
const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
|
|
1819
|
+
if (!contentDir) return [];
|
|
1820
|
+
return resolveRouteCollisions(
|
|
1821
|
+
scanMarkdownDocs(root, contentDir, {
|
|
1822
|
+
idForDoc: nextraRecordId,
|
|
1823
|
+
urlPrefix: optionString(config.options, ["urlPrefix", "contentDirBasePath"]) ?? "/"
|
|
1824
|
+
})
|
|
1825
|
+
);
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1828
|
+
|
|
1794
1829
|
// src/index-builder/human-adapters/plain-markdown.ts
|
|
1795
1830
|
var plainMarkdownAdapter = {
|
|
1796
1831
|
plugin: "plain-markdown",
|
|
@@ -1800,11 +1835,73 @@ var plainMarkdownAdapter = {
|
|
|
1800
1835
|
}
|
|
1801
1836
|
};
|
|
1802
1837
|
|
|
1838
|
+
// src/index-builder/human-adapters/starlight.ts
|
|
1839
|
+
import { slug as githubSlug } from "github-slugger";
|
|
1840
|
+
var isStarlightPage = (relPath, raw) => {
|
|
1841
|
+
if (relPath.split("/").some((part) => part.startsWith(".") || part.startsWith("_"))) return false;
|
|
1842
|
+
return parseFrontmatter2(raw).draft !== "true";
|
|
1843
|
+
};
|
|
1844
|
+
var starlightFileSlug = (relPath) => routeSlug(relPath).split("/").map((part) => githubSlug(part)).filter(Boolean).join("/");
|
|
1845
|
+
var starlightSlug = (relPath, raw) => {
|
|
1846
|
+
const slug2 = parseFrontmatter2(raw).slug;
|
|
1847
|
+
return slug2 ? slug2.replace(/^\/+|\/+$/g, "") : starlightFileSlug(relPath);
|
|
1848
|
+
};
|
|
1849
|
+
var starlightAdapter = {
|
|
1850
|
+
plugin: "starlight",
|
|
1851
|
+
scan: ({ root, config }) => {
|
|
1852
|
+
const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
|
|
1853
|
+
if (!contentDir) return [];
|
|
1854
|
+
return scanMarkdownDocs(root, contentDir, {
|
|
1855
|
+
includeRelPath: isStarlightPage,
|
|
1856
|
+
slugForDoc: starlightSlug,
|
|
1857
|
+
urlPrefix: config.options?.urlPrefix
|
|
1858
|
+
});
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1861
|
+
|
|
1862
|
+
// src/index-builder/human-adapters/vitepress.ts
|
|
1863
|
+
import { minimatch } from "minimatch";
|
|
1864
|
+
var isVitePressPage = (relPath) => !relPath.split("/").some((part) => part === ".vitepress" || part.startsWith("."));
|
|
1865
|
+
var srcExcludePatterns = (value) => {
|
|
1866
|
+
if (value === void 0) return [];
|
|
1867
|
+
if (!Array.isArray(value) || value.length > 64) {
|
|
1868
|
+
throw new Error("VitePress srcExclude must be an array of at most 64 glob patterns.");
|
|
1869
|
+
}
|
|
1870
|
+
return value.map((pattern) => {
|
|
1871
|
+
if (typeof pattern !== "string" || !pattern || pattern.length > 256 || pattern.includes("\0")) {
|
|
1872
|
+
throw new Error("Each VitePress srcExclude pattern must be a non-empty string up to 256 characters.");
|
|
1873
|
+
}
|
|
1874
|
+
return pattern;
|
|
1875
|
+
});
|
|
1876
|
+
};
|
|
1877
|
+
var isExcluded = (relPath, patterns) => patterns.some((pattern) => minimatch(relPath, pattern, { dot: true }));
|
|
1878
|
+
var vitepressSlug = (relPath, cleanUrls) => {
|
|
1879
|
+
const slug2 = routeSlug(relPath);
|
|
1880
|
+
if (cleanUrls || /(?:^|\/)index\.mdx?$/.test(relPath)) return slug2;
|
|
1881
|
+
return `${slug2}.html`;
|
|
1882
|
+
};
|
|
1883
|
+
var vitepressAdapter = {
|
|
1884
|
+
plugin: "vitepress",
|
|
1885
|
+
scan: ({ root, config }) => {
|
|
1886
|
+
const docsDir = optionString(config.options, ["docsDir", "root", "srcDir"]);
|
|
1887
|
+
if (!docsDir) return [];
|
|
1888
|
+
const srcExclude = srcExcludePatterns(config.options?.srcExclude);
|
|
1889
|
+
return scanMarkdownDocs(root, docsDir, {
|
|
1890
|
+
includeRelPath: (relPath) => isVitePressPage(relPath) && !isExcluded(relPath, srcExclude),
|
|
1891
|
+
slugForDoc: (relPath) => vitepressSlug(relPath, config.options?.cleanUrls === true),
|
|
1892
|
+
urlPrefix: config.options?.urlPrefix
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
|
|
1803
1897
|
// src/index-builder/human-adapters/index.ts
|
|
1804
1898
|
var ADAPTERS = [
|
|
1805
1899
|
plainMarkdownAdapter,
|
|
1806
1900
|
fumadocsAdapter,
|
|
1807
|
-
docusaurusAdapter
|
|
1901
|
+
docusaurusAdapter,
|
|
1902
|
+
vitepressAdapter,
|
|
1903
|
+
starlightAdapter,
|
|
1904
|
+
nextraAdapter
|
|
1808
1905
|
];
|
|
1809
1906
|
var humanConfigs = (config) => {
|
|
1810
1907
|
const human = config.corpus.human;
|
|
@@ -1839,12 +1936,121 @@ var scanHumanDocRecords = (root, config) => {
|
|
|
1839
1936
|
};
|
|
1840
1937
|
var scanHumanDocs = (root, config) => Object.fromEntries(scanHumanDocRecords(root, config).map((doc) => [doc.id, doc.url]));
|
|
1841
1938
|
|
|
1939
|
+
// src/index-builder/plugins/nx.ts
|
|
1940
|
+
import { existsSync as existsSync6, lstatSync as lstatSync2, readFileSync as readFileSync5, realpathSync as realpathSync5 } from "fs";
|
|
1941
|
+
import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve5, sep as sep4 } from "path";
|
|
1942
|
+
var NX_SCAN_SKIP = /* @__PURE__ */ new Set([
|
|
1943
|
+
"node_modules",
|
|
1944
|
+
".git",
|
|
1945
|
+
".nx",
|
|
1946
|
+
"dist",
|
|
1947
|
+
"coverage",
|
|
1948
|
+
".doc-bridge"
|
|
1949
|
+
]);
|
|
1950
|
+
var NX_PROJECT_NAME = /^(?:@[A-Za-z0-9._-]+\/)?[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
1951
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1952
|
+
var readJsonRecord = (path) => {
|
|
1953
|
+
try {
|
|
1954
|
+
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
1955
|
+
return isRecord(parsed) ? parsed : void 0;
|
|
1956
|
+
} catch {
|
|
1957
|
+
return void 0;
|
|
1958
|
+
}
|
|
1959
|
+
};
|
|
1960
|
+
var safeProjectPath = (root, manifestDir, declaredRoot) => {
|
|
1961
|
+
const candidate = typeof declaredRoot === "string" ? resolve5(root, declaredRoot) : manifestDir;
|
|
1962
|
+
const rel = toPosix(relative3(root, candidate)) || ".";
|
|
1963
|
+
if (isAbsolute3(rel) || rel === ".." || rel.startsWith("../")) return void 0;
|
|
1964
|
+
try {
|
|
1965
|
+
if (!lstatSync2(candidate).isDirectory()) return void 0;
|
|
1966
|
+
const canonicalRoot = realpathSync5.native(root);
|
|
1967
|
+
const canonicalCandidate = realpathSync5.native(candidate);
|
|
1968
|
+
const canonicalRel = relative3(canonicalRoot, canonicalCandidate);
|
|
1969
|
+
if (isAbsolute3(canonicalRel) || canonicalRel === ".." || canonicalRel.startsWith(`..${sep4}`)) {
|
|
1970
|
+
return void 0;
|
|
1971
|
+
}
|
|
1972
|
+
} catch {
|
|
1973
|
+
return void 0;
|
|
1974
|
+
}
|
|
1975
|
+
return rel;
|
|
1976
|
+
};
|
|
1977
|
+
var packageId = (name) => name.startsWith("@") ? name.split("/").at(-1) ?? name : name;
|
|
1978
|
+
var commandPrefix = (root) => {
|
|
1979
|
+
const manager = detectPackageManager(root);
|
|
1980
|
+
if (manager === "pnpm") return "pnpm exec nx run";
|
|
1981
|
+
if (manager === "yarn") return "yarn nx run";
|
|
1982
|
+
if (manager === "bun") return "bunx nx run";
|
|
1983
|
+
return "npx nx run";
|
|
1984
|
+
};
|
|
1985
|
+
var inferredChecks = (root, config, projectName2, targets) => {
|
|
1986
|
+
const prefix = commandPrefix(root);
|
|
1987
|
+
const strict = (config.gates?.preset ?? "minimal") !== "minimal";
|
|
1988
|
+
const checks = [
|
|
1989
|
+
...targets.has("test") ? [`${prefix} ${projectName2}:test`] : [],
|
|
1990
|
+
...strict && targets.has("lint") ? [`${prefix} ${projectName2}:lint`] : []
|
|
1991
|
+
];
|
|
1992
|
+
return checks.length ? checks : void 0;
|
|
1993
|
+
};
|
|
1994
|
+
var discoverNxProjects = (root, config) => {
|
|
1995
|
+
if (!existsSync6(resolve5(root, "nx.json"))) return [];
|
|
1996
|
+
const manifests = walkFiles(root, {
|
|
1997
|
+
extensions: ["project.json", "package.json"],
|
|
1998
|
+
skipDirs: NX_SCAN_SKIP,
|
|
1999
|
+
maxFiles: 1e4
|
|
2000
|
+
});
|
|
2001
|
+
const projects = /* @__PURE__ */ new Map();
|
|
2002
|
+
for (const manifest of manifests) {
|
|
2003
|
+
const json = readJsonRecord(manifest);
|
|
2004
|
+
if (!json) continue;
|
|
2005
|
+
const manifestDir = dirname3(manifest);
|
|
2006
|
+
const manifestName = basename2(manifest);
|
|
2007
|
+
const isProjectJson = manifestName === "project.json";
|
|
2008
|
+
if (!isProjectJson && manifestName !== "package.json") continue;
|
|
2009
|
+
const nx = json.nx;
|
|
2010
|
+
if (!isProjectJson && !isRecord(nx)) continue;
|
|
2011
|
+
const path = safeProjectPath(root, manifestDir, isProjectJson ? json.root : void 0);
|
|
2012
|
+
if (!path) continue;
|
|
2013
|
+
const projectPackage = isProjectJson ? readJsonRecord(resolve5(root, path, "package.json")) : void 0;
|
|
2014
|
+
const projectName2 = typeof json.name === "string" ? json.name : typeof projectPackage?.name === "string" ? projectPackage.name : basename2(path === "." ? root : path);
|
|
2015
|
+
if (!NX_PROJECT_NAME.test(projectName2)) continue;
|
|
2016
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2017
|
+
const targetRecord = isProjectJson ? json.targets : isRecord(nx) ? nx.targets : void 0;
|
|
2018
|
+
if (isRecord(targetRecord)) {
|
|
2019
|
+
for (const target of Object.keys(targetRecord)) targets.add(target);
|
|
2020
|
+
}
|
|
2021
|
+
if (!isProjectJson && isRecord(json.scripts)) {
|
|
2022
|
+
for (const script of Object.keys(json.scripts)) targets.add(script);
|
|
2023
|
+
}
|
|
2024
|
+
const id = packageId(projectName2);
|
|
2025
|
+
const rank = isProjectJson ? 2 : 1;
|
|
2026
|
+
const existing = projects.get(id);
|
|
2027
|
+
if (existing && existing.path !== path) {
|
|
2028
|
+
throw new Error(
|
|
2029
|
+
`Nx project identity collision for "${id}": "${existing.name ?? id}" at "${existing.path}" and "${projectName2}" at "${path}". Use unique Nx project names.`
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
2032
|
+
const mergedTargets = [.../* @__PURE__ */ new Set([...existing?.targets ?? [], ...targets])];
|
|
2033
|
+
const projectJsonWins = rank >= (existing?.rank ?? 0);
|
|
2034
|
+
const resolvedName = projectJsonWins ? projectName2 : existing?.name ?? projectName2;
|
|
2035
|
+
const checks = inferredChecks(root, config, resolvedName, new Set(mergedTargets));
|
|
2036
|
+
projects.set(id, {
|
|
2037
|
+
id,
|
|
2038
|
+
path,
|
|
2039
|
+
name: resolvedName,
|
|
2040
|
+
...checks ? { checks } : {},
|
|
2041
|
+
rank: projectJsonWins ? rank : existing?.rank ?? rank,
|
|
2042
|
+
targets: mergedTargets
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
return [...projects.values()].sort((a, b) => a.id.localeCompare(b.id)).map(({ rank: _rank, targets: _targets, ...project }) => project);
|
|
2046
|
+
};
|
|
2047
|
+
|
|
1842
2048
|
// src/index-builder/plugins/pnpm-monorepo.ts
|
|
1843
|
-
import { existsSync as
|
|
1844
|
-
import { basename as
|
|
2049
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
2050
|
+
import { basename as basename3, join as join6 } from "path";
|
|
1845
2051
|
|
|
1846
2052
|
// src/lib/glob-expand.ts
|
|
1847
|
-
import { existsSync as
|
|
2053
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
1848
2054
|
import { join as join5 } from "path";
|
|
1849
2055
|
var expandWorkspaceGlobs = (root, patterns) => {
|
|
1850
2056
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -1852,12 +2058,12 @@ var expandWorkspaceGlobs = (root, patterns) => {
|
|
|
1852
2058
|
const normalized = toPosix(pattern).replace(/\/$/, "");
|
|
1853
2059
|
if (!normalized.includes("*")) {
|
|
1854
2060
|
const abs = join5(root, normalized);
|
|
1855
|
-
if (
|
|
2061
|
+
if (existsSync7(abs)) dirs.add(toPosix(abs));
|
|
1856
2062
|
continue;
|
|
1857
2063
|
}
|
|
1858
2064
|
const star = normalized.indexOf("*");
|
|
1859
2065
|
const base = join5(root, normalized.slice(0, star).replace(/\/$/, ""));
|
|
1860
|
-
if (!
|
|
2066
|
+
if (!existsSync7(base)) continue;
|
|
1861
2067
|
for (const name of readdirSync2(base)) {
|
|
1862
2068
|
const abs = join5(base, name);
|
|
1863
2069
|
try {
|
|
@@ -1892,9 +2098,9 @@ var parsePnpmWorkspace = (yaml) => {
|
|
|
1892
2098
|
};
|
|
1893
2099
|
var readPackageJson = (dir) => {
|
|
1894
2100
|
const file = join6(dir, "package.json");
|
|
1895
|
-
if (!
|
|
2101
|
+
if (!existsSync8(file)) return null;
|
|
1896
2102
|
try {
|
|
1897
|
-
return JSON.parse(
|
|
2103
|
+
return JSON.parse(readFileSync6(file, "utf8"));
|
|
1898
2104
|
} catch {
|
|
1899
2105
|
return null;
|
|
1900
2106
|
}
|
|
@@ -1904,8 +2110,8 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1904
2110
|
let patterns = explicit;
|
|
1905
2111
|
if (!patterns?.length) {
|
|
1906
2112
|
const workspaceFile = join6(root, "pnpm-workspace.yaml");
|
|
1907
|
-
if (
|
|
1908
|
-
patterns = parsePnpmWorkspace(
|
|
2113
|
+
if (existsSync8(workspaceFile)) {
|
|
2114
|
+
patterns = parsePnpmWorkspace(readFileSync6(workspaceFile, "utf8"));
|
|
1909
2115
|
}
|
|
1910
2116
|
}
|
|
1911
2117
|
if (!patterns?.length) return [];
|
|
@@ -1915,7 +2121,7 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1915
2121
|
const pkg = readPackageJson(abs);
|
|
1916
2122
|
if (!pkg) continue;
|
|
1917
2123
|
const rel = toPosix(abs.replace(`${toPosix(root)}/`, ""));
|
|
1918
|
-
const folderId =
|
|
2124
|
+
const folderId = basename3(abs);
|
|
1919
2125
|
const id = pkg.name?.startsWith("@") ? pkg.name.split("/").pop() ?? folderId : pkg.name ?? folderId;
|
|
1920
2126
|
out.push({ id, path: rel, ...pkg.name ? { name: pkg.name } : {} });
|
|
1921
2127
|
}
|
|
@@ -1926,7 +2132,7 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1926
2132
|
var projectName = (root, config) => {
|
|
1927
2133
|
if (config.project?.name) return config.project.name;
|
|
1928
2134
|
try {
|
|
1929
|
-
const pkg = JSON.parse(
|
|
2135
|
+
const pkg = JSON.parse(readFileSync7(join7(root, "package.json"), "utf8"));
|
|
1930
2136
|
if (pkg.name) return pkg.name;
|
|
1931
2137
|
} catch {
|
|
1932
2138
|
}
|
|
@@ -1934,7 +2140,7 @@ var projectName = (root, config) => {
|
|
|
1934
2140
|
};
|
|
1935
2141
|
var existingGeneratedAt = (indexPath, contentHash) => {
|
|
1936
2142
|
try {
|
|
1937
|
-
const index = JSON.parse(
|
|
2143
|
+
const index = JSON.parse(readFileSync7(indexPath, "utf8"));
|
|
1938
2144
|
return index.contentHash === contentHash && typeof index.generatedAt === "string" ? index.generatedAt : void 0;
|
|
1939
2145
|
} catch {
|
|
1940
2146
|
return void 0;
|
|
@@ -1949,7 +2155,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1949
2155
|
const corpus = scanAgentCorpus(root, config);
|
|
1950
2156
|
const knowledge = corpus.map(({ absPath: _a, relPath: _r, frontmatter: _f, ...entry }) => entry);
|
|
1951
2157
|
const shouldDiscover = config.routing?.plugin === "pnpm-monorepo" || Boolean(config.routing?.options?.packages?.length) || config.routing?.plugin === "npm-workspaces" || config.routing?.plugin === "yarn-workspaces";
|
|
1952
|
-
const discovered = shouldDiscover ? discoverPnpmPackages(root, config) : [];
|
|
2158
|
+
const discovered = config.routing?.plugin === "nx" ? discoverNxProjects(root, config) : shouldDiscover ? discoverPnpmPackages(root, config) : [];
|
|
1953
2159
|
const packages = collectPackages(config, discovered, corpus);
|
|
1954
2160
|
const humanDocs = scanHumanDocs(root, config);
|
|
1955
2161
|
const { lookup, handoffs } = buildLookup(config, packages, corpus, outFile, humanDocs, root);
|
|
@@ -1971,7 +2177,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1971
2177
|
lookup
|
|
1972
2178
|
};
|
|
1973
2179
|
if (write) {
|
|
1974
|
-
mkdirSync(
|
|
2180
|
+
mkdirSync(dirname4(indexPath), { recursive: true });
|
|
1975
2181
|
writeFileSync(indexPath, `${JSON.stringify(index, null, 2)}
|
|
1976
2182
|
`, "utf8");
|
|
1977
2183
|
}
|
|
@@ -1994,7 +2200,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1994
2200
|
const capabilitiesOut = config.index?.capabilities?.outFile ?? ".doc-bridge/capabilities.json";
|
|
1995
2201
|
capabilitiesPath = join7(root, capabilitiesOut);
|
|
1996
2202
|
if (write) {
|
|
1997
|
-
mkdirSync(
|
|
2203
|
+
mkdirSync(dirname4(capabilitiesPath), { recursive: true });
|
|
1998
2204
|
writeFileSync(
|
|
1999
2205
|
capabilitiesPath,
|
|
2000
2206
|
renderCapabilitiesJson(config, index, {
|
|
@@ -2040,11 +2246,11 @@ function formatEcosystemLlmsSection(options) {
|
|
|
2040
2246
|
}
|
|
2041
2247
|
|
|
2042
2248
|
// src/gates/run-gates.ts
|
|
2043
|
-
import { readFileSync as
|
|
2249
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
2044
2250
|
|
|
2045
2251
|
// src/conformance/documentation-standard-v1.ts
|
|
2046
|
-
import { existsSync as
|
|
2047
|
-
import { isAbsolute as
|
|
2252
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync as realpathSync6, statSync as statSync3 } from "fs";
|
|
2253
|
+
import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve6, sep as sep5 } from "path";
|
|
2048
2254
|
|
|
2049
2255
|
// src/conformance/ecosystem-contract.ts
|
|
2050
2256
|
import { z as z5 } from "zod";
|
|
@@ -2223,15 +2429,15 @@ var DOCUMENTATION_STANDARD_V1_ID = "documentation-standard-v1";
|
|
|
2223
2429
|
var DOCUMENTATION_STANDARD_V1_STATUS = "stable";
|
|
2224
2430
|
var MAX_TEXT_EVIDENCE_BYTES = 4 * 1024 * 1024;
|
|
2225
2431
|
var safePath = (root, path) => {
|
|
2226
|
-
const rootAbs =
|
|
2227
|
-
const unresolved =
|
|
2228
|
-
const unresolvedRel =
|
|
2229
|
-
if (
|
|
2230
|
-
if (!
|
|
2432
|
+
const rootAbs = realpathSync6.native(resolve6(root));
|
|
2433
|
+
const unresolved = resolve6(rootAbs, path);
|
|
2434
|
+
const unresolvedRel = relative4(rootAbs, unresolved);
|
|
2435
|
+
if (isAbsolute4(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep5}`)) return void 0;
|
|
2436
|
+
if (!existsSync9(unresolved)) return unresolved;
|
|
2231
2437
|
try {
|
|
2232
|
-
const abs =
|
|
2233
|
-
const rel =
|
|
2234
|
-
return !
|
|
2438
|
+
const abs = realpathSync6.native(unresolved);
|
|
2439
|
+
const rel = relative4(rootAbs, abs);
|
|
2440
|
+
return !isAbsolute4(rel) && rel !== ".." && !rel.startsWith(`..${sep5}`) ? abs : void 0;
|
|
2235
2441
|
} catch {
|
|
2236
2442
|
return void 0;
|
|
2237
2443
|
}
|
|
@@ -2245,7 +2451,7 @@ var fileEvidence = (root, path, options) => {
|
|
|
2245
2451
|
evidence: { path, detail: "Path escapes the project root." }
|
|
2246
2452
|
};
|
|
2247
2453
|
}
|
|
2248
|
-
if (!
|
|
2454
|
+
if (!existsSync9(abs)) {
|
|
2249
2455
|
return { exists: false, content: "", evidence: { path, detail: "File does not exist." } };
|
|
2250
2456
|
}
|
|
2251
2457
|
try {
|
|
@@ -2260,7 +2466,7 @@ var fileEvidence = (root, path, options) => {
|
|
|
2260
2466
|
return {
|
|
2261
2467
|
exists: true,
|
|
2262
2468
|
content: "",
|
|
2263
|
-
evidence: { path: toPosix(
|
|
2469
|
+
evidence: { path: toPosix(relative4(resolve6(root), abs)) || ".", detail: "File exists and is non-empty." }
|
|
2264
2470
|
};
|
|
2265
2471
|
}
|
|
2266
2472
|
if (stat.size > MAX_TEXT_EVIDENCE_BYTES) {
|
|
@@ -2270,12 +2476,12 @@ var fileEvidence = (root, path, options) => {
|
|
|
2270
2476
|
evidence: { path, detail: `Text evidence exceeds ${MAX_TEXT_EVIDENCE_BYTES} bytes.` }
|
|
2271
2477
|
};
|
|
2272
2478
|
}
|
|
2273
|
-
const content =
|
|
2479
|
+
const content = readFileSync8(abs, "utf8");
|
|
2274
2480
|
return {
|
|
2275
2481
|
exists: content.trim().length > 0,
|
|
2276
2482
|
content,
|
|
2277
2483
|
evidence: {
|
|
2278
|
-
path: toPosix(
|
|
2484
|
+
path: toPosix(relative4(resolve6(root), abs)) || ".",
|
|
2279
2485
|
detail: content.trim().length > 0 ? "File exists and is non-empty." : "File is empty."
|
|
2280
2486
|
}
|
|
2281
2487
|
};
|
|
@@ -2310,7 +2516,7 @@ var humanDocsRule = (root, config) => {
|
|
|
2310
2516
|
passed: docs.length > 0,
|
|
2311
2517
|
message: docs.length > 0 ? `Found ${docs.length} human document(s).` : "No human documentation was discovered.",
|
|
2312
2518
|
evidence: docs.slice(0, 10).map((doc) => ({
|
|
2313
|
-
path: toPosix(
|
|
2519
|
+
path: toPosix(relative4(resolve6(root), doc.path)),
|
|
2314
2520
|
detail: `Human route: ${doc.url}`
|
|
2315
2521
|
})),
|
|
2316
2522
|
remediation: {
|
|
@@ -2321,10 +2527,10 @@ var humanDocsRule = (root, config) => {
|
|
|
2321
2527
|
};
|
|
2322
2528
|
var llmsRule = (root, config, options) => {
|
|
2323
2529
|
const llmsPath = config.index?.llmsTxt?.outFile ?? "llms.txt";
|
|
2324
|
-
const llmsKey = safePath(root, llmsPath) ??
|
|
2530
|
+
const llmsKey = safePath(root, llmsPath) ?? resolve6(root, llmsPath);
|
|
2325
2531
|
const rawSources = /* @__PURE__ */ new Map();
|
|
2326
2532
|
for (const path of options.rawSources ?? []) {
|
|
2327
|
-
const key = safePath(root, path) ??
|
|
2533
|
+
const key = safePath(root, path) ?? resolve6(root, path);
|
|
2328
2534
|
if (key !== llmsKey && !rawSources.has(key)) rawSources.set(key, path);
|
|
2329
2535
|
}
|
|
2330
2536
|
const paths = [llmsPath, ...rawSources.values()];
|
|
@@ -2576,8 +2782,8 @@ var formatDocumentationStandardText = (report) => [
|
|
|
2576
2782
|
];
|
|
2577
2783
|
|
|
2578
2784
|
// src/query/load-index.ts
|
|
2579
|
-
import { existsSync as
|
|
2580
|
-
import { join as join8, resolve as
|
|
2785
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
2786
|
+
import { join as join8, resolve as resolve7 } from "path";
|
|
2581
2787
|
var IndexNotFoundError = class extends Error {
|
|
2582
2788
|
constructor(path) {
|
|
2583
2789
|
super(`Missing index at ${path}. Run: ak-docs index`);
|
|
@@ -2589,11 +2795,11 @@ var IndexNotFoundError = class extends Error {
|
|
|
2589
2795
|
var indexFilePath = (root, config) => join8(root, config.index?.outFile ?? ".doc-bridge/index.json");
|
|
2590
2796
|
var loadDocBridgeIndex = (root, config) => {
|
|
2591
2797
|
const path = indexFilePath(root, config);
|
|
2592
|
-
if (!
|
|
2593
|
-
const raw = JSON.parse(
|
|
2798
|
+
if (!existsSync10(path)) throw new IndexNotFoundError(path);
|
|
2799
|
+
const raw = JSON.parse(readFileSync9(path, "utf8"));
|
|
2594
2800
|
return parseDocBridgeIndex(raw);
|
|
2595
2801
|
};
|
|
2596
|
-
var resolveRoot = (cwd) =>
|
|
2802
|
+
var resolveRoot = (cwd) => resolve7(cwd ?? process.cwd());
|
|
2597
2803
|
|
|
2598
2804
|
// src/gates/run-gates.ts
|
|
2599
2805
|
var RESERVED_GATE_IDS = /* @__PURE__ */ new Set(["link-rot", "routing-currency", "bootstrap-size"]);
|
|
@@ -2666,7 +2872,7 @@ var runOkfTypeGate = (root, config) => {
|
|
|
2666
2872
|
const required = config.corpus.agent.okf?.requireType ?? config.gates?.preset === "strict";
|
|
2667
2873
|
if (!required) return { id: "okf-type", ok: true, message: "OKF type frontmatter not required" };
|
|
2668
2874
|
const allowed = config.corpus.agent.okf?.allowedTypes;
|
|
2669
|
-
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(
|
|
2875
|
+
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync10(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
|
|
2670
2876
|
if (bad.length) {
|
|
2671
2877
|
return {
|
|
2672
2878
|
id: "okf-type",
|
|
@@ -2693,10 +2899,10 @@ var DOCS_STYLE_RULES = {
|
|
|
2693
2899
|
"playbook-okf-soft": ["title", "no-stale-wording"],
|
|
2694
2900
|
"title-only": ["title"]
|
|
2695
2901
|
};
|
|
2696
|
-
var
|
|
2902
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2697
2903
|
var docsStyleOptions = (config) => {
|
|
2698
2904
|
const raw = config.gates?.options?.["docs-style"];
|
|
2699
|
-
if (!
|
|
2905
|
+
if (!isRecord2(raw)) {
|
|
2700
2906
|
if (config.gates?.preset === "playbook") {
|
|
2701
2907
|
return { profile: "playbook-okf-soft", required: DOCS_STYLE_RULES["playbook-okf-soft"] };
|
|
2702
2908
|
}
|
|
@@ -2740,7 +2946,7 @@ var runDocsStyleGate = (root, config) => {
|
|
|
2740
2946
|
}
|
|
2741
2947
|
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({
|
|
2742
2948
|
path: doc.path,
|
|
2743
|
-
missing: missingStyleRules(
|
|
2949
|
+
missing: missingStyleRules(readFileSync10(doc.absPath, "utf8"), required)
|
|
2744
2950
|
})).filter((doc) => doc.missing.length > 0);
|
|
2745
2951
|
if (bad.length) {
|
|
2746
2952
|
return {
|
|
@@ -2785,8 +2991,8 @@ var resolveGateIds = (config) => {
|
|
|
2785
2991
|
};
|
|
2786
2992
|
|
|
2787
2993
|
// src/mcp/server.ts
|
|
2788
|
-
import { readFileSync as
|
|
2789
|
-
import { relative as
|
|
2994
|
+
import { readFileSync as readFileSync12, realpathSync as realpathSync7 } from "fs";
|
|
2995
|
+
import { relative as relative5, resolve as resolve8 } from "path";
|
|
2790
2996
|
import { z as z6, ZodError } from "zod";
|
|
2791
2997
|
|
|
2792
2998
|
// src/query/search.ts
|
|
@@ -2905,15 +3111,15 @@ var createDocBridgeRetriever = (index, options = {}) => ({
|
|
|
2905
3111
|
});
|
|
2906
3112
|
|
|
2907
3113
|
// src/memory/ingest.ts
|
|
2908
|
-
import { existsSync as
|
|
3114
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11 } from "fs";
|
|
2909
3115
|
import { join as join9 } from "path";
|
|
2910
3116
|
var memoryFact = (raw, id) => firstParagraph(raw) ?? firstHeading(raw) ?? id;
|
|
2911
3117
|
var relativePath = (root, abs) => toPosix(abs).replace(`${toPosix(root)}/`, "");
|
|
2912
3118
|
var ingestMarkdownDir = (root, dir, source, confidence) => {
|
|
2913
|
-
if (!
|
|
3119
|
+
if (!existsSync11(dir)) return [];
|
|
2914
3120
|
return walkFiles(dir, { extensions: [".md", ".mdc"] }).map((abs) => {
|
|
2915
3121
|
const rel = relativePath(root, abs);
|
|
2916
|
-
const raw =
|
|
3122
|
+
const raw = readFileSync11(abs, "utf8");
|
|
2917
3123
|
const id = slugFromPath(rel);
|
|
2918
3124
|
return {
|
|
2919
3125
|
schemaVersion: 1,
|
|
@@ -3247,12 +3453,12 @@ var findDocPath = (index, args) => {
|
|
|
3247
3453
|
return doc.path;
|
|
3248
3454
|
};
|
|
3249
3455
|
var resolveDocPath = (root, relPath) => {
|
|
3250
|
-
const rootAbs =
|
|
3251
|
-
const unresolved =
|
|
3252
|
-
const unresolvedRel =
|
|
3456
|
+
const rootAbs = realpathSync7.native(root);
|
|
3457
|
+
const unresolved = resolve8(rootAbs, relPath);
|
|
3458
|
+
const unresolvedRel = relative5(rootAbs, unresolved);
|
|
3253
3459
|
if (unresolvedRel.startsWith("..")) throw new Error("doc.get path escapes project root");
|
|
3254
|
-
const abs =
|
|
3255
|
-
const rel =
|
|
3460
|
+
const abs = realpathSync7.native(unresolved);
|
|
3461
|
+
const rel = relative5(rootAbs, abs);
|
|
3256
3462
|
if (rel.startsWith("..")) throw new Error("doc.get path escapes project root");
|
|
3257
3463
|
return abs;
|
|
3258
3464
|
};
|
|
@@ -3286,7 +3492,7 @@ var handleMcpRequest = (ctx, request) => {
|
|
|
3286
3492
|
}
|
|
3287
3493
|
if (name === "doc.get") {
|
|
3288
3494
|
const relPath = findDocPath(index(), parseToolArgs("doc.get", DocGetArgsSchema, args));
|
|
3289
|
-
return textResult(
|
|
3495
|
+
return textResult(readFileSync12(resolveDocPath(ctx.root, relPath), "utf8"));
|
|
3290
3496
|
}
|
|
3291
3497
|
if (name === "gate.status") return textResult(runGates(ctx.root, ctx.config));
|
|
3292
3498
|
if (name === "retriever.query") {
|
|
@@ -3378,9 +3584,9 @@ var startMcpStdioServer = (ctx) => {
|
|
|
3378
3584
|
};
|
|
3379
3585
|
|
|
3380
3586
|
// src/mcp/install.ts
|
|
3381
|
-
import { existsSync as
|
|
3587
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync2, readFileSync as readFileSync13, writeFileSync as writeFileSync2 } from "fs";
|
|
3382
3588
|
import { homedir } from "os";
|
|
3383
|
-
import { dirname as
|
|
3589
|
+
import { dirname as dirname5, join as join10, resolve as resolve9 } from "path";
|
|
3384
3590
|
var SERVER_NAME = "ak-docs";
|
|
3385
3591
|
var mcpServerEntry = (root) => ({
|
|
3386
3592
|
command: "npx",
|
|
@@ -3388,26 +3594,26 @@ var mcpServerEntry = (root) => ({
|
|
|
3388
3594
|
cwd: root
|
|
3389
3595
|
});
|
|
3390
3596
|
var readJson = (path) => {
|
|
3391
|
-
if (!
|
|
3597
|
+
if (!existsSync12(path)) return {};
|
|
3392
3598
|
try {
|
|
3393
|
-
const parsed = JSON.parse(
|
|
3599
|
+
const parsed = JSON.parse(readFileSync13(path, "utf8"));
|
|
3394
3600
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
3395
3601
|
} catch {
|
|
3396
3602
|
return {};
|
|
3397
3603
|
}
|
|
3398
3604
|
};
|
|
3399
3605
|
var writeJson = (path, value) => {
|
|
3400
|
-
mkdirSync2(
|
|
3606
|
+
mkdirSync2(dirname5(path), { recursive: true });
|
|
3401
3607
|
writeFileSync2(path, `${JSON.stringify(value, null, 2)}
|
|
3402
3608
|
`, "utf8");
|
|
3403
3609
|
};
|
|
3404
3610
|
var resolveTargetPath = (target, root) => {
|
|
3405
|
-
if (target === "cursor") return
|
|
3611
|
+
if (target === "cursor") return resolve9(root, ".cursor", "mcp.json");
|
|
3406
3612
|
return join10(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
3407
3613
|
};
|
|
3408
3614
|
var installMcpConfig = (root, target) => {
|
|
3409
3615
|
const configPath = resolveTargetPath(target, root);
|
|
3410
|
-
const created = !
|
|
3616
|
+
const created = !existsSync12(configPath);
|
|
3411
3617
|
const existing = readJson(configPath);
|
|
3412
3618
|
const servers = existing.mcpServers && typeof existing.mcpServers === "object" && !Array.isArray(existing.mcpServers) ? { ...existing.mcpServers } : {};
|
|
3413
3619
|
servers[SERVER_NAME] = mcpServerEntry(root);
|
|
@@ -3673,22 +3879,23 @@ var formatDoctorText = (report) => {
|
|
|
3673
3879
|
};
|
|
3674
3880
|
|
|
3675
3881
|
// src/index-builder/watch-index.ts
|
|
3676
|
-
import { existsSync as
|
|
3677
|
-
import { dirname as
|
|
3882
|
+
import { existsSync as existsSync13, watch } from "fs";
|
|
3883
|
+
import { dirname as dirname6, resolve as resolve10 } from "path";
|
|
3678
3884
|
var WATCH_PATTERN = /\.(md|mdx|json|ya?ml|mdc)$/i;
|
|
3885
|
+
var NX_MANIFEST_PATTERN = /(^|[/\\])(project|package)\.json$/i;
|
|
3679
3886
|
var collectWatchRoots = (root, config, configPath) => {
|
|
3680
3887
|
const roots = /* @__PURE__ */ new Set();
|
|
3681
|
-
roots.add(
|
|
3888
|
+
roots.add(resolve10(root, config.corpus.agent.root));
|
|
3682
3889
|
const humanSources = config.corpus.human ? Array.isArray(config.corpus.human) ? config.corpus.human : [config.corpus.human] : [];
|
|
3683
3890
|
for (const source of humanSources) {
|
|
3684
3891
|
const humanOpts = source.options ?? {};
|
|
3685
|
-
for (const key of ["contentDir", "docsDir", "root"]) {
|
|
3892
|
+
for (const key of ["contentDir", "docsDir", "root", "srcDir"]) {
|
|
3686
3893
|
const value = humanOpts[key];
|
|
3687
|
-
if (typeof value === "string" && value.length) roots.add(
|
|
3894
|
+
if (typeof value === "string" && value.length) roots.add(resolve10(root, value));
|
|
3688
3895
|
}
|
|
3689
3896
|
}
|
|
3690
|
-
if (configPath) roots.add(
|
|
3691
|
-
return [...roots].filter((dir) =>
|
|
3897
|
+
if (configPath) roots.add(dirname6(resolve10(configPath)));
|
|
3898
|
+
return [...roots].filter((dir) => existsSync13(dir));
|
|
3692
3899
|
};
|
|
3693
3900
|
var watchDocBridgeIndex = (opts) => {
|
|
3694
3901
|
const debounceMs = opts.debounceMs ?? 350;
|
|
@@ -3729,8 +3936,15 @@ var watchDocBridgeIndex = (opts) => {
|
|
|
3729
3936
|
rebuild();
|
|
3730
3937
|
});
|
|
3731
3938
|
}
|
|
3732
|
-
const
|
|
3733
|
-
if (
|
|
3939
|
+
const nxRoot = resolve10(opts.root);
|
|
3940
|
+
if (opts.config.routing?.plugin === "nx" && existsSync13(nxRoot)) {
|
|
3941
|
+
watch(nxRoot, { recursive: true }, (_event, filename) => {
|
|
3942
|
+
if (!filename || !NX_MANIFEST_PATTERN.test(filename)) return;
|
|
3943
|
+
rebuild();
|
|
3944
|
+
});
|
|
3945
|
+
}
|
|
3946
|
+
const configDir = resolve10(opts.root);
|
|
3947
|
+
if (existsSync13(configDir)) {
|
|
3734
3948
|
watch(configDir, (_event, filename) => {
|
|
3735
3949
|
if (!filename || !/doc-bridge\.config/.test(filename)) return;
|
|
3736
3950
|
rebuild();
|
|
@@ -3749,7 +3963,7 @@ var watchDocBridgeIndex = (opts) => {
|
|
|
3749
3963
|
|
|
3750
3964
|
// src/memory/github-pr.ts
|
|
3751
3965
|
import { execFileSync, spawnSync } from "child_process";
|
|
3752
|
-
import { existsSync as
|
|
3966
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
3753
3967
|
import { join as join12 } from "path";
|
|
3754
3968
|
var run = (cmd, args, cwd) => {
|
|
3755
3969
|
const result = spawnSync(cmd, [...args], { cwd, encoding: "utf8" });
|
|
@@ -3797,7 +4011,7 @@ var promoteMemoryToGithubPr = (root, draft, options = {}) => {
|
|
|
3797
4011
|
message: `Wrote draft to ${relDraft}. Run the printed git/gh commands to open a draft PR.`
|
|
3798
4012
|
};
|
|
3799
4013
|
}
|
|
3800
|
-
if (!
|
|
4014
|
+
if (!existsSync14(join12(root, ".git"))) {
|
|
3801
4015
|
return {
|
|
3802
4016
|
ok: false,
|
|
3803
4017
|
dryRun: false,
|
|
@@ -3900,8 +4114,8 @@ ${auth.out}`
|
|
|
3900
4114
|
};
|
|
3901
4115
|
|
|
3902
4116
|
// src/federation/llms.ts
|
|
3903
|
-
import { existsSync as
|
|
3904
|
-
import { resolve as
|
|
4117
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
|
|
4118
|
+
import { resolve as resolve11 } from "path";
|
|
3905
4119
|
var tokenize2 = (value) => value.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length >= 2);
|
|
3906
4120
|
var scoreText = (query, text) => {
|
|
3907
4121
|
const hay = text.toLowerCase();
|
|
@@ -3916,9 +4130,9 @@ var defaultFetchText = async (url) => {
|
|
|
3916
4130
|
var sourceText = async (root, source, fetchText) => {
|
|
3917
4131
|
try {
|
|
3918
4132
|
if (/^https?:\/\//.test(source)) return await fetchText(source);
|
|
3919
|
-
const path =
|
|
3920
|
-
if (!
|
|
3921
|
-
return
|
|
4133
|
+
const path = resolve11(root, source);
|
|
4134
|
+
if (!existsSync15(path)) return null;
|
|
4135
|
+
return readFileSync14(path, "utf8");
|
|
3922
4136
|
} catch {
|
|
3923
4137
|
return null;
|
|
3924
4138
|
}
|
|
@@ -4003,7 +4217,7 @@ var retrieveHybridChunks = async (root, config, index, query, options = {}) => {
|
|
|
4003
4217
|
};
|
|
4004
4218
|
|
|
4005
4219
|
// src/intelligence/rag.ts
|
|
4006
|
-
import { readFileSync as
|
|
4220
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
4007
4221
|
import { join as join14 } from "path";
|
|
4008
4222
|
|
|
4009
4223
|
// src/intelligence/adapter.ts
|
|
@@ -4145,7 +4359,7 @@ var loadDocuments = (root, index, sources) => {
|
|
|
4145
4359
|
const abs = join14(root, entry.path);
|
|
4146
4360
|
let content = "";
|
|
4147
4361
|
try {
|
|
4148
|
-
content =
|
|
4362
|
+
content = readFileSync15(abs, "utf8");
|
|
4149
4363
|
} catch {
|
|
4150
4364
|
content = [entry.title, entry.description].filter(Boolean).join("\n\n");
|
|
4151
4365
|
}
|
|
@@ -4455,6 +4669,7 @@ export {
|
|
|
4455
4669
|
createDocBridgeRetriever,
|
|
4456
4670
|
defaultPromotionDraftPath,
|
|
4457
4671
|
defineConfig,
|
|
4672
|
+
discoverNxProjects,
|
|
4458
4673
|
docBridgePatternMarkdown,
|
|
4459
4674
|
docBridgePatternPayload,
|
|
4460
4675
|
doctorBadgeMetrics,
|