@gmickel/gno 1.46.0 → 2.0.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/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/assets/skill/SKILL.md +7 -6
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +32 -33
- package/bunfig.toml +2 -0
- package/package.json +40 -26
- package/spec/cli.md +21 -4
- package/spec/db/schema.sql +146 -1
- package/spec/mcp.md +26 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +2 -0
- package/src/cli/commands/ask.ts +6 -1
- package/src/cli/commands/daemon.ts +21 -8
- package/src/cli/commands/embed.ts +77 -41
- package/src/cli/detach.ts +3 -2
- package/src/config/types.ts +3 -3
- package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
- package/src/converters/adapters/officeparser/adapter.ts +1 -2
- package/src/converters/versions.ts +6 -8
- package/src/core/context-evidence.ts +8 -4
- package/src/core/job-manager.ts +95 -13
- package/src/core/network-boundary-inventory.ts +10 -0
- package/src/core/shutdown-budget.ts +45 -0
- package/src/embed/backlog.ts +107 -4
- package/src/embed/batch.ts +42 -2
- package/src/embed/fingerprint.ts +16 -0
- package/src/embed/retry.ts +113 -5
- package/src/embed/variant-backlog.ts +105 -0
- package/src/embed/variant-plan.ts +62 -0
- package/src/embed/variant-retry.ts +113 -0
- package/src/ingestion/graph-reconciliation.ts +327 -0
- package/src/ingestion/sync.ts +9 -272
- package/src/llm/http-inference.ts +6 -0
- package/src/llm/httpEmbedding.ts +37 -6
- package/src/llm/httpGeneration.ts +18 -3
- package/src/llm/httpRerank.ts +23 -5
- package/src/llm/inference-cancellation.ts +168 -0
- package/src/llm/inference-scope.ts +202 -0
- package/src/llm/lazy-ports.ts +115 -0
- package/src/llm/native-worker/client.ts +541 -0
- package/src/llm/native-worker/dispatcher.ts +228 -0
- package/src/llm/native-worker/embedding-identity.ts +33 -0
- package/src/llm/native-worker/entry.ts +173 -0
- package/src/llm/native-worker/errors.ts +32 -0
- package/src/llm/native-worker/evaluation.ts +16 -0
- package/src/llm/native-worker/owned-exit.ts +108 -0
- package/src/llm/native-worker/owner.ts +141 -0
- package/src/llm/native-worker/ports.ts +317 -0
- package/src/llm/native-worker/protocol.ts +442 -0
- package/src/llm/native-worker/runtime-config.ts +92 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
- package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
- package/src/llm/nodeLlamaCpp/generation.ts +34 -5
- package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
- package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
- package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
- package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
- package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
- package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
- package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
- package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
- package/src/llm/types.ts +35 -5
- package/src/mcp/context.ts +27 -0
- package/src/mcp/http-transport.ts +12 -10
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tool-profile.ts +30 -8
- package/src/mcp/tools/context.ts +8 -11
- package/src/mcp/tools/embed.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +1 -1
- package/src/mcp/tools/index.ts +10 -8
- package/src/mcp/tools/query.ts +14 -30
- package/src/mcp/tools/vsearch.ts +1 -1
- package/src/pipeline/answer.ts +23 -3
- package/src/pipeline/claim-verifier.ts +6 -0
- package/src/pipeline/expansion.ts +43 -40
- package/src/pipeline/explain.ts +6 -2
- package/src/pipeline/filters.ts +63 -0
- package/src/pipeline/fusion.ts +29 -9
- package/src/pipeline/graph-retrieval.ts +29 -9
- package/src/pipeline/hybrid.ts +198 -55
- package/src/pipeline/hydration.ts +161 -0
- package/src/pipeline/owner-fusion.ts +87 -0
- package/src/pipeline/rerank.ts +35 -11
- package/src/pipeline/search.ts +13 -2
- package/src/pipeline/types.ts +5 -3
- package/src/pipeline/vsearch.ts +87 -7
- package/src/sdk/client.ts +47 -3
- package/src/sdk/embed.ts +63 -39
- package/src/serve/background-runtime.ts +1 -1
- package/src/serve/context.ts +41 -56
- package/src/serve/embed-scheduler.ts +58 -35
- package/src/serve/public/components/IndexingProgress.tsx +46 -60
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/shiki-language-ids.ts +14 -0
- package/src/serve/resident-admission.ts +36 -36
- package/src/serve/resident-background-work.ts +20 -2
- package/src/serve/resident-request.ts +11 -5
- package/src/serve/resident-runtime.ts +97 -61
- package/src/serve/resident-shutdown.ts +153 -0
- package/src/serve/routes/api.ts +3 -1
- package/src/serve/server.ts +47 -26
- package/src/store/migrations/028-vector-variants.ts +54 -0
- package/src/store/migrations/029-graph-reference-state.ts +77 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +251 -183
- package/src/store/sqlite/eligibility.ts +174 -0
- package/src/store/sqlite/graph-edge-application.ts +66 -0
- package/src/store/sqlite/graph-reference-state.ts +194 -0
- package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
- package/src/store/types.ts +80 -12
- package/src/store/vector/eligibility.ts +36 -0
- package/src/store/vector/freshness.ts +33 -6
- package/src/store/vector/lazy.ts +81 -0
- package/src/store/vector/sqlite-vec.ts +106 -54
- package/src/store/vector/stats.ts +14 -3
- package/src/store/vector/types.ts +35 -2
- package/src/store/vector/variant-search.ts +192 -0
- package/src/store/vector/variants.ts +451 -0
- package/vendor/converters/markitdown-ts/LICENSE +21 -0
- package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
- package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
- package/vendor/converters/markitdown-ts/package.json +77 -0
- package/vendor/converters/officeparser/LICENSE +21 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
- package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
- package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
- package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
- package/vendor/converters/officeparser/dist/cli.js +381 -0
- package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
- package/vendor/converters/officeparser/dist/defaults.js +218 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
- package/vendor/converters/officeparser/dist/index.d.ts +60 -0
- package/vendor/converters/officeparser/dist/index.js +72 -0
- package/vendor/converters/officeparser/dist/index.mjs +18 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
- package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
- package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
- package/vendor/converters/officeparser/dist/types.js +107 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
- package/vendor/converters/officeparser/package.json +147 -0
- package/vendor/converters/upstream-manifest.json +124 -0
- package/vendor/dependency-fixes/README.md +77 -0
- package/vendor/dependency-fixes/vendor-converters.py +83 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-627emwpj.js +0 -75
- /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
package/src/ingestion/sync.ts
CHANGED
|
@@ -14,7 +14,6 @@ import type { NormalizedContentTypeRule } from "../config";
|
|
|
14
14
|
import type { Collection } from "../config/types";
|
|
15
15
|
import type {
|
|
16
16
|
ChunkInput,
|
|
17
|
-
DocEdgeInput,
|
|
18
17
|
DocLinkInput,
|
|
19
18
|
DocumentInput,
|
|
20
19
|
DocumentRow,
|
|
@@ -49,16 +48,12 @@ import { DEFAULT_LIMITS, type RecordAdapter } from "../converters/types";
|
|
|
49
48
|
import {
|
|
50
49
|
diffDocumentStructure,
|
|
51
50
|
extractDocumentStructure,
|
|
52
|
-
isRelationMap,
|
|
53
|
-
normalizeRelationEdgeType,
|
|
54
|
-
normalizeRelationTarget,
|
|
55
51
|
} from "../core/change-diff";
|
|
56
52
|
import { enforceCollectionEgress } from "../core/egress-enforcement";
|
|
57
53
|
import {
|
|
58
54
|
normalizeMarkdownPath,
|
|
59
55
|
normalizeWikiName,
|
|
60
56
|
parseLinks,
|
|
61
|
-
parseTargetParts,
|
|
62
57
|
} from "../core/links";
|
|
63
58
|
import { extractMemoryScopes } from "../core/memory-record";
|
|
64
59
|
import { normalizeTag, validateTag } from "../core/tags";
|
|
@@ -68,6 +63,7 @@ import {
|
|
|
68
63
|
parseFrontmatter,
|
|
69
64
|
stripFrontmatter,
|
|
70
65
|
} from "./frontmatter";
|
|
66
|
+
import { projectGraph } from "./graph-reconciliation";
|
|
71
67
|
import { buildLineOffsets } from "./position";
|
|
72
68
|
import { processRecordContainer } from "./record-container";
|
|
73
69
|
import {
|
|
@@ -104,8 +100,6 @@ const MAX_CONCURRENCY = 16;
|
|
|
104
100
|
export const INGEST_VERSION = 6;
|
|
105
101
|
const EMPTY_CONTENT_TYPE_RULES_FINGERPRINT =
|
|
106
102
|
fingerprintContentTypeMetadataRules([]);
|
|
107
|
-
const RELATION_EDGE_TYPE_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
108
|
-
const PROJECTION_YIELD_INTERVAL = 25;
|
|
109
103
|
const NON_RETRYABLE_CONVERSION_ERROR_CODES = new Set([
|
|
110
104
|
"CORRUPT",
|
|
111
105
|
"PERMISSION",
|
|
@@ -113,98 +107,6 @@ const NON_RETRYABLE_CONVERSION_ERROR_CODES = new Set([
|
|
|
113
107
|
"UNSUPPORTED",
|
|
114
108
|
]);
|
|
115
109
|
|
|
116
|
-
function findDocByWikiRef(
|
|
117
|
-
docs: DocumentRow[],
|
|
118
|
-
targetRef: string,
|
|
119
|
-
collection?: string
|
|
120
|
-
): DocumentRow | undefined {
|
|
121
|
-
const normalized = normalizeWikiName(targetRef);
|
|
122
|
-
const candidates = collection
|
|
123
|
-
? docs.filter((doc) => doc.collection === collection)
|
|
124
|
-
: docs;
|
|
125
|
-
|
|
126
|
-
return candidates.find((doc) => {
|
|
127
|
-
const title = doc.title ?? doc.relPath.split("/").pop() ?? doc.relPath;
|
|
128
|
-
const relStem = doc.relPath.replace(/\.[^/.]+$/, "");
|
|
129
|
-
return (
|
|
130
|
-
normalizeWikiName(title) === normalized ||
|
|
131
|
-
normalizeWikiName(doc.relPath) === normalized ||
|
|
132
|
-
normalizeWikiName(relStem) === normalized
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function resolveRelationTarget(
|
|
138
|
-
docs: DocumentRow[],
|
|
139
|
-
sourceDoc: DocumentRow,
|
|
140
|
-
rawTarget: string
|
|
141
|
-
): DocumentRow | undefined {
|
|
142
|
-
const target = normalizeRelationTarget(rawTarget);
|
|
143
|
-
if (!target) {
|
|
144
|
-
return undefined;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (target.startsWith("#")) {
|
|
148
|
-
return docs.find((doc) => doc.docid === target);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (target.startsWith("gno://")) {
|
|
152
|
-
return docs.find((doc) => doc.uri === target);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const parts = parseTargetParts(target);
|
|
156
|
-
const targetCollection = parts.collection;
|
|
157
|
-
const targetRef = parts.ref;
|
|
158
|
-
if (!targetRef) {
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (targetCollection) {
|
|
163
|
-
const exact = docs.find(
|
|
164
|
-
(doc) => doc.collection === targetCollection && doc.relPath === targetRef
|
|
165
|
-
);
|
|
166
|
-
return exact ?? findDocByWikiRef(docs, targetRef, targetCollection);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const sameCollectionPath = normalizeMarkdownPath(
|
|
170
|
-
targetRef,
|
|
171
|
-
sourceDoc.relPath
|
|
172
|
-
);
|
|
173
|
-
if (sameCollectionPath) {
|
|
174
|
-
const exact = docs.find(
|
|
175
|
-
(doc) =>
|
|
176
|
-
doc.collection === sourceDoc.collection &&
|
|
177
|
-
doc.relPath === sameCollectionPath
|
|
178
|
-
);
|
|
179
|
-
if (exact) {
|
|
180
|
-
return exact;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const explicitCollPath = docs.find(
|
|
185
|
-
(doc) => `${doc.collection}/${doc.relPath}` === targetRef
|
|
186
|
-
);
|
|
187
|
-
if (explicitCollPath) {
|
|
188
|
-
return explicitCollPath;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return (
|
|
192
|
-
findDocByWikiRef(docs, targetRef, sourceDoc.collection) ??
|
|
193
|
-
findDocByWikiRef(docs, targetRef)
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function getPrimaryGraphHint(
|
|
198
|
-
contentType: string | null | undefined,
|
|
199
|
-
rules: NormalizedContentTypeRule[]
|
|
200
|
-
): string | undefined {
|
|
201
|
-
if (!contentType) {
|
|
202
|
-
return undefined;
|
|
203
|
-
}
|
|
204
|
-
const rule = rules.find((candidate) => candidate.id === contentType);
|
|
205
|
-
return rule?.graphHints?.[0];
|
|
206
|
-
}
|
|
207
|
-
|
|
208
110
|
/**
|
|
209
111
|
* Decide whether to process a file or skip it.
|
|
210
112
|
* Handles repair cases where sourceHash matches but content is incomplete.
|
|
@@ -219,6 +121,11 @@ function decideAction(
|
|
|
219
121
|
if (!existing) {
|
|
220
122
|
return { kind: "process", reason: "new file" };
|
|
221
123
|
}
|
|
124
|
+
// Identical bytes can reappear after deletion; restore through the normal
|
|
125
|
+
// conversion/upsert path so identity, derived data and journal agree.
|
|
126
|
+
if (!existing.active) {
|
|
127
|
+
return { kind: "repair", reason: "source restored" };
|
|
128
|
+
}
|
|
222
129
|
|
|
223
130
|
// Source hash changed - must process
|
|
224
131
|
if (existing.sourceHash !== sourceHash) {
|
|
@@ -1784,182 +1691,12 @@ export class SyncService {
|
|
|
1784
1691
|
return null;
|
|
1785
1692
|
}
|
|
1786
1693
|
|
|
1787
|
-
private
|
|
1694
|
+
private projectTypedEdges(
|
|
1788
1695
|
store: StorePort,
|
|
1789
1696
|
options: SyncOptions,
|
|
1790
1697
|
sourceDocumentIds?: Set<number>
|
|
1791
1698
|
): Promise<Array<{ relPath: string; code: string; message: string }>> {
|
|
1792
|
-
|
|
1793
|
-
[];
|
|
1794
|
-
|
|
1795
|
-
const selectedSourceIds = sourceDocumentIds
|
|
1796
|
-
? [...sourceDocumentIds]
|
|
1797
|
-
: undefined;
|
|
1798
|
-
const backfillResult = await store.backfillDocEdges(selectedSourceIds);
|
|
1799
|
-
if (!backfillResult.ok) {
|
|
1800
|
-
return [
|
|
1801
|
-
{
|
|
1802
|
-
relPath: "(typed edge backfill)",
|
|
1803
|
-
code: backfillResult.error.code,
|
|
1804
|
-
message: backfillResult.error.message,
|
|
1805
|
-
},
|
|
1806
|
-
];
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
const docsResult = await store.listDocuments();
|
|
1810
|
-
if (!docsResult.ok) {
|
|
1811
|
-
return [
|
|
1812
|
-
{
|
|
1813
|
-
relPath: "(typed edge projection)",
|
|
1814
|
-
code: docsResult.error.code,
|
|
1815
|
-
message: docsResult.error.message,
|
|
1816
|
-
},
|
|
1817
|
-
];
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
const activeDocs = docsResult.value.filter((doc) => doc.active);
|
|
1821
|
-
const activeIds = new Set(activeDocs.map((doc) => doc.id));
|
|
1822
|
-
if (selectedSourceIds) {
|
|
1823
|
-
for (const documentId of selectedSourceIds) {
|
|
1824
|
-
if (!activeIds.has(documentId)) {
|
|
1825
|
-
// Clear typed edges for inactivated projection sources.
|
|
1826
|
-
const clearResult = await store.setDocEdges(
|
|
1827
|
-
documentId,
|
|
1828
|
-
[],
|
|
1829
|
-
"frontmatter-relation"
|
|
1830
|
-
);
|
|
1831
|
-
if (!clearResult.ok) {
|
|
1832
|
-
errors.push({
|
|
1833
|
-
relPath: `(doc:${documentId})`,
|
|
1834
|
-
code: clearResult.error.code,
|
|
1835
|
-
message: clearResult.error.message,
|
|
1836
|
-
});
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
const projectedDocs = sourceDocumentIds
|
|
1842
|
-
? activeDocs.filter((doc) => sourceDocumentIds.has(doc.id))
|
|
1843
|
-
: activeDocs;
|
|
1844
|
-
|
|
1845
|
-
for (const [docIndex, doc] of projectedDocs.entries()) {
|
|
1846
|
-
if (docIndex > 0 && docIndex % PROJECTION_YIELD_INTERVAL === 0) {
|
|
1847
|
-
await Bun.sleep(0);
|
|
1848
|
-
}
|
|
1849
|
-
if (!doc.mirrorHash) {
|
|
1850
|
-
continue;
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
const contentResult = await store.getContent(doc.mirrorHash);
|
|
1854
|
-
if (!contentResult.ok || contentResult.value === null) {
|
|
1855
|
-
continue;
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
const relationsValue = parseFrontmatter(contentResult.value).metadata
|
|
1859
|
-
.relations;
|
|
1860
|
-
const relationEdges: DocEdgeInput[] = [];
|
|
1861
|
-
|
|
1862
|
-
if (isRelationMap(relationsValue)) {
|
|
1863
|
-
for (const [rawEdgeType, targets] of Object.entries(relationsValue)) {
|
|
1864
|
-
const edgeType = normalizeRelationEdgeType(rawEdgeType);
|
|
1865
|
-
if (!RELATION_EDGE_TYPE_PATTERN.test(edgeType)) {
|
|
1866
|
-
continue;
|
|
1867
|
-
}
|
|
1868
|
-
for (const target of targets) {
|
|
1869
|
-
const targetDoc = resolveRelationTarget(activeDocs, doc, target);
|
|
1870
|
-
if (targetDoc) {
|
|
1871
|
-
relationEdges.push({
|
|
1872
|
-
targetDocId: targetDoc.id,
|
|
1873
|
-
edgeType,
|
|
1874
|
-
confidence: "manual",
|
|
1875
|
-
});
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
const relationTargetIds = new Set(
|
|
1881
|
-
relationEdges.map((edge) => edge.targetDocId)
|
|
1882
|
-
);
|
|
1883
|
-
|
|
1884
|
-
const relationsResult = await store.setDocEdges(
|
|
1885
|
-
doc.id,
|
|
1886
|
-
relationEdges,
|
|
1887
|
-
"frontmatter-relation"
|
|
1888
|
-
);
|
|
1889
|
-
if (!relationsResult.ok) {
|
|
1890
|
-
errors.push({
|
|
1891
|
-
relPath: doc.relPath,
|
|
1892
|
-
code: relationsResult.error.code,
|
|
1893
|
-
message: relationsResult.error.message,
|
|
1894
|
-
});
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
const primaryHint = getPrimaryGraphHint(
|
|
1898
|
-
doc.contentType,
|
|
1899
|
-
options.contentTypeRules ?? []
|
|
1900
|
-
);
|
|
1901
|
-
if (!primaryHint || !RELATION_EDGE_TYPE_PATTERN.test(primaryHint)) {
|
|
1902
|
-
continue;
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
const linksResult = await store.getLinksForDoc(doc.id);
|
|
1906
|
-
if (!linksResult.ok) {
|
|
1907
|
-
errors.push({
|
|
1908
|
-
relPath: doc.relPath,
|
|
1909
|
-
code: linksResult.error.code,
|
|
1910
|
-
message: linksResult.error.message,
|
|
1911
|
-
});
|
|
1912
|
-
continue;
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
const wikiEdges: DocEdgeInput[] = [];
|
|
1916
|
-
const markdownEdges: DocEdgeInput[] = [];
|
|
1917
|
-
for (const link of linksResult.value) {
|
|
1918
|
-
const targetRef =
|
|
1919
|
-
link.linkType === "markdown"
|
|
1920
|
-
? `${doc.collection}/${link.targetRefNorm}`
|
|
1921
|
-
: link.targetCollection
|
|
1922
|
-
? `${link.targetCollection}:${link.targetRef}`
|
|
1923
|
-
: link.targetRefNorm;
|
|
1924
|
-
const targetDoc = resolveRelationTarget(activeDocs, doc, targetRef);
|
|
1925
|
-
if (!targetDoc || relationTargetIds.has(targetDoc.id)) {
|
|
1926
|
-
continue;
|
|
1927
|
-
}
|
|
1928
|
-
const edge = {
|
|
1929
|
-
targetDocId: targetDoc.id,
|
|
1930
|
-
edgeType: primaryHint,
|
|
1931
|
-
confidence: "configured" as const,
|
|
1932
|
-
};
|
|
1933
|
-
if (link.linkType === "wiki") {
|
|
1934
|
-
wikiEdges.push(edge);
|
|
1935
|
-
} else {
|
|
1936
|
-
markdownEdges.push(edge);
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
const wikiResult = await store.setDocEdges(doc.id, wikiEdges, "wikilink");
|
|
1941
|
-
if (!wikiResult.ok) {
|
|
1942
|
-
errors.push({
|
|
1943
|
-
relPath: doc.relPath,
|
|
1944
|
-
code: wikiResult.error.code,
|
|
1945
|
-
message: wikiResult.error.message,
|
|
1946
|
-
});
|
|
1947
|
-
}
|
|
1948
|
-
const markdownResult = await store.setDocEdges(
|
|
1949
|
-
doc.id,
|
|
1950
|
-
markdownEdges,
|
|
1951
|
-
"markdown-link"
|
|
1952
|
-
);
|
|
1953
|
-
if (!markdownResult.ok) {
|
|
1954
|
-
errors.push({
|
|
1955
|
-
relPath: doc.relPath,
|
|
1956
|
-
code: markdownResult.error.code,
|
|
1957
|
-
message: markdownResult.error.message,
|
|
1958
|
-
});
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
return errors;
|
|
1699
|
+
return projectGraph(store, options, sourceDocumentIds);
|
|
1963
1700
|
}
|
|
1964
1701
|
|
|
1965
1702
|
/** Run an exact global typed-edge reconciliation with cooperative yields. */
|
|
@@ -1967,7 +1704,7 @@ export class SyncService {
|
|
|
1967
1704
|
store: StorePort,
|
|
1968
1705
|
options: SyncOptions = {}
|
|
1969
1706
|
): Promise<Array<{ relPath: string; code: string; message: string }>> {
|
|
1970
|
-
return
|
|
1707
|
+
return projectGraph(store, options, undefined, true);
|
|
1971
1708
|
}
|
|
1972
1709
|
|
|
1973
1710
|
/**
|
|
@@ -21,6 +21,8 @@ import { classifyHttpDestination, prepareHttpDestination } from "./http-policy";
|
|
|
21
21
|
const REDIRECT_STATUSES = new Set([301, 302, 307, 308]);
|
|
22
22
|
|
|
23
23
|
export interface HttpInferenceOptions {
|
|
24
|
+
/** Resolved models.inferenceTimeout; measured across the complete HTTP call. */
|
|
25
|
+
inferenceTimeout?: number;
|
|
24
26
|
collections: readonly Collection[];
|
|
25
27
|
collectionNames: readonly string[];
|
|
26
28
|
authenticated?: boolean;
|
|
@@ -64,6 +66,7 @@ export const requestHttpInference = async (
|
|
|
64
66
|
init: BunFetchRequestInit,
|
|
65
67
|
options: HttpInferenceOptions
|
|
66
68
|
): Promise<Response> => {
|
|
69
|
+
init.signal?.throwIfAborted();
|
|
67
70
|
const states = scopedStates(options);
|
|
68
71
|
if (states.length === 0) {
|
|
69
72
|
enforce(states, "remote", options);
|
|
@@ -118,6 +121,7 @@ export const requestHttpInference = async (
|
|
|
118
121
|
|
|
119
122
|
let currentUrl = url;
|
|
120
123
|
for (;;) {
|
|
124
|
+
init.signal?.throwIfAborted();
|
|
121
125
|
enforce(states, prepared.value.classification.zone, options);
|
|
122
126
|
const connection = await prepared.value.acquireConnection();
|
|
123
127
|
if (!connection.ok) {
|
|
@@ -134,7 +138,9 @@ export const requestHttpInference = async (
|
|
|
134
138
|
})
|
|
135
139
|
);
|
|
136
140
|
}
|
|
141
|
+
init.signal?.throwIfAborted();
|
|
137
142
|
const response = await connection.value.request(init, options.fetchFn);
|
|
143
|
+
init.signal?.throwIfAborted();
|
|
138
144
|
if (!REDIRECT_STATUSES.has(response.status)) return response;
|
|
139
145
|
|
|
140
146
|
const location = response.headers.get("location");
|
package/src/llm/httpEmbedding.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import type { HttpInferenceOptions } from "./http-inference";
|
|
2
|
+
import type { InferenceOptions } from "./types";
|
|
1
3
|
/**
|
|
2
4
|
* HTTP-based embedding port implementation.
|
|
3
5
|
* Calls OpenAI-compatible embedding endpoints.
|
|
4
6
|
*
|
|
5
7
|
* @module src/llm/httpEmbedding
|
|
6
8
|
*/
|
|
7
|
-
|
|
8
|
-
import type { HttpInferenceOptions } from "./http-inference";
|
|
9
9
|
import type { EmbeddingPort, LlmResult } from "./types";
|
|
10
10
|
|
|
11
11
|
import { EgressDeniedError } from "../core/egress-enforcement";
|
|
12
12
|
import { egressDeniedInferenceError, inferenceFailedError } from "./errors";
|
|
13
13
|
import { requestHttpInference } from "./http-inference";
|
|
14
|
+
import { runHttpInference } from "./inference-scope";
|
|
14
15
|
|
|
15
16
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
17
|
// Types
|
|
@@ -58,20 +59,35 @@ export class HttpEmbedding implements EmbeddingPort {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
async init(): Promise<LlmResult<void>> {
|
|
62
|
+
async init(options?: InferenceOptions): Promise<LlmResult<void>> {
|
|
62
63
|
// Test connection with a simple embedding
|
|
63
|
-
const result = await this.embed("test");
|
|
64
|
+
const result = await this.embed("test", options);
|
|
64
65
|
if (!result.ok) {
|
|
65
66
|
return result;
|
|
66
67
|
}
|
|
67
68
|
return { ok: true, value: undefined };
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
async embed(
|
|
71
|
+
async embed(
|
|
72
|
+
text: string,
|
|
73
|
+
options?: InferenceOptions
|
|
74
|
+
): Promise<LlmResult<number[]>> {
|
|
75
|
+
return runHttpInference(
|
|
76
|
+
options,
|
|
77
|
+
(operational) => this.embedRequest(text, operational),
|
|
78
|
+
this.requestOptions.inferenceTimeout
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private async embedRequest(
|
|
83
|
+
text: string,
|
|
84
|
+
options: InferenceOptions
|
|
85
|
+
): Promise<LlmResult<number[]>> {
|
|
71
86
|
try {
|
|
72
87
|
const response = await requestHttpInference(
|
|
73
88
|
this.apiUrl,
|
|
74
89
|
{
|
|
90
|
+
signal: options.signal,
|
|
75
91
|
method: "POST",
|
|
76
92
|
headers: {
|
|
77
93
|
"Content-Type": "application/json",
|
|
@@ -128,11 +144,26 @@ export class HttpEmbedding implements EmbeddingPort {
|
|
|
128
144
|
}
|
|
129
145
|
}
|
|
130
146
|
|
|
131
|
-
async embedBatch(
|
|
147
|
+
async embedBatch(
|
|
148
|
+
texts: string[],
|
|
149
|
+
options?: InferenceOptions
|
|
150
|
+
): Promise<LlmResult<number[][]>> {
|
|
151
|
+
return runHttpInference(
|
|
152
|
+
options,
|
|
153
|
+
(operational) => this.embedBatchRequest(texts, operational),
|
|
154
|
+
this.requestOptions.inferenceTimeout
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private async embedBatchRequest(
|
|
159
|
+
texts: string[],
|
|
160
|
+
options: InferenceOptions
|
|
161
|
+
): Promise<LlmResult<number[][]>> {
|
|
132
162
|
try {
|
|
133
163
|
const response = await requestHttpInference(
|
|
134
164
|
this.apiUrl,
|
|
135
165
|
{
|
|
166
|
+
signal: options.signal,
|
|
136
167
|
method: "POST",
|
|
137
168
|
headers: {
|
|
138
169
|
"Content-Type": "application/json",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import type { HttpInferenceOptions } from "./http-inference";
|
|
2
|
+
import type { InferenceOptions } from "./types";
|
|
1
3
|
/**
|
|
2
4
|
* HTTP-based generation port implementation.
|
|
3
5
|
* Calls OpenAI-compatible chat completion endpoints.
|
|
4
6
|
*
|
|
5
7
|
* @module src/llm/httpGeneration
|
|
6
8
|
*/
|
|
7
|
-
|
|
8
|
-
import type { HttpInferenceOptions } from "./http-inference";
|
|
9
9
|
import type { GenerationPort, GenParams, LlmResult } from "./types";
|
|
10
10
|
|
|
11
11
|
import { EgressDeniedError } from "../core/egress-enforcement";
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
structuredOutputUnavailableError,
|
|
16
16
|
} from "./errors";
|
|
17
17
|
import { requestHttpInference } from "./http-inference";
|
|
18
|
+
import { runHttpInference } from "./inference-scope";
|
|
18
19
|
|
|
19
20
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
21
|
// Types
|
|
@@ -71,7 +72,20 @@ export class HttpGeneration implements GenerationPort {
|
|
|
71
72
|
|
|
72
73
|
async generate(
|
|
73
74
|
prompt: string,
|
|
74
|
-
params?: GenParams
|
|
75
|
+
params?: GenParams,
|
|
76
|
+
options?: InferenceOptions
|
|
77
|
+
): Promise<LlmResult<string>> {
|
|
78
|
+
return runHttpInference(
|
|
79
|
+
options,
|
|
80
|
+
(operational) => this.generateRequest(prompt, params, operational),
|
|
81
|
+
this.requestOptions.inferenceTimeout
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private async generateRequest(
|
|
86
|
+
prompt: string,
|
|
87
|
+
params: GenParams | undefined,
|
|
88
|
+
options: InferenceOptions
|
|
75
89
|
): Promise<LlmResult<string>> {
|
|
76
90
|
if (params?.jsonSchema) {
|
|
77
91
|
return {
|
|
@@ -83,6 +97,7 @@ export class HttpGeneration implements GenerationPort {
|
|
|
83
97
|
const response = await requestHttpInference(
|
|
84
98
|
this.apiUrl,
|
|
85
99
|
{
|
|
100
|
+
signal: options.signal,
|
|
86
101
|
method: "POST",
|
|
87
102
|
headers: {
|
|
88
103
|
"Content-Type": "application/json",
|
package/src/llm/httpRerank.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import type { HttpInferenceOptions } from "./http-inference";
|
|
2
|
+
import type { InferenceOptions } from "./types";
|
|
1
3
|
/**
|
|
2
4
|
* HTTP-based rerank port implementation.
|
|
3
5
|
* Calls OpenAI-compatible completions endpoints for reranking.
|
|
4
6
|
*
|
|
5
7
|
* @module src/llm/httpRerank
|
|
6
8
|
*/
|
|
7
|
-
|
|
8
|
-
import type { HttpInferenceOptions } from "./http-inference";
|
|
9
9
|
import type { LlmResult, RerankPort, RerankScore } from "./types";
|
|
10
10
|
|
|
11
11
|
import { EgressDeniedError } from "../core/egress-enforcement";
|
|
12
12
|
import { egressDeniedInferenceError, inferenceFailedError } from "./errors";
|
|
13
13
|
import { requestHttpInference } from "./http-inference";
|
|
14
|
+
import { runHttpInference } from "./inference-scope";
|
|
14
15
|
|
|
15
16
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
17
|
// Types
|
|
@@ -63,7 +64,20 @@ export class HttpRerank implements RerankPort {
|
|
|
63
64
|
|
|
64
65
|
async rerank(
|
|
65
66
|
query: string,
|
|
66
|
-
documents: string[]
|
|
67
|
+
documents: string[],
|
|
68
|
+
options?: InferenceOptions
|
|
69
|
+
): Promise<LlmResult<RerankScore[]>> {
|
|
70
|
+
return runHttpInference(
|
|
71
|
+
options,
|
|
72
|
+
(operational) => this.rerankRequest(query, documents, operational),
|
|
73
|
+
this.requestOptions.inferenceTimeout
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private async rerankRequest(
|
|
78
|
+
query: string,
|
|
79
|
+
documents: string[],
|
|
80
|
+
options: InferenceOptions
|
|
67
81
|
): Promise<LlmResult<RerankScore[]>> {
|
|
68
82
|
if (documents.length === 0) {
|
|
69
83
|
return { ok: true, value: [] };
|
|
@@ -74,7 +88,7 @@ export class HttpRerank implements RerankPort {
|
|
|
74
88
|
const prompts = documents.map((doc) => this.buildPrompt(query, doc));
|
|
75
89
|
|
|
76
90
|
// Score all documents in a single batch request
|
|
77
|
-
const scoresResult = await this.scoreBatch(prompts);
|
|
91
|
+
const scoresResult = await this.scoreBatch(prompts, options);
|
|
78
92
|
|
|
79
93
|
if (!scoresResult.ok) {
|
|
80
94
|
return { ok: false, error: scoresResult.error };
|
|
@@ -112,11 +126,15 @@ export class HttpRerank implements RerankPort {
|
|
|
112
126
|
return `<Instruct>: ${this.instruction}\n<Query>: ${query}\n<Document>: ${document}\n<Score>:`;
|
|
113
127
|
}
|
|
114
128
|
|
|
115
|
-
private async scoreBatch(
|
|
129
|
+
private async scoreBatch(
|
|
130
|
+
prompts: string[],
|
|
131
|
+
options: InferenceOptions
|
|
132
|
+
): Promise<LlmResult<number[]>> {
|
|
116
133
|
try {
|
|
117
134
|
const response = await requestHttpInference(
|
|
118
135
|
this.apiUrl,
|
|
119
136
|
{
|
|
137
|
+
signal: options.signal,
|
|
120
138
|
method: "POST",
|
|
121
139
|
headers: {
|
|
122
140
|
"Content-Type": "application/json",
|