@gmickel/gno 1.27.1 → 1.28.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 +2 -2
- package/assets/skill/SKILL.md +26 -1
- package/browser-extension/artifacts/{gno-browser-clipper-v1.27.1.zip → gno-browser-clipper-v1.28.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.28.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/spec/cli.md +41 -4
- package/spec/db/schema.sql +12 -0
- package/spec/mcp.md +5 -0
- package/spec/output-schemas/ask.schema.json +125 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +94 -1
- package/spec/output-schemas/get.schema.json +94 -0
- package/spec/output-schemas/mcp-job-status.schema.json +28 -0
- package/spec/output-schemas/multi-get.schema.json +128 -0
- package/spec/output-schemas/record-import.schema.json +193 -0
- package/spec/output-schemas/search-result.schema.json +94 -0
- package/spec/output-schemas/search-results.schema.json +125 -0
- package/spec/project-profile.schema.json +66 -0
- package/src/app/context-format.ts +1 -1
- package/src/cli/commands/get.ts +12 -2
- package/src/cli/commands/index-cmd.ts +13 -0
- package/src/cli/commands/multi-get.ts +9 -2
- package/src/cli/commands/shared.ts +28 -0
- package/src/cli/commands/update.ts +5 -0
- package/src/cli/program.ts +4 -0
- package/src/config/project-profile.ts +2 -0
- package/src/config/types.ts +16 -0
- package/src/converters/adapters/browser-export/adapter.ts +199 -0
- package/src/converters/adapters/browser-export/formats.ts +358 -0
- package/src/converters/adapters/email/adapter.ts +429 -0
- package/src/converters/adapters/email/html.ts +162 -0
- package/src/converters/adapters/email/mime.ts +454 -0
- package/src/converters/adapters/email/parameters.ts +77 -0
- package/src/converters/adapters/ical/adapter.ts +475 -0
- package/src/converters/adapters/ical/recurrence.ts +186 -0
- package/src/converters/adapters/jsonl/adapter.ts +238 -0
- package/src/converters/adapters/jsonl/config.ts +105 -0
- package/src/converters/adapters/shared/html-text.ts +165 -0
- package/src/converters/adapters/shared/record-utils.ts +79 -0
- package/src/converters/adapters/shared/utf8-lines.ts +141 -0
- package/src/converters/adapters/transcript/adapter.ts +295 -0
- package/src/converters/adapters/transcript/json.ts +184 -0
- package/src/converters/adapters/transcript/model.ts +171 -0
- package/src/converters/adapters/transcript/text.ts +58 -0
- package/src/converters/adapters/transcript/timed.ts +152 -0
- package/src/converters/index.ts +11 -1
- package/src/converters/mime.ts +8 -0
- package/src/converters/pipeline.ts +15 -1
- package/src/converters/registry.ts +37 -1
- package/src/converters/types.ts +136 -0
- package/src/core/context-capsule-schema.ts +87 -0
- package/src/core/context-capsule.ts +20 -0
- package/src/core/context-evidence.ts +7 -1
- package/src/core/document-capabilities.ts +12 -0
- package/src/core/project-profile-apply-state.ts +5 -0
- package/src/core/project-profile.ts +4 -0
- package/src/core/record-metadata.ts +49 -0
- package/src/ingestion/record-adapter-canonical.ts +433 -0
- package/src/ingestion/record-adapter.ts +437 -0
- package/src/ingestion/record-container.ts +688 -0
- package/src/ingestion/record-path.ts +20 -0
- package/src/ingestion/record-sync.ts +70 -0
- package/src/ingestion/sync.ts +228 -36
- package/src/ingestion/types.ts +69 -1
- package/src/ingestion/walker.ts +31 -11
- package/src/mcp/tools/get.ts +10 -2
- package/src/mcp/tools/multi-get.ts +9 -2
- package/src/mcp/tools/workspace-write.ts +2 -0
- package/src/pipeline/filters.ts +1 -1
- package/src/pipeline/graph-retrieval.ts +7 -4
- package/src/pipeline/hybrid.ts +7 -4
- package/src/pipeline/result-context.ts +12 -4
- package/src/pipeline/search.ts +11 -4
- package/src/pipeline/types.ts +3 -0
- package/src/pipeline/vsearch.ts +26 -8
- package/src/sdk/documents.ts +13 -5
- package/src/serve/browse-tree.ts +4 -2
- package/src/serve/routes/api.ts +63 -65
- package/src/store/migrations/022-record-export-lineage.ts +42 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/sqlite/adapter.ts +114 -7
- package/src/store/types.ts +40 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.27.1.zip.sha256 +0 -1
package/src/mcp/tools/get.ts
CHANGED
|
@@ -15,6 +15,10 @@ import {
|
|
|
15
15
|
type DocumentCapabilities,
|
|
16
16
|
} from "../../core/document-capabilities";
|
|
17
17
|
import { resolveEffectiveIndex } from "../../core/indexed-reference";
|
|
18
|
+
import {
|
|
19
|
+
projectRecordEvidenceMetadata,
|
|
20
|
+
type RecordEvidenceMetadata,
|
|
21
|
+
} from "../../core/record-metadata";
|
|
18
22
|
import { parseRef } from "../../core/ref-parser";
|
|
19
23
|
import {
|
|
20
24
|
attachRetrievalTraceMetadata,
|
|
@@ -54,6 +58,7 @@ interface GetResponse {
|
|
|
54
58
|
converterVersion?: string;
|
|
55
59
|
mirrorHash?: string;
|
|
56
60
|
};
|
|
61
|
+
record?: RecordEvidenceMetadata;
|
|
57
62
|
capabilities: DocumentCapabilities;
|
|
58
63
|
}
|
|
59
64
|
|
|
@@ -210,13 +215,14 @@ export function handleGet(
|
|
|
210
215
|
|
|
211
216
|
// Build absPath
|
|
212
217
|
const uriParsed = parseUri(doc.uri);
|
|
218
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
213
219
|
let absPath: string | undefined;
|
|
214
220
|
if (uriParsed) {
|
|
215
221
|
const collection = ctx.collections.find(
|
|
216
222
|
(c) => c.name === uriParsed.collection
|
|
217
223
|
);
|
|
218
224
|
if (collection) {
|
|
219
|
-
absPath = pathJoin(collection.path,
|
|
225
|
+
absPath = pathJoin(collection.path, sourceRelPath);
|
|
220
226
|
}
|
|
221
227
|
}
|
|
222
228
|
|
|
@@ -230,7 +236,7 @@ export function handleGet(
|
|
|
230
236
|
language: doc.languageHint ?? undefined,
|
|
231
237
|
source: {
|
|
232
238
|
absPath,
|
|
233
|
-
relPath:
|
|
239
|
+
relPath: sourceRelPath,
|
|
234
240
|
mime: doc.sourceMime,
|
|
235
241
|
ext: doc.sourceExt,
|
|
236
242
|
modifiedAt: doc.sourceMtime,
|
|
@@ -244,10 +250,12 @@ export function handleGet(
|
|
|
244
250
|
mirrorHash: doc.mirrorHash,
|
|
245
251
|
}
|
|
246
252
|
: undefined,
|
|
253
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
247
254
|
capabilities: getDocumentCapabilities({
|
|
248
255
|
sourceExt: doc.sourceExt,
|
|
249
256
|
sourceMime: doc.sourceMime,
|
|
250
257
|
contentAvailable: doc.mirrorHash !== null,
|
|
258
|
+
recordKey: doc.recordKey,
|
|
251
259
|
}),
|
|
252
260
|
};
|
|
253
261
|
|
|
@@ -11,6 +11,10 @@ import type { ToolContext } from "../server";
|
|
|
11
11
|
|
|
12
12
|
import { decorateUriForIndex, parseUri } from "../../app/constants";
|
|
13
13
|
import { resolveEffectiveIndex } from "../../core/indexed-reference";
|
|
14
|
+
import {
|
|
15
|
+
projectRecordEvidenceMetadata,
|
|
16
|
+
type RecordEvidenceMetadata,
|
|
17
|
+
} from "../../core/record-metadata";
|
|
14
18
|
import { parseRef } from "../../core/ref-parser";
|
|
15
19
|
import { openScopedIndexStore } from "../../store/sqlite/scoped-index";
|
|
16
20
|
import { runTool, type ToolResult } from "./index";
|
|
@@ -37,6 +41,7 @@ interface DocumentResult {
|
|
|
37
41
|
modifiedAt?: string;
|
|
38
42
|
sizeBytes?: number;
|
|
39
43
|
};
|
|
44
|
+
record?: RecordEvidenceMetadata;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
interface MultiGetResponse {
|
|
@@ -234,13 +239,14 @@ export function handleMultiGet(
|
|
|
234
239
|
|
|
235
240
|
// Build absPath
|
|
236
241
|
const uriParsed = parseUri(doc.uri);
|
|
242
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
237
243
|
let absPath: string | undefined;
|
|
238
244
|
if (uriParsed) {
|
|
239
245
|
const collection = ctx.collections.find(
|
|
240
246
|
(c) => c.name === uriParsed.collection
|
|
241
247
|
);
|
|
242
248
|
if (collection) {
|
|
243
|
-
absPath = pathJoin(collection.path,
|
|
249
|
+
absPath = pathJoin(collection.path, sourceRelPath);
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
@@ -253,12 +259,13 @@ export function handleMultiGet(
|
|
|
253
259
|
truncated,
|
|
254
260
|
source: {
|
|
255
261
|
absPath,
|
|
256
|
-
relPath:
|
|
262
|
+
relPath: sourceRelPath,
|
|
257
263
|
mime: doc.sourceMime,
|
|
258
264
|
ext: doc.sourceExt,
|
|
259
265
|
modifiedAt: doc.sourceMtime,
|
|
260
266
|
sizeBytes: doc.sourceSize,
|
|
261
267
|
},
|
|
268
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
262
269
|
});
|
|
263
270
|
}
|
|
264
271
|
|
|
@@ -141,11 +141,13 @@ function ensureEditable(doc: {
|
|
|
141
141
|
sourceExt: string;
|
|
142
142
|
sourceMime: string;
|
|
143
143
|
mirrorHash: string | null;
|
|
144
|
+
recordKey?: string | null;
|
|
144
145
|
}) {
|
|
145
146
|
const capabilities = getDocumentCapabilities({
|
|
146
147
|
sourceExt: doc.sourceExt,
|
|
147
148
|
sourceMime: doc.sourceMime,
|
|
148
149
|
contentAvailable: doc.mirrorHash !== null,
|
|
150
|
+
recordKey: doc.recordKey,
|
|
149
151
|
});
|
|
150
152
|
if (!capabilities.editable) {
|
|
151
153
|
throw new Error(
|
package/src/pipeline/filters.ts
CHANGED
|
@@ -42,6 +42,9 @@ const EMPTY_EDGE_CONFIDENCE: Record<GraphEdgeConfidence, number> = {
|
|
|
42
42
|
similarity: 0,
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
const sourceRelPath = (doc: DocumentRow): string =>
|
|
46
|
+
doc.recordSourcePath ?? doc.relPath;
|
|
47
|
+
|
|
45
48
|
const confidenceWeight = (confidence: GraphEdgeConfidence): number => {
|
|
46
49
|
switch (confidence) {
|
|
47
50
|
case "explicit":
|
|
@@ -253,8 +256,8 @@ export async function expandGraphCandidates(
|
|
|
253
256
|
}
|
|
254
257
|
if (
|
|
255
258
|
options.relPathPrefix !== undefined &&
|
|
256
|
-
doc
|
|
257
|
-
!doc.
|
|
259
|
+
sourceRelPath(doc) !== options.relPathPrefix &&
|
|
260
|
+
!sourceRelPath(doc).startsWith(`${options.relPathPrefix}/`)
|
|
258
261
|
) {
|
|
259
262
|
continue;
|
|
260
263
|
}
|
|
@@ -337,8 +340,8 @@ export async function expandGraphCandidates(
|
|
|
337
340
|
(doc) =>
|
|
338
341
|
doc.mirrorHash &&
|
|
339
342
|
(options.relPathPrefix === undefined ||
|
|
340
|
-
doc
|
|
341
|
-
doc.
|
|
343
|
+
sourceRelPath(doc) === options.relPathPrefix ||
|
|
344
|
+
sourceRelPath(doc).startsWith(`${options.relPathPrefix}/`)) &&
|
|
342
345
|
matchesDocumentFilters(doc, options)
|
|
343
346
|
);
|
|
344
347
|
const docs = await filterDocsByTags(store, metadataFilteredDocs, options);
|
package/src/pipeline/hybrid.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
} from "./types";
|
|
22
22
|
|
|
23
23
|
import { normalizeContentTypes } from "../config/content-types";
|
|
24
|
+
import { projectRecordEvidenceMetadata } from "../core/record-metadata";
|
|
24
25
|
import { embedTextsWithRecovery } from "../embed/batch";
|
|
25
26
|
import { err, ok } from "../store/types";
|
|
26
27
|
import { createChunkLookup } from "./chunk-lookup";
|
|
@@ -840,10 +841,11 @@ export async function searchHybrid(
|
|
|
840
841
|
};
|
|
841
842
|
const matchesMetadataFilters = (doc: DocumentRow): boolean => {
|
|
842
843
|
const relPathPrefix = options.retrievalScope?.relPathPrefix;
|
|
844
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
843
845
|
if (
|
|
844
846
|
relPathPrefix !== undefined &&
|
|
845
|
-
|
|
846
|
-
!
|
|
847
|
+
sourceRelPath !== relPathPrefix &&
|
|
848
|
+
!sourceRelPath.startsWith(`${relPathPrefix}/`)
|
|
847
849
|
) {
|
|
848
850
|
return false;
|
|
849
851
|
}
|
|
@@ -1052,9 +1054,9 @@ export async function searchHybrid(
|
|
|
1052
1054
|
snippetLanguage: chunk.language ?? undefined,
|
|
1053
1055
|
snippetRange,
|
|
1054
1056
|
source: {
|
|
1055
|
-
relPath: doc.relPath,
|
|
1057
|
+
relPath: doc.recordSourcePath ?? doc.relPath,
|
|
1056
1058
|
absPath: collectionPath
|
|
1057
|
-
? `${collectionPath}/${doc.relPath}`
|
|
1059
|
+
? `${collectionPath}/${doc.recordSourcePath ?? doc.relPath}`
|
|
1058
1060
|
: undefined,
|
|
1059
1061
|
mime: doc.sourceMime,
|
|
1060
1062
|
ext: doc.sourceExt,
|
|
@@ -1068,6 +1070,7 @@ export async function searchHybrid(
|
|
|
1068
1070
|
converterId: doc.converterId ?? undefined,
|
|
1069
1071
|
converterVersion: doc.converterVersion ?? undefined,
|
|
1070
1072
|
},
|
|
1073
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
1071
1074
|
};
|
|
1072
1075
|
const auxiliaryBaseScore =
|
|
1073
1076
|
auxiliaryBaseScores.get(`${candidate.mirrorHash}:${candidate.seq}`) ??
|
|
@@ -16,10 +16,18 @@ export async function attachSearchResultContexts(
|
|
|
16
16
|
results: SearchResult[]
|
|
17
17
|
): Promise<void> {
|
|
18
18
|
const validResults = results
|
|
19
|
-
.map((result) =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
.map((result) => {
|
|
20
|
+
const uriIdentity = contextIdentityFromUri(result.uri);
|
|
21
|
+
return {
|
|
22
|
+
identity: uriIdentity
|
|
23
|
+
? {
|
|
24
|
+
collection: uriIdentity.collection,
|
|
25
|
+
relPath: result.source.relPath,
|
|
26
|
+
}
|
|
27
|
+
: null,
|
|
28
|
+
result,
|
|
29
|
+
};
|
|
30
|
+
})
|
|
23
31
|
.filter(
|
|
24
32
|
(
|
|
25
33
|
entry
|
package/src/pipeline/search.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
SearchResults,
|
|
16
16
|
} from "./types";
|
|
17
17
|
|
|
18
|
+
import { projectRecordEvidenceMetadata } from "../core/record-metadata";
|
|
18
19
|
import { getContentBatch } from "../store/content-batch";
|
|
19
20
|
import { err, ok } from "../store/types";
|
|
20
21
|
import { createChunkLookup } from "./chunk-lookup";
|
|
@@ -85,8 +86,9 @@ interface BuildResultContext {
|
|
|
85
86
|
/** Build SearchResult from FtsResult and related data */
|
|
86
87
|
function buildSearchResult(ctx: BuildResultContext): SearchResult {
|
|
87
88
|
const { fts, chunk, collectionPath, options, fullContent } = ctx;
|
|
89
|
+
const sourceRelPath = fts.recordSourcePath ?? fts.relPath ?? "";
|
|
88
90
|
const source: SearchResultSource = {
|
|
89
|
-
relPath:
|
|
91
|
+
relPath: sourceRelPath,
|
|
90
92
|
// Use actual source metadata with fallback to markdown defaults
|
|
91
93
|
mime: fts.sourceMime ?? "text/markdown",
|
|
92
94
|
ext: fts.sourceExt ?? ".md",
|
|
@@ -97,8 +99,8 @@ function buildSearchResult(ctx: BuildResultContext): SearchResult {
|
|
|
97
99
|
};
|
|
98
100
|
|
|
99
101
|
// Add absPath if we have collection path (cross-platform safe)
|
|
100
|
-
if (collectionPath &&
|
|
101
|
-
source.absPath = pathJoin(collectionPath,
|
|
102
|
+
if (collectionPath && sourceRelPath) {
|
|
103
|
+
source.absPath = pathJoin(collectionPath, sourceRelPath);
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
// Determine snippet content and range
|
|
@@ -134,6 +136,7 @@ function buildSearchResult(ctx: BuildResultContext): SearchResult {
|
|
|
134
136
|
snippetRange,
|
|
135
137
|
source,
|
|
136
138
|
conversion: fts.mirrorHash ? { mirrorHash: fts.mirrorHash } : undefined,
|
|
139
|
+
record: projectRecordEvidenceMetadata(fts),
|
|
137
140
|
};
|
|
138
141
|
if (!(chunk && fts.mirrorHash)) return result;
|
|
139
142
|
return attachSearchResultPlannerMetadata(result, {
|
|
@@ -287,7 +290,11 @@ export async function searchBm25(
|
|
|
287
290
|
|
|
288
291
|
const excluded =
|
|
289
292
|
matchesExcludedText(
|
|
290
|
-
[
|
|
293
|
+
[
|
|
294
|
+
fts.title ?? "",
|
|
295
|
+
fts.recordSourcePath ?? fts.relPath ?? "",
|
|
296
|
+
fts.snippet ?? "",
|
|
297
|
+
],
|
|
291
298
|
options.exclude
|
|
292
299
|
) ||
|
|
293
300
|
matchesExcludedChunks(
|
package/src/pipeline/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
ContextCapsuleV1,
|
|
11
11
|
ContextCapsuleVerification,
|
|
12
12
|
} from "../core/context-capsule";
|
|
13
|
+
import type { RecordEvidenceMetadata } from "../core/record-metadata";
|
|
13
14
|
import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
|
|
14
15
|
import type { StoreResult } from "../store/types";
|
|
15
16
|
import type { ClaimVerificationResult } from "./claim-verification";
|
|
@@ -86,6 +87,8 @@ export interface SearchResult {
|
|
|
86
87
|
context?: string;
|
|
87
88
|
source: SearchResultSource;
|
|
88
89
|
conversion?: SearchResultConversion;
|
|
90
|
+
/** Bounded logical-record provenance for file/export adapters. */
|
|
91
|
+
record?: RecordEvidenceMetadata;
|
|
89
92
|
[SEARCH_RESULT_PLANNER_METADATA]?: SearchResultPlannerMetadata;
|
|
90
93
|
}
|
|
91
94
|
|
package/src/pipeline/vsearch.ts
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Config } from "../config/types";
|
|
9
9
|
import type { EmbeddingPort } from "../llm/types";
|
|
10
|
-
import type { StorePort } from "../store/types";
|
|
10
|
+
import type { DocumentRow, StorePort } from "../store/types";
|
|
11
11
|
import type { VectorIndexPort } from "../store/vector/types";
|
|
12
12
|
import type { SearchOptions, SearchResult, SearchResults } from "./types";
|
|
13
13
|
|
|
14
14
|
import { normalizeContentTypes } from "../config/content-types";
|
|
15
|
+
import { projectRecordEvidenceMetadata } from "../core/record-metadata";
|
|
15
16
|
import { getContentBatch } from "../store/content-batch";
|
|
16
17
|
import { err, ok } from "../store/types";
|
|
17
18
|
import { createChunkLookup } from "./chunk-lookup";
|
|
@@ -213,11 +214,12 @@ export async function searchVectorWithEmbedding(
|
|
|
213
214
|
const docs = auxiliaryRankingActive ? matchingDocs : [matchingDocs.at(-1)!];
|
|
214
215
|
for (const doc of docs) {
|
|
215
216
|
const collectionPath = collectionPaths.get(doc.collection);
|
|
217
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
216
218
|
const excluded =
|
|
217
219
|
matchesExcludedText(
|
|
218
220
|
[
|
|
219
221
|
doc.title ?? "",
|
|
220
|
-
|
|
222
|
+
sourceRelPath,
|
|
221
223
|
doc.author ?? "",
|
|
222
224
|
doc.contentType ?? "",
|
|
223
225
|
...(doc.categories ?? []),
|
|
@@ -248,9 +250,9 @@ export async function searchVectorWithEmbedding(
|
|
|
248
250
|
endLine: chunk.endLine,
|
|
249
251
|
},
|
|
250
252
|
source: {
|
|
251
|
-
relPath:
|
|
253
|
+
relPath: sourceRelPath,
|
|
252
254
|
absPath: collectionPath
|
|
253
|
-
? `${collectionPath}/${
|
|
255
|
+
? `${collectionPath}/${sourceRelPath}`
|
|
254
256
|
: undefined,
|
|
255
257
|
mime: doc.sourceMime,
|
|
256
258
|
ext: doc.sourceExt,
|
|
@@ -266,6 +268,7 @@ export async function searchVectorWithEmbedding(
|
|
|
266
268
|
converterVersion: doc.converterVersion ?? undefined,
|
|
267
269
|
}
|
|
268
270
|
: undefined,
|
|
271
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
269
272
|
},
|
|
270
273
|
doc.collection,
|
|
271
274
|
contentTypeRules,
|
|
@@ -332,6 +335,7 @@ export async function searchVectorWithEmbedding(
|
|
|
332
335
|
: undefined;
|
|
333
336
|
|
|
334
337
|
const collectionPath = collectionPaths.get(doc.collection);
|
|
338
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
335
339
|
|
|
336
340
|
const result = applyContentTypeBoost(
|
|
337
341
|
{
|
|
@@ -349,9 +353,9 @@ export async function searchVectorWithEmbedding(
|
|
|
349
353
|
? undefined
|
|
350
354
|
: { startLine: chunk.startLine, endLine: chunk.endLine },
|
|
351
355
|
source: {
|
|
352
|
-
relPath:
|
|
356
|
+
relPath: sourceRelPath,
|
|
353
357
|
absPath: collectionPath
|
|
354
|
-
? `${collectionPath}/${
|
|
358
|
+
? `${collectionPath}/${sourceRelPath}`
|
|
355
359
|
: undefined,
|
|
356
360
|
mime: doc.sourceMime,
|
|
357
361
|
ext: doc.sourceExt,
|
|
@@ -367,6 +371,7 @@ export async function searchVectorWithEmbedding(
|
|
|
367
371
|
converterVersion: doc.converterVersion ?? undefined,
|
|
368
372
|
}
|
|
369
373
|
: undefined,
|
|
374
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
370
375
|
},
|
|
371
376
|
doc.collection,
|
|
372
377
|
contentTypeRules,
|
|
@@ -514,6 +519,12 @@ interface DocumentInfo {
|
|
|
514
519
|
mirrorHash: string | null;
|
|
515
520
|
converterId: string | null;
|
|
516
521
|
converterVersion: string | null;
|
|
522
|
+
recordKey: DocumentRow["recordKey"];
|
|
523
|
+
recordSourcePath: DocumentRow["recordSourcePath"];
|
|
524
|
+
recordSourceLocator: DocumentRow["recordSourceLocator"];
|
|
525
|
+
recordMetadata: DocumentRow["recordMetadata"];
|
|
526
|
+
recordAnchors: DocumentRow["recordAnchors"];
|
|
527
|
+
recordAdapterFingerprint: DocumentRow["recordAdapterFingerprint"];
|
|
517
528
|
}
|
|
518
529
|
|
|
519
530
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -611,10 +622,11 @@ async function buildDocumentMap(
|
|
|
611
622
|
}
|
|
612
623
|
|
|
613
624
|
for (const doc of activeDocs) {
|
|
625
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
614
626
|
if (
|
|
615
627
|
options.relPathPrefix !== undefined &&
|
|
616
|
-
|
|
617
|
-
!
|
|
628
|
+
sourceRelPath !== options.relPathPrefix &&
|
|
629
|
+
!sourceRelPath.startsWith(`${options.relPathPrefix}/`)
|
|
618
630
|
) {
|
|
619
631
|
continue;
|
|
620
632
|
}
|
|
@@ -655,6 +667,12 @@ async function buildDocumentMap(
|
|
|
655
667
|
mirrorHash: doc.mirrorHash,
|
|
656
668
|
converterId: doc.converterId,
|
|
657
669
|
converterVersion: doc.converterVersion,
|
|
670
|
+
recordKey: doc.recordKey,
|
|
671
|
+
recordSourcePath: doc.recordSourcePath,
|
|
672
|
+
recordSourceLocator: doc.recordSourceLocator,
|
|
673
|
+
recordMetadata: doc.recordMetadata,
|
|
674
|
+
recordAnchors: doc.recordAnchors,
|
|
675
|
+
recordAdapterFingerprint: doc.recordAdapterFingerprint,
|
|
658
676
|
};
|
|
659
677
|
const matchingDocuments = result.get(doc.mirrorHash!) ?? [];
|
|
660
678
|
matchingDocuments.push(documentInfo);
|
package/src/sdk/documents.ts
CHANGED
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
} from "./types";
|
|
24
24
|
|
|
25
25
|
import { getDocumentCapabilities } from "../core/document-capabilities";
|
|
26
|
+
import { projectRecordEvidenceMetadata } from "../core/record-metadata";
|
|
26
27
|
import { isGlobPattern, parseRef, splitRefs } from "../core/ref-parser";
|
|
27
28
|
import {
|
|
28
29
|
attachRetrievalTraceMetadata,
|
|
@@ -53,9 +54,10 @@ function buildSourceMeta(
|
|
|
53
54
|
config: Config
|
|
54
55
|
): GetResponse["source"] {
|
|
55
56
|
const coll = config.collections.find((c) => c.name === doc.collection);
|
|
57
|
+
const relPath = doc.recordSourcePath ?? doc.relPath;
|
|
56
58
|
return {
|
|
57
|
-
absPath: coll ? `${coll.path}/${
|
|
58
|
-
relPath
|
|
59
|
+
absPath: coll ? `${coll.path}/${relPath}` : undefined,
|
|
60
|
+
relPath,
|
|
59
61
|
mime: doc.sourceMime,
|
|
60
62
|
ext: doc.sourceExt,
|
|
61
63
|
sizeBytes: doc.sourceSize,
|
|
@@ -129,10 +131,12 @@ async function getDocumentByRefUntraced(
|
|
|
129
131
|
language: doc.languageHint ?? undefined,
|
|
130
132
|
source: buildSourceMeta(doc, config),
|
|
131
133
|
conversion: buildConversionMeta(doc),
|
|
134
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
132
135
|
capabilities: getDocumentCapabilities({
|
|
133
136
|
sourceExt: doc.sourceExt,
|
|
134
137
|
sourceMime: doc.sourceMime,
|
|
135
138
|
contentAvailable: doc.mirrorHash !== null,
|
|
139
|
+
recordKey: doc.recordKey,
|
|
136
140
|
}),
|
|
137
141
|
};
|
|
138
142
|
}
|
|
@@ -156,10 +160,12 @@ async function getDocumentByRefUntraced(
|
|
|
156
160
|
language: doc.languageHint ?? undefined,
|
|
157
161
|
source: buildSourceMeta(doc, config),
|
|
158
162
|
conversion: buildConversionMeta(doc),
|
|
163
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
159
164
|
capabilities: getDocumentCapabilities({
|
|
160
165
|
sourceExt: doc.sourceExt,
|
|
161
166
|
sourceMime: doc.sourceMime,
|
|
162
167
|
contentAvailable: doc.mirrorHash !== null,
|
|
168
|
+
recordKey: doc.recordKey,
|
|
163
169
|
}),
|
|
164
170
|
};
|
|
165
171
|
}
|
|
@@ -318,6 +324,7 @@ export async function multiGetDocuments(
|
|
|
318
324
|
maxBytes
|
|
319
325
|
);
|
|
320
326
|
const coll = config.collections.find((c) => c.name === doc.collection);
|
|
327
|
+
const sourceRelPath = doc.recordSourcePath ?? doc.relPath;
|
|
321
328
|
documents.push({
|
|
322
329
|
docid: doc.docid,
|
|
323
330
|
uri: doc.uri,
|
|
@@ -326,11 +333,12 @@ export async function multiGetDocuments(
|
|
|
326
333
|
truncated: truncated || undefined,
|
|
327
334
|
totalLines: content.split("\n").length,
|
|
328
335
|
source: {
|
|
329
|
-
absPath: coll ? `${coll.path}/${
|
|
330
|
-
relPath:
|
|
336
|
+
absPath: coll ? `${coll.path}/${sourceRelPath}` : undefined,
|
|
337
|
+
relPath: sourceRelPath,
|
|
331
338
|
mime: doc.sourceMime,
|
|
332
339
|
ext: doc.sourceExt,
|
|
333
340
|
},
|
|
341
|
+
record: projectRecordEvidenceMetadata(doc),
|
|
334
342
|
});
|
|
335
343
|
}
|
|
336
344
|
|
|
@@ -385,7 +393,7 @@ export async function listDocuments(
|
|
|
385
393
|
uri: d.uri,
|
|
386
394
|
title: d.title ?? undefined,
|
|
387
395
|
source: {
|
|
388
|
-
relPath: d.relPath,
|
|
396
|
+
relPath: d.recordSourcePath ?? d.relPath,
|
|
389
397
|
mime: d.sourceMime,
|
|
390
398
|
ext: d.sourceExt,
|
|
391
399
|
},
|
package/src/serve/browse-tree.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface BrowseTreeNode {
|
|
|
15
15
|
type BrowseCollectionLike = Pick<CollectionRow, "name">;
|
|
16
16
|
type BrowseDocumentLike = Pick<
|
|
17
17
|
DocumentRow,
|
|
18
|
-
"collection" | "relPath" | "active"
|
|
18
|
+
"collection" | "relPath" | "recordSourcePath" | "active"
|
|
19
19
|
>;
|
|
20
20
|
type BrowseFolderLike = {
|
|
21
21
|
collection: string;
|
|
@@ -128,7 +128,9 @@ export function buildBrowseTree(
|
|
|
128
128
|
|
|
129
129
|
root.documentCount += 1;
|
|
130
130
|
|
|
131
|
-
const normalizedRelPath = normalizeBrowsePath(
|
|
131
|
+
const normalizedRelPath = normalizeBrowsePath(
|
|
132
|
+
doc.recordSourcePath ?? doc.relPath
|
|
133
|
+
);
|
|
132
134
|
const parts = normalizedRelPath.split("/").filter(Boolean);
|
|
133
135
|
const folderParts = parts.slice(0, -1);
|
|
134
136
|
|