@treeseed/sdk 0.1.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -506
- package/dist/{src/cli-tools.d.ts → cli-tools.d.ts} +1 -1
- package/dist/cli-tools.js +5 -3
- package/dist/{src/content-store.d.ts → content-store.d.ts} +3 -2
- package/dist/content-store.js +52 -20
- package/dist/{src/d1-store.d.ts → d1-store.d.ts} +62 -1
- package/dist/d1-store.js +625 -65
- package/dist/field-aliases.d.ts +11 -0
- package/dist/field-aliases.js +41 -0
- package/dist/graph/build.d.ts +19 -0
- package/dist/graph/build.js +949 -0
- package/dist/graph/dsl.d.ts +2 -0
- package/dist/graph/dsl.js +243 -0
- package/dist/graph/query.d.ts +47 -0
- package/dist/graph/query.js +447 -0
- package/dist/graph/ranking.d.ts +3 -0
- package/dist/graph/ranking.js +483 -0
- package/dist/graph/schema.d.ts +142 -0
- package/dist/graph/schema.js +133 -0
- package/dist/graph.d.ts +52 -0
- package/dist/graph.js +133 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +91 -2
- package/dist/model-registry.d.ts +8 -0
- package/dist/model-registry.js +351 -25
- package/dist/operations/providers/default.d.ts +10 -0
- package/dist/operations/providers/default.js +514 -0
- package/dist/operations/runtime.d.ts +7 -0
- package/dist/operations/runtime.js +60 -0
- package/dist/operations/services/config-runtime.d.ts +269 -0
- package/dist/operations/services/config-runtime.js +1397 -0
- package/dist/operations/services/d1-migration.d.ts +6 -0
- package/dist/operations/services/d1-migration.js +89 -0
- package/dist/operations/services/deploy.d.ts +371 -0
- package/dist/operations/services/deploy.js +981 -0
- package/dist/operations/services/git-workflow.d.ts +49 -0
- package/dist/operations/services/git-workflow.js +218 -0
- package/dist/operations/services/github-automation.d.ts +156 -0
- package/dist/operations/services/github-automation.js +256 -0
- package/dist/operations/services/local-dev.d.ts +9 -0
- package/dist/operations/services/local-dev.js +106 -0
- package/dist/operations/services/mailpit-runtime.d.ts +4 -0
- package/dist/operations/services/mailpit-runtime.js +59 -0
- package/dist/operations/services/railway-deploy.d.ts +53 -0
- package/dist/operations/services/railway-deploy.js +123 -0
- package/dist/operations/services/runtime-paths.d.ts +19 -0
- package/dist/operations/services/runtime-paths.js +54 -0
- package/dist/operations/services/runtime-tools.d.ts +117 -0
- package/dist/operations/services/runtime-tools.js +358 -0
- package/dist/operations/services/save-deploy-preflight.d.ts +34 -0
- package/dist/operations/services/save-deploy-preflight.js +76 -0
- package/dist/operations/services/template-registry.d.ts +88 -0
- package/dist/operations/services/template-registry.js +407 -0
- package/dist/operations/services/watch-dev.d.ts +21 -0
- package/dist/operations/services/watch-dev.js +284 -0
- package/dist/operations/services/workspace-preflight.d.ts +40 -0
- package/dist/operations/services/workspace-preflight.js +165 -0
- package/dist/operations/services/workspace-save.d.ts +42 -0
- package/dist/operations/services/workspace-save.js +235 -0
- package/dist/operations/services/workspace-tools.d.ts +16 -0
- package/dist/operations/services/workspace-tools.js +270 -0
- package/dist/operations-registry.d.ts +5 -0
- package/dist/operations-registry.js +68 -0
- package/dist/operations-types.d.ts +71 -0
- package/dist/operations-types.js +17 -0
- package/dist/operations.d.ts +6 -0
- package/dist/operations.js +16 -0
- package/dist/platform/books-data.d.ts +1 -0
- package/dist/platform/books-data.js +1 -0
- package/dist/platform/contracts.d.ts +158 -0
- package/dist/platform/contracts.js +0 -0
- package/dist/platform/deploy/config.d.ts +4 -0
- package/dist/platform/deploy/config.js +222 -0
- package/dist/platform/deploy-config.d.ts +1 -0
- package/dist/platform/deploy-config.js +1 -0
- package/dist/platform/deploy-runtime.d.ts +18 -0
- package/dist/platform/deploy-runtime.js +78 -0
- package/dist/platform/env.yaml +394 -0
- package/dist/platform/environment.d.ts +130 -0
- package/dist/platform/environment.js +331 -0
- package/dist/platform/plugin.d.ts +2 -0
- package/dist/platform/plugin.js +4 -0
- package/dist/platform/plugins/constants.d.ts +22 -0
- package/dist/platform/plugins/constants.js +29 -0
- package/dist/platform/plugins/plugin.d.ts +51 -0
- package/dist/platform/plugins/plugin.js +6 -0
- package/dist/platform/plugins/runtime.d.ts +35 -0
- package/dist/platform/plugins/runtime.js +161 -0
- package/dist/platform/plugins.d.ts +6 -0
- package/dist/platform/plugins.js +38 -0
- package/dist/platform/site-config-schema.js +1 -0
- package/dist/platform/tenant/config.d.ts +9 -0
- package/dist/platform/tenant/config.js +154 -0
- package/dist/platform/tenant/runtime-config.d.ts +4 -0
- package/dist/platform/tenant/runtime-config.js +20 -0
- package/dist/platform/tenant-config.d.ts +1 -0
- package/dist/platform/tenant-config.js +1 -0
- package/dist/platform/utils/books-data.d.ts +29 -0
- package/dist/platform/utils/books-data.js +82 -0
- package/dist/platform/utils/site-config-schema.js +321 -0
- package/dist/remote.d.ts +175 -0
- package/dist/remote.js +202 -0
- package/dist/runtime.js +35 -22
- package/dist/scripts/aggregate-book.js +121 -0
- package/dist/scripts/build-dist.js +54 -13
- package/dist/scripts/build-tenant-worker.js +36 -0
- package/dist/scripts/cleanup-markdown.js +373 -0
- package/dist/scripts/cli-test-fixtures.js +48 -0
- package/dist/scripts/config-treeseed.js +95 -0
- package/dist/scripts/ensure-mailpit.js +29 -0
- package/dist/scripts/local-dev.js +129 -0
- package/dist/scripts/logs-mailpit.js +2 -0
- package/dist/scripts/patch-starlight-content-path.js +172 -0
- package/dist/scripts/release-verify.js +34 -6
- package/dist/scripts/run-fixture-astro-command.js +18 -0
- package/dist/scripts/scaffold-site.js +65 -0
- package/dist/scripts/stop-mailpit.js +5 -0
- package/dist/scripts/sync-dev-vars.js +6 -0
- package/dist/scripts/sync-template.js +20 -0
- package/dist/scripts/template-catalog.test.js +100 -0
- package/dist/scripts/template-command.js +31 -0
- package/dist/scripts/tenant-astro-command.js +3 -0
- package/dist/scripts/tenant-build.js +16 -0
- package/dist/scripts/tenant-check.js +7 -0
- package/dist/scripts/tenant-d1-migrate-local.js +11 -0
- package/dist/scripts/tenant-deploy.js +180 -0
- package/dist/scripts/tenant-destroy.js +104 -0
- package/dist/scripts/tenant-dev.js +171 -0
- package/dist/scripts/tenant-lint.js +4 -0
- package/dist/scripts/tenant-test.js +4 -0
- package/dist/scripts/test-cloudflare-local.js +212 -0
- package/dist/scripts/test-scaffold.js +314 -0
- package/dist/scripts/test-smoke.js +71 -13
- package/dist/scripts/treeseed-assert-release-tag-version.js +21 -0
- package/dist/scripts/treeseed-build-dist.js +134 -0
- package/dist/scripts/treeseed-publish-package.js +19 -0
- package/dist/scripts/treeseed-release-verify.js +131 -0
- package/dist/scripts/treeseed-run-ts.js +45 -0
- package/dist/scripts/validate-templates.js +6 -0
- package/dist/scripts/verify-driver.js +29 -0
- package/dist/scripts/workflow-commands.test.js +39 -0
- package/dist/scripts/workspace-close.js +24 -0
- package/dist/scripts/workspace-command-e2e.js +718 -0
- package/dist/scripts/workspace-lint.js +9 -0
- package/dist/scripts/workspace-preflight.js +22 -0
- package/dist/scripts/workspace-publish-changed-packages.js +16 -0
- package/dist/scripts/workspace-release-verify.js +81 -0
- package/dist/scripts/workspace-release.js +42 -0
- package/dist/scripts/workspace-save.js +124 -0
- package/dist/scripts/workspace-start-warning.js +3 -0
- package/dist/scripts/workspace-start.js +71 -0
- package/dist/scripts/workspace-test-unit.js +4 -0
- package/dist/scripts/workspace-test.js +11 -0
- package/dist/sdk-fields.d.ts +11 -0
- package/dist/sdk-fields.js +169 -0
- package/dist/sdk-filters.d.ts +4 -0
- package/dist/sdk-filters.js +12 -15
- package/dist/sdk-types.d.ts +796 -0
- package/dist/sdk-types.js +7 -1
- package/dist/sdk-version.d.ts +2 -0
- package/dist/sdk-version.js +42 -0
- package/dist/sdk.d.ts +215 -0
- package/dist/sdk.js +235 -11
- package/dist/stores/cursor-store.js +9 -3
- package/dist/stores/lease-store.js +8 -2
- package/dist/{src/stores → stores}/message-store.d.ts +1 -1
- package/dist/stores/message-store.js +27 -3
- package/dist/stores/operational-store.d.ts +24 -0
- package/dist/stores/operational-store.js +279 -0
- package/dist/stores/run-store.js +8 -1
- package/dist/stores/subscription-store.js +7 -5
- package/dist/template-catalog.d.ts +13 -0
- package/dist/template-catalog.js +141 -0
- package/dist/treeseed/services/compose.yml +7 -0
- package/dist/treeseed/template-catalog/catalog.fixture.json +55 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +2 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +3 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +32 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +40 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +3 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +19 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +26 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +9 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +90 -0
- package/dist/utils/agents/contracts/messages.d.ts +88 -0
- package/dist/utils/agents/contracts/messages.js +138 -0
- package/dist/utils/agents/contracts/run.d.ts +20 -0
- package/dist/utils/agents/contracts/run.js +0 -0
- package/dist/utils/agents/runtime-types.d.ts +117 -0
- package/dist/utils/agents/runtime-types.js +4 -0
- package/dist/verification.d.ts +20 -0
- package/dist/verification.js +98 -0
- package/dist/workflow/operations.d.ts +396 -0
- package/dist/workflow/operations.js +841 -0
- package/dist/workflow-state.d.ts +56 -0
- package/dist/workflow-state.js +195 -0
- package/dist/workflow-support.d.ts +9 -0
- package/dist/workflow-support.js +176 -0
- package/dist/workflow.d.ts +111 -0
- package/dist/workflow.js +97 -0
- package/package.json +111 -5
- package/scripts/verify-driver.mjs +29 -0
- package/dist/scripts/.ts-run-1775630384291-crtqr3izsa.js +0 -22
- package/dist/scripts/.ts-run-1775630388025-vnjle0z75a.js +0 -129
- package/dist/scripts/assert-release-tag-version.d.ts +0 -1
- package/dist/scripts/build-dist.d.ts +0 -1
- package/dist/scripts/fixture-tools.d.ts +0 -5
- package/dist/scripts/package-tools.d.ts +0 -15
- package/dist/scripts/publish-package.d.ts +0 -1
- package/dist/scripts/release-verify.d.ts +0 -1
- package/dist/scripts/test-smoke.d.ts +0 -1
- package/dist/src/index.d.ts +0 -6
- package/dist/src/model-registry.d.ts +0 -4
- package/dist/src/sdk-filters.d.ts +0 -4
- package/dist/src/sdk-types.d.ts +0 -285
- package/dist/src/sdk.d.ts +0 -109
- package/dist/test/test-fixture.d.ts +0 -1
- package/dist/test/utils/envelopes.test.d.ts +0 -1
- package/dist/test/utils/sdk.test.d.ts +0 -1
- package/dist/vitest.config.d.ts +0 -2
- /package/dist/{src/frontmatter.d.ts → frontmatter.d.ts} +0 -0
- /package/dist/{src/git-runtime.d.ts → git-runtime.d.ts} +0 -0
- /package/dist/{src/runtime.d.ts → runtime.d.ts} +0 -0
- /package/dist/{src/stores → stores}/cursor-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/envelopes.d.ts +0 -0
- /package/dist/{src/stores → stores}/helpers.d.ts +0 -0
- /package/dist/{src/stores → stores}/lease-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/run-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/subscription-store.d.ts +0 -0
- /package/dist/{src/types → types}/agents.d.ts +0 -0
- /package/dist/{src/types → types}/cloudflare.d.ts +0 -0
- /package/dist/{src/wrangler-d1.d.ts → wrangler-d1.d.ts} +0 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import { normalizeText } from "./schema.js";
|
|
2
|
+
const BM25F_FIELDS = {
|
|
3
|
+
title: { weight: 4.8, b: 0.3 },
|
|
4
|
+
headings: { weight: 3.6, b: 0.35 },
|
|
5
|
+
tags: { weight: 2.8, b: 0.2 },
|
|
6
|
+
ids: { weight: 4.2, b: 0.1 },
|
|
7
|
+
summary: { weight: 2.2, b: 0.4 },
|
|
8
|
+
body: { weight: 1, b: 0.8 },
|
|
9
|
+
path: { weight: 1.2, b: 0.25 },
|
|
10
|
+
references: { weight: 0.8, b: 0.15 }
|
|
11
|
+
};
|
|
12
|
+
const DEFAULT_EDGE_WEIGHTS = {
|
|
13
|
+
HAS_SECTION: 0.8,
|
|
14
|
+
BELONGS_TO_FILE: 0.8,
|
|
15
|
+
PARENT_SECTION: 2.2,
|
|
16
|
+
CHILD_SECTION: 2.2,
|
|
17
|
+
NEXT_SECTION: 0.6,
|
|
18
|
+
PREV_SECTION: 0.6,
|
|
19
|
+
LINKS_TO: 1.1,
|
|
20
|
+
REFERENCES: 2.6,
|
|
21
|
+
MENTIONS: 0.8,
|
|
22
|
+
HAS_TAG: 0.4,
|
|
23
|
+
IN_SERIES: 0.5,
|
|
24
|
+
SAME_DIRECTORY: 0.4,
|
|
25
|
+
SAME_COLLECTION: 0.4,
|
|
26
|
+
DEFINES: 0.7,
|
|
27
|
+
DEFINED_BY: 0.7,
|
|
28
|
+
RELATES_TO: 0.9,
|
|
29
|
+
DEPENDS_ON: 3.3,
|
|
30
|
+
IMPLEMENTS: 3.1,
|
|
31
|
+
EXTENDS: 2,
|
|
32
|
+
SUPERSEDES: 0.7,
|
|
33
|
+
BELONGS_TO: 1.3,
|
|
34
|
+
ABOUT: 1.6,
|
|
35
|
+
USED_BY: 1.3,
|
|
36
|
+
GENERATED_FROM: 1.6
|
|
37
|
+
};
|
|
38
|
+
const TOKEN_REGEX = /[a-z0-9]+/gu;
|
|
39
|
+
const BM25F_K1 = 1.2;
|
|
40
|
+
const RWR_RESTART_PROBABILITY = 0.2;
|
|
41
|
+
const RWR_ITERATIONS = 18;
|
|
42
|
+
const MAX_SEED_COUNT = 12;
|
|
43
|
+
function tokenize(value) {
|
|
44
|
+
return normalizeText(value).match(TOKEN_REGEX) ?? [];
|
|
45
|
+
}
|
|
46
|
+
function mapTermFrequencies(tokens) {
|
|
47
|
+
const counts = /* @__PURE__ */ new Map();
|
|
48
|
+
for (const token of tokens) {
|
|
49
|
+
counts.set(token, (counts.get(token) ?? 0) + 1);
|
|
50
|
+
}
|
|
51
|
+
return counts;
|
|
52
|
+
}
|
|
53
|
+
function nodeScope(node) {
|
|
54
|
+
if (node.nodeType === "File") {
|
|
55
|
+
return "files";
|
|
56
|
+
}
|
|
57
|
+
if (node.nodeType === "Section") {
|
|
58
|
+
return "sections";
|
|
59
|
+
}
|
|
60
|
+
return "entities";
|
|
61
|
+
}
|
|
62
|
+
function normalizeDateScore(updatedAt) {
|
|
63
|
+
if (!updatedAt) {
|
|
64
|
+
return 0.35;
|
|
65
|
+
}
|
|
66
|
+
const parsed = Date.parse(updatedAt);
|
|
67
|
+
if (Number.isNaN(parsed)) {
|
|
68
|
+
return 0.35;
|
|
69
|
+
}
|
|
70
|
+
const ageDays = Math.max(0, (Date.now() - parsed) / (1e3 * 60 * 60 * 24));
|
|
71
|
+
if (ageDays <= 30) return 1;
|
|
72
|
+
if (ageDays <= 90) return 0.8;
|
|
73
|
+
if (ageDays <= 180) return 0.55;
|
|
74
|
+
if (ageDays <= 365) return 0.35;
|
|
75
|
+
return 0.15;
|
|
76
|
+
}
|
|
77
|
+
function clamp01(value) {
|
|
78
|
+
return Math.max(0, Math.min(1, value));
|
|
79
|
+
}
|
|
80
|
+
function stagePreference(node, stage) {
|
|
81
|
+
const frontmatter = node.data?.frontmatter;
|
|
82
|
+
const rawType = typeof frontmatter?.type === "string" ? frontmatter.type : node.entityType ?? node.sourceModel ?? node.nodeType;
|
|
83
|
+
const type = normalizeText(String(rawType ?? ""));
|
|
84
|
+
const title = normalizeText(node.title ?? "");
|
|
85
|
+
const isCanonical = node.canonical === true || normalizeText(node.status ?? "") === "canonical";
|
|
86
|
+
switch (stage) {
|
|
87
|
+
case "plan":
|
|
88
|
+
return clamp01(
|
|
89
|
+
(isCanonical ? 0.5 : 0) + (["architecture", "decision", "objective", "knowledge"].includes(type) ? 0.35 : 0) + (["knowledge", "objective", "book"].includes(normalizeText(node.sourceModel ?? "")) ? 0.2 : 0)
|
|
90
|
+
);
|
|
91
|
+
case "implement":
|
|
92
|
+
return clamp01(
|
|
93
|
+
(node.nodeType === "Section" ? 0.25 : 0) + (["api", "schema", "guide", "example"].includes(type) ? 0.55 : 0) + (title.includes("api") || title.includes("schema") || title.includes("example") ? 0.2 : 0)
|
|
94
|
+
);
|
|
95
|
+
case "research":
|
|
96
|
+
return clamp01(0.25 + (node.nodeType === "File" ? 0.1 : 0));
|
|
97
|
+
case "debug":
|
|
98
|
+
return clamp01(
|
|
99
|
+
(["runbook", "troubleshooting", "guide"].includes(type) ? 0.55 : 0) + (title.includes("debug") || title.includes("troubleshoot") ? 0.2 : 0) + (node.nodeType === "Section" ? 0.1 : 0)
|
|
100
|
+
);
|
|
101
|
+
case "review":
|
|
102
|
+
return clamp01(
|
|
103
|
+
(isCanonical ? 0.45 : 0) + (type === "decision" ? 0.35 : 0) + (normalizeText(node.status ?? "") === "deprecated" ? -0.3 : 0)
|
|
104
|
+
);
|
|
105
|
+
default:
|
|
106
|
+
return 0.2;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function canonicalityScore(node, outgoing, incoming) {
|
|
110
|
+
const status = normalizeText(node.status ?? "");
|
|
111
|
+
const hasOutgoingSupersedes = (outgoing.get(node.id) ?? []).some((edge) => edge.edgeType === "SUPERSEDES");
|
|
112
|
+
const hasIncomingSupersedes = (incoming.get(node.id) ?? []).some((edge) => edge.edgeType === "SUPERSEDES");
|
|
113
|
+
let score = node.canonical === true || status === "canonical" ? 1 : status === "live" || status === "in progress" ? 0.6 : status === "deprecated" ? 0.1 : 0.35;
|
|
114
|
+
if (hasOutgoingSupersedes) {
|
|
115
|
+
score += 0.15;
|
|
116
|
+
}
|
|
117
|
+
if (hasIncomingSupersedes) {
|
|
118
|
+
score -= 0.3;
|
|
119
|
+
}
|
|
120
|
+
return clamp01(score);
|
|
121
|
+
}
|
|
122
|
+
function createRankingDocument(node, sectionsByFileId, outgoingEdgeTargets) {
|
|
123
|
+
const frontmatter = node.data?.frontmatter;
|
|
124
|
+
const summary = typeof frontmatter?.summary === "string" ? frontmatter.summary : typeof frontmatter?.description === "string" ? frontmatter.description : "";
|
|
125
|
+
const relatedSectionTitles = node.nodeType === "File" ? (sectionsByFileId.get(node.id) ?? []).map((section) => `${section.heading ?? ""} ${section.headingPath ?? ""}`).join(" ") : node.nodeType === "Section" ? `${node.heading ?? ""} ${node.headingPath ?? ""}` : "";
|
|
126
|
+
const ids = [
|
|
127
|
+
node.id,
|
|
128
|
+
node.entityId,
|
|
129
|
+
node.fileId,
|
|
130
|
+
node.slug,
|
|
131
|
+
node.canonicalId,
|
|
132
|
+
typeof node.data?.explicitId === "string" ? node.data.explicitId : null
|
|
133
|
+
].filter((entry) => typeof entry === "string" && entry.trim().length > 0).join(" ");
|
|
134
|
+
const references = (outgoingEdgeTargets.get(node.id) ?? []).join(" ");
|
|
135
|
+
const fields = {
|
|
136
|
+
title: node.title ?? node.id,
|
|
137
|
+
headings: relatedSectionTitles,
|
|
138
|
+
tags: (node.tags ?? []).join(" "),
|
|
139
|
+
ids,
|
|
140
|
+
summary,
|
|
141
|
+
body: node.text ?? "",
|
|
142
|
+
path: [node.path ?? "", node.sourceModel ?? "", node.slug ?? "", typeof node.data?.relativePath === "string" ? node.data.relativePath : ""].join(" "),
|
|
143
|
+
references
|
|
144
|
+
};
|
|
145
|
+
const fieldTerms = /* @__PURE__ */ new Map();
|
|
146
|
+
const fieldLengths = {};
|
|
147
|
+
for (const field of Object.keys(fields)) {
|
|
148
|
+
const tokens = tokenize(fields[field]);
|
|
149
|
+
fieldTerms.set(field, mapTermFrequencies(tokens));
|
|
150
|
+
fieldLengths[field] = tokens.length;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
node,
|
|
154
|
+
scope: nodeScope(node),
|
|
155
|
+
title: node.title ?? node.id,
|
|
156
|
+
fieldTerms,
|
|
157
|
+
fieldLengths,
|
|
158
|
+
normalizedTitle: normalizeText(node.title ?? node.id),
|
|
159
|
+
normalizedPath: normalizeText(node.path ?? node.slug ?? node.id)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function matchesScope(document, scope) {
|
|
163
|
+
return scope === "all" || document.scope === scope;
|
|
164
|
+
}
|
|
165
|
+
function createDefaultGraphRankingProvider() {
|
|
166
|
+
return {
|
|
167
|
+
id: "default-bm25f-ppr",
|
|
168
|
+
capabilities: ["bm25f", "query-biased-ppr", "diagnostics"],
|
|
169
|
+
buildIndex(input) {
|
|
170
|
+
const nodesById = new Map(input.nodes.map((node) => [node.id, node]));
|
|
171
|
+
const edgesById = new Map(input.edges.map((edge) => [edge.id, edge]));
|
|
172
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
173
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
174
|
+
const sectionsByFileId = /* @__PURE__ */ new Map();
|
|
175
|
+
const outgoingEdgeTargets = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const node of input.nodes) {
|
|
177
|
+
if (node.nodeType === "Section" && node.fileId) {
|
|
178
|
+
const sections = sectionsByFileId.get(node.fileId) ?? [];
|
|
179
|
+
sections.push(node);
|
|
180
|
+
sectionsByFileId.set(node.fileId, sections);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
for (const sections of sectionsByFileId.values()) {
|
|
184
|
+
sections.sort((left, right) => Number(left.data?.ordinal ?? 0) - Number(right.data?.ordinal ?? 0));
|
|
185
|
+
}
|
|
186
|
+
for (const edge of input.edges) {
|
|
187
|
+
const weight = DEFAULT_EDGE_WEIGHTS[edge.type] ?? 1;
|
|
188
|
+
const sourceEdges = outgoing.get(edge.sourceId) ?? [];
|
|
189
|
+
sourceEdges.push({ neighborId: edge.targetId, edgeId: edge.id, edgeType: edge.type, weight });
|
|
190
|
+
outgoing.set(edge.sourceId, sourceEdges);
|
|
191
|
+
const targetEdges = incoming.get(edge.targetId) ?? [];
|
|
192
|
+
targetEdges.push({ neighborId: edge.sourceId, edgeId: edge.id, edgeType: edge.type, weight });
|
|
193
|
+
incoming.set(edge.targetId, targetEdges);
|
|
194
|
+
const targetNode = nodesById.get(edge.targetId);
|
|
195
|
+
if (targetNode) {
|
|
196
|
+
const references = outgoingEdgeTargets.get(edge.sourceId) ?? [];
|
|
197
|
+
references.push(targetNode.slug ?? targetNode.title ?? targetNode.id);
|
|
198
|
+
outgoingEdgeTargets.set(edge.sourceId, references);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const documents = input.nodes.filter((node) => !["Tag", "Series", "Reference"].includes(node.nodeType)).map((node) => createRankingDocument(node, sectionsByFileId, outgoingEdgeTargets));
|
|
202
|
+
const docsByScope = {
|
|
203
|
+
files: documents.filter((doc) => doc.scope === "files"),
|
|
204
|
+
sections: documents.filter((doc) => doc.scope === "sections"),
|
|
205
|
+
entities: documents.filter((doc) => doc.scope === "entities"),
|
|
206
|
+
all: documents
|
|
207
|
+
};
|
|
208
|
+
const averageFieldLengths = {};
|
|
209
|
+
for (const field of Object.keys(BM25F_FIELDS)) {
|
|
210
|
+
const total = documents.reduce((sum, document) => sum + document.fieldLengths[field], 0);
|
|
211
|
+
averageFieldLengths[field] = documents.length > 0 ? Math.max(1, total / documents.length) : 1;
|
|
212
|
+
}
|
|
213
|
+
const documentFrequency = /* @__PURE__ */ new Map();
|
|
214
|
+
for (const document of documents) {
|
|
215
|
+
const seen = /* @__PURE__ */ new Set();
|
|
216
|
+
for (const frequencies of document.fieldTerms.values()) {
|
|
217
|
+
for (const term of frequencies.keys()) {
|
|
218
|
+
seen.add(term);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const term of seen) {
|
|
222
|
+
documentFrequency.set(term, (documentFrequency.get(term) ?? 0) + 1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function bm25fScore(document, query) {
|
|
226
|
+
const queryTerms = tokenize(query);
|
|
227
|
+
if (queryTerms.length === 0) {
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
let score = 0;
|
|
231
|
+
for (const term of queryTerms) {
|
|
232
|
+
const matchingTerms = /* @__PURE__ */ new Set();
|
|
233
|
+
for (const frequencies of document.fieldTerms.values()) {
|
|
234
|
+
for (const candidate of frequencies.keys()) {
|
|
235
|
+
if (candidate === term || candidate.startsWith(term)) {
|
|
236
|
+
matchingTerms.add(candidate);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (matchingTerms.size === 0) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
let weightedTf = 0;
|
|
244
|
+
let termDf = 0;
|
|
245
|
+
for (const matched of matchingTerms) {
|
|
246
|
+
termDf += documentFrequency.get(matched) ?? 0;
|
|
247
|
+
for (const field of Object.keys(BM25F_FIELDS)) {
|
|
248
|
+
const tf = document.fieldTerms.get(field)?.get(matched) ?? 0;
|
|
249
|
+
if (tf <= 0) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const { weight, b } = BM25F_FIELDS[field];
|
|
253
|
+
const normalizedTf = tf / (1 - b + b * (document.fieldLengths[field] / averageFieldLengths[field]));
|
|
254
|
+
weightedTf += weight * normalizedTf;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (weightedTf <= 0) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const idf = Math.log(1 + (documents.length - termDf + 0.5) / (termDf + 0.5));
|
|
261
|
+
score += idf * ((BM25F_K1 + 1) * weightedTf / (BM25F_K1 + weightedTf));
|
|
262
|
+
}
|
|
263
|
+
const normalizedQuery = normalizeText(query);
|
|
264
|
+
if (normalizedQuery && document.normalizedTitle.includes(normalizedQuery)) {
|
|
265
|
+
score += 2.5;
|
|
266
|
+
}
|
|
267
|
+
if (normalizedQuery && document.normalizedPath.includes(normalizedQuery)) {
|
|
268
|
+
score += 1.25;
|
|
269
|
+
}
|
|
270
|
+
return score;
|
|
271
|
+
}
|
|
272
|
+
function search(request) {
|
|
273
|
+
const collection = docsByScope[request.scope];
|
|
274
|
+
const scored = collection.map((document) => ({
|
|
275
|
+
document,
|
|
276
|
+
score: bm25fScore(document, request.query)
|
|
277
|
+
})).filter((entry) => request.query.trim().length === 0 || entry.score > 0).sort((left, right) => right.score - left.score || left.document.title.localeCompare(right.document.title) || left.document.node.id.localeCompare(right.document.node.id)).slice(0, request.options?.limit ?? 20);
|
|
278
|
+
return scored.map(({ document, score }) => ({
|
|
279
|
+
node: document.node,
|
|
280
|
+
score,
|
|
281
|
+
reason: `bm25f:${document.scope}`,
|
|
282
|
+
highlights: tokenize(request.query),
|
|
283
|
+
context: document.node.nodeType === "File" ? { topSections: (sectionsByFileId.get(document.node.id) ?? []).slice(0, 3).map((section) => section.id) } : document.node.nodeType === "Section" ? { fileId: document.node.fileId ?? null } : { fileId: document.node.fileId ?? null }
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
286
|
+
function buildTraversals(request) {
|
|
287
|
+
const allowedNodeIds = new Set(request.allowedNodeIds ?? documents.map((document) => document.node.id));
|
|
288
|
+
const requestedWeights = request.request.options?.edgeWeights ?? {};
|
|
289
|
+
const allowedEdgeTypes = request.allowedEdgeTypes?.length ? new Set(request.allowedEdgeTypes) : null;
|
|
290
|
+
const direction = request.request.options?.direction ?? "both";
|
|
291
|
+
const depthLimit = request.request.options?.depth ?? 1;
|
|
292
|
+
const seeds = request.seedIds.slice(0, MAX_SEED_COUNT);
|
|
293
|
+
const queue = seeds.map((nodeId) => ({ nodeId, depth: 0, seedId: nodeId }));
|
|
294
|
+
const distances = /* @__PURE__ */ new Map();
|
|
295
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
296
|
+
const seedIdsByNode = /* @__PURE__ */ new Map();
|
|
297
|
+
const viaEdgeTypes = /* @__PURE__ */ new Map();
|
|
298
|
+
const traversedEdgeIds = /* @__PURE__ */ new Set();
|
|
299
|
+
for (const seedId of seeds) {
|
|
300
|
+
distances.set(seedId, 0);
|
|
301
|
+
reasons.set(seedId, /* @__PURE__ */ new Set(["seed"]));
|
|
302
|
+
seedIdsByNode.set(seedId, /* @__PURE__ */ new Set([seedId]));
|
|
303
|
+
viaEdgeTypes.set(seedId, /* @__PURE__ */ new Set());
|
|
304
|
+
}
|
|
305
|
+
while (queue.length > 0) {
|
|
306
|
+
const current = queue.shift();
|
|
307
|
+
if (current.depth >= depthLimit) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
const traversals = [];
|
|
311
|
+
if (direction !== "incoming") {
|
|
312
|
+
traversals.push(...(outgoing.get(current.nodeId) ?? []).map((edge) => ({ ...edge, weight: requestedWeights[edge.edgeType] ?? edge.weight })));
|
|
313
|
+
}
|
|
314
|
+
if (direction !== "outgoing") {
|
|
315
|
+
traversals.push(...(incoming.get(current.nodeId) ?? []).map((edge) => ({ ...edge, weight: requestedWeights[edge.edgeType] ?? edge.weight })));
|
|
316
|
+
}
|
|
317
|
+
for (const traversal of traversals) {
|
|
318
|
+
if (allowedEdgeTypes && !allowedEdgeTypes.has(traversal.edgeType)) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (!allowedNodeIds.has(traversal.neighborId)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
traversedEdgeIds.add(traversal.edgeId);
|
|
325
|
+
const nextDepth = current.depth + 1;
|
|
326
|
+
const previousDepth = distances.get(traversal.neighborId);
|
|
327
|
+
if (previousDepth === void 0 || nextDepth < previousDepth) {
|
|
328
|
+
distances.set(traversal.neighborId, nextDepth);
|
|
329
|
+
queue.push({ nodeId: traversal.neighborId, depth: nextDepth, seedId: current.seedId });
|
|
330
|
+
}
|
|
331
|
+
const nodeReasons = reasons.get(traversal.neighborId) ?? /* @__PURE__ */ new Set();
|
|
332
|
+
nodeReasons.add(`via:${traversal.edgeType}`);
|
|
333
|
+
reasons.set(traversal.neighborId, nodeReasons);
|
|
334
|
+
const nodeSeedIds = seedIdsByNode.get(traversal.neighborId) ?? /* @__PURE__ */ new Set();
|
|
335
|
+
nodeSeedIds.add(current.seedId);
|
|
336
|
+
seedIdsByNode.set(traversal.neighborId, nodeSeedIds);
|
|
337
|
+
const nodeVia = viaEdgeTypes.get(traversal.neighborId) ?? /* @__PURE__ */ new Set();
|
|
338
|
+
nodeVia.add(traversal.edgeType);
|
|
339
|
+
viaEdgeTypes.set(traversal.neighborId, nodeVia);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return { allowedNodeIds, distances, reasons, seedIdsByNode, viaEdgeTypes, traversedEdgeIds };
|
|
343
|
+
}
|
|
344
|
+
function runQueryBiasedPageRank(request, lexicalScores) {
|
|
345
|
+
const traversal = buildTraversals(request);
|
|
346
|
+
const frontierIds = [...traversal.distances.keys()];
|
|
347
|
+
if (frontierIds.length === 0) {
|
|
348
|
+
return { scores: /* @__PURE__ */ new Map(), traversal };
|
|
349
|
+
}
|
|
350
|
+
const seedWeights = /* @__PURE__ */ new Map();
|
|
351
|
+
const fallbackWeight = request.seedMatches?.length ? request.seedMatches[0].score || 1 : 1;
|
|
352
|
+
for (const seedId of request.seedIds.slice(0, MAX_SEED_COUNT)) {
|
|
353
|
+
const lexical = lexicalScores.get(seedId) ?? request.seedMatches?.find((match) => match.node.id === seedId)?.score ?? fallbackWeight;
|
|
354
|
+
seedWeights.set(seedId, Math.max(lexical, 1e-4));
|
|
355
|
+
}
|
|
356
|
+
const seedWeightSum = [...seedWeights.values()].reduce((sum, value) => sum + value, 0) || 1;
|
|
357
|
+
const seedProbability = new Map([...seedWeights.entries()].map(([nodeId, value]) => [nodeId, value / seedWeightSum]));
|
|
358
|
+
let current = new Map(frontierIds.map((nodeId) => [nodeId, seedProbability.get(nodeId) ?? 0]));
|
|
359
|
+
const requestedWeights = request.request.options?.edgeWeights ?? {};
|
|
360
|
+
const allowedEdgeTypes = request.allowedEdgeTypes?.length ? new Set(request.allowedEdgeTypes) : null;
|
|
361
|
+
const direction = request.request.options?.direction ?? "both";
|
|
362
|
+
for (let iteration = 0; iteration < RWR_ITERATIONS; iteration += 1) {
|
|
363
|
+
const next = new Map(frontierIds.map((nodeId) => [nodeId, RWR_RESTART_PROBABILITY * (seedProbability.get(nodeId) ?? 0)]));
|
|
364
|
+
for (const nodeId of frontierIds) {
|
|
365
|
+
const currentScore = current.get(nodeId) ?? 0;
|
|
366
|
+
if (currentScore <= 0) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
const traversals = [];
|
|
370
|
+
if (direction !== "incoming") {
|
|
371
|
+
traversals.push(...(outgoing.get(nodeId) ?? []).map((edge) => ({ ...edge, weight: requestedWeights[edge.edgeType] ?? edge.weight })));
|
|
372
|
+
}
|
|
373
|
+
if (direction !== "outgoing") {
|
|
374
|
+
traversals.push(...(incoming.get(nodeId) ?? []).map((edge) => ({ ...edge, weight: requestedWeights[edge.edgeType] ?? edge.weight })));
|
|
375
|
+
}
|
|
376
|
+
const filtered = traversals.filter((edge) => frontierIds.includes(edge.neighborId) && (!allowedEdgeTypes || allowedEdgeTypes.has(edge.edgeType)));
|
|
377
|
+
const weightSum = filtered.reduce((sum, edge) => sum + Math.max(edge.weight, 1e-4), 0);
|
|
378
|
+
if (weightSum <= 0) {
|
|
379
|
+
const restart = next.get(nodeId) ?? 0;
|
|
380
|
+
next.set(nodeId, restart + (1 - RWR_RESTART_PROBABILITY) * currentScore);
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
for (const edge of filtered) {
|
|
384
|
+
const share = (1 - RWR_RESTART_PROBABILITY) * currentScore * Math.max(edge.weight, 1e-4) / weightSum;
|
|
385
|
+
next.set(edge.neighborId, (next.get(edge.neighborId) ?? 0) + share);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
current = next;
|
|
389
|
+
}
|
|
390
|
+
return { scores: current, traversal };
|
|
391
|
+
}
|
|
392
|
+
function rankQuery(request) {
|
|
393
|
+
const eligibleIds = new Set(request.allowedNodeIds ?? documents.map((document) => document.node.id));
|
|
394
|
+
const lexicalScores = /* @__PURE__ */ new Map();
|
|
395
|
+
if (request.request.query?.trim()) {
|
|
396
|
+
for (const document of documents) {
|
|
397
|
+
if (!eligibleIds.has(document.node.id)) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const score = bm25fScore(document, request.request.query);
|
|
401
|
+
if (score > 0) {
|
|
402
|
+
lexicalScores.set(document.node.id, score);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
for (const match of request.seedMatches ?? []) {
|
|
407
|
+
if (eligibleIds.has(match.node.id)) {
|
|
408
|
+
lexicalScores.set(match.node.id, Math.max(match.score, lexicalScores.get(match.node.id) ?? 0));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
for (const seedId of request.seedIds) {
|
|
412
|
+
if (eligibleIds.has(seedId)) {
|
|
413
|
+
lexicalScores.set(seedId, Math.max(lexicalScores.get(seedId) ?? 0, 1));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const maxLexical = Math.max(1, ...lexicalScores.values());
|
|
417
|
+
const { scores: graphScores, traversal } = runQueryBiasedPageRank(request, lexicalScores);
|
|
418
|
+
const maxGraph = Math.max(1e-6, ...graphScores.values(), 0);
|
|
419
|
+
const maxNodes = request.request.options?.maxNodes ?? request.request.options?.limit ?? 25;
|
|
420
|
+
const ranked = [...traversal.distances.entries()].map(([nodeId, depth]) => {
|
|
421
|
+
const node = nodesById.get(nodeId);
|
|
422
|
+
const lexicalScore = clamp01((lexicalScores.get(nodeId) ?? 0) / maxLexical);
|
|
423
|
+
const graphScore = clamp01((graphScores.get(nodeId) ?? 0) / maxGraph);
|
|
424
|
+
const nodeCanonicality = canonicalityScore(node, outgoing, incoming);
|
|
425
|
+
const freshnessScore = normalizeDateScore(node.updatedAt);
|
|
426
|
+
const stageScore = stagePreference(node, request.request.stage);
|
|
427
|
+
const priorScore = clamp01(0.5 * nodeCanonicality + 0.2 * freshnessScore + 0.3 * stageScore);
|
|
428
|
+
const finalScore = 0.55 * lexicalScore + 0.25 * graphScore + 0.2 * priorScore;
|
|
429
|
+
const diagnostics = {
|
|
430
|
+
providerId: "default-bm25f-ppr",
|
|
431
|
+
lexicalScore,
|
|
432
|
+
graphScore,
|
|
433
|
+
priorScore,
|
|
434
|
+
canonicalityScore: nodeCanonicality,
|
|
435
|
+
freshnessScore,
|
|
436
|
+
stageScore,
|
|
437
|
+
finalScore
|
|
438
|
+
};
|
|
439
|
+
return {
|
|
440
|
+
nodeId,
|
|
441
|
+
score: finalScore,
|
|
442
|
+
depth,
|
|
443
|
+
reasons: [...traversal.reasons.get(nodeId) ?? /* @__PURE__ */ new Set(["seed"])],
|
|
444
|
+
seedIds: [...traversal.seedIdsByNode.get(nodeId) ?? new Set(request.seedIds.includes(nodeId) ? [nodeId] : request.seedIds)],
|
|
445
|
+
viaEdgeTypes: [...traversal.viaEdgeTypes.get(nodeId) ?? /* @__PURE__ */ new Set()],
|
|
446
|
+
diagnostics
|
|
447
|
+
};
|
|
448
|
+
}).filter((entry) => entry.score >= (request.request.options?.scoreThreshold ?? Number.NEGATIVE_INFINITY)).sort((left, right) => right.score - left.score || left.depth - right.depth || (nodesById.get(left.nodeId)?.title ?? left.nodeId).localeCompare(nodesById.get(right.nodeId)?.title ?? right.nodeId)).slice(0, maxNodes);
|
|
449
|
+
return {
|
|
450
|
+
providerId: "default-bm25f-ppr",
|
|
451
|
+
nodes: ranked,
|
|
452
|
+
edgeIds: [...traversal.traversedEdgeIds],
|
|
453
|
+
diagnostics: {
|
|
454
|
+
seedCount: request.seedIds.length,
|
|
455
|
+
frontierNodeCount: traversal.distances.size,
|
|
456
|
+
maxLexicalScore: maxLexical,
|
|
457
|
+
maxGraphScore: maxGraph
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
search,
|
|
463
|
+
rankQuery,
|
|
464
|
+
serialize() {
|
|
465
|
+
return {
|
|
466
|
+
providerId: "default-bm25f-ppr",
|
|
467
|
+
documentCount: documents.length,
|
|
468
|
+
scopeCounts: {
|
|
469
|
+
files: docsByScope.files.length,
|
|
470
|
+
sections: docsByScope.sections.length,
|
|
471
|
+
entities: docsByScope.entities.length
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
const DEFAULT_GRAPH_RANKING_PROVIDER = createDefaultGraphRankingProvider();
|
|
480
|
+
export {
|
|
481
|
+
DEFAULT_GRAPH_RANKING_PROVIDER,
|
|
482
|
+
createDefaultGraphRankingProvider
|
|
483
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { SdkGraphEdge, SdkGraphEdgeType, SdkGraphModelConfig, SdkGraphNode, SdkGraphNodeType, SdkModelDefinition, SdkModelRegistry } from '../sdk-types.ts';
|
|
2
|
+
export declare const GRAPH_SNAPSHOT_VERSION = 1;
|
|
3
|
+
export declare const AUTHORED_GRAPH_EDGE_TYPES: ["REFERENCES", "HAS_TAG", "IN_SERIES", "RELATES_TO", "DEPENDS_ON", "IMPLEMENTS", "EXTENDS", "SUPERSEDES", "BELONGS_TO", "ABOUT", "USED_BY", "GENERATED_FROM"];
|
|
4
|
+
export type AuthoredGraphEdgeType = (typeof AUTHORED_GRAPH_EDGE_TYPES)[number];
|
|
5
|
+
export type GraphFileCatalogEntry = {
|
|
6
|
+
path: string;
|
|
7
|
+
relativePath: string;
|
|
8
|
+
model: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
fileId: string;
|
|
11
|
+
hash: string;
|
|
12
|
+
};
|
|
13
|
+
export type ParsedGraphLink = {
|
|
14
|
+
url: string;
|
|
15
|
+
text: string;
|
|
16
|
+
startOffset: number;
|
|
17
|
+
endOffset: number;
|
|
18
|
+
};
|
|
19
|
+
export type ParsedGraphHeading = {
|
|
20
|
+
text: string;
|
|
21
|
+
slug: string;
|
|
22
|
+
level: number;
|
|
23
|
+
startOffset: number;
|
|
24
|
+
endOffset: number;
|
|
25
|
+
};
|
|
26
|
+
export type ParsedGraphSection = {
|
|
27
|
+
id: string;
|
|
28
|
+
fileId: string;
|
|
29
|
+
heading: string | null;
|
|
30
|
+
headingSlug: string;
|
|
31
|
+
headingPath: string;
|
|
32
|
+
level: number;
|
|
33
|
+
ordinal: number;
|
|
34
|
+
startOffset: number;
|
|
35
|
+
endOffset: number;
|
|
36
|
+
rawText: string;
|
|
37
|
+
normalizedText: string;
|
|
38
|
+
outboundLinks: ParsedGraphLink[];
|
|
39
|
+
referencedEntityIds: string[];
|
|
40
|
+
};
|
|
41
|
+
export type ParsedGraphDocument = {
|
|
42
|
+
fileId: string;
|
|
43
|
+
entityId: string;
|
|
44
|
+
model: string;
|
|
45
|
+
entityType: string;
|
|
46
|
+
slug: string;
|
|
47
|
+
title: string;
|
|
48
|
+
path: string;
|
|
49
|
+
relativePath: string;
|
|
50
|
+
dirname: string;
|
|
51
|
+
body: string;
|
|
52
|
+
normalizedBody: string;
|
|
53
|
+
frontmatter: Record<string, unknown>;
|
|
54
|
+
explicitId: string | null;
|
|
55
|
+
tags: string[];
|
|
56
|
+
series: string | null;
|
|
57
|
+
status: string | null;
|
|
58
|
+
canonical: boolean;
|
|
59
|
+
canonicalRef: string | null;
|
|
60
|
+
version: string | null;
|
|
61
|
+
domain: string | null;
|
|
62
|
+
audience: string[];
|
|
63
|
+
updatedAt: string | null;
|
|
64
|
+
sections: ParsedGraphSection[];
|
|
65
|
+
headings: ParsedGraphHeading[];
|
|
66
|
+
links: ParsedGraphLink[];
|
|
67
|
+
mdxImports: string[];
|
|
68
|
+
explicitReferences: Array<{
|
|
69
|
+
field: string;
|
|
70
|
+
value: string;
|
|
71
|
+
targetModels?: string[];
|
|
72
|
+
edgeType: AuthoredGraphEdgeType;
|
|
73
|
+
}>;
|
|
74
|
+
};
|
|
75
|
+
export type GraphValidation = {
|
|
76
|
+
missingIds: string[];
|
|
77
|
+
duplicateIds: string[];
|
|
78
|
+
brokenReferences: Array<{
|
|
79
|
+
ownerFileId: string;
|
|
80
|
+
value: string;
|
|
81
|
+
edgeType: SdkGraphEdgeType;
|
|
82
|
+
}>;
|
|
83
|
+
invalidEdgeTypes: Array<{
|
|
84
|
+
ownerFileId: string;
|
|
85
|
+
field: string;
|
|
86
|
+
edgeType: string;
|
|
87
|
+
}>;
|
|
88
|
+
invalidCanonicalRefs: Array<{
|
|
89
|
+
ownerFileId: string;
|
|
90
|
+
value: string;
|
|
91
|
+
}>;
|
|
92
|
+
invalidSupersedesRefs: Array<{
|
|
93
|
+
ownerFileId: string;
|
|
94
|
+
value: string;
|
|
95
|
+
}>;
|
|
96
|
+
};
|
|
97
|
+
export type GraphMetrics = {
|
|
98
|
+
totalFiles: number;
|
|
99
|
+
totalSections: number;
|
|
100
|
+
totalEntities: number;
|
|
101
|
+
totalEdges: number;
|
|
102
|
+
unresolvedReferences: number;
|
|
103
|
+
validation: {
|
|
104
|
+
missingIds: number;
|
|
105
|
+
duplicateIds: number;
|
|
106
|
+
brokenReferences: number;
|
|
107
|
+
invalidEdgeTypes: number;
|
|
108
|
+
invalidCanonicalRefs: number;
|
|
109
|
+
invalidSupersedesRefs: number;
|
|
110
|
+
};
|
|
111
|
+
queryCounts: Record<string, number>;
|
|
112
|
+
topTraversedEdgeTypes: Record<string, number>;
|
|
113
|
+
lastRefreshAt: string | null;
|
|
114
|
+
};
|
|
115
|
+
export type GraphDelta = {
|
|
116
|
+
added: string[];
|
|
117
|
+
modified: string[];
|
|
118
|
+
removed: string[];
|
|
119
|
+
};
|
|
120
|
+
export type GraphSnapshot = {
|
|
121
|
+
version: number;
|
|
122
|
+
modelSignature: string;
|
|
123
|
+
documents: ParsedGraphDocument[];
|
|
124
|
+
nodes: SdkGraphNode[];
|
|
125
|
+
edges: SdkGraphEdge[];
|
|
126
|
+
catalog: GraphFileCatalogEntry[];
|
|
127
|
+
metrics: GraphMetrics;
|
|
128
|
+
validation: GraphValidation;
|
|
129
|
+
delta: GraphDelta;
|
|
130
|
+
};
|
|
131
|
+
export declare function sha1(value: string): string;
|
|
132
|
+
export declare function computeEdgeId(sourceId: string, edgeType: SdkGraphEdgeType, targetId: string, provenance?: string): string;
|
|
133
|
+
export declare function createFileNodeId(model: string, slug: string): string;
|
|
134
|
+
export declare function createEntityNodeId(definition: SdkModelDefinition, slug: string, frontmatter: Record<string, unknown>): string;
|
|
135
|
+
export declare function normalizeText(value: string): string;
|
|
136
|
+
export declare function ensureArray(value: unknown): string[];
|
|
137
|
+
export declare function builtinEntityTypeFor(model: string): SdkGraphNodeType;
|
|
138
|
+
export declare function resolveGraphModelConfig(definition: SdkModelDefinition): Required<SdkGraphModelConfig>;
|
|
139
|
+
export declare function computeModelSignature(models: SdkModelRegistry): string;
|
|
140
|
+
export declare function graphSnapshotRoot(repoRoot: string): string;
|
|
141
|
+
export declare function emptyGraphMetrics(): GraphMetrics;
|
|
142
|
+
export declare function emptyGraphValidation(): GraphValidation;
|