daftari 1.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/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +259 -0
- package/dist/access/locks.d.ts +19 -0
- package/dist/access/locks.d.ts.map +1 -0
- package/dist/access/locks.js +112 -0
- package/dist/access/locks.js.map +1 -0
- package/dist/access/rbac.d.ts +18 -0
- package/dist/access/rbac.d.ts.map +1 -0
- package/dist/access/rbac.js +48 -0
- package/dist/access/rbac.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +216 -0
- package/dist/cli.js.map +1 -0
- package/dist/curation/lint.d.ts +20 -0
- package/dist/curation/lint.d.ts.map +1 -0
- package/dist/curation/lint.js +176 -0
- package/dist/curation/lint.js.map +1 -0
- package/dist/curation/provenance.d.ts +21 -0
- package/dist/curation/provenance.d.ts.map +1 -0
- package/dist/curation/provenance.js +80 -0
- package/dist/curation/provenance.js.map +1 -0
- package/dist/curation/staleness.d.ts +19 -0
- package/dist/curation/staleness.d.ts.map +1 -0
- package/dist/curation/staleness.js +67 -0
- package/dist/curation/staleness.js.map +1 -0
- package/dist/curation/tension.d.ts +20 -0
- package/dist/curation/tension.d.ts.map +1 -0
- package/dist/curation/tension.js +134 -0
- package/dist/curation/tension.js.map +1 -0
- package/dist/frontmatter/parser.d.ts +10 -0
- package/dist/frontmatter/parser.d.ts.map +1 -0
- package/dist/frontmatter/parser.js +29 -0
- package/dist/frontmatter/parser.js.map +1 -0
- package/dist/frontmatter/schema.d.ts +7 -0
- package/dist/frontmatter/schema.d.ts.map +1 -0
- package/dist/frontmatter/schema.js +115 -0
- package/dist/frontmatter/schema.js.map +1 -0
- package/dist/frontmatter/types.d.ts +41 -0
- package/dist/frontmatter/types.d.ts.map +1 -0
- package/dist/frontmatter/types.js +8 -0
- package/dist/frontmatter/types.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/search/bm25.d.ts +19 -0
- package/dist/search/bm25.d.ts.map +1 -0
- package/dist/search/bm25.js +115 -0
- package/dist/search/bm25.js.map +1 -0
- package/dist/search/hybrid.d.ts +38 -0
- package/dist/search/hybrid.d.ts.map +1 -0
- package/dist/search/hybrid.js +162 -0
- package/dist/search/hybrid.js.map +1 -0
- package/dist/search/reindex.d.ts +15 -0
- package/dist/search/reindex.d.ts.map +1 -0
- package/dist/search/reindex.js +189 -0
- package/dist/search/reindex.js.map +1 -0
- package/dist/search/vector.d.ts +9 -0
- package/dist/search/vector.d.ts.map +1 -0
- package/dist/search/vector.js +128 -0
- package/dist/search/vector.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +72 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/index-db.d.ts +37 -0
- package/dist/storage/index-db.d.ts.map +1 -0
- package/dist/storage/index-db.js +145 -0
- package/dist/storage/index-db.js.map +1 -0
- package/dist/storage/local.d.ts +6 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +57 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/tools/curation.d.ts +22 -0
- package/dist/tools/curation.d.ts.map +1 -0
- package/dist/tools/curation.js +202 -0
- package/dist/tools/curation.js.map +1 -0
- package/dist/tools/read.d.ts +74 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +254 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/search.d.ts +13 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +190 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/write.d.ts +18 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +465 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/utils/config.d.ts +12 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +94 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/git.d.ts +23 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +114 -0
- package/dist/utils/git.js.map +1 -0
- package/package.json +69 -0
- package/templates/config.yaml +31 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Vector (semantic) search half of hybrid search.
|
|
2
|
+
//
|
|
3
|
+
// Documents are split into chunks; each chunk is embedded into a 384-dim
|
|
4
|
+
// vector with the all-MiniLM-L6-v2 sentence-transformer (run locally via
|
|
5
|
+
// @huggingface/transformers — no network at query time once the model is cached).
|
|
6
|
+
// Similarity is cosine distance. Embeddings come back L2-normalised, so cosine
|
|
7
|
+
// reduces to a dot product, but cosineSimilarity stays general for safety.
|
|
8
|
+
//
|
|
9
|
+
// The model loads lazily and is memoised for the process. Loading can fail
|
|
10
|
+
// (e.g. no network on first run, before the model is cached); embed() surfaces
|
|
11
|
+
// that as Result.err so the caller can fall back to lexical-only ranking.
|
|
12
|
+
import { err, ok } from "../frontmatter/types.js";
|
|
13
|
+
export const EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
14
|
+
export const EMBEDDING_DIM = 384;
|
|
15
|
+
const CHUNK_MAX_CHARS = 800;
|
|
16
|
+
// Splits a document body into embeddable chunks. Paragraphs (blank-line
|
|
17
|
+
// separated) are packed greedily up to CHUNK_MAX_CHARS; a single paragraph
|
|
18
|
+
// longer than the cap is hard-split. Always returns at least one chunk so an
|
|
19
|
+
// empty body still produces a (possibly empty) vector slot.
|
|
20
|
+
export function chunkText(text) {
|
|
21
|
+
const paragraphs = text
|
|
22
|
+
.split(/\n\s*\n/)
|
|
23
|
+
.map((p) => p.trim())
|
|
24
|
+
.filter((p) => p.length > 0);
|
|
25
|
+
const chunks = [];
|
|
26
|
+
let current = "";
|
|
27
|
+
for (const para of paragraphs) {
|
|
28
|
+
if (para.length > CHUNK_MAX_CHARS) {
|
|
29
|
+
if (current) {
|
|
30
|
+
chunks.push(current);
|
|
31
|
+
current = "";
|
|
32
|
+
}
|
|
33
|
+
for (let i = 0; i < para.length; i += CHUNK_MAX_CHARS) {
|
|
34
|
+
chunks.push(para.slice(i, i + CHUNK_MAX_CHARS));
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (current.length + para.length + 2 > CHUNK_MAX_CHARS && current) {
|
|
39
|
+
chunks.push(current);
|
|
40
|
+
current = para;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
current = current ? `${current}\n\n${para}` : para;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (current)
|
|
47
|
+
chunks.push(current);
|
|
48
|
+
return chunks.length > 0 ? chunks : [text.trim()];
|
|
49
|
+
}
|
|
50
|
+
// Cosine similarity in [-1, 1]. Mismatched lengths or a zero vector yield 0.
|
|
51
|
+
export function cosineSimilarity(a, b) {
|
|
52
|
+
if (a.length !== b.length || a.length === 0)
|
|
53
|
+
return 0;
|
|
54
|
+
let dot = 0;
|
|
55
|
+
let normA = 0;
|
|
56
|
+
let normB = 0;
|
|
57
|
+
for (let i = 0; i < a.length; i++) {
|
|
58
|
+
const x = a[i];
|
|
59
|
+
const y = b[i];
|
|
60
|
+
dot += x * y;
|
|
61
|
+
normA += x * x;
|
|
62
|
+
normB += y * y;
|
|
63
|
+
}
|
|
64
|
+
if (normA === 0 || normB === 0)
|
|
65
|
+
return 0;
|
|
66
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
67
|
+
}
|
|
68
|
+
// Mean of a set of vectors — used to represent a whole document by averaging
|
|
69
|
+
// its chunk embeddings. Returns null when there is nothing to average.
|
|
70
|
+
export function meanEmbedding(vectors) {
|
|
71
|
+
if (vectors.length === 0)
|
|
72
|
+
return null;
|
|
73
|
+
const dim = vectors[0]?.length ?? 0;
|
|
74
|
+
if (dim === 0)
|
|
75
|
+
return null;
|
|
76
|
+
const sum = new Float32Array(dim);
|
|
77
|
+
for (const v of vectors) {
|
|
78
|
+
if (v.length !== dim)
|
|
79
|
+
continue;
|
|
80
|
+
for (let i = 0; i < dim; i++)
|
|
81
|
+
sum[i] = sum[i] + v[i];
|
|
82
|
+
}
|
|
83
|
+
for (let i = 0; i < dim; i++)
|
|
84
|
+
sum[i] = sum[i] / vectors.length;
|
|
85
|
+
return sum;
|
|
86
|
+
}
|
|
87
|
+
let extractorPromise = null;
|
|
88
|
+
async function getExtractor() {
|
|
89
|
+
if (!extractorPromise) {
|
|
90
|
+
extractorPromise = import("@huggingface/transformers").then(({ pipeline }) => pipeline("feature-extraction", EMBEDDING_MODEL));
|
|
91
|
+
}
|
|
92
|
+
return extractorPromise;
|
|
93
|
+
}
|
|
94
|
+
// Embeds a batch of texts. The whole batch goes through the model in one call.
|
|
95
|
+
// Returns one Float32Array per input text. An empty input yields an empty
|
|
96
|
+
// array without loading the model.
|
|
97
|
+
export async function embed(texts) {
|
|
98
|
+
if (texts.length === 0)
|
|
99
|
+
return ok([]);
|
|
100
|
+
try {
|
|
101
|
+
const extractor = await getExtractor();
|
|
102
|
+
const output = await extractor(texts, {
|
|
103
|
+
pooling: "mean",
|
|
104
|
+
normalize: true,
|
|
105
|
+
});
|
|
106
|
+
const dim = output.dims[output.dims.length - 1] ?? EMBEDDING_DIM;
|
|
107
|
+
const vectors = [];
|
|
108
|
+
for (let i = 0; i < texts.length; i++) {
|
|
109
|
+
vectors.push(output.data.slice(i * dim, (i + 1) * dim));
|
|
110
|
+
}
|
|
111
|
+
return ok(vectors);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
115
|
+
return err(new Error(`embedding failed: ${reason}`));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Convenience wrapper for embedding a single query string.
|
|
119
|
+
export async function embedQuery(text) {
|
|
120
|
+
const result = await embed([text]);
|
|
121
|
+
if (!result.ok)
|
|
122
|
+
return result;
|
|
123
|
+
const first = result.value[0];
|
|
124
|
+
if (!first)
|
|
125
|
+
return err(new Error("embedding produced no vector"));
|
|
126
|
+
return ok(first);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=vector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector.js","sourceRoot":"","sources":["../../src/search/vector.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import { type AccessContext } from "./access/rbac.js";
|
|
3
|
+
export declare const SERVER_NAME = "daftari";
|
|
4
|
+
export declare const SERVER_VERSION: string;
|
|
5
|
+
export declare function createServer(vaultRoot: string, access?: AccessContext): Server;
|
|
6
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAAE,KAAK,aAAa,EAAe,MAAM,kBAAkB,CAAC;AAMnE,eAAO,MAAM,WAAW,YAAY,CAAC;AAQrC,eAAO,MAAM,cAAc,QAAmB,CAAC;AAK/C,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,GAAE,aAA6B,GAAG,MAAM,CAqD7F"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// MCP server wiring. Builds a Server, registers the read-path tools, and
|
|
2
|
+
// bridges each tool's Result<T, Error> into the MCP tool-call response shape.
|
|
3
|
+
//
|
|
4
|
+
// Tool handlers never throw; they return Result. The CallTool request handler
|
|
5
|
+
// additionally guards against unexpected throws at the transport boundary so a
|
|
6
|
+
// bug cannot take the stdio connection down.
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
import { guestAccess } from "./access/rbac.js";
|
|
11
|
+
import { curationTools } from "./tools/curation.js";
|
|
12
|
+
import { readTools } from "./tools/read.js";
|
|
13
|
+
import { searchTools } from "./tools/search.js";
|
|
14
|
+
import { writeTools } from "./tools/write.js";
|
|
15
|
+
export const SERVER_NAME = "daftari";
|
|
16
|
+
// The version is read from the package manifest so it never drifts from the
|
|
17
|
+
// published version. src/server.ts and dist/server.js both sit one level under
|
|
18
|
+
// the package root, so this relative path resolves the same in dev and build.
|
|
19
|
+
const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
20
|
+
export const SERVER_VERSION = manifest.version;
|
|
21
|
+
// The server runs as one access identity for its whole lifetime — the
|
|
22
|
+
// --user / --role it was started with. Every tool call is enforced against it.
|
|
23
|
+
// Absent an explicit context the server falls back to the deny-all guest.
|
|
24
|
+
export function createServer(vaultRoot, access = guestAccess()) {
|
|
25
|
+
const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
|
|
26
|
+
const tools = [...readTools, ...searchTools, ...writeTools, ...curationTools];
|
|
27
|
+
const byName = new Map(tools.map((t) => [t.name, t]));
|
|
28
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
29
|
+
tools: tools.map((t) => ({
|
|
30
|
+
name: t.name,
|
|
31
|
+
description: t.description,
|
|
32
|
+
inputSchema: t.inputSchema,
|
|
33
|
+
})),
|
|
34
|
+
}));
|
|
35
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
36
|
+
const name = request.params.name;
|
|
37
|
+
const tool = byName.get(name);
|
|
38
|
+
if (!tool) {
|
|
39
|
+
return {
|
|
40
|
+
isError: true,
|
|
41
|
+
content: [{ type: "text", text: `unknown tool: ${name}` }],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const args = (request.params.arguments ?? {});
|
|
46
|
+
const result = await tool.handler(vaultRoot, args, access);
|
|
47
|
+
if (!result.ok) {
|
|
48
|
+
return {
|
|
49
|
+
isError: true,
|
|
50
|
+
content: [{ type: "text", text: `Error: ${result.error.message}` }],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
content: [
|
|
55
|
+
{
|
|
56
|
+
type: "text",
|
|
57
|
+
text: JSON.stringify(result.value, null, 2),
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
64
|
+
return {
|
|
65
|
+
isError: true,
|
|
66
|
+
content: [{ type: "text", text: `Unexpected error in ${name}: ${reason}` }],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return server;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { type Result } from "../frontmatter/types.js";
|
|
3
|
+
export type IndexDb = Database.Database;
|
|
4
|
+
export interface IndexedDocument {
|
|
5
|
+
path: string;
|
|
6
|
+
title: string;
|
|
7
|
+
collection: string;
|
|
8
|
+
domain: string;
|
|
9
|
+
status: string;
|
|
10
|
+
confidence: string;
|
|
11
|
+
updated: string;
|
|
12
|
+
tags: string[];
|
|
13
|
+
content: string;
|
|
14
|
+
tokens: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface IndexedChunk {
|
|
17
|
+
path: string;
|
|
18
|
+
chunkIndex: number;
|
|
19
|
+
text: string;
|
|
20
|
+
embedding: Float32Array | null;
|
|
21
|
+
}
|
|
22
|
+
export declare function indexDbPath(vaultRoot: string): string;
|
|
23
|
+
export declare function openIndexDb(vaultRoot: string): Result<IndexDb, Error>;
|
|
24
|
+
export declare function clearIndex(db: IndexDb): void;
|
|
25
|
+
export declare function deleteDocument(db: IndexDb, path: string): void;
|
|
26
|
+
export declare function embeddingToBlob(vec: Float32Array): Buffer;
|
|
27
|
+
export declare function blobToEmbedding(blob: Buffer): Float32Array;
|
|
28
|
+
export declare function insertDocument(db: IndexDb, doc: IndexedDocument): void;
|
|
29
|
+
export declare function insertChunk(db: IndexDb, chunk: IndexedChunk): void;
|
|
30
|
+
export declare function setMeta(db: IndexDb, key: string, value: string): void;
|
|
31
|
+
export declare function getAllDocuments(db: IndexDb): IndexedDocument[];
|
|
32
|
+
export declare function getDocument(db: IndexDb, path: string): IndexedDocument | null;
|
|
33
|
+
export declare function getAllChunks(db: IndexDb): IndexedChunk[];
|
|
34
|
+
export declare function getChunksForPath(db: IndexDb, path: string): IndexedChunk[];
|
|
35
|
+
export declare function getMeta(db: IndexDb, key: string): string | null;
|
|
36
|
+
export declare function documentCount(db: IndexDb): number;
|
|
37
|
+
//# sourceMappingURL=index-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-db.d.ts","sourceRoot":"","sources":["../../src/storage/index-db.ts"],"names":[],"mappings":"AAgBA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC;AAExC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;CAChC;AAID,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAErD;AA4BD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAWrE;AAID,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAE5C;AAKD,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAG9D;AAID,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAM1D;AAID,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,GAAG,IAAI,CAiBtE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAUlE;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAErE;AAgCD,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,eAAe,EAAE,CAG9D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAK7E;AAkBD,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,YAAY,EAAE,CAGxD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAK1E;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAGjD"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// SQLite index store for search.
|
|
2
|
+
//
|
|
3
|
+
// The index is a derived cache: it holds nothing the markdown files don't
|
|
4
|
+
// already hold, so .daftari/index.db can be deleted and rebuilt at any time
|
|
5
|
+
// (see search/reindex.ts). Two tables carry the search payload:
|
|
6
|
+
//
|
|
7
|
+
// documents — one row per markdown file: frontmatter fields, the full body,
|
|
8
|
+
// and the BM25 token list (JSON).
|
|
9
|
+
// chunks — one row per embedded text chunk: the chunk text and its vector
|
|
10
|
+
// embedding (Float32 BLOB, or NULL when embedding was skipped).
|
|
11
|
+
//
|
|
12
|
+
// A small meta table records index-wide facts (embedding dimension, whether
|
|
13
|
+
// vectors were built, when the index was last rebuilt).
|
|
14
|
+
import { mkdirSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import Database from "better-sqlite3";
|
|
17
|
+
import { err, ok } from "../frontmatter/types.js";
|
|
18
|
+
// The .daftari control directory is excluded from vault listings, so the index
|
|
19
|
+
// file lives there without ever being mistaken for vault content.
|
|
20
|
+
export function indexDbPath(vaultRoot) {
|
|
21
|
+
return join(vaultRoot, ".daftari", "index.db");
|
|
22
|
+
}
|
|
23
|
+
const SCHEMA = `
|
|
24
|
+
CREATE TABLE IF NOT EXISTS documents (
|
|
25
|
+
path TEXT PRIMARY KEY,
|
|
26
|
+
title TEXT NOT NULL,
|
|
27
|
+
collection TEXT NOT NULL,
|
|
28
|
+
domain TEXT NOT NULL,
|
|
29
|
+
status TEXT NOT NULL,
|
|
30
|
+
confidence TEXT NOT NULL,
|
|
31
|
+
updated TEXT NOT NULL,
|
|
32
|
+
tags TEXT NOT NULL,
|
|
33
|
+
content TEXT NOT NULL,
|
|
34
|
+
tokens TEXT NOT NULL
|
|
35
|
+
);
|
|
36
|
+
CREATE TABLE IF NOT EXISTS chunks (
|
|
37
|
+
path TEXT NOT NULL,
|
|
38
|
+
chunk_index INTEGER NOT NULL,
|
|
39
|
+
text TEXT NOT NULL,
|
|
40
|
+
embedding BLOB,
|
|
41
|
+
PRIMARY KEY (path, chunk_index)
|
|
42
|
+
);
|
|
43
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
44
|
+
key TEXT PRIMARY KEY,
|
|
45
|
+
value TEXT NOT NULL
|
|
46
|
+
);
|
|
47
|
+
`;
|
|
48
|
+
export function openIndexDb(vaultRoot) {
|
|
49
|
+
try {
|
|
50
|
+
mkdirSync(join(vaultRoot, ".daftari"), { recursive: true });
|
|
51
|
+
const db = new Database(indexDbPath(vaultRoot));
|
|
52
|
+
db.pragma("journal_mode = WAL");
|
|
53
|
+
db.exec(SCHEMA);
|
|
54
|
+
return ok(db);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
58
|
+
return err(new Error(`cannot open index db: ${reason}`));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Drops every indexed row. Called at the start of a rebuild so a reindex never
|
|
62
|
+
// leaves rows for files that have since been deleted.
|
|
63
|
+
export function clearIndex(db) {
|
|
64
|
+
db.exec("DELETE FROM documents; DELETE FROM chunks;");
|
|
65
|
+
}
|
|
66
|
+
// Drops one document and all its chunks. Used by the write path to evict a
|
|
67
|
+
// document's stale rows before re-inserting it: a plain INSERT OR REPLACE on
|
|
68
|
+
// chunks would leave orphaned high-index rows behind if the document shrank.
|
|
69
|
+
export function deleteDocument(db, path) {
|
|
70
|
+
db.prepare("DELETE FROM documents WHERE path = ?").run(path);
|
|
71
|
+
db.prepare("DELETE FROM chunks WHERE path = ?").run(path);
|
|
72
|
+
}
|
|
73
|
+
// --- Float32 <-> BLOB ------------------------------------------------------
|
|
74
|
+
export function embeddingToBlob(vec) {
|
|
75
|
+
return Buffer.from(vec.buffer, vec.byteOffset, vec.byteLength);
|
|
76
|
+
}
|
|
77
|
+
export function blobToEmbedding(blob) {
|
|
78
|
+
// Copy into a fresh, 4-byte-aligned buffer: a Buffer from SQLite may share a
|
|
79
|
+
// pool with an arbitrary byteOffset, which Float32Array cannot view directly.
|
|
80
|
+
const copy = new Uint8Array(blob.length);
|
|
81
|
+
copy.set(blob);
|
|
82
|
+
return new Float32Array(copy.buffer);
|
|
83
|
+
}
|
|
84
|
+
// --- writes ----------------------------------------------------------------
|
|
85
|
+
export function insertDocument(db, doc) {
|
|
86
|
+
db.prepare(`INSERT OR REPLACE INTO documents
|
|
87
|
+
(path, title, collection, domain, status, confidence, updated, tags, content, tokens)
|
|
88
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(doc.path, doc.title, doc.collection, doc.domain, doc.status, doc.confidence, doc.updated, JSON.stringify(doc.tags), doc.content, JSON.stringify(doc.tokens));
|
|
89
|
+
}
|
|
90
|
+
export function insertChunk(db, chunk) {
|
|
91
|
+
db.prepare(`INSERT OR REPLACE INTO chunks (path, chunk_index, text, embedding)
|
|
92
|
+
VALUES (?, ?, ?, ?)`).run(chunk.path, chunk.chunkIndex, chunk.text, chunk.embedding ? embeddingToBlob(chunk.embedding) : null);
|
|
93
|
+
}
|
|
94
|
+
export function setMeta(db, key, value) {
|
|
95
|
+
db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run(key, value);
|
|
96
|
+
}
|
|
97
|
+
function rowToDocument(row) {
|
|
98
|
+
return {
|
|
99
|
+
path: row.path,
|
|
100
|
+
title: row.title,
|
|
101
|
+
collection: row.collection,
|
|
102
|
+
domain: row.domain,
|
|
103
|
+
status: row.status,
|
|
104
|
+
confidence: row.confidence,
|
|
105
|
+
updated: row.updated,
|
|
106
|
+
tags: JSON.parse(row.tags),
|
|
107
|
+
content: row.content,
|
|
108
|
+
tokens: JSON.parse(row.tokens),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export function getAllDocuments(db) {
|
|
112
|
+
const rows = db.prepare("SELECT * FROM documents ORDER BY path").all();
|
|
113
|
+
return rows.map(rowToDocument);
|
|
114
|
+
}
|
|
115
|
+
export function getDocument(db, path) {
|
|
116
|
+
const row = db.prepare("SELECT * FROM documents WHERE path = ?").get(path);
|
|
117
|
+
return row ? rowToDocument(row) : null;
|
|
118
|
+
}
|
|
119
|
+
function rowToChunk(row) {
|
|
120
|
+
return {
|
|
121
|
+
path: row.path,
|
|
122
|
+
chunkIndex: row.chunk_index,
|
|
123
|
+
text: row.text,
|
|
124
|
+
embedding: row.embedding ? blobToEmbedding(row.embedding) : null,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function getAllChunks(db) {
|
|
128
|
+
const rows = db.prepare("SELECT * FROM chunks ORDER BY path, chunk_index").all();
|
|
129
|
+
return rows.map(rowToChunk);
|
|
130
|
+
}
|
|
131
|
+
export function getChunksForPath(db, path) {
|
|
132
|
+
const rows = db
|
|
133
|
+
.prepare("SELECT * FROM chunks WHERE path = ? ORDER BY chunk_index")
|
|
134
|
+
.all(path);
|
|
135
|
+
return rows.map(rowToChunk);
|
|
136
|
+
}
|
|
137
|
+
export function getMeta(db, key) {
|
|
138
|
+
const row = db.prepare("SELECT value FROM meta WHERE key = ?").get(key);
|
|
139
|
+
return row ? row.value : null;
|
|
140
|
+
}
|
|
141
|
+
export function documentCount(db) {
|
|
142
|
+
const row = db.prepare("SELECT COUNT(*) AS n FROM documents").get();
|
|
143
|
+
return row.n;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=index-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-db.js","sourceRoot":"","sources":["../../src/storage/index-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Result } from "../frontmatter/types.js";
|
|
2
|
+
export declare function resolveVaultPath(vaultRoot: string, relativePath: string): Result<string, Error>;
|
|
3
|
+
export declare function directoryExists(path: string): Promise<boolean>;
|
|
4
|
+
export declare function readFile(absolutePath: string): Promise<Result<string, Error>>;
|
|
5
|
+
export declare function listFiles(vaultRoot: string, pattern?: string): Promise<Result<string[], Error>>;
|
|
6
|
+
//# sourceMappingURL=local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AASA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAI/D,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAQ/F;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpE;AAED,wBAAsB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAQnF;AAID,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,SAAY,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAalC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Local filesystem storage backend.
|
|
2
|
+
//
|
|
3
|
+
// Phase 1 is read-only: list markdown files under a vault root and read their
|
|
4
|
+
// contents. A pluggable backend interface (storage/interface.ts) and the
|
|
5
|
+
// SQLite index (storage/index-db.ts) are deferred to later phases.
|
|
6
|
+
import { readFile as fsReadFile, stat } from "node:fs/promises";
|
|
7
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
8
|
+
import { glob } from "glob";
|
|
9
|
+
import { err, ok } from "../frontmatter/types.js";
|
|
10
|
+
// Resolves a vault-relative path to an absolute path, refusing anything that
|
|
11
|
+
// escapes the vault root (path traversal) or resolves to the root itself.
|
|
12
|
+
export function resolveVaultPath(vaultRoot, relativePath) {
|
|
13
|
+
const root = resolve(vaultRoot);
|
|
14
|
+
const target = resolve(root, relativePath);
|
|
15
|
+
const rel = relative(root, target);
|
|
16
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
17
|
+
return err(new Error(`path escapes vault root: ${relativePath}`));
|
|
18
|
+
}
|
|
19
|
+
return ok(target);
|
|
20
|
+
}
|
|
21
|
+
export async function directoryExists(path) {
|
|
22
|
+
try {
|
|
23
|
+
const s = await stat(path);
|
|
24
|
+
return s.isDirectory();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function readFile(absolutePath) {
|
|
31
|
+
try {
|
|
32
|
+
const content = await fsReadFile(absolutePath, "utf-8");
|
|
33
|
+
return ok(content);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
37
|
+
return err(new Error(`cannot read file: ${reason}`));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Lists files under vaultRoot matching a glob pattern. Returns vault-relative
|
|
41
|
+
// POSIX-style paths, sorted. The .daftari control directory is always excluded.
|
|
42
|
+
export async function listFiles(vaultRoot, pattern = "**/*.md") {
|
|
43
|
+
try {
|
|
44
|
+
const matches = await glob(pattern, {
|
|
45
|
+
cwd: resolve(vaultRoot),
|
|
46
|
+
nodir: true,
|
|
47
|
+
posix: true,
|
|
48
|
+
ignore: ["**/.daftari/**", "**/node_modules/**"],
|
|
49
|
+
});
|
|
50
|
+
return ok([...matches].sort());
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
54
|
+
return err(new Error(`cannot list files: ${reason}`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,8EAA8E;AAC9E,yEAAyE;AACzE,mEAAmE;AAEnE,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,yBAAyB,CAAC;AAE/D,6EAA6E;AAC7E,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,YAAoB;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,YAAoB;IACjD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAiB,EACjB,OAAO,GAAG,SAAS;IAEnB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;YAClC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC;YACvB,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;SACjD,CAAC,CAAC;QACH,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AccessContext } from "../access/rbac.js";
|
|
2
|
+
import { type LintCheckName, type LintFinding } from "../curation/lint.js";
|
|
3
|
+
import { type ProvenanceEntry } from "../curation/provenance.js";
|
|
4
|
+
import { type TensionEntry } from "../curation/tension.js";
|
|
5
|
+
import { type Result } from "../frontmatter/types.js";
|
|
6
|
+
import type { ToolDefinition } from "./read.js";
|
|
7
|
+
export declare function vaultTensionLog(vaultRoot: string, args: Record<string, unknown>, access?: AccessContext): Promise<Result<TensionEntry, Error>>;
|
|
8
|
+
export interface VaultLintResult {
|
|
9
|
+
generatedAt: string;
|
|
10
|
+
filter: LintCheckName | null;
|
|
11
|
+
checks: Partial<Record<LintCheckName, LintFinding[]>>;
|
|
12
|
+
totalFindings: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function vaultLint(vaultRoot: string, args?: Record<string, unknown>, access?: AccessContext): Promise<Result<VaultLintResult, Error>>;
|
|
15
|
+
export interface VaultProvenanceResult {
|
|
16
|
+
path: string;
|
|
17
|
+
count: number;
|
|
18
|
+
history: ProvenanceEntry[];
|
|
19
|
+
}
|
|
20
|
+
export declare function vaultProvenance(vaultRoot: string, args: Record<string, unknown>, access?: AccessContext): Promise<Result<VaultProvenanceResult, Error>>;
|
|
21
|
+
export declare const curationTools: ToolDefinition[];
|
|
22
|
+
//# sourceMappingURL=curation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curation.d.ts","sourceRoot":"","sources":["../../src/tools/curation.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,aAAa,EAAc,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAe,KAAK,aAAa,EAAE,KAAK,WAAW,EAAW,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,KAAK,eAAe,EAAqB,MAAM,2BAA2B,CAAC;AACpF,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAM,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAkBhD,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAoCtC;AAMD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IACtD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAqCzC;AAMD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAID,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAiB/C;AAMD,eAAO,MAAM,aAAa,EAAE,cAAc,EAgFzC,CAAC"}
|