@agentskit/doc-bridge 1.2.4 → 1.3.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 +21 -0
- package/CONTRIBUTING.md +6 -0
- package/PRIVACY.md +38 -0
- package/README.md +30 -3
- package/SECURITY.md +7 -2
- package/action.yml +1 -1
- package/dist/cli/program.js +400 -156
- 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 +47 -12
- package/dist/index.js +376 -131
- package/dist/index.js.map +1 -1
- package/docs/POSITIONING.md +1 -1
- package/docs/examples.md +4 -0
- package/docs/getting-started.md +1 -1
- package/docs/landing/index.html +1 -1
- package/docs/mcp.md +16 -0
- package/docs/qa/vitepress-starlight-adapters.md +19 -0
- 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/.mcpbignore +8 -0
- package/mcpb/icon.png +0 -0
- package/mcpb/manifest.json +96 -0
- package/package.json +14 -11
- 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/mcp/server.ts +58 -26
- package/src/version.ts +1 -1
package/dist/cli/program.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/cli/program.ts
|
|
2
|
-
import { existsSync as
|
|
3
|
-
import { dirname as
|
|
2
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync4 } from "fs";
|
|
3
|
+
import { dirname as dirname8, resolve as resolve13 } from "path";
|
|
4
4
|
import { createInterface } from "readline/promises";
|
|
5
5
|
|
|
6
6
|
// src/config/load-config.ts
|
|
@@ -333,6 +333,8 @@ var HumanCorpusPluginIdSchema = z.enum([
|
|
|
333
333
|
"docusaurus",
|
|
334
334
|
"mkdocs",
|
|
335
335
|
"vitepress",
|
|
336
|
+
"starlight",
|
|
337
|
+
"nextra",
|
|
336
338
|
"custom"
|
|
337
339
|
]);
|
|
338
340
|
var AgentCorpusConfigSchema = z.object({
|
|
@@ -372,7 +374,7 @@ var OwnershipEntrySchema = z.object({
|
|
|
372
374
|
humanDoc: z.string().min(1).max(512).optional()
|
|
373
375
|
}).strict();
|
|
374
376
|
var RoutingConfigSchema = z.object({
|
|
375
|
-
plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "pattern-files", "custom"]).optional(),
|
|
377
|
+
plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "nx", "pattern-files", "custom"]).optional(),
|
|
376
378
|
options: z.object({
|
|
377
379
|
packages: z.array(z.string().min(1).max(256)).max(128).optional(),
|
|
378
380
|
/** Infer ownership from corpus paths/frontmatter (default true). */
|
|
@@ -665,8 +667,8 @@ var projectRootFromConfigPath = (configFilePath, projectRootField) => {
|
|
|
665
667
|
};
|
|
666
668
|
|
|
667
669
|
// src/conformance/documentation-standard-v1.ts
|
|
668
|
-
import { existsSync as
|
|
669
|
-
import { isAbsolute as
|
|
670
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync as realpathSync6, statSync as statSync3 } from "fs";
|
|
671
|
+
import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve6, sep as sep5 } from "path";
|
|
670
672
|
|
|
671
673
|
// src/conformance/ecosystem-contract.ts
|
|
672
674
|
import { z as z2 } from "zod";
|
|
@@ -841,8 +843,8 @@ var parseCanonicalEcosystemContract = (manifestInput, claimsInput) => {
|
|
|
841
843
|
};
|
|
842
844
|
|
|
843
845
|
// src/index-builder/build-index.ts
|
|
844
|
-
import { mkdirSync, readFileSync as
|
|
845
|
-
import { dirname as
|
|
846
|
+
import { mkdirSync, readFileSync as readFileSync7, writeFileSync } from "fs";
|
|
847
|
+
import { dirname as dirname4, join as join7 } from "path";
|
|
846
848
|
|
|
847
849
|
// src/lib/paths.ts
|
|
848
850
|
import { existsSync as existsSync2, realpathSync } from "fs";
|
|
@@ -1111,17 +1113,17 @@ var scanAgentCorpus = (root, config) => {
|
|
|
1111
1113
|
};
|
|
1112
1114
|
});
|
|
1113
1115
|
};
|
|
1114
|
-
var guessAgentDocForPackage = (corpus,
|
|
1116
|
+
var guessAgentDocForPackage = (corpus, packageId2) => {
|
|
1115
1117
|
const candidates = [
|
|
1116
|
-
(doc) => frontmatterString(doc.frontmatter, "package") ===
|
|
1117
|
-
(doc) => doc.id ===
|
|
1118
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1119
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1120
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1121
|
-
(doc) => doc.relPath.endsWith(`/packages/${
|
|
1122
|
-
(doc) => doc.relPath.endsWith(`/${
|
|
1123
|
-
(doc) => doc.relPath.endsWith(`/${
|
|
1124
|
-
(doc) => doc.relPath.includes(`/packages/${
|
|
1118
|
+
(doc) => frontmatterString(doc.frontmatter, "package") === packageId2,
|
|
1119
|
+
(doc) => doc.id === packageId2,
|
|
1120
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}.md`),
|
|
1121
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}.mdx`),
|
|
1122
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.md`),
|
|
1123
|
+
(doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.mdx`),
|
|
1124
|
+
(doc) => doc.relPath.endsWith(`/${packageId2}.md`),
|
|
1125
|
+
(doc) => doc.relPath.endsWith(`/${packageId2}.mdx`),
|
|
1126
|
+
(doc) => doc.relPath.includes(`/packages/${packageId2}/`)
|
|
1125
1127
|
];
|
|
1126
1128
|
for (const match of candidates) {
|
|
1127
1129
|
const hit = corpus.find(match);
|
|
@@ -1213,7 +1215,8 @@ var collectPackages = (config, discovered, corpus) => {
|
|
|
1213
1215
|
byId.set(pkg.id, {
|
|
1214
1216
|
id: pkg.id,
|
|
1215
1217
|
path: existing.path || pkg.path,
|
|
1216
|
-
...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {}
|
|
1218
|
+
...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {},
|
|
1219
|
+
...pkg.checks ? { checks: pkg.checks } : existing.checks ? { checks: existing.checks } : {}
|
|
1217
1220
|
});
|
|
1218
1221
|
}
|
|
1219
1222
|
const seeds = [
|
|
@@ -1232,24 +1235,24 @@ var collectPackages = (config, discovered, corpus) => {
|
|
|
1232
1235
|
}
|
|
1233
1236
|
return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
1234
1237
|
};
|
|
1235
|
-
var resolveHumanDoc = (
|
|
1238
|
+
var resolveHumanDoc = (packageId2, override, fmHuman, humanDocs = {}) => {
|
|
1236
1239
|
if (override) return override;
|
|
1237
1240
|
if (fmHuman) return fmHuman;
|
|
1238
|
-
if (humanDocs[
|
|
1241
|
+
if (humanDocs[packageId2]) return humanDocs[packageId2];
|
|
1239
1242
|
const aliases = [
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
`packages/${
|
|
1245
|
-
`reference/packages/${
|
|
1246
|
-
`packages/${
|
|
1243
|
+
packageId2,
|
|
1244
|
+
packageId2.replace(/^@[^/]+\//, ""),
|
|
1245
|
+
packageId2.replace(/^os-/, ""),
|
|
1246
|
+
packageId2.replace(/-pattern$/, ""),
|
|
1247
|
+
`packages/${packageId2}`,
|
|
1248
|
+
`reference/packages/${packageId2}`,
|
|
1249
|
+
`packages/${packageId2}/index`
|
|
1247
1250
|
];
|
|
1248
1251
|
for (const alias of aliases) {
|
|
1249
1252
|
if (humanDocs[alias]) return humanDocs[alias];
|
|
1250
1253
|
}
|
|
1251
1254
|
for (const [key, url] of Object.entries(humanDocs)) {
|
|
1252
|
-
if (key ===
|
|
1255
|
+
if (key === packageId2 || key.endsWith(`/${packageId2}`) || key.endsWith(`/${packageId2}/index`) || key.endsWith(`-${packageId2}`)) {
|
|
1253
1256
|
return url;
|
|
1254
1257
|
}
|
|
1255
1258
|
}
|
|
@@ -1273,7 +1276,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
|
|
|
1273
1276
|
const purpose = override?.purpose ?? fm?.purpose;
|
|
1274
1277
|
const path = override?.path ?? fm?.path ?? pkg.path;
|
|
1275
1278
|
const checks = [
|
|
1276
|
-
...override?.checks ?? fm?.checks ?? defaultChecksForTarget(root, {
|
|
1279
|
+
...override?.checks ?? fm?.checks ?? pkg.checks ?? defaultChecksForTarget(root, {
|
|
1277
1280
|
packageId: pkg.id,
|
|
1278
1281
|
packagePath: path,
|
|
1279
1282
|
...pkg.name ? { packageName: pkg.name } : {},
|
|
@@ -1347,7 +1350,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
|
|
|
1347
1350
|
};
|
|
1348
1351
|
|
|
1349
1352
|
// src/version.ts
|
|
1350
|
-
var PACKAGE_VERSION = "1.
|
|
1353
|
+
var PACKAGE_VERSION = "1.3.0";
|
|
1351
1354
|
|
|
1352
1355
|
// src/index-builder/capabilities.ts
|
|
1353
1356
|
var renderCapabilitiesJson = (config, index, paths) => {
|
|
@@ -1604,6 +1607,38 @@ var fumadocsAdapter = {
|
|
|
1604
1607
|
}
|
|
1605
1608
|
};
|
|
1606
1609
|
|
|
1610
|
+
// src/index-builder/human-adapters/nextra.ts
|
|
1611
|
+
var nextraRecordId = (relPath, raw) => {
|
|
1612
|
+
const frontmatter = parseFrontmatter2(raw);
|
|
1613
|
+
return frontmatter.package ?? frontmatter.module ?? frontmatter.id ?? (routeSlug(relPath) || "index");
|
|
1614
|
+
};
|
|
1615
|
+
var isIndexPage = (path) => /(^|[/\\])index\.mdx?$/i.test(path);
|
|
1616
|
+
var resolveRouteCollisions = (records) => {
|
|
1617
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
1618
|
+
for (const record of records) {
|
|
1619
|
+
const normalized = { ...record, url: record.url || "/" };
|
|
1620
|
+
const indexPage = isIndexPage(record.path);
|
|
1621
|
+
const existing = byUrl.get(normalized.url);
|
|
1622
|
+
if (!existing || indexPage || !existing.indexPage) {
|
|
1623
|
+
byUrl.set(normalized.url, { record: normalized, indexPage });
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
return [...byUrl.values()].map(({ record }) => record);
|
|
1627
|
+
};
|
|
1628
|
+
var nextraAdapter = {
|
|
1629
|
+
plugin: "nextra",
|
|
1630
|
+
scan: ({ root, config }) => {
|
|
1631
|
+
const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
|
|
1632
|
+
if (!contentDir) return [];
|
|
1633
|
+
return resolveRouteCollisions(
|
|
1634
|
+
scanMarkdownDocs(root, contentDir, {
|
|
1635
|
+
idForDoc: nextraRecordId,
|
|
1636
|
+
urlPrefix: optionString(config.options, ["urlPrefix", "contentDirBasePath"]) ?? "/"
|
|
1637
|
+
})
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1607
1642
|
// src/index-builder/human-adapters/plain-markdown.ts
|
|
1608
1643
|
var plainMarkdownAdapter = {
|
|
1609
1644
|
plugin: "plain-markdown",
|
|
@@ -1613,11 +1648,73 @@ var plainMarkdownAdapter = {
|
|
|
1613
1648
|
}
|
|
1614
1649
|
};
|
|
1615
1650
|
|
|
1651
|
+
// src/index-builder/human-adapters/starlight.ts
|
|
1652
|
+
import { slug as githubSlug } from "github-slugger";
|
|
1653
|
+
var isStarlightPage = (relPath, raw) => {
|
|
1654
|
+
if (relPath.split("/").some((part) => part.startsWith(".") || part.startsWith("_"))) return false;
|
|
1655
|
+
return parseFrontmatter2(raw).draft !== "true";
|
|
1656
|
+
};
|
|
1657
|
+
var starlightFileSlug = (relPath) => routeSlug(relPath).split("/").map((part) => githubSlug(part)).filter(Boolean).join("/");
|
|
1658
|
+
var starlightSlug = (relPath, raw) => {
|
|
1659
|
+
const slug2 = parseFrontmatter2(raw).slug;
|
|
1660
|
+
return slug2 ? slug2.replace(/^\/+|\/+$/g, "") : starlightFileSlug(relPath);
|
|
1661
|
+
};
|
|
1662
|
+
var starlightAdapter = {
|
|
1663
|
+
plugin: "starlight",
|
|
1664
|
+
scan: ({ root, config }) => {
|
|
1665
|
+
const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
|
|
1666
|
+
if (!contentDir) return [];
|
|
1667
|
+
return scanMarkdownDocs(root, contentDir, {
|
|
1668
|
+
includeRelPath: isStarlightPage,
|
|
1669
|
+
slugForDoc: starlightSlug,
|
|
1670
|
+
urlPrefix: config.options?.urlPrefix
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
// src/index-builder/human-adapters/vitepress.ts
|
|
1676
|
+
import { minimatch } from "minimatch";
|
|
1677
|
+
var isVitePressPage = (relPath) => !relPath.split("/").some((part) => part === ".vitepress" || part.startsWith("."));
|
|
1678
|
+
var srcExcludePatterns = (value) => {
|
|
1679
|
+
if (value === void 0) return [];
|
|
1680
|
+
if (!Array.isArray(value) || value.length > 64) {
|
|
1681
|
+
throw new Error("VitePress srcExclude must be an array of at most 64 glob patterns.");
|
|
1682
|
+
}
|
|
1683
|
+
return value.map((pattern) => {
|
|
1684
|
+
if (typeof pattern !== "string" || !pattern || pattern.length > 256 || pattern.includes("\0")) {
|
|
1685
|
+
throw new Error("Each VitePress srcExclude pattern must be a non-empty string up to 256 characters.");
|
|
1686
|
+
}
|
|
1687
|
+
return pattern;
|
|
1688
|
+
});
|
|
1689
|
+
};
|
|
1690
|
+
var isExcluded = (relPath, patterns) => patterns.some((pattern) => minimatch(relPath, pattern, { dot: true }));
|
|
1691
|
+
var vitepressSlug = (relPath, cleanUrls) => {
|
|
1692
|
+
const slug2 = routeSlug(relPath);
|
|
1693
|
+
if (cleanUrls || /(?:^|\/)index\.mdx?$/.test(relPath)) return slug2;
|
|
1694
|
+
return `${slug2}.html`;
|
|
1695
|
+
};
|
|
1696
|
+
var vitepressAdapter = {
|
|
1697
|
+
plugin: "vitepress",
|
|
1698
|
+
scan: ({ root, config }) => {
|
|
1699
|
+
const docsDir = optionString(config.options, ["docsDir", "root", "srcDir"]);
|
|
1700
|
+
if (!docsDir) return [];
|
|
1701
|
+
const srcExclude = srcExcludePatterns(config.options?.srcExclude);
|
|
1702
|
+
return scanMarkdownDocs(root, docsDir, {
|
|
1703
|
+
includeRelPath: (relPath) => isVitePressPage(relPath) && !isExcluded(relPath, srcExclude),
|
|
1704
|
+
slugForDoc: (relPath) => vitepressSlug(relPath, config.options?.cleanUrls === true),
|
|
1705
|
+
urlPrefix: config.options?.urlPrefix
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
};
|
|
1709
|
+
|
|
1616
1710
|
// src/index-builder/human-adapters/index.ts
|
|
1617
1711
|
var ADAPTERS = [
|
|
1618
1712
|
plainMarkdownAdapter,
|
|
1619
1713
|
fumadocsAdapter,
|
|
1620
|
-
docusaurusAdapter
|
|
1714
|
+
docusaurusAdapter,
|
|
1715
|
+
vitepressAdapter,
|
|
1716
|
+
starlightAdapter,
|
|
1717
|
+
nextraAdapter
|
|
1621
1718
|
];
|
|
1622
1719
|
var humanConfigs = (config) => {
|
|
1623
1720
|
const human = config.corpus.human;
|
|
@@ -1652,12 +1749,121 @@ var scanHumanDocRecords = (root, config) => {
|
|
|
1652
1749
|
};
|
|
1653
1750
|
var scanHumanDocs = (root, config) => Object.fromEntries(scanHumanDocRecords(root, config).map((doc) => [doc.id, doc.url]));
|
|
1654
1751
|
|
|
1752
|
+
// src/index-builder/plugins/nx.ts
|
|
1753
|
+
import { existsSync as existsSync6, lstatSync as lstatSync2, readFileSync as readFileSync5, realpathSync as realpathSync5 } from "fs";
|
|
1754
|
+
import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve5, sep as sep4 } from "path";
|
|
1755
|
+
var NX_SCAN_SKIP = /* @__PURE__ */ new Set([
|
|
1756
|
+
"node_modules",
|
|
1757
|
+
".git",
|
|
1758
|
+
".nx",
|
|
1759
|
+
"dist",
|
|
1760
|
+
"coverage",
|
|
1761
|
+
".doc-bridge"
|
|
1762
|
+
]);
|
|
1763
|
+
var NX_PROJECT_NAME = /^(?:@[A-Za-z0-9._-]+\/)?[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
1764
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1765
|
+
var readJsonRecord = (path) => {
|
|
1766
|
+
try {
|
|
1767
|
+
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
1768
|
+
return isRecord(parsed) ? parsed : void 0;
|
|
1769
|
+
} catch {
|
|
1770
|
+
return void 0;
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
var safeProjectPath = (root, manifestDir, declaredRoot) => {
|
|
1774
|
+
const candidate = typeof declaredRoot === "string" ? resolve5(root, declaredRoot) : manifestDir;
|
|
1775
|
+
const rel = toPosix(relative3(root, candidate)) || ".";
|
|
1776
|
+
if (isAbsolute3(rel) || rel === ".." || rel.startsWith("../")) return void 0;
|
|
1777
|
+
try {
|
|
1778
|
+
if (!lstatSync2(candidate).isDirectory()) return void 0;
|
|
1779
|
+
const canonicalRoot = realpathSync5.native(root);
|
|
1780
|
+
const canonicalCandidate = realpathSync5.native(candidate);
|
|
1781
|
+
const canonicalRel = relative3(canonicalRoot, canonicalCandidate);
|
|
1782
|
+
if (isAbsolute3(canonicalRel) || canonicalRel === ".." || canonicalRel.startsWith(`..${sep4}`)) {
|
|
1783
|
+
return void 0;
|
|
1784
|
+
}
|
|
1785
|
+
} catch {
|
|
1786
|
+
return void 0;
|
|
1787
|
+
}
|
|
1788
|
+
return rel;
|
|
1789
|
+
};
|
|
1790
|
+
var packageId = (name) => name.startsWith("@") ? name.split("/").at(-1) ?? name : name;
|
|
1791
|
+
var commandPrefix = (root) => {
|
|
1792
|
+
const manager = detectPackageManager(root);
|
|
1793
|
+
if (manager === "pnpm") return "pnpm exec nx run";
|
|
1794
|
+
if (manager === "yarn") return "yarn nx run";
|
|
1795
|
+
if (manager === "bun") return "bunx nx run";
|
|
1796
|
+
return "npx nx run";
|
|
1797
|
+
};
|
|
1798
|
+
var inferredChecks = (root, config, projectName2, targets) => {
|
|
1799
|
+
const prefix = commandPrefix(root);
|
|
1800
|
+
const strict = (config.gates?.preset ?? "minimal") !== "minimal";
|
|
1801
|
+
const checks = [
|
|
1802
|
+
...targets.has("test") ? [`${prefix} ${projectName2}:test`] : [],
|
|
1803
|
+
...strict && targets.has("lint") ? [`${prefix} ${projectName2}:lint`] : []
|
|
1804
|
+
];
|
|
1805
|
+
return checks.length ? checks : void 0;
|
|
1806
|
+
};
|
|
1807
|
+
var discoverNxProjects = (root, config) => {
|
|
1808
|
+
if (!existsSync6(resolve5(root, "nx.json"))) return [];
|
|
1809
|
+
const manifests = walkFiles(root, {
|
|
1810
|
+
extensions: ["project.json", "package.json"],
|
|
1811
|
+
skipDirs: NX_SCAN_SKIP,
|
|
1812
|
+
maxFiles: 1e4
|
|
1813
|
+
});
|
|
1814
|
+
const projects = /* @__PURE__ */ new Map();
|
|
1815
|
+
for (const manifest of manifests) {
|
|
1816
|
+
const json = readJsonRecord(manifest);
|
|
1817
|
+
if (!json) continue;
|
|
1818
|
+
const manifestDir = dirname3(manifest);
|
|
1819
|
+
const manifestName = basename2(manifest);
|
|
1820
|
+
const isProjectJson = manifestName === "project.json";
|
|
1821
|
+
if (!isProjectJson && manifestName !== "package.json") continue;
|
|
1822
|
+
const nx = json.nx;
|
|
1823
|
+
if (!isProjectJson && !isRecord(nx)) continue;
|
|
1824
|
+
const path = safeProjectPath(root, manifestDir, isProjectJson ? json.root : void 0);
|
|
1825
|
+
if (!path) continue;
|
|
1826
|
+
const projectPackage = isProjectJson ? readJsonRecord(resolve5(root, path, "package.json")) : void 0;
|
|
1827
|
+
const projectName2 = typeof json.name === "string" ? json.name : typeof projectPackage?.name === "string" ? projectPackage.name : basename2(path === "." ? root : path);
|
|
1828
|
+
if (!NX_PROJECT_NAME.test(projectName2)) continue;
|
|
1829
|
+
const targets = /* @__PURE__ */ new Set();
|
|
1830
|
+
const targetRecord = isProjectJson ? json.targets : isRecord(nx) ? nx.targets : void 0;
|
|
1831
|
+
if (isRecord(targetRecord)) {
|
|
1832
|
+
for (const target of Object.keys(targetRecord)) targets.add(target);
|
|
1833
|
+
}
|
|
1834
|
+
if (!isProjectJson && isRecord(json.scripts)) {
|
|
1835
|
+
for (const script of Object.keys(json.scripts)) targets.add(script);
|
|
1836
|
+
}
|
|
1837
|
+
const id = packageId(projectName2);
|
|
1838
|
+
const rank = isProjectJson ? 2 : 1;
|
|
1839
|
+
const existing = projects.get(id);
|
|
1840
|
+
if (existing && existing.path !== path) {
|
|
1841
|
+
throw new Error(
|
|
1842
|
+
`Nx project identity collision for "${id}": "${existing.name ?? id}" at "${existing.path}" and "${projectName2}" at "${path}". Use unique Nx project names.`
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
const mergedTargets = [.../* @__PURE__ */ new Set([...existing?.targets ?? [], ...targets])];
|
|
1846
|
+
const projectJsonWins = rank >= (existing?.rank ?? 0);
|
|
1847
|
+
const resolvedName = projectJsonWins ? projectName2 : existing?.name ?? projectName2;
|
|
1848
|
+
const checks = inferredChecks(root, config, resolvedName, new Set(mergedTargets));
|
|
1849
|
+
projects.set(id, {
|
|
1850
|
+
id,
|
|
1851
|
+
path,
|
|
1852
|
+
name: resolvedName,
|
|
1853
|
+
...checks ? { checks } : {},
|
|
1854
|
+
rank: projectJsonWins ? rank : existing?.rank ?? rank,
|
|
1855
|
+
targets: mergedTargets
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1858
|
+
return [...projects.values()].sort((a, b) => a.id.localeCompare(b.id)).map(({ rank: _rank, targets: _targets, ...project }) => project);
|
|
1859
|
+
};
|
|
1860
|
+
|
|
1655
1861
|
// src/index-builder/plugins/pnpm-monorepo.ts
|
|
1656
|
-
import { existsSync as
|
|
1657
|
-
import { basename as
|
|
1862
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
|
|
1863
|
+
import { basename as basename3, join as join6 } from "path";
|
|
1658
1864
|
|
|
1659
1865
|
// src/lib/glob-expand.ts
|
|
1660
|
-
import { existsSync as
|
|
1866
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
1661
1867
|
import { join as join5 } from "path";
|
|
1662
1868
|
var expandWorkspaceGlobs = (root, patterns) => {
|
|
1663
1869
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -1665,12 +1871,12 @@ var expandWorkspaceGlobs = (root, patterns) => {
|
|
|
1665
1871
|
const normalized = toPosix(pattern).replace(/\/$/, "");
|
|
1666
1872
|
if (!normalized.includes("*")) {
|
|
1667
1873
|
const abs = join5(root, normalized);
|
|
1668
|
-
if (
|
|
1874
|
+
if (existsSync7(abs)) dirs.add(toPosix(abs));
|
|
1669
1875
|
continue;
|
|
1670
1876
|
}
|
|
1671
1877
|
const star = normalized.indexOf("*");
|
|
1672
1878
|
const base = join5(root, normalized.slice(0, star).replace(/\/$/, ""));
|
|
1673
|
-
if (!
|
|
1879
|
+
if (!existsSync7(base)) continue;
|
|
1674
1880
|
for (const name of readdirSync2(base)) {
|
|
1675
1881
|
const abs = join5(base, name);
|
|
1676
1882
|
try {
|
|
@@ -1705,9 +1911,9 @@ var parsePnpmWorkspace = (yaml) => {
|
|
|
1705
1911
|
};
|
|
1706
1912
|
var readPackageJson = (dir) => {
|
|
1707
1913
|
const file = join6(dir, "package.json");
|
|
1708
|
-
if (!
|
|
1914
|
+
if (!existsSync8(file)) return null;
|
|
1709
1915
|
try {
|
|
1710
|
-
return JSON.parse(
|
|
1916
|
+
return JSON.parse(readFileSync6(file, "utf8"));
|
|
1711
1917
|
} catch {
|
|
1712
1918
|
return null;
|
|
1713
1919
|
}
|
|
@@ -1717,8 +1923,8 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1717
1923
|
let patterns = explicit;
|
|
1718
1924
|
if (!patterns?.length) {
|
|
1719
1925
|
const workspaceFile = join6(root, "pnpm-workspace.yaml");
|
|
1720
|
-
if (
|
|
1721
|
-
patterns = parsePnpmWorkspace(
|
|
1926
|
+
if (existsSync8(workspaceFile)) {
|
|
1927
|
+
patterns = parsePnpmWorkspace(readFileSync6(workspaceFile, "utf8"));
|
|
1722
1928
|
}
|
|
1723
1929
|
}
|
|
1724
1930
|
if (!patterns?.length) return [];
|
|
@@ -1728,7 +1934,7 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1728
1934
|
const pkg = readPackageJson(abs);
|
|
1729
1935
|
if (!pkg) continue;
|
|
1730
1936
|
const rel = toPosix(abs.replace(`${toPosix(root)}/`, ""));
|
|
1731
|
-
const folderId =
|
|
1937
|
+
const folderId = basename3(abs);
|
|
1732
1938
|
const id = pkg.name?.startsWith("@") ? pkg.name.split("/").pop() ?? folderId : pkg.name ?? folderId;
|
|
1733
1939
|
out.push({ id, path: rel, ...pkg.name ? { name: pkg.name } : {} });
|
|
1734
1940
|
}
|
|
@@ -1739,7 +1945,7 @@ var discoverPnpmPackages = (root, config) => {
|
|
|
1739
1945
|
var projectName = (root, config) => {
|
|
1740
1946
|
if (config.project?.name) return config.project.name;
|
|
1741
1947
|
try {
|
|
1742
|
-
const pkg = JSON.parse(
|
|
1948
|
+
const pkg = JSON.parse(readFileSync7(join7(root, "package.json"), "utf8"));
|
|
1743
1949
|
if (pkg.name) return pkg.name;
|
|
1744
1950
|
} catch {
|
|
1745
1951
|
}
|
|
@@ -1747,7 +1953,7 @@ var projectName = (root, config) => {
|
|
|
1747
1953
|
};
|
|
1748
1954
|
var existingGeneratedAt = (indexPath, contentHash) => {
|
|
1749
1955
|
try {
|
|
1750
|
-
const index = JSON.parse(
|
|
1956
|
+
const index = JSON.parse(readFileSync7(indexPath, "utf8"));
|
|
1751
1957
|
return index.contentHash === contentHash && typeof index.generatedAt === "string" ? index.generatedAt : void 0;
|
|
1752
1958
|
} catch {
|
|
1753
1959
|
return void 0;
|
|
@@ -1762,7 +1968,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1762
1968
|
const corpus = scanAgentCorpus(root, config);
|
|
1763
1969
|
const knowledge = corpus.map(({ absPath: _a, relPath: _r, frontmatter: _f, ...entry }) => entry);
|
|
1764
1970
|
const shouldDiscover = config.routing?.plugin === "pnpm-monorepo" || Boolean(config.routing?.options?.packages?.length) || config.routing?.plugin === "npm-workspaces" || config.routing?.plugin === "yarn-workspaces";
|
|
1765
|
-
const discovered = shouldDiscover ? discoverPnpmPackages(root, config) : [];
|
|
1971
|
+
const discovered = config.routing?.plugin === "nx" ? discoverNxProjects(root, config) : shouldDiscover ? discoverPnpmPackages(root, config) : [];
|
|
1766
1972
|
const packages = collectPackages(config, discovered, corpus);
|
|
1767
1973
|
const humanDocs = scanHumanDocs(root, config);
|
|
1768
1974
|
const { lookup, handoffs } = buildLookup(config, packages, corpus, outFile, humanDocs, root);
|
|
@@ -1784,7 +1990,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1784
1990
|
lookup
|
|
1785
1991
|
};
|
|
1786
1992
|
if (write) {
|
|
1787
|
-
mkdirSync(
|
|
1993
|
+
mkdirSync(dirname4(indexPath), { recursive: true });
|
|
1788
1994
|
writeFileSync(indexPath, `${JSON.stringify(index, null, 2)}
|
|
1789
1995
|
`, "utf8");
|
|
1790
1996
|
}
|
|
@@ -1807,7 +2013,7 @@ var buildDocBridgeIndex = (opts) => {
|
|
|
1807
2013
|
const capabilitiesOut = config.index?.capabilities?.outFile ?? ".doc-bridge/capabilities.json";
|
|
1808
2014
|
capabilitiesPath = join7(root, capabilitiesOut);
|
|
1809
2015
|
if (write) {
|
|
1810
|
-
mkdirSync(
|
|
2016
|
+
mkdirSync(dirname4(capabilitiesPath), { recursive: true });
|
|
1811
2017
|
writeFileSync(
|
|
1812
2018
|
capabilitiesPath,
|
|
1813
2019
|
renderCapabilitiesJson(config, index, {
|
|
@@ -1831,15 +2037,15 @@ var DOCUMENTATION_STANDARD_V1_ID = "documentation-standard-v1";
|
|
|
1831
2037
|
var DOCUMENTATION_STANDARD_V1_STATUS = "stable";
|
|
1832
2038
|
var MAX_TEXT_EVIDENCE_BYTES = 4 * 1024 * 1024;
|
|
1833
2039
|
var safePath = (root, path) => {
|
|
1834
|
-
const rootAbs =
|
|
1835
|
-
const unresolved =
|
|
1836
|
-
const unresolvedRel =
|
|
1837
|
-
if (
|
|
1838
|
-
if (!
|
|
2040
|
+
const rootAbs = realpathSync6.native(resolve6(root));
|
|
2041
|
+
const unresolved = resolve6(rootAbs, path);
|
|
2042
|
+
const unresolvedRel = relative4(rootAbs, unresolved);
|
|
2043
|
+
if (isAbsolute4(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep5}`)) return void 0;
|
|
2044
|
+
if (!existsSync9(unresolved)) return unresolved;
|
|
1839
2045
|
try {
|
|
1840
|
-
const abs =
|
|
1841
|
-
const rel =
|
|
1842
|
-
return !
|
|
2046
|
+
const abs = realpathSync6.native(unresolved);
|
|
2047
|
+
const rel = relative4(rootAbs, abs);
|
|
2048
|
+
return !isAbsolute4(rel) && rel !== ".." && !rel.startsWith(`..${sep5}`) ? abs : void 0;
|
|
1843
2049
|
} catch {
|
|
1844
2050
|
return void 0;
|
|
1845
2051
|
}
|
|
@@ -1853,7 +2059,7 @@ var fileEvidence = (root, path, options) => {
|
|
|
1853
2059
|
evidence: { path, detail: "Path escapes the project root." }
|
|
1854
2060
|
};
|
|
1855
2061
|
}
|
|
1856
|
-
if (!
|
|
2062
|
+
if (!existsSync9(abs)) {
|
|
1857
2063
|
return { exists: false, content: "", evidence: { path, detail: "File does not exist." } };
|
|
1858
2064
|
}
|
|
1859
2065
|
try {
|
|
@@ -1868,7 +2074,7 @@ var fileEvidence = (root, path, options) => {
|
|
|
1868
2074
|
return {
|
|
1869
2075
|
exists: true,
|
|
1870
2076
|
content: "",
|
|
1871
|
-
evidence: { path: toPosix(
|
|
2077
|
+
evidence: { path: toPosix(relative4(resolve6(root), abs)) || ".", detail: "File exists and is non-empty." }
|
|
1872
2078
|
};
|
|
1873
2079
|
}
|
|
1874
2080
|
if (stat.size > MAX_TEXT_EVIDENCE_BYTES) {
|
|
@@ -1878,12 +2084,12 @@ var fileEvidence = (root, path, options) => {
|
|
|
1878
2084
|
evidence: { path, detail: `Text evidence exceeds ${MAX_TEXT_EVIDENCE_BYTES} bytes.` }
|
|
1879
2085
|
};
|
|
1880
2086
|
}
|
|
1881
|
-
const content =
|
|
2087
|
+
const content = readFileSync8(abs, "utf8");
|
|
1882
2088
|
return {
|
|
1883
2089
|
exists: content.trim().length > 0,
|
|
1884
2090
|
content,
|
|
1885
2091
|
evidence: {
|
|
1886
|
-
path: toPosix(
|
|
2092
|
+
path: toPosix(relative4(resolve6(root), abs)) || ".",
|
|
1887
2093
|
detail: content.trim().length > 0 ? "File exists and is non-empty." : "File is empty."
|
|
1888
2094
|
}
|
|
1889
2095
|
};
|
|
@@ -1918,7 +2124,7 @@ var humanDocsRule = (root, config) => {
|
|
|
1918
2124
|
passed: docs.length > 0,
|
|
1919
2125
|
message: docs.length > 0 ? `Found ${docs.length} human document(s).` : "No human documentation was discovered.",
|
|
1920
2126
|
evidence: docs.slice(0, 10).map((doc) => ({
|
|
1921
|
-
path: toPosix(
|
|
2127
|
+
path: toPosix(relative4(resolve6(root), doc.path)),
|
|
1922
2128
|
detail: `Human route: ${doc.url}`
|
|
1923
2129
|
})),
|
|
1924
2130
|
remediation: {
|
|
@@ -1929,10 +2135,10 @@ var humanDocsRule = (root, config) => {
|
|
|
1929
2135
|
};
|
|
1930
2136
|
var llmsRule = (root, config, options) => {
|
|
1931
2137
|
const llmsPath = config.index?.llmsTxt?.outFile ?? "llms.txt";
|
|
1932
|
-
const llmsKey = safePath(root, llmsPath) ??
|
|
2138
|
+
const llmsKey = safePath(root, llmsPath) ?? resolve6(root, llmsPath);
|
|
1933
2139
|
const rawSources = /* @__PURE__ */ new Map();
|
|
1934
2140
|
for (const path of options.rawSources ?? []) {
|
|
1935
|
-
const key = safePath(root, path) ??
|
|
2141
|
+
const key = safePath(root, path) ?? resolve6(root, path);
|
|
1936
2142
|
if (key !== llmsKey && !rawSources.has(key)) rawSources.set(key, path);
|
|
1937
2143
|
}
|
|
1938
2144
|
const paths = [llmsPath, ...rawSources.values()];
|
|
@@ -2184,8 +2390,8 @@ var formatDocumentationStandardText = (report) => [
|
|
|
2184
2390
|
];
|
|
2185
2391
|
|
|
2186
2392
|
// src/federation/llms.ts
|
|
2187
|
-
import { existsSync as
|
|
2188
|
-
import { resolve as
|
|
2393
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
|
|
2394
|
+
import { resolve as resolve7 } from "path";
|
|
2189
2395
|
|
|
2190
2396
|
// src/query/search.ts
|
|
2191
2397
|
var tokenize = (value) => value.toLowerCase().split(/[^a-z0-9@/_-]+/).filter((t) => t.length >= 2);
|
|
@@ -2314,9 +2520,9 @@ var defaultFetchText = async (url) => {
|
|
|
2314
2520
|
var sourceText = async (root, source, fetchText) => {
|
|
2315
2521
|
try {
|
|
2316
2522
|
if (/^https?:\/\//.test(source)) return await fetchText(source);
|
|
2317
|
-
const path =
|
|
2318
|
-
if (!
|
|
2319
|
-
return
|
|
2523
|
+
const path = resolve7(root, source);
|
|
2524
|
+
if (!existsSync10(path)) return null;
|
|
2525
|
+
return readFileSync9(path, "utf8");
|
|
2320
2526
|
} catch {
|
|
2321
2527
|
return null;
|
|
2322
2528
|
}
|
|
@@ -2401,11 +2607,11 @@ var retrieveHybridChunks = async (root, config, index, query, options = {}) => {
|
|
|
2401
2607
|
};
|
|
2402
2608
|
|
|
2403
2609
|
// src/gates/run-gates.ts
|
|
2404
|
-
import { readFileSync as
|
|
2610
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
2405
2611
|
|
|
2406
2612
|
// src/query/load-index.ts
|
|
2407
|
-
import { existsSync as
|
|
2408
|
-
import { join as join8, resolve as
|
|
2613
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
2614
|
+
import { join as join8, resolve as resolve8 } from "path";
|
|
2409
2615
|
|
|
2410
2616
|
// src/schemas/agent-handoff.ts
|
|
2411
2617
|
import { z as z3 } from "zod";
|
|
@@ -2621,8 +2827,8 @@ var IndexNotFoundError = class extends Error {
|
|
|
2621
2827
|
var indexFilePath = (root, config) => join8(root, config.index?.outFile ?? ".doc-bridge/index.json");
|
|
2622
2828
|
var loadDocBridgeIndex = (root, config) => {
|
|
2623
2829
|
const path = indexFilePath(root, config);
|
|
2624
|
-
if (!
|
|
2625
|
-
const raw = JSON.parse(
|
|
2830
|
+
if (!existsSync11(path)) throw new IndexNotFoundError(path);
|
|
2831
|
+
const raw = JSON.parse(readFileSync10(path, "utf8"));
|
|
2626
2832
|
return parseDocBridgeIndex(raw);
|
|
2627
2833
|
};
|
|
2628
2834
|
|
|
@@ -2697,7 +2903,7 @@ var runOkfTypeGate = (root, config) => {
|
|
|
2697
2903
|
const required = config.corpus.agent.okf?.requireType ?? config.gates?.preset === "strict";
|
|
2698
2904
|
if (!required) return { id: "okf-type", ok: true, message: "OKF type frontmatter not required" };
|
|
2699
2905
|
const allowed = config.corpus.agent.okf?.allowedTypes;
|
|
2700
|
-
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(
|
|
2906
|
+
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync11(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
|
|
2701
2907
|
if (bad.length) {
|
|
2702
2908
|
return {
|
|
2703
2909
|
id: "okf-type",
|
|
@@ -2724,10 +2930,10 @@ var DOCS_STYLE_RULES = {
|
|
|
2724
2930
|
"playbook-okf-soft": ["title", "no-stale-wording"],
|
|
2725
2931
|
"title-only": ["title"]
|
|
2726
2932
|
};
|
|
2727
|
-
var
|
|
2933
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2728
2934
|
var docsStyleOptions = (config) => {
|
|
2729
2935
|
const raw = config.gates?.options?.["docs-style"];
|
|
2730
|
-
if (!
|
|
2936
|
+
if (!isRecord2(raw)) {
|
|
2731
2937
|
if (config.gates?.preset === "playbook") {
|
|
2732
2938
|
return { profile: "playbook-okf-soft", required: DOCS_STYLE_RULES["playbook-okf-soft"] };
|
|
2733
2939
|
}
|
|
@@ -2771,7 +2977,7 @@ var runDocsStyleGate = (root, config) => {
|
|
|
2771
2977
|
}
|
|
2772
2978
|
const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({
|
|
2773
2979
|
path: doc.path,
|
|
2774
|
-
missing: missingStyleRules(
|
|
2980
|
+
missing: missingStyleRules(readFileSync11(doc.absPath, "utf8"), required)
|
|
2775
2981
|
})).filter((doc) => doc.missing.length > 0);
|
|
2776
2982
|
if (bad.length) {
|
|
2777
2983
|
return {
|
|
@@ -3056,7 +3262,7 @@ var resolveIntelligenceRuntime = async (config) => {
|
|
|
3056
3262
|
var defaultVectorStorePath = (root) => join9(root, ".doc-bridge", "vectors");
|
|
3057
3263
|
|
|
3058
3264
|
// src/intelligence/rag.ts
|
|
3059
|
-
import { readFileSync as
|
|
3265
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
3060
3266
|
import { join as join10 } from "path";
|
|
3061
3267
|
var loadDocuments = (root, index, sources) => {
|
|
3062
3268
|
const includeAgent = sources.includes("agent") || sources.length === 0;
|
|
@@ -3066,7 +3272,7 @@ var loadDocuments = (root, index, sources) => {
|
|
|
3066
3272
|
const abs = join10(root, entry.path);
|
|
3067
3273
|
let content = "";
|
|
3068
3274
|
try {
|
|
3069
|
-
content =
|
|
3275
|
+
content = readFileSync12(abs, "utf8");
|
|
3070
3276
|
} catch {
|
|
3071
3277
|
content = [entry.title, entry.description].filter(Boolean).join("\n\n");
|
|
3072
3278
|
}
|
|
@@ -3219,15 +3425,15 @@ var startInkChat = async (root, config, index) => {
|
|
|
3219
3425
|
};
|
|
3220
3426
|
|
|
3221
3427
|
// src/memory/ingest.ts
|
|
3222
|
-
import { existsSync as
|
|
3428
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13 } from "fs";
|
|
3223
3429
|
import { join as join11 } from "path";
|
|
3224
3430
|
var memoryFact = (raw, id) => firstParagraph(raw) ?? firstHeading(raw) ?? id;
|
|
3225
3431
|
var relativePath = (root, abs) => toPosix(abs).replace(`${toPosix(root)}/`, "");
|
|
3226
3432
|
var ingestMarkdownDir = (root, dir, source, confidence) => {
|
|
3227
|
-
if (!
|
|
3433
|
+
if (!existsSync12(dir)) return [];
|
|
3228
3434
|
return walkFiles(dir, { extensions: [".md", ".mdc"] }).map((abs) => {
|
|
3229
3435
|
const rel = relativePath(root, abs);
|
|
3230
|
-
const raw =
|
|
3436
|
+
const raw = readFileSync13(abs, "utf8");
|
|
3231
3437
|
const id = slugFromPath(rel);
|
|
3232
3438
|
return {
|
|
3233
3439
|
schemaVersion: 1,
|
|
@@ -3332,7 +3538,7 @@ var draftMemoryPromotion = (classifications) => {
|
|
|
3332
3538
|
|
|
3333
3539
|
// src/memory/github-pr.ts
|
|
3334
3540
|
import { execFileSync, spawnSync } from "child_process";
|
|
3335
|
-
import { existsSync as
|
|
3541
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3336
3542
|
import { join as join12 } from "path";
|
|
3337
3543
|
var run = (cmd, args, cwd) => {
|
|
3338
3544
|
const result = spawnSync(cmd, [...args], { cwd, encoding: "utf8" });
|
|
@@ -3380,7 +3586,7 @@ var promoteMemoryToGithubPr = (root, draft, options = {}) => {
|
|
|
3380
3586
|
message: `Wrote draft to ${relDraft}. Run the printed git/gh commands to open a draft PR.`
|
|
3381
3587
|
};
|
|
3382
3588
|
}
|
|
3383
|
-
if (!
|
|
3589
|
+
if (!existsSync13(join12(root, ".git"))) {
|
|
3384
3590
|
return {
|
|
3385
3591
|
ok: false,
|
|
3386
3592
|
dryRun: false,
|
|
@@ -3483,22 +3689,23 @@ ${auth.out}`
|
|
|
3483
3689
|
};
|
|
3484
3690
|
|
|
3485
3691
|
// src/index-builder/watch-index.ts
|
|
3486
|
-
import { existsSync as
|
|
3487
|
-
import { dirname as
|
|
3692
|
+
import { existsSync as existsSync14, watch } from "fs";
|
|
3693
|
+
import { dirname as dirname5, resolve as resolve9 } from "path";
|
|
3488
3694
|
var WATCH_PATTERN = /\.(md|mdx|json|ya?ml|mdc)$/i;
|
|
3695
|
+
var NX_MANIFEST_PATTERN = /(^|[/\\])(project|package)\.json$/i;
|
|
3489
3696
|
var collectWatchRoots = (root, config, configPath) => {
|
|
3490
3697
|
const roots = /* @__PURE__ */ new Set();
|
|
3491
|
-
roots.add(
|
|
3698
|
+
roots.add(resolve9(root, config.corpus.agent.root));
|
|
3492
3699
|
const humanSources = config.corpus.human ? Array.isArray(config.corpus.human) ? config.corpus.human : [config.corpus.human] : [];
|
|
3493
3700
|
for (const source of humanSources) {
|
|
3494
3701
|
const humanOpts = source.options ?? {};
|
|
3495
|
-
for (const key of ["contentDir", "docsDir", "root"]) {
|
|
3702
|
+
for (const key of ["contentDir", "docsDir", "root", "srcDir"]) {
|
|
3496
3703
|
const value = humanOpts[key];
|
|
3497
|
-
if (typeof value === "string" && value.length) roots.add(
|
|
3704
|
+
if (typeof value === "string" && value.length) roots.add(resolve9(root, value));
|
|
3498
3705
|
}
|
|
3499
3706
|
}
|
|
3500
|
-
if (configPath) roots.add(
|
|
3501
|
-
return [...roots].filter((dir) =>
|
|
3707
|
+
if (configPath) roots.add(dirname5(resolve9(configPath)));
|
|
3708
|
+
return [...roots].filter((dir) => existsSync14(dir));
|
|
3502
3709
|
};
|
|
3503
3710
|
var watchDocBridgeIndex = (opts) => {
|
|
3504
3711
|
const debounceMs = opts.debounceMs ?? 350;
|
|
@@ -3539,8 +3746,15 @@ var watchDocBridgeIndex = (opts) => {
|
|
|
3539
3746
|
rebuild();
|
|
3540
3747
|
});
|
|
3541
3748
|
}
|
|
3542
|
-
const
|
|
3543
|
-
if (
|
|
3749
|
+
const nxRoot = resolve9(opts.root);
|
|
3750
|
+
if (opts.config.routing?.plugin === "nx" && existsSync14(nxRoot)) {
|
|
3751
|
+
watch(nxRoot, { recursive: true }, (_event, filename) => {
|
|
3752
|
+
if (!filename || !NX_MANIFEST_PATTERN.test(filename)) return;
|
|
3753
|
+
rebuild();
|
|
3754
|
+
});
|
|
3755
|
+
}
|
|
3756
|
+
const configDir = resolve9(opts.root);
|
|
3757
|
+
if (existsSync14(configDir)) {
|
|
3544
3758
|
watch(configDir, (_event, filename) => {
|
|
3545
3759
|
if (!filename || !/doc-bridge\.config/.test(filename)) return;
|
|
3546
3760
|
rebuild();
|
|
@@ -3716,15 +3930,15 @@ var docBridgePatternPayload = () => ({
|
|
|
3716
3930
|
});
|
|
3717
3931
|
|
|
3718
3932
|
// src/cli/demo.ts
|
|
3719
|
-
import { cpSync, existsSync as
|
|
3933
|
+
import { cpSync, existsSync as existsSync16, mkdtempSync, readFileSync as readFileSync15, rmSync } from "fs";
|
|
3720
3934
|
import { tmpdir } from "os";
|
|
3721
|
-
import { dirname as
|
|
3935
|
+
import { dirname as dirname7, join as join15, resolve as resolve11 } from "path";
|
|
3722
3936
|
import { fileURLToPath } from "url";
|
|
3723
3937
|
|
|
3724
3938
|
// src/mcp/install.ts
|
|
3725
|
-
import { existsSync as
|
|
3939
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync3, readFileSync as readFileSync14, writeFileSync as writeFileSync3 } from "fs";
|
|
3726
3940
|
import { homedir } from "os";
|
|
3727
|
-
import { dirname as
|
|
3941
|
+
import { dirname as dirname6, join as join14, resolve as resolve10 } from "path";
|
|
3728
3942
|
var SERVER_NAME = "ak-docs";
|
|
3729
3943
|
var mcpServerEntry = (root) => ({
|
|
3730
3944
|
command: "npx",
|
|
@@ -3732,26 +3946,26 @@ var mcpServerEntry = (root) => ({
|
|
|
3732
3946
|
cwd: root
|
|
3733
3947
|
});
|
|
3734
3948
|
var readJson = (path) => {
|
|
3735
|
-
if (!
|
|
3949
|
+
if (!existsSync15(path)) return {};
|
|
3736
3950
|
try {
|
|
3737
|
-
const parsed = JSON.parse(
|
|
3951
|
+
const parsed = JSON.parse(readFileSync14(path, "utf8"));
|
|
3738
3952
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
3739
3953
|
} catch {
|
|
3740
3954
|
return {};
|
|
3741
3955
|
}
|
|
3742
3956
|
};
|
|
3743
3957
|
var writeJson = (path, value) => {
|
|
3744
|
-
mkdirSync3(
|
|
3958
|
+
mkdirSync3(dirname6(path), { recursive: true });
|
|
3745
3959
|
writeFileSync3(path, `${JSON.stringify(value, null, 2)}
|
|
3746
3960
|
`, "utf8");
|
|
3747
3961
|
};
|
|
3748
3962
|
var resolveTargetPath = (target, root) => {
|
|
3749
|
-
if (target === "cursor") return
|
|
3963
|
+
if (target === "cursor") return resolve10(root, ".cursor", "mcp.json");
|
|
3750
3964
|
return join14(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
3751
3965
|
};
|
|
3752
3966
|
var installMcpConfig = (root, target) => {
|
|
3753
3967
|
const configPath = resolveTargetPath(target, root);
|
|
3754
|
-
const created = !
|
|
3968
|
+
const created = !existsSync15(configPath);
|
|
3755
3969
|
const existing = readJson(configPath);
|
|
3756
3970
|
const servers = existing.mcpServers && typeof existing.mcpServers === "object" && !Array.isArray(existing.mcpServers) ? { ...existing.mcpServers } : {};
|
|
3757
3971
|
servers[SERVER_NAME] = mcpServerEntry(root);
|
|
@@ -3776,7 +3990,7 @@ var installMcpConfig = (root, target) => {
|
|
|
3776
3990
|
var mcpSnippet = (root) => JSON.stringify({ mcpServers: { [SERVER_NAME]: mcpServerEntry(root) } }, null, 2);
|
|
3777
3991
|
|
|
3778
3992
|
// src/cli/demo.ts
|
|
3779
|
-
var packageRoot =
|
|
3993
|
+
var packageRoot = resolve11(dirname7(fileURLToPath(import.meta.url)), "..", "..");
|
|
3780
3994
|
var fixturePath = (fixture) => {
|
|
3781
3995
|
if (fixture === "monorepo") {
|
|
3782
3996
|
return join15(packageRoot, "examples", "demo-monorepo");
|
|
@@ -3797,10 +4011,10 @@ var formatHandoffText = (handoff) => {
|
|
|
3797
4011
|
var runDemo = (root, config, fixture = "example", options = {}) => {
|
|
3798
4012
|
const targetPackage = fixture === "monorepo" ? "auth" : "example";
|
|
3799
4013
|
const fixtureDir = fixturePath(fixture);
|
|
3800
|
-
if (options.copyFixture &&
|
|
4014
|
+
if (options.copyFixture && existsSync16(fixtureDir)) {
|
|
3801
4015
|
for (const rel of ["doc-bridge.config.json", "docs", "packages", "pnpm-workspace.yaml", "package.json"]) {
|
|
3802
4016
|
const src = join15(fixtureDir, rel);
|
|
3803
|
-
if (!
|
|
4017
|
+
if (!existsSync16(src)) continue;
|
|
3804
4018
|
const dest = join15(root, rel);
|
|
3805
4019
|
cpSync(src, dest, { recursive: true });
|
|
3806
4020
|
}
|
|
@@ -3859,11 +4073,11 @@ var withDemoWorkspace = (fixture, fn) => {
|
|
|
3859
4073
|
const dir = mkdtempSync(join15(tmpdir(), "ak-docs-demo-"));
|
|
3860
4074
|
try {
|
|
3861
4075
|
const fixtureDir = fixturePath(fixture);
|
|
3862
|
-
if (!
|
|
4076
|
+
if (!existsSync16(fixtureDir)) {
|
|
3863
4077
|
throw new Error(`Demo fixture "${fixture}" not found at ${fixtureDir}`);
|
|
3864
4078
|
}
|
|
3865
4079
|
cpSync(fixtureDir, dir, { recursive: true });
|
|
3866
|
-
const config = JSON.parse(
|
|
4080
|
+
const config = JSON.parse(readFileSync15(join15(dir, "doc-bridge.config.json"), "utf8"));
|
|
3867
4081
|
return fn(dir, config);
|
|
3868
4082
|
} finally {
|
|
3869
4083
|
rmSync(dir, { recursive: true, force: true });
|
|
@@ -4074,13 +4288,15 @@ var formatDoctorText = (report) => {
|
|
|
4074
4288
|
};
|
|
4075
4289
|
|
|
4076
4290
|
// src/mcp/server.ts
|
|
4077
|
-
import { readFileSync as
|
|
4078
|
-
import { relative as
|
|
4291
|
+
import { readFileSync as readFileSync16, realpathSync as realpathSync7 } from "fs";
|
|
4292
|
+
import { relative as relative5, resolve as resolve12 } from "path";
|
|
4079
4293
|
import { z as z6, ZodError } from "zod";
|
|
4080
4294
|
var MCP_TOOLS = [
|
|
4081
4295
|
{
|
|
4082
4296
|
name: "handoff.resolve",
|
|
4083
|
-
|
|
4297
|
+
title: "Resolve repository handoff",
|
|
4298
|
+
description: "Resolve a package or ownership id to its deterministic AgentHandoff.",
|
|
4299
|
+
annotations: { readOnlyHint: true },
|
|
4084
4300
|
inputSchema: {
|
|
4085
4301
|
type: "object",
|
|
4086
4302
|
properties: { id: { type: "string" }, kind: { type: "string", enum: ["package", "ownership"] } },
|
|
@@ -4089,7 +4305,9 @@ var MCP_TOOLS = [
|
|
|
4089
4305
|
},
|
|
4090
4306
|
{
|
|
4091
4307
|
name: "doc.search",
|
|
4092
|
-
|
|
4308
|
+
title: "Search repository documentation",
|
|
4309
|
+
description: "Search the deterministic Doc Bridge index for repository documentation.",
|
|
4310
|
+
annotations: { readOnlyHint: true },
|
|
4093
4311
|
inputSchema: {
|
|
4094
4312
|
type: "object",
|
|
4095
4313
|
properties: { term: { type: "string" }, limit: { type: "number" } },
|
|
@@ -4098,7 +4316,9 @@ var MCP_TOOLS = [
|
|
|
4098
4316
|
},
|
|
4099
4317
|
{
|
|
4100
4318
|
name: "doc.get",
|
|
4101
|
-
|
|
4319
|
+
title: "Read indexed documentation",
|
|
4320
|
+
description: "Read one indexed agent documentation file by id or indexed path.",
|
|
4321
|
+
annotations: { readOnlyHint: true },
|
|
4102
4322
|
inputSchema: {
|
|
4103
4323
|
type: "object",
|
|
4104
4324
|
properties: { id: { type: "string" }, path: { type: "string" } }
|
|
@@ -4106,12 +4326,16 @@ var MCP_TOOLS = [
|
|
|
4106
4326
|
},
|
|
4107
4327
|
{
|
|
4108
4328
|
name: "gate.status",
|
|
4109
|
-
|
|
4329
|
+
title: "Check documentation gates",
|
|
4330
|
+
description: "Evaluate documentation gates without writing files.",
|
|
4331
|
+
annotations: { readOnlyHint: true },
|
|
4110
4332
|
inputSchema: { type: "object", properties: {} }
|
|
4111
4333
|
},
|
|
4112
4334
|
{
|
|
4113
4335
|
name: "retriever.query",
|
|
4114
|
-
|
|
4336
|
+
title: "Retrieve documentation context",
|
|
4337
|
+
description: "Return relevant local Doc Bridge index chunks for a query.",
|
|
4338
|
+
annotations: { readOnlyHint: true },
|
|
4115
4339
|
inputSchema: {
|
|
4116
4340
|
type: "object",
|
|
4117
4341
|
properties: { query: { type: "string" }, limit: { type: "number" } },
|
|
@@ -4120,17 +4344,23 @@ var MCP_TOOLS = [
|
|
|
4120
4344
|
},
|
|
4121
4345
|
{
|
|
4122
4346
|
name: "memory.classify",
|
|
4123
|
-
|
|
4347
|
+
title: "Classify memory candidates",
|
|
4348
|
+
description: "Classify local memory candidates into agent, human, playbook, or discard routes.",
|
|
4349
|
+
annotations: { readOnlyHint: true },
|
|
4124
4350
|
inputSchema: { type: "object", properties: {} }
|
|
4125
4351
|
},
|
|
4126
4352
|
{
|
|
4127
4353
|
name: "memory.promoteDraft",
|
|
4128
|
-
|
|
4354
|
+
title: "Draft memory promotion",
|
|
4355
|
+
description: "Build a reviewable draft promotion body from local memory candidates without publishing it.",
|
|
4356
|
+
annotations: { readOnlyHint: true },
|
|
4129
4357
|
inputSchema: { type: "object", properties: {} }
|
|
4130
4358
|
},
|
|
4131
4359
|
{
|
|
4132
4360
|
name: "registry.topology",
|
|
4133
|
-
|
|
4361
|
+
title: "Inspect registry topology",
|
|
4362
|
+
description: "Return the static Doc Bridge curator and delegate topology.",
|
|
4363
|
+
annotations: { readOnlyHint: true },
|
|
4134
4364
|
inputSchema: { type: "object", properties: {} }
|
|
4135
4365
|
}
|
|
4136
4366
|
];
|
|
@@ -4181,12 +4411,12 @@ var findDocPath = (index, args) => {
|
|
|
4181
4411
|
return doc.path;
|
|
4182
4412
|
};
|
|
4183
4413
|
var resolveDocPath = (root, relPath) => {
|
|
4184
|
-
const rootAbs =
|
|
4185
|
-
const unresolved =
|
|
4186
|
-
const unresolvedRel =
|
|
4414
|
+
const rootAbs = realpathSync7.native(root);
|
|
4415
|
+
const unresolved = resolve12(rootAbs, relPath);
|
|
4416
|
+
const unresolvedRel = relative5(rootAbs, unresolved);
|
|
4187
4417
|
if (unresolvedRel.startsWith("..")) throw new Error("doc.get path escapes project root");
|
|
4188
|
-
const abs =
|
|
4189
|
-
const rel =
|
|
4418
|
+
const abs = realpathSync7.native(unresolved);
|
|
4419
|
+
const rel = relative5(rootAbs, abs);
|
|
4190
4420
|
if (rel.startsWith("..")) throw new Error("doc.get path escapes project root");
|
|
4191
4421
|
return abs;
|
|
4192
4422
|
};
|
|
@@ -4220,7 +4450,7 @@ var handleMcpRequest = (ctx, request) => {
|
|
|
4220
4450
|
}
|
|
4221
4451
|
if (name === "doc.get") {
|
|
4222
4452
|
const relPath = findDocPath(index(), parseToolArgs("doc.get", DocGetArgsSchema, args));
|
|
4223
|
-
return textResult(
|
|
4453
|
+
return textResult(readFileSync16(resolveDocPath(ctx.root, relPath), "utf8"));
|
|
4224
4454
|
}
|
|
4225
4455
|
if (name === "gate.status") return textResult(runGates(ctx.root, ctx.config));
|
|
4226
4456
|
if (name === "retriever.query") {
|
|
@@ -4247,13 +4477,14 @@ var handleMcpRequest = (ctx, request) => {
|
|
|
4247
4477
|
if (request.method?.startsWith("notifications/")) return void 0;
|
|
4248
4478
|
throw new Error(`Unsupported MCP method "${request.method ?? ""}"`);
|
|
4249
4479
|
};
|
|
4250
|
-
var writeFrame = (payload) => {
|
|
4480
|
+
var writeFrame = (payload, framing) => {
|
|
4251
4481
|
const body = JSON.stringify(payload);
|
|
4252
|
-
process.stdout.write(
|
|
4482
|
+
process.stdout.write(framing === "json-line" ? `${body}
|
|
4483
|
+
` : `Content-Length: ${Buffer.byteLength(body)}\r
|
|
4253
4484
|
\r
|
|
4254
4485
|
${body}`);
|
|
4255
4486
|
};
|
|
4256
|
-
var respond = (ctx, request) => {
|
|
4487
|
+
var respond = (ctx, request, framing) => {
|
|
4257
4488
|
if (request.id === void 0) {
|
|
4258
4489
|
try {
|
|
4259
4490
|
handleMcpRequest(ctx, request);
|
|
@@ -4263,13 +4494,13 @@ var respond = (ctx, request) => {
|
|
|
4263
4494
|
}
|
|
4264
4495
|
try {
|
|
4265
4496
|
const result = handleMcpRequest(ctx, request);
|
|
4266
|
-
writeFrame({ jsonrpc: "2.0", id: request.id, result: result ?? {} });
|
|
4497
|
+
writeFrame({ jsonrpc: "2.0", id: request.id, result: result ?? {} }, framing);
|
|
4267
4498
|
} catch (error) {
|
|
4268
4499
|
writeFrame({
|
|
4269
4500
|
jsonrpc: "2.0",
|
|
4270
4501
|
id: request.id,
|
|
4271
4502
|
error: { code: -32e3, message: error instanceof Error ? error.message : String(error) }
|
|
4272
|
-
});
|
|
4503
|
+
}, framing);
|
|
4273
4504
|
}
|
|
4274
4505
|
};
|
|
4275
4506
|
var startMcpStdioServer = (ctx) => {
|
|
@@ -4277,21 +4508,34 @@ var startMcpStdioServer = (ctx) => {
|
|
|
4277
4508
|
process.stdin.on("data", (chunk) => {
|
|
4278
4509
|
buffer = Buffer.concat([buffer, chunk]);
|
|
4279
4510
|
while (true) {
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4511
|
+
if (/^content-length:/i.test(buffer.subarray(0, Math.min(buffer.length, 32)).toString("utf8"))) {
|
|
4512
|
+
const headerEnd = buffer.indexOf("\r\n\r\n");
|
|
4513
|
+
if (headerEnd === -1) return;
|
|
4514
|
+
const header = buffer.subarray(0, headerEnd).toString("utf8");
|
|
4515
|
+
const match = /content-length:\s*(\d+)/i.exec(header);
|
|
4516
|
+
if (!match?.[1]) {
|
|
4517
|
+
buffer = buffer.subarray(headerEnd + 4);
|
|
4518
|
+
continue;
|
|
4519
|
+
}
|
|
4520
|
+
const length = Number(match[1]);
|
|
4521
|
+
const bodyStart = headerEnd + 4;
|
|
4522
|
+
const bodyEnd = bodyStart + length;
|
|
4523
|
+
if (buffer.length < bodyEnd) return;
|
|
4524
|
+
const raw2 = buffer.subarray(bodyStart, bodyEnd).toString("utf8");
|
|
4525
|
+
buffer = buffer.subarray(bodyEnd);
|
|
4526
|
+
respond(ctx, JSON.parse(raw2), "content-length");
|
|
4286
4527
|
continue;
|
|
4287
4528
|
}
|
|
4288
|
-
const
|
|
4289
|
-
|
|
4290
|
-
const
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4529
|
+
const lineEnd = buffer.indexOf("\n");
|
|
4530
|
+
if (lineEnd === -1) return;
|
|
4531
|
+
const raw = buffer.subarray(0, lineEnd).toString("utf8").trim();
|
|
4532
|
+
buffer = buffer.subarray(lineEnd + 1);
|
|
4533
|
+
if (!raw) continue;
|
|
4534
|
+
try {
|
|
4535
|
+
respond(ctx, JSON.parse(raw), "json-line");
|
|
4536
|
+
} catch {
|
|
4537
|
+
writeFrame({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } }, "json-line");
|
|
4538
|
+
}
|
|
4295
4539
|
}
|
|
4296
4540
|
});
|
|
4297
4541
|
process.stdin.resume();
|
|
@@ -4475,12 +4719,12 @@ var readIndexedDoc = (root, config, idOrPath) => {
|
|
|
4475
4719
|
const index = loadDocBridgeIndex(root, config);
|
|
4476
4720
|
const entry = index.knowledge.find((doc) => doc.id === idOrPath || doc.path === idOrPath);
|
|
4477
4721
|
if (!entry) throw new Error(`Unknown indexed doc "${idOrPath}". Try: search ${idOrPath}`);
|
|
4478
|
-
const abs =
|
|
4479
|
-
const rootAbs =
|
|
4722
|
+
const abs = resolve13(root, entry.path);
|
|
4723
|
+
const rootAbs = resolve13(root);
|
|
4480
4724
|
if (abs !== rootAbs && !abs.startsWith(`${rootAbs}/`)) {
|
|
4481
4725
|
throw new Error(`Indexed doc escapes project root: ${entry.path}`);
|
|
4482
4726
|
}
|
|
4483
|
-
return
|
|
4727
|
+
return readFileSync17(abs, "utf8");
|
|
4484
4728
|
};
|
|
4485
4729
|
var runAskRepl = async (root, config) => {
|
|
4486
4730
|
const index = loadDocBridgeIndex(root, config);
|
|
@@ -4556,8 +4800,8 @@ var diagnosticNextCommands = (config, result) => {
|
|
|
4556
4800
|
];
|
|
4557
4801
|
};
|
|
4558
4802
|
var writeIfMissing = (path, contents) => {
|
|
4559
|
-
if (
|
|
4560
|
-
mkdirSync5(
|
|
4803
|
+
if (existsSync17(path)) return false;
|
|
4804
|
+
mkdirSync5(dirname8(path), { recursive: true });
|
|
4561
4805
|
writeFileSync4(path, contents, "utf8");
|
|
4562
4806
|
return true;
|
|
4563
4807
|
};
|
|
@@ -4661,7 +4905,7 @@ var scaffoldWorkspaceDocs = (root, config) => {
|
|
|
4661
4905
|
const created = [];
|
|
4662
4906
|
const skipped = [];
|
|
4663
4907
|
for (const pkg of discoverPnpmPackages(root, config)) {
|
|
4664
|
-
const path =
|
|
4908
|
+
const path = resolve13(root, config.corpus.agent.root, "packages", `${pkg.id}.md`);
|
|
4665
4909
|
if (writeIfMissing(path, workspaceDocDraft(pkg.id, pkg.path))) created.push(path);
|
|
4666
4910
|
else skipped.push(path);
|
|
4667
4911
|
}
|
|
@@ -4671,11 +4915,11 @@ var bootstrapAgentDocs = (root, config) => {
|
|
|
4671
4915
|
const created = [];
|
|
4672
4916
|
const skipped = [];
|
|
4673
4917
|
for (const doc of scanHumanDocRecords(root, config)) {
|
|
4674
|
-
const raw =
|
|
4918
|
+
const raw = readFileSync17(doc.path, "utf8");
|
|
4675
4919
|
const body = raw.replace(/^---\n[\s\S]*?\n---\n?/, "");
|
|
4676
4920
|
const title = firstHeading(body) ?? doc.id;
|
|
4677
4921
|
const description = firstParagraph(body);
|
|
4678
|
-
const draftPath =
|
|
4922
|
+
const draftPath = resolve13(root, config.corpus.agent.root, "human", `${doc.id}.md`);
|
|
4679
4923
|
const draft = [
|
|
4680
4924
|
"---",
|
|
4681
4925
|
"type: knowledge",
|
|
@@ -4739,8 +4983,8 @@ var runCli = (argv) => {
|
|
|
4739
4983
|
return 1;
|
|
4740
4984
|
}
|
|
4741
4985
|
try {
|
|
4742
|
-
const abs =
|
|
4743
|
-
const raw =
|
|
4986
|
+
const abs = resolve13(file);
|
|
4987
|
+
const raw = readFileSync17(abs, "utf8");
|
|
4744
4988
|
const handoff = parseAgentHandoff(JSON.parse(raw));
|
|
4745
4989
|
writeJson2({ ok: true, handoff });
|
|
4746
4990
|
return 0;
|
|
@@ -4753,10 +4997,10 @@ var runCli = (argv) => {
|
|
|
4753
4997
|
if (command === "init") {
|
|
4754
4998
|
const root = process.cwd();
|
|
4755
4999
|
const withDemo = flags.has("--demo") || !flags.has("--no-demo");
|
|
4756
|
-
const configFile =
|
|
4757
|
-
const docsIndex =
|
|
4758
|
-
const exampleDoc =
|
|
4759
|
-
const agentsMd =
|
|
5000
|
+
const configFile = resolve13(root, configPath ?? "doc-bridge.config.json");
|
|
5001
|
+
const docsIndex = resolve13(root, "docs/for-agents/INDEX.md");
|
|
5002
|
+
const exampleDoc = resolve13(root, "docs/for-agents/packages/example.md");
|
|
5003
|
+
const agentsMd = resolve13(root, "AGENTS.md");
|
|
4760
5004
|
const configWritten = writeIfMissing(configFile, initConfigContents(configFile, withDemo));
|
|
4761
5005
|
const indexWritten = writeIfMissing(
|
|
4762
5006
|
docsIndex,
|
|
@@ -4764,7 +5008,7 @@ var runCli = (argv) => {
|
|
|
4764
5008
|
);
|
|
4765
5009
|
const exampleWritten = withDemo ? writeIfMissing(exampleDoc, exampleAgentDoc) : false;
|
|
4766
5010
|
const agentsWritten = writeIfMissing(agentsMd, agentsMdSnippet);
|
|
4767
|
-
if (withDemo) writeIfMissing(
|
|
5011
|
+
if (withDemo) writeIfMissing(resolve13(root, "src/.gitkeep"), "");
|
|
4768
5012
|
const scaffold = flags.has("--scaffold-workspaces") ? scaffoldWorkspaceDocs(root, loadProject(configFile).config) : void 0;
|
|
4769
5013
|
writeJson2({
|
|
4770
5014
|
ok: true,
|
|
@@ -5007,8 +5251,8 @@ var runCli = (argv) => {
|
|
|
5007
5251
|
const { config, root } = loadProject(configPath);
|
|
5008
5252
|
const report = runDoctor(root, config);
|
|
5009
5253
|
if (flags.has("--write-badge")) {
|
|
5010
|
-
const badgePath =
|
|
5011
|
-
mkdirSync5(
|
|
5254
|
+
const badgePath = resolve13(root, ".doc-bridge", "coverage-badge.json");
|
|
5255
|
+
mkdirSync5(dirname8(badgePath), { recursive: true });
|
|
5012
5256
|
writeFileSync4(badgePath, `${formatDoctorBadgeJson(report.badge)}
|
|
5013
5257
|
`, "utf8");
|
|
5014
5258
|
}
|