gnosys-mcp 0.1.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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +927 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1092 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/bootstrap.d.ts +56 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +163 -0
- package/dist/lib/bootstrap.js.map +1 -0
- package/dist/lib/history.d.ts +39 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +86 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/ingest.d.ts +47 -0
- package/dist/lib/ingest.d.ts.map +1 -0
- package/dist/lib/ingest.js +134 -0
- package/dist/lib/ingest.js.map +1 -0
- package/dist/lib/lensing.d.ts +35 -0
- package/dist/lib/lensing.d.ts.map +1 -0
- package/dist/lib/lensing.js +85 -0
- package/dist/lib/lensing.js.map +1 -0
- package/dist/lib/resolver.d.ts +84 -0
- package/dist/lib/resolver.d.ts.map +1 -0
- package/dist/lib/resolver.js +269 -0
- package/dist/lib/resolver.js.map +1 -0
- package/dist/lib/search.d.ts +50 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +166 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/store.d.ts +67 -0
- package/dist/lib/store.d.ts.map +1 -0
- package/dist/lib/store.js +168 -0
- package/dist/lib/store.js.map +1 -0
- package/dist/lib/tags.d.ts +26 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/tags.js +109 -0
- package/dist/lib/tags.js.map +1 -0
- package/dist/lib/timeline.d.ts +34 -0
- package/dist/lib/timeline.d.ts.map +1 -0
- package/dist/lib/timeline.js +116 -0
- package/dist/lib/timeline.js.map +1 -0
- package/dist/lib/wikilinks.d.ts +63 -0
- package/dist/lib/wikilinks.d.ts.map +1 -0
- package/dist/lib/wikilinks.js +146 -0
- package/dist/lib/wikilinks.js.map +1 -0
- package/dist/test/bootstrap.test.d.ts +2 -0
- package/dist/test/bootstrap.test.d.ts.map +1 -0
- package/dist/test/bootstrap.test.js +208 -0
- package/dist/test/bootstrap.test.js.map +1 -0
- package/dist/test/history.test.d.ts +2 -0
- package/dist/test/history.test.d.ts.map +1 -0
- package/dist/test/history.test.js +141 -0
- package/dist/test/history.test.js.map +1 -0
- package/dist/test/ingest.test.d.ts +2 -0
- package/dist/test/ingest.test.d.ts.map +1 -0
- package/dist/test/ingest.test.js +132 -0
- package/dist/test/ingest.test.js.map +1 -0
- package/dist/test/lensing.test.d.ts +2 -0
- package/dist/test/lensing.test.d.ts.map +1 -0
- package/dist/test/lensing.test.js +154 -0
- package/dist/test/lensing.test.js.map +1 -0
- package/dist/test/search.test.d.ts +2 -0
- package/dist/test/search.test.d.ts.map +1 -0
- package/dist/test/search.test.js +129 -0
- package/dist/test/search.test.js.map +1 -0
- package/dist/test/store.test.d.ts +2 -0
- package/dist/test/store.test.d.ts.map +1 -0
- package/dist/test/store.test.js +152 -0
- package/dist/test/store.test.js.map +1 -0
- package/dist/test/tags.test.d.ts +2 -0
- package/dist/test/tags.test.d.ts.map +1 -0
- package/dist/test/tags.test.js +81 -0
- package/dist/test/tags.test.js.map +1 -0
- package/dist/test/timeline.test.d.ts +2 -0
- package/dist/test/timeline.test.d.ts.map +1 -0
- package/dist/test/timeline.test.js +127 -0
- package/dist/test/timeline.test.js.map +1 -0
- package/dist/test/wikilinks.test.d.ts +2 -0
- package/dist/test/wikilinks.test.d.ts.map +1 -0
- package/dist/test/wikilinks.test.js +178 -0
- package/dist/test/wikilinks.test.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Search — SQLite FTS5 keyword index for fast text search.
|
|
3
|
+
* FTS5-based search and discovery across all Gnosys stores.
|
|
4
|
+
*/
|
|
5
|
+
import { GnosysStore } from "./store.js";
|
|
6
|
+
export interface SearchResult {
|
|
7
|
+
relative_path: string;
|
|
8
|
+
title: string;
|
|
9
|
+
snippet: string;
|
|
10
|
+
rank: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DiscoverResult {
|
|
13
|
+
relative_path: string;
|
|
14
|
+
title: string;
|
|
15
|
+
relevance: string;
|
|
16
|
+
rank: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class GnosysSearch {
|
|
19
|
+
private db;
|
|
20
|
+
private storePath;
|
|
21
|
+
constructor(storePath: string);
|
|
22
|
+
private initSchema;
|
|
23
|
+
/**
|
|
24
|
+
* Clear the entire search index.
|
|
25
|
+
*/
|
|
26
|
+
clearIndex(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Rebuild the entire search index from a single store.
|
|
29
|
+
* Clears all existing entries first.
|
|
30
|
+
*/
|
|
31
|
+
reindex(store: GnosysStore): Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* Add memories from a store to the index WITHOUT clearing existing entries.
|
|
34
|
+
* Used for multi-store indexing: clear once, then addStoreMemories for each store.
|
|
35
|
+
* Optional storeLabel prefix is prepended to relative_path for disambiguation.
|
|
36
|
+
*/
|
|
37
|
+
addStoreMemories(store: GnosysStore, storeLabel?: string): Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Search memories by keyword query.
|
|
40
|
+
*/
|
|
41
|
+
search(query: string, limit?: number): SearchResult[];
|
|
42
|
+
/**
|
|
43
|
+
* Discover memories by searching relevance keyword clouds.
|
|
44
|
+
* Returns lightweight metadata only — no file contents.
|
|
45
|
+
* This is the primary discovery mechanism replacing the static manifest.
|
|
46
|
+
*/
|
|
47
|
+
discover(query: string, limit?: number): DiscoverResult[];
|
|
48
|
+
close(): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,WAAW,EAAU,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAsB7B,OAAO,CAAC,UAAU;IAclB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;;OAGG;IACG,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAKlD;;;;OAIG;IACG,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkChF;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,YAAY,EAAE;IAoCzD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,cAAc,EAAE;IAoC7D,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Search — SQLite FTS5 keyword index for fast text search.
|
|
3
|
+
* FTS5-based search and discovery across all Gnosys stores.
|
|
4
|
+
*/
|
|
5
|
+
import Database from "better-sqlite3";
|
|
6
|
+
import path from "path";
|
|
7
|
+
export class GnosysSearch {
|
|
8
|
+
db;
|
|
9
|
+
storePath;
|
|
10
|
+
constructor(storePath) {
|
|
11
|
+
this.storePath = storePath;
|
|
12
|
+
// Try file-based DB first, fall back to in-memory.
|
|
13
|
+
// We must verify writes actually work — some filesystems (e.g., mounted
|
|
14
|
+
// volumes in sandboxed environments) allow file creation but block the
|
|
15
|
+
// journal/WAL delete operations that SQLite requires.
|
|
16
|
+
try {
|
|
17
|
+
const dbPath = path.join(storePath, ".gnosys", "search.db");
|
|
18
|
+
this.db = new Database(dbPath);
|
|
19
|
+
this.initSchema();
|
|
20
|
+
// Smoke-test: insert + delete to confirm journal ops work
|
|
21
|
+
this.db.exec("CREATE TABLE IF NOT EXISTS _write_test (v INTEGER); INSERT INTO _write_test VALUES (1); DELETE FROM _write_test; DROP TABLE _write_test;");
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Fallback to in-memory (works everywhere, rebuilt on each start)
|
|
25
|
+
try {
|
|
26
|
+
this.db?.close();
|
|
27
|
+
}
|
|
28
|
+
catch { /* ignore */ }
|
|
29
|
+
this.db = new Database(":memory:");
|
|
30
|
+
this.initSchema();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
initSchema() {
|
|
34
|
+
this.db.exec(`
|
|
35
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
36
|
+
relative_path,
|
|
37
|
+
title,
|
|
38
|
+
category,
|
|
39
|
+
tags,
|
|
40
|
+
relevance,
|
|
41
|
+
content,
|
|
42
|
+
tokenize='porter unicode61'
|
|
43
|
+
);
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Clear the entire search index.
|
|
48
|
+
*/
|
|
49
|
+
clearIndex() {
|
|
50
|
+
this.db.exec("DELETE FROM memories_fts");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Rebuild the entire search index from a single store.
|
|
54
|
+
* Clears all existing entries first.
|
|
55
|
+
*/
|
|
56
|
+
async reindex(store) {
|
|
57
|
+
this.clearIndex();
|
|
58
|
+
return this.addStoreMemories(store);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Add memories from a store to the index WITHOUT clearing existing entries.
|
|
62
|
+
* Used for multi-store indexing: clear once, then addStoreMemories for each store.
|
|
63
|
+
* Optional storeLabel prefix is prepended to relative_path for disambiguation.
|
|
64
|
+
*/
|
|
65
|
+
async addStoreMemories(store, storeLabel) {
|
|
66
|
+
const memories = await store.getAllMemories();
|
|
67
|
+
const insert = this.db.prepare("INSERT INTO memories_fts (relative_path, title, category, tags, relevance, content) VALUES (?, ?, ?, ?, ?, ?)");
|
|
68
|
+
const tx = this.db.transaction(() => {
|
|
69
|
+
for (const m of memories) {
|
|
70
|
+
const tags = Array.isArray(m.frontmatter.tags)
|
|
71
|
+
? m.frontmatter.tags.join(" ")
|
|
72
|
+
: Object.values(m.frontmatter.tags).flat().join(" ");
|
|
73
|
+
const relevance = m.frontmatter.relevance || "";
|
|
74
|
+
const indexPath = storeLabel
|
|
75
|
+
? `${storeLabel}:${m.relativePath}`
|
|
76
|
+
: m.relativePath;
|
|
77
|
+
insert.run(indexPath, m.frontmatter.title, m.frontmatter.category, tags, relevance, m.content);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
tx();
|
|
81
|
+
return memories.length;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Search memories by keyword query.
|
|
85
|
+
*/
|
|
86
|
+
search(query, limit = 20) {
|
|
87
|
+
// FTS5 query — escape special characters
|
|
88
|
+
const safeQuery = query.replace(/['"]/g, "").trim();
|
|
89
|
+
if (!safeQuery)
|
|
90
|
+
return [];
|
|
91
|
+
const stmt = this.db.prepare(`
|
|
92
|
+
SELECT
|
|
93
|
+
relative_path,
|
|
94
|
+
title,
|
|
95
|
+
snippet(memories_fts, 5, '>>>', '<<<', '...', 40) as snippet,
|
|
96
|
+
rank
|
|
97
|
+
FROM memories_fts
|
|
98
|
+
WHERE memories_fts MATCH ?
|
|
99
|
+
ORDER BY rank
|
|
100
|
+
LIMIT ?
|
|
101
|
+
`);
|
|
102
|
+
try {
|
|
103
|
+
return stmt.all(safeQuery, limit);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// If FTS5 query fails, fall back to simple LIKE search
|
|
107
|
+
const likeStmt = this.db.prepare(`
|
|
108
|
+
SELECT
|
|
109
|
+
relative_path,
|
|
110
|
+
title,
|
|
111
|
+
substr(content, 1, 200) as snippet,
|
|
112
|
+
0 as rank
|
|
113
|
+
FROM memories_fts
|
|
114
|
+
WHERE content LIKE ? OR title LIKE ? OR tags LIKE ?
|
|
115
|
+
LIMIT ?
|
|
116
|
+
`);
|
|
117
|
+
const pattern = `%${safeQuery}%`;
|
|
118
|
+
return likeStmt.all(pattern, pattern, pattern, limit);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Discover memories by searching relevance keyword clouds.
|
|
123
|
+
* Returns lightweight metadata only — no file contents.
|
|
124
|
+
* This is the primary discovery mechanism replacing the static manifest.
|
|
125
|
+
*/
|
|
126
|
+
discover(query, limit = 20) {
|
|
127
|
+
const safeQuery = query.replace(/['"]/g, "").trim();
|
|
128
|
+
if (!safeQuery)
|
|
129
|
+
return [];
|
|
130
|
+
// Search primarily on relevance + title + tags (not content body)
|
|
131
|
+
// FTS5 column filter: {relevance title tags}
|
|
132
|
+
const stmt = this.db.prepare(`
|
|
133
|
+
SELECT
|
|
134
|
+
relative_path,
|
|
135
|
+
title,
|
|
136
|
+
relevance,
|
|
137
|
+
rank
|
|
138
|
+
FROM memories_fts
|
|
139
|
+
WHERE memories_fts MATCH ?
|
|
140
|
+
ORDER BY rank
|
|
141
|
+
LIMIT ?
|
|
142
|
+
`);
|
|
143
|
+
try {
|
|
144
|
+
// Try column-filtered search on relevance/title/tags first
|
|
145
|
+
const colQuery = `{relevance title tags} : ${safeQuery}`;
|
|
146
|
+
const results = stmt.all(colQuery, limit);
|
|
147
|
+
if (results.length > 0)
|
|
148
|
+
return results;
|
|
149
|
+
// Fall back to full-text search if column filter finds nothing
|
|
150
|
+
return stmt.all(safeQuery, limit);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// If FTS5 column filter syntax fails, fall back to full search
|
|
154
|
+
try {
|
|
155
|
+
return stmt.all(safeQuery, limit);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
close() {
|
|
163
|
+
this.db.close();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Store — Core module for reading/writing atomic memory files.
|
|
3
|
+
* The filesystem is the source of truth. All memories are markdown files
|
|
4
|
+
* with YAML frontmatter organized in category directories.
|
|
5
|
+
*/
|
|
6
|
+
export interface MemoryFrontmatter {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
category: string;
|
|
10
|
+
tags: Record<string, string[]> | string[];
|
|
11
|
+
relevance: string;
|
|
12
|
+
author: "human" | "ai" | "human+ai";
|
|
13
|
+
authority: "declared" | "observed" | "imported" | "inferred";
|
|
14
|
+
confidence: number;
|
|
15
|
+
created: string;
|
|
16
|
+
modified: string;
|
|
17
|
+
last_reviewed?: string | null;
|
|
18
|
+
status: "active" | "archived" | "superseded";
|
|
19
|
+
supersedes?: string | null;
|
|
20
|
+
superseded_by?: string | null;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface Memory {
|
|
24
|
+
frontmatter: MemoryFrontmatter;
|
|
25
|
+
content: string;
|
|
26
|
+
filePath: string;
|
|
27
|
+
relativePath: string;
|
|
28
|
+
}
|
|
29
|
+
export declare class GnosysStore {
|
|
30
|
+
private storePath;
|
|
31
|
+
private gitEnabled;
|
|
32
|
+
constructor(storePath: string);
|
|
33
|
+
init(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Read all memory files from the store.
|
|
36
|
+
*/
|
|
37
|
+
getAllMemories(): Promise<Memory[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Read a single memory by relative path.
|
|
40
|
+
*/
|
|
41
|
+
readMemory(relativePath: string): Promise<Memory | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Write a new memory to the store.
|
|
44
|
+
*/
|
|
45
|
+
writeMemory(category: string, filename: string, frontmatter: MemoryFrontmatter, content: string): Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Update an existing memory.
|
|
48
|
+
*/
|
|
49
|
+
updateMemory(relativePath: string, updates: Partial<MemoryFrontmatter>, newContent?: string): Promise<Memory | null>;
|
|
50
|
+
/**
|
|
51
|
+
* List all categories (directories) in the store.
|
|
52
|
+
*/
|
|
53
|
+
getCategories(): Promise<string[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Generate a unique ID for a new memory.
|
|
56
|
+
*/
|
|
57
|
+
generateId(category: string): Promise<string>;
|
|
58
|
+
/**
|
|
59
|
+
* Get the store path.
|
|
60
|
+
*/
|
|
61
|
+
getStorePath(): string;
|
|
62
|
+
/**
|
|
63
|
+
* Auto-commit changes to git (silent, never user-facing).
|
|
64
|
+
*/
|
|
65
|
+
private autoCommit;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/lib/store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;IACpC,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAU;gBAEhB,SAAS,EAAE,MAAM;IAKvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAkBzC;;OAEG;IACG,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmB9D;;OAEG;IACG,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAgBlB;;OAEG;IACG,YAAY,CAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,EACnC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAyBzB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAaxC;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAenD;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;YACW,UAAU;CAYzB"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Store — Core module for reading/writing atomic memory files.
|
|
3
|
+
* The filesystem is the source of truth. All memories are markdown files
|
|
4
|
+
* with YAML frontmatter organized in category directories.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import matter from "gray-matter";
|
|
9
|
+
import { glob } from "glob";
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
export class GnosysStore {
|
|
12
|
+
storePath;
|
|
13
|
+
gitEnabled;
|
|
14
|
+
constructor(storePath) {
|
|
15
|
+
this.storePath = path.resolve(storePath);
|
|
16
|
+
this.gitEnabled = false;
|
|
17
|
+
}
|
|
18
|
+
async init() {
|
|
19
|
+
// Ensure store directory exists
|
|
20
|
+
await fs.mkdir(this.storePath, { recursive: true });
|
|
21
|
+
await fs.mkdir(path.join(this.storePath, ".gnosys"), { recursive: true });
|
|
22
|
+
// Init git if not already
|
|
23
|
+
try {
|
|
24
|
+
const gitDir = path.join(this.storePath, ".git");
|
|
25
|
+
const stat = await fs.stat(gitDir).catch(() => null);
|
|
26
|
+
if (!stat) {
|
|
27
|
+
execSync("git init", { cwd: this.storePath, stdio: "pipe" });
|
|
28
|
+
}
|
|
29
|
+
this.gitEnabled = true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
this.gitEnabled = false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read all memory files from the store.
|
|
37
|
+
*/
|
|
38
|
+
async getAllMemories() {
|
|
39
|
+
const files = await glob("**/*.md", {
|
|
40
|
+
cwd: this.storePath,
|
|
41
|
+
ignore: ["MANIFEST.md", "CHANGELOG.md", ".gnosys/**", "node_modules/**"],
|
|
42
|
+
});
|
|
43
|
+
const memories = [];
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
try {
|
|
46
|
+
const memory = await this.readMemory(file);
|
|
47
|
+
if (memory)
|
|
48
|
+
memories.push(memory);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Skip files that can't be parsed
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return memories;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read a single memory by relative path.
|
|
58
|
+
*/
|
|
59
|
+
async readMemory(relativePath) {
|
|
60
|
+
const fullPath = path.join(this.storePath, relativePath);
|
|
61
|
+
try {
|
|
62
|
+
const raw = await fs.readFile(fullPath, "utf-8");
|
|
63
|
+
const parsed = matter(raw);
|
|
64
|
+
if (!parsed.data.id)
|
|
65
|
+
return null; // Not a valid memory file
|
|
66
|
+
return {
|
|
67
|
+
frontmatter: parsed.data,
|
|
68
|
+
content: parsed.content.trim(),
|
|
69
|
+
filePath: fullPath,
|
|
70
|
+
relativePath,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Write a new memory to the store.
|
|
79
|
+
*/
|
|
80
|
+
async writeMemory(category, filename, frontmatter, content) {
|
|
81
|
+
const dir = path.join(this.storePath, category);
|
|
82
|
+
await fs.mkdir(dir, { recursive: true });
|
|
83
|
+
const filePath = path.join(dir, filename);
|
|
84
|
+
const relativePath = path.join(category, filename);
|
|
85
|
+
const fileContent = matter.stringify(content, frontmatter);
|
|
86
|
+
await fs.writeFile(filePath, fileContent, "utf-8");
|
|
87
|
+
// Auto git commit
|
|
88
|
+
await this.autoCommit(`Add memory: ${frontmatter.title}`);
|
|
89
|
+
return relativePath;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Update an existing memory.
|
|
93
|
+
*/
|
|
94
|
+
async updateMemory(relativePath, updates, newContent) {
|
|
95
|
+
const existing = await this.readMemory(relativePath);
|
|
96
|
+
if (!existing)
|
|
97
|
+
return null;
|
|
98
|
+
const updatedFrontmatter = {
|
|
99
|
+
...existing.frontmatter,
|
|
100
|
+
...updates,
|
|
101
|
+
modified: new Date().toISOString().split("T")[0],
|
|
102
|
+
};
|
|
103
|
+
const updatedContent = newContent ?? existing.content;
|
|
104
|
+
const fullPath = path.join(this.storePath, relativePath);
|
|
105
|
+
const fileContent = matter.stringify(updatedContent, updatedFrontmatter);
|
|
106
|
+
await fs.writeFile(fullPath, fileContent, "utf-8");
|
|
107
|
+
await this.autoCommit(`Update memory: ${updatedFrontmatter.title}`);
|
|
108
|
+
return {
|
|
109
|
+
frontmatter: updatedFrontmatter,
|
|
110
|
+
content: updatedContent,
|
|
111
|
+
filePath: fullPath,
|
|
112
|
+
relativePath,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* List all categories (directories) in the store.
|
|
117
|
+
*/
|
|
118
|
+
async getCategories() {
|
|
119
|
+
const entries = await fs.readdir(this.storePath, { withFileTypes: true });
|
|
120
|
+
return entries
|
|
121
|
+
.filter((e) => e.isDirectory() &&
|
|
122
|
+
!e.name.startsWith(".") &&
|
|
123
|
+
e.name !== "node_modules")
|
|
124
|
+
.map((e) => e.name)
|
|
125
|
+
.sort();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate a unique ID for a new memory.
|
|
129
|
+
*/
|
|
130
|
+
async generateId(category) {
|
|
131
|
+
const prefix = category.substring(0, 4);
|
|
132
|
+
const memories = await this.getAllMemories();
|
|
133
|
+
const existingIds = memories
|
|
134
|
+
.map((m) => m.frontmatter.id)
|
|
135
|
+
.filter((id) => id.startsWith(prefix));
|
|
136
|
+
let maxNum = 0;
|
|
137
|
+
for (const id of existingIds) {
|
|
138
|
+
const match = id.match(/(\d+)$/);
|
|
139
|
+
if (match)
|
|
140
|
+
maxNum = Math.max(maxNum, parseInt(match[1]));
|
|
141
|
+
}
|
|
142
|
+
return `${prefix}-${String(maxNum + 1).padStart(3, "0")}`;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get the store path.
|
|
146
|
+
*/
|
|
147
|
+
getStorePath() {
|
|
148
|
+
return this.storePath;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Auto-commit changes to git (silent, never user-facing).
|
|
152
|
+
*/
|
|
153
|
+
async autoCommit(message) {
|
|
154
|
+
if (!this.gitEnabled)
|
|
155
|
+
return;
|
|
156
|
+
try {
|
|
157
|
+
execSync("git add -A", { cwd: this.storePath, stdio: "pipe" });
|
|
158
|
+
execSync(`git commit -m "${message}" --allow-empty-message`, {
|
|
159
|
+
cwd: this.storePath,
|
|
160
|
+
stdio: "pipe",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// Git commit can fail if nothing changed — that's fine
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/lib/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Tag Registry — Categorized controlled vocabulary for tags.
|
|
3
|
+
* Stored in .gnosys/tags.yml. The ingestion LLM must use existing tags
|
|
4
|
+
* but can propose new ones for approval.
|
|
5
|
+
*/
|
|
6
|
+
export interface TagRegistry {
|
|
7
|
+
domain: string[];
|
|
8
|
+
type: string[];
|
|
9
|
+
concern: string[];
|
|
10
|
+
status_tag: string[];
|
|
11
|
+
[category: string]: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare class GnosysTagRegistry {
|
|
14
|
+
private registryPath;
|
|
15
|
+
private registry;
|
|
16
|
+
constructor(storePath: string);
|
|
17
|
+
load(): Promise<TagRegistry>;
|
|
18
|
+
save(): Promise<void>;
|
|
19
|
+
getRegistry(): TagRegistry;
|
|
20
|
+
getAllTags(): string[];
|
|
21
|
+
getTagsByCategory(category: string): string[];
|
|
22
|
+
hasTag(tag: string): boolean;
|
|
23
|
+
findTagCategory(tag: string): string | null;
|
|
24
|
+
addTag(category: string, tag: string): Promise<boolean>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/lib/tags.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAmDD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAc;gBAElB,SAAS,EAAE,MAAM;IAKvB,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAW5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,WAAW,IAAI,WAAW;IAI1B,UAAU,IAAI,MAAM,EAAE;IAItB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAI7C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOrC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAS9D"}
|
package/dist/lib/tags.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Tag Registry — Categorized controlled vocabulary for tags.
|
|
3
|
+
* Stored in .gnosys/tags.yml. The ingestion LLM must use existing tags
|
|
4
|
+
* but can propose new ones for approval.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
const DEFAULT_REGISTRY = {
|
|
9
|
+
domain: [
|
|
10
|
+
"auth",
|
|
11
|
+
"database",
|
|
12
|
+
"frontend",
|
|
13
|
+
"backend",
|
|
14
|
+
"deployment",
|
|
15
|
+
"api",
|
|
16
|
+
"cli",
|
|
17
|
+
"mcp",
|
|
18
|
+
"wiki",
|
|
19
|
+
"obsidian",
|
|
20
|
+
"architecture",
|
|
21
|
+
"retrieval",
|
|
22
|
+
"search",
|
|
23
|
+
"ingestion",
|
|
24
|
+
"memory",
|
|
25
|
+
"lensing",
|
|
26
|
+
"decay",
|
|
27
|
+
"reinforcement",
|
|
28
|
+
"contradiction",
|
|
29
|
+
"tags",
|
|
30
|
+
"git",
|
|
31
|
+
"typescript",
|
|
32
|
+
"tooling",
|
|
33
|
+
"roadmap",
|
|
34
|
+
"scope",
|
|
35
|
+
],
|
|
36
|
+
type: [
|
|
37
|
+
"decision",
|
|
38
|
+
"convention",
|
|
39
|
+
"architecture",
|
|
40
|
+
"concept",
|
|
41
|
+
"requirement",
|
|
42
|
+
"landscape",
|
|
43
|
+
"open-question",
|
|
44
|
+
],
|
|
45
|
+
concern: [
|
|
46
|
+
"security",
|
|
47
|
+
"performance",
|
|
48
|
+
"scalability",
|
|
49
|
+
"dx",
|
|
50
|
+
"adoption",
|
|
51
|
+
"community",
|
|
52
|
+
"portability",
|
|
53
|
+
],
|
|
54
|
+
status_tag: ["core", "experimental", "deprecated", "phased"],
|
|
55
|
+
};
|
|
56
|
+
export class GnosysTagRegistry {
|
|
57
|
+
registryPath;
|
|
58
|
+
registry;
|
|
59
|
+
constructor(storePath) {
|
|
60
|
+
this.registryPath = path.join(storePath, ".gnosys", "tags.json");
|
|
61
|
+
this.registry = { ...DEFAULT_REGISTRY };
|
|
62
|
+
}
|
|
63
|
+
async load() {
|
|
64
|
+
try {
|
|
65
|
+
const raw = await fs.readFile(this.registryPath, "utf-8");
|
|
66
|
+
this.registry = JSON.parse(raw);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// File doesn't exist yet — use defaults and create it
|
|
70
|
+
await this.save();
|
|
71
|
+
}
|
|
72
|
+
return this.registry;
|
|
73
|
+
}
|
|
74
|
+
async save() {
|
|
75
|
+
const dir = path.dirname(this.registryPath);
|
|
76
|
+
await fs.mkdir(dir, { recursive: true });
|
|
77
|
+
await fs.writeFile(this.registryPath, JSON.stringify(this.registry, null, 2), "utf-8");
|
|
78
|
+
}
|
|
79
|
+
getRegistry() {
|
|
80
|
+
return this.registry;
|
|
81
|
+
}
|
|
82
|
+
getAllTags() {
|
|
83
|
+
return [...new Set(Object.values(this.registry).flat())].sort();
|
|
84
|
+
}
|
|
85
|
+
getTagsByCategory(category) {
|
|
86
|
+
return this.registry[category] || [];
|
|
87
|
+
}
|
|
88
|
+
hasTag(tag) {
|
|
89
|
+
return Object.values(this.registry).some((tags) => tags.includes(tag));
|
|
90
|
+
}
|
|
91
|
+
findTagCategory(tag) {
|
|
92
|
+
for (const [category, tags] of Object.entries(this.registry)) {
|
|
93
|
+
if (tags.includes(tag))
|
|
94
|
+
return category;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
async addTag(category, tag) {
|
|
99
|
+
if (!this.registry[category]) {
|
|
100
|
+
this.registry[category] = [];
|
|
101
|
+
}
|
|
102
|
+
if (this.registry[category].includes(tag))
|
|
103
|
+
return false;
|
|
104
|
+
this.registry[category].push(tag);
|
|
105
|
+
await this.save();
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/lib/tags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnosys Timeline — Temporal views and statistics for memory stores.
|
|
3
|
+
*
|
|
4
|
+
* Group memories by time period to see knowledge evolution.
|
|
5
|
+
* Compute summary statistics across the store.
|
|
6
|
+
*/
|
|
7
|
+
import { Memory } from "./store.js";
|
|
8
|
+
export type TimePeriod = "day" | "week" | "month" | "year";
|
|
9
|
+
export interface TimelineEntry {
|
|
10
|
+
period: string;
|
|
11
|
+
created: number;
|
|
12
|
+
modified: number;
|
|
13
|
+
titles: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface MemoryStats {
|
|
16
|
+
totalCount: number;
|
|
17
|
+
byCategory: Record<string, number>;
|
|
18
|
+
byStatus: Record<string, number>;
|
|
19
|
+
byAuthor: Record<string, number>;
|
|
20
|
+
byAuthority: Record<string, number>;
|
|
21
|
+
averageConfidence: number;
|
|
22
|
+
oldestCreated: string | null;
|
|
23
|
+
newestCreated: string | null;
|
|
24
|
+
lastModified: string | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Group memories by time period based on their created/modified dates.
|
|
28
|
+
*/
|
|
29
|
+
export declare function groupByPeriod(memories: Memory[], period: TimePeriod): TimelineEntry[];
|
|
30
|
+
/**
|
|
31
|
+
* Compute summary statistics across all memories.
|
|
32
|
+
*/
|
|
33
|
+
export declare function computeStats(memories: Memory[]): MemoryStats;
|
|
34
|
+
//# sourceMappingURL=timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../src/lib/timeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,GAAG,aAAa,EAAE,CAkCrF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,WAAW,CAmC5D"}
|