contextmate 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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/dist/src/adapters/base.d.ts +32 -0
  4. package/dist/src/adapters/base.d.ts.map +1 -0
  5. package/dist/src/adapters/base.js +49 -0
  6. package/dist/src/adapters/base.js.map +1 -0
  7. package/dist/src/adapters/claude.d.ts +30 -0
  8. package/dist/src/adapters/claude.d.ts.map +1 -0
  9. package/dist/src/adapters/claude.js +534 -0
  10. package/dist/src/adapters/claude.js.map +1 -0
  11. package/dist/src/adapters/index.d.ts +7 -0
  12. package/dist/src/adapters/index.d.ts.map +1 -0
  13. package/dist/src/adapters/index.js +16 -0
  14. package/dist/src/adapters/index.js.map +1 -0
  15. package/dist/src/adapters/openclaw.d.ts +15 -0
  16. package/dist/src/adapters/openclaw.d.ts.map +1 -0
  17. package/dist/src/adapters/openclaw.js +198 -0
  18. package/dist/src/adapters/openclaw.js.map +1 -0
  19. package/dist/src/bin/contextmate.d.ts +3 -0
  20. package/dist/src/bin/contextmate.d.ts.map +1 -0
  21. package/dist/src/bin/contextmate.js +4 -0
  22. package/dist/src/bin/contextmate.js.map +1 -0
  23. package/dist/src/cli/adapter.d.ts +3 -0
  24. package/dist/src/cli/adapter.d.ts.map +1 -0
  25. package/dist/src/cli/adapter.js +187 -0
  26. package/dist/src/cli/adapter.js.map +1 -0
  27. package/dist/src/cli/daemon.d.ts +3 -0
  28. package/dist/src/cli/daemon.d.ts.map +1 -0
  29. package/dist/src/cli/daemon.js +212 -0
  30. package/dist/src/cli/daemon.js.map +1 -0
  31. package/dist/src/cli/files.d.ts +3 -0
  32. package/dist/src/cli/files.d.ts.map +1 -0
  33. package/dist/src/cli/files.js +158 -0
  34. package/dist/src/cli/files.js.map +1 -0
  35. package/dist/src/cli/index.d.ts +3 -0
  36. package/dist/src/cli/index.d.ts.map +1 -0
  37. package/dist/src/cli/index.js +20 -0
  38. package/dist/src/cli/index.js.map +1 -0
  39. package/dist/src/cli/init.d.ts +3 -0
  40. package/dist/src/cli/init.d.ts.map +1 -0
  41. package/dist/src/cli/init.js +88 -0
  42. package/dist/src/cli/init.js.map +1 -0
  43. package/dist/src/cli/log.d.ts +3 -0
  44. package/dist/src/cli/log.d.ts.map +1 -0
  45. package/dist/src/cli/log.js +141 -0
  46. package/dist/src/cli/log.js.map +1 -0
  47. package/dist/src/cli/mcp.d.ts +3 -0
  48. package/dist/src/cli/mcp.d.ts.map +1 -0
  49. package/dist/src/cli/mcp.js +186 -0
  50. package/dist/src/cli/mcp.js.map +1 -0
  51. package/dist/src/cli/status.d.ts +3 -0
  52. package/dist/src/cli/status.d.ts.map +1 -0
  53. package/dist/src/cli/status.js +107 -0
  54. package/dist/src/cli/status.js.map +1 -0
  55. package/dist/src/config.d.ts +42 -0
  56. package/dist/src/config.d.ts.map +1 -0
  57. package/dist/src/config.js +93 -0
  58. package/dist/src/config.js.map +1 -0
  59. package/dist/src/crypto/auth.d.ts +4 -0
  60. package/dist/src/crypto/auth.d.ts.map +1 -0
  61. package/dist/src/crypto/auth.js +21 -0
  62. package/dist/src/crypto/auth.js.map +1 -0
  63. package/dist/src/crypto/encrypt.d.ts +9 -0
  64. package/dist/src/crypto/encrypt.d.ts.map +1 -0
  65. package/dist/src/crypto/encrypt.js +39 -0
  66. package/dist/src/crypto/encrypt.js.map +1 -0
  67. package/dist/src/crypto/index.d.ts +4 -0
  68. package/dist/src/crypto/index.d.ts.map +1 -0
  69. package/dist/src/crypto/index.js +4 -0
  70. package/dist/src/crypto/index.js.map +1 -0
  71. package/dist/src/crypto/keys.d.ts +9 -0
  72. package/dist/src/crypto/keys.d.ts.map +1 -0
  73. package/dist/src/crypto/keys.js +43 -0
  74. package/dist/src/crypto/keys.js.map +1 -0
  75. package/dist/src/mcp/embeddings.d.ts +16 -0
  76. package/dist/src/mcp/embeddings.d.ts.map +1 -0
  77. package/dist/src/mcp/embeddings.js +237 -0
  78. package/dist/src/mcp/embeddings.js.map +1 -0
  79. package/dist/src/mcp/index.d.ts +10 -0
  80. package/dist/src/mcp/index.d.ts.map +1 -0
  81. package/dist/src/mcp/index.js +6 -0
  82. package/dist/src/mcp/index.js.map +1 -0
  83. package/dist/src/mcp/rerank.d.ts +14 -0
  84. package/dist/src/mcp/rerank.d.ts.map +1 -0
  85. package/dist/src/mcp/rerank.js +47 -0
  86. package/dist/src/mcp/rerank.js.map +1 -0
  87. package/dist/src/mcp/scope.d.ts +26 -0
  88. package/dist/src/mcp/scope.d.ts.map +1 -0
  89. package/dist/src/mcp/scope.js +71 -0
  90. package/dist/src/mcp/scope.js.map +1 -0
  91. package/dist/src/mcp/search.d.ts +18 -0
  92. package/dist/src/mcp/search.d.ts.map +1 -0
  93. package/dist/src/mcp/search.js +110 -0
  94. package/dist/src/mcp/search.js.map +1 -0
  95. package/dist/src/mcp/server.d.ts +15 -0
  96. package/dist/src/mcp/server.d.ts.map +1 -0
  97. package/dist/src/mcp/server.js +340 -0
  98. package/dist/src/mcp/server.js.map +1 -0
  99. package/dist/src/sync/client.d.ts +25 -0
  100. package/dist/src/sync/client.d.ts.map +1 -0
  101. package/dist/src/sync/client.js +109 -0
  102. package/dist/src/sync/client.js.map +1 -0
  103. package/dist/src/sync/engine.d.ts +21 -0
  104. package/dist/src/sync/engine.d.ts.map +1 -0
  105. package/dist/src/sync/engine.js +304 -0
  106. package/dist/src/sync/engine.js.map +1 -0
  107. package/dist/src/sync/index.d.ts +6 -0
  108. package/dist/src/sync/index.d.ts.map +1 -0
  109. package/dist/src/sync/index.js +6 -0
  110. package/dist/src/sync/index.js.map +1 -0
  111. package/dist/src/sync/state.d.ts +33 -0
  112. package/dist/src/sync/state.d.ts.map +1 -0
  113. package/dist/src/sync/state.js +146 -0
  114. package/dist/src/sync/state.js.map +1 -0
  115. package/dist/src/sync/watcher.d.ts +14 -0
  116. package/dist/src/sync/watcher.d.ts.map +1 -0
  117. package/dist/src/sync/watcher.js +74 -0
  118. package/dist/src/sync/watcher.js.map +1 -0
  119. package/dist/src/sync/websocket.d.ts +22 -0
  120. package/dist/src/sync/websocket.d.ts.map +1 -0
  121. package/dist/src/sync/websocket.js +103 -0
  122. package/dist/src/sync/websocket.js.map +1 -0
  123. package/dist/src/types.d.ts +63 -0
  124. package/dist/src/types.d.ts.map +1 -0
  125. package/dist/src/types.js +2 -0
  126. package/dist/src/types.js.map +1 -0
  127. package/dist/src/utils/paths.d.ts +9 -0
  128. package/dist/src/utils/paths.d.ts.map +1 -0
  129. package/dist/src/utils/paths.js +24 -0
  130. package/dist/src/utils/paths.js.map +1 -0
  131. package/package.json +61 -0
@@ -0,0 +1,43 @@
1
+ import argon2 from 'argon2';
2
+ import { hkdf } from '@noble/hashes/hkdf';
3
+ import { sha256 } from '@noble/hashes/sha256';
4
+ import { randomBytes } from 'node:crypto';
5
+ const KEY_LENGTH = 32;
6
+ export function generateSalt() {
7
+ return new Uint8Array(randomBytes(KEY_LENGTH));
8
+ }
9
+ export async function deriveMasterKey(passphrase, salt) {
10
+ const hash = await argon2.hash(passphrase, {
11
+ type: argon2.argon2id,
12
+ salt: Buffer.from(salt),
13
+ timeCost: 3,
14
+ memoryCost: 65536,
15
+ parallelism: 4,
16
+ hashLength: KEY_LENGTH,
17
+ raw: true,
18
+ });
19
+ return new Uint8Array(hash);
20
+ }
21
+ export function deriveVaultKey(masterKey) {
22
+ return hkdf(sha256, masterKey, undefined, 'contextmate-vault-enc', KEY_LENGTH);
23
+ }
24
+ export function deriveFolderKey(vaultKey, folderId) {
25
+ return hkdf(sha256, vaultKey, undefined, 'contextmate-folder-' + folderId, KEY_LENGTH);
26
+ }
27
+ export function deriveFileKey(folderKey, fileId) {
28
+ return hkdf(sha256, folderKey, undefined, 'contextmate-file-' + fileId, KEY_LENGTH);
29
+ }
30
+ export function deriveAuthKey(masterKey) {
31
+ return hkdf(sha256, masterKey, undefined, 'contextmate-auth', KEY_LENGTH);
32
+ }
33
+ export function deriveSharingKey(masterKey) {
34
+ return hkdf(sha256, masterKey, undefined, 'contextmate-sharing', KEY_LENGTH);
35
+ }
36
+ export function deriveKeyForPath(vaultKey, filePath) {
37
+ const segments = filePath.split('/');
38
+ const folder = segments[0];
39
+ const rest = segments.slice(1).join('/');
40
+ const folderKey = deriveFolderKey(vaultKey, folder);
41
+ return deriveFileKey(folderKey, rest);
42
+ }
43
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/crypto/keys.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,IAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE;QACzC,IAAI,EAAE,MAAM,CAAC,QAAQ;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QACvB,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,UAAU;QACtB,GAAG,EAAE,IAAI;KACV,CAAC,CAAC;IACH,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAqB;IAClD,OAAO,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,uBAAuB,EAAE,UAAU,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,QAAoB,EACpB,QAAgB;IAEhB,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,GAAG,QAAQ,EAAE,UAAU,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAAqB,EACrB,MAAc;IAEd,OAAO,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,GAAG,MAAM,EAAE,UAAU,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAqB;IACjD,OAAO,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAqB;IACpD,OAAO,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAoB,EACpB,QAAgB;IAEhB,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface VectorSearchResult {
2
+ path: string;
3
+ score: number;
4
+ }
5
+ export declare class VectorIndex {
6
+ private db;
7
+ constructor(dbPath: string);
8
+ indexFile(path: string, content: string): void;
9
+ removeFromIndex(path: string): void;
10
+ recomputeIdf(): void;
11
+ search(query: string, limit?: number): VectorSearchResult[];
12
+ rebuildIndex(vaultPath: string): Promise<void>;
13
+ close(): void;
14
+ private collectMdFiles;
15
+ }
16
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../../src/mcp/embeddings.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAmBD,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAsB1B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA6D9C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8BnC,YAAY,IAAI,IAAI;IAuDpB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,kBAAkB,EAAE;IA4EzD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD,KAAK,IAAI,IAAI;YAIC,cAAc;CAqB7B"}
@@ -0,0 +1,237 @@
1
+ import Database from 'better-sqlite3';
2
+ import { readdir, readFile } from 'node:fs/promises';
3
+ import { join, relative } from 'node:path';
4
+ const STOPWORDS = new Set([
5
+ 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'have', 'has',
6
+ 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should', 'may',
7
+ 'might', 'shall', 'can', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by',
8
+ 'from', 'or', 'and', 'not', 'but', 'if', 'then', 'as', 'it', 'its', 'this',
9
+ 'that', 'which', 'who', 'what', 'when', 'where', 'how', 'all', 'each',
10
+ 'every', 'both', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor',
11
+ 'too', 'very', 'just', 'also', 'than',
12
+ ]);
13
+ function tokenize(text) {
14
+ return text
15
+ .toLowerCase()
16
+ .split(/[^a-z0-9']+/)
17
+ .filter((w) => w.length >= 2 && !STOPWORDS.has(w));
18
+ }
19
+ export class VectorIndex {
20
+ db;
21
+ constructor(dbPath) {
22
+ this.db = new Database(dbPath);
23
+ this.db.pragma('journal_mode = WAL');
24
+ this.db.exec(`
25
+ CREATE TABLE IF NOT EXISTS vocabulary (
26
+ term TEXT PRIMARY KEY,
27
+ idf REAL NOT NULL DEFAULT 0,
28
+ doc_count INTEGER NOT NULL DEFAULT 0
29
+ );
30
+ CREATE TABLE IF NOT EXISTS documents (
31
+ path TEXT PRIMARY KEY,
32
+ tf_vector TEXT NOT NULL,
33
+ magnitude REAL NOT NULL DEFAULT 0,
34
+ updated_at INTEGER NOT NULL
35
+ );
36
+ CREATE TABLE IF NOT EXISTS stats (
37
+ key TEXT PRIMARY KEY,
38
+ value TEXT NOT NULL
39
+ );
40
+ `);
41
+ }
42
+ indexFile(path, content) {
43
+ const tokens = tokenize(content);
44
+ if (tokens.length === 0) {
45
+ this.removeFromIndex(path);
46
+ return;
47
+ }
48
+ const totalWords = tokens.length;
49
+ const termCounts = new Map();
50
+ for (const token of tokens) {
51
+ termCounts.set(token, (termCounts.get(token) ?? 0) + 1);
52
+ }
53
+ // Build raw TF vector (count / total_words)
54
+ const tfVector = {};
55
+ for (const [term, count] of termCounts) {
56
+ tfVector[term] = count / totalWords;
57
+ }
58
+ const now = Date.now();
59
+ const txn = this.db.transaction(() => {
60
+ // Check if document already exists — need to decrement old vocab counts
61
+ const existing = this.db.prepare('SELECT tf_vector FROM documents WHERE path = ?').get(path);
62
+ if (existing) {
63
+ const oldVector = JSON.parse(existing.tf_vector);
64
+ for (const term of Object.keys(oldVector)) {
65
+ this.db.prepare('UPDATE vocabulary SET doc_count = MAX(doc_count - 1, 0) WHERE term = ?').run(term);
66
+ }
67
+ }
68
+ // Update vocabulary with new term counts
69
+ const upsertVocab = this.db.prepare(`
70
+ INSERT INTO vocabulary (term, idf, doc_count) VALUES (?, 0, 1)
71
+ ON CONFLICT(term) DO UPDATE SET doc_count = doc_count + 1
72
+ `);
73
+ for (const term of termCounts.keys()) {
74
+ upsertVocab.run(term);
75
+ }
76
+ // Store document (magnitude will be recomputed during recomputeIdf)
77
+ this.db.prepare('INSERT OR REPLACE INTO documents (path, tf_vector, magnitude, updated_at) VALUES (?, ?, 0, ?)').run(path, JSON.stringify(tfVector), now);
78
+ // Update total docs count
79
+ const docCount = this.db.prepare('SELECT COUNT(*) as cnt FROM documents').get();
80
+ this.db.prepare("INSERT OR REPLACE INTO stats (key, value) VALUES ('total_docs', ?)").run(String(docCount.cnt));
81
+ });
82
+ txn();
83
+ }
84
+ removeFromIndex(path) {
85
+ const txn = this.db.transaction(() => {
86
+ const existing = this.db.prepare('SELECT tf_vector FROM documents WHERE path = ?').get(path);
87
+ if (existing) {
88
+ const oldVector = JSON.parse(existing.tf_vector);
89
+ for (const term of Object.keys(oldVector)) {
90
+ this.db.prepare('UPDATE vocabulary SET doc_count = MAX(doc_count - 1, 0) WHERE term = ?').run(term);
91
+ }
92
+ this.db.prepare('DELETE FROM documents WHERE path = ?').run(path);
93
+ // Clean up zero-count vocabulary entries
94
+ this.db.prepare('DELETE FROM vocabulary WHERE doc_count <= 0').run();
95
+ // Update total docs count
96
+ const docCount = this.db.prepare('SELECT COUNT(*) as cnt FROM documents').get();
97
+ this.db.prepare("INSERT OR REPLACE INTO stats (key, value) VALUES ('total_docs', ?)").run(String(docCount.cnt));
98
+ }
99
+ });
100
+ txn();
101
+ }
102
+ recomputeIdf() {
103
+ const txn = this.db.transaction(() => {
104
+ const statsRow = this.db.prepare("SELECT value FROM stats WHERE key = 'total_docs'").get();
105
+ const totalDocs = statsRow ? parseInt(statsRow.value, 10) : 0;
106
+ if (totalDocs === 0)
107
+ return;
108
+ // Update IDF for all terms: log(1 + N / (1 + df))
109
+ this.db.prepare('UPDATE vocabulary SET idf = ln(1.0 + CAST(? AS REAL) / (1.0 + doc_count))').run(totalDocs);
110
+ // Load all IDF values into memory for vector recomputation
111
+ const vocabRows = this.db.prepare('SELECT term, idf FROM vocabulary').all();
112
+ const idfMap = new Map();
113
+ for (const row of vocabRows) {
114
+ idfMap.set(row.term, row.idf);
115
+ }
116
+ // Recompute TF-IDF vectors and magnitudes for all documents
117
+ const docs = this.db.prepare('SELECT path, tf_vector FROM documents').all();
118
+ const updateDoc = this.db.prepare('UPDATE documents SET tf_vector = ?, magnitude = ? WHERE path = ?');
119
+ for (const doc of docs) {
120
+ const rawTf = JSON.parse(doc.tf_vector);
121
+ const tfidfVector = {};
122
+ let magnitudeSq = 0;
123
+ for (const [term, tf] of Object.entries(rawTf)) {
124
+ const idf = idfMap.get(term) ?? 0;
125
+ const tfidf = tf * idf;
126
+ if (tfidf > 0) {
127
+ tfidfVector[term] = tfidf;
128
+ magnitudeSq += tfidf * tfidf;
129
+ }
130
+ }
131
+ const magnitude = Math.sqrt(magnitudeSq);
132
+ updateDoc.run(JSON.stringify(tfidfVector), magnitude, doc.path);
133
+ }
134
+ });
135
+ txn();
136
+ }
137
+ search(query, limit = 10) {
138
+ const tokens = tokenize(query);
139
+ if (tokens.length === 0)
140
+ return [];
141
+ // Build query term frequencies
142
+ const totalWords = tokens.length;
143
+ const termCounts = new Map();
144
+ for (const token of tokens) {
145
+ termCounts.set(token, (termCounts.get(token) ?? 0) + 1);
146
+ }
147
+ // Load IDF values for query terms
148
+ const placeholders = Array.from(termCounts.keys())
149
+ .map(() => '?')
150
+ .join(', ');
151
+ const vocabRows = this.db
152
+ .prepare(`SELECT term, idf FROM vocabulary WHERE term IN (${placeholders})`)
153
+ .all(...termCounts.keys());
154
+ const idfMap = new Map();
155
+ for (const row of vocabRows) {
156
+ idfMap.set(row.term, row.idf);
157
+ }
158
+ // Build query TF-IDF vector
159
+ const queryVector = {};
160
+ let queryMagSq = 0;
161
+ for (const [term, count] of termCounts) {
162
+ const tf = count / totalWords;
163
+ const idf = idfMap.get(term) ?? 0;
164
+ const tfidf = tf * idf;
165
+ if (tfidf > 0) {
166
+ queryVector[term] = tfidf;
167
+ queryMagSq += tfidf * tfidf;
168
+ }
169
+ }
170
+ const queryMag = Math.sqrt(queryMagSq);
171
+ if (queryMag === 0)
172
+ return [];
173
+ // Load all documents and compute cosine similarity
174
+ const docs = this.db
175
+ .prepare('SELECT path, tf_vector, magnitude FROM documents')
176
+ .all();
177
+ const results = [];
178
+ for (const doc of docs) {
179
+ if (doc.magnitude === 0)
180
+ continue;
181
+ const docVector = JSON.parse(doc.tf_vector);
182
+ // Compute dot product (only iterate over query terms since they're sparse)
183
+ let dot = 0;
184
+ for (const [term, qVal] of Object.entries(queryVector)) {
185
+ const dVal = docVector[term];
186
+ if (dVal !== undefined) {
187
+ dot += qVal * dVal;
188
+ }
189
+ }
190
+ if (dot > 0) {
191
+ const similarity = dot / (queryMag * doc.magnitude);
192
+ results.push({ path: doc.path, score: similarity });
193
+ }
194
+ }
195
+ // Sort by score descending, take top-k
196
+ results.sort((a, b) => b.score - a.score);
197
+ return results.slice(0, limit);
198
+ }
199
+ async rebuildIndex(vaultPath) {
200
+ this.db.exec('DELETE FROM documents');
201
+ this.db.exec('DELETE FROM vocabulary');
202
+ this.db.exec('DELETE FROM stats');
203
+ const mdFiles = await this.collectMdFiles(vaultPath, vaultPath);
204
+ for (const filePath of mdFiles) {
205
+ const content = await readFile(join(vaultPath, filePath), 'utf-8');
206
+ this.indexFile(filePath, content);
207
+ }
208
+ this.recomputeIdf();
209
+ }
210
+ close() {
211
+ this.db.close();
212
+ }
213
+ async collectMdFiles(dir, basePath) {
214
+ const results = [];
215
+ let entries;
216
+ try {
217
+ entries = await readdir(dir, { withFileTypes: true });
218
+ }
219
+ catch {
220
+ return results;
221
+ }
222
+ for (const entry of entries) {
223
+ const fullPath = join(dir, entry.name);
224
+ if (entry.isDirectory()) {
225
+ if (entry.name.startsWith('.'))
226
+ continue;
227
+ const sub = await this.collectMdFiles(fullPath, basePath);
228
+ results.push(...sub);
229
+ }
230
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
231
+ results.push(relative(basePath, fullPath));
232
+ }
233
+ }
234
+ return results;
235
+ }
236
+ }
237
+ //# sourceMappingURL=embeddings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/mcp/embeddings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export { SearchIndex } from './search.js';
2
+ export type { SearchResult } from './search.js';
3
+ export { VectorIndex } from './embeddings.js';
4
+ export type { VectorSearchResult } from './embeddings.js';
5
+ export { hybridSearch } from './rerank.js';
6
+ export type { MergedResult } from './rerank.js';
7
+ export { createMcpServer, startMcpServer } from './server.js';
8
+ export type { McpServerOptions } from './server.js';
9
+ export { matchesScope, hasPermission, requiredPermission, extractFilePath } from './scope.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { SearchIndex } from './search.js';
2
+ export { VectorIndex } from './embeddings.js';
3
+ export { hybridSearch } from './rerank.js';
4
+ export { createMcpServer, startMcpServer } from './server.js';
5
+ export { matchesScope, hasPermission, requiredPermission, extractFilePath } from './scope.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SearchResult } from './search.js';
2
+ import type { VectorSearchResult } from './embeddings.js';
3
+ export interface MergedResult {
4
+ path: string;
5
+ score: number;
6
+ snippet?: string;
7
+ sources: ('bm25' | 'vector')[];
8
+ }
9
+ export declare function hybridSearch(bm25Results: SearchResult[], vectorResults: VectorSearchResult[], opts?: {
10
+ bm25Weight?: number;
11
+ vectorWeight?: number;
12
+ k?: number;
13
+ }): MergedResult[];
14
+ //# sourceMappingURL=rerank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rerank.d.ts","sourceRoot":"","sources":["../../../src/mcp/rerank.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CAAC,MAAM,GAAG,QAAQ,CAAC,EAAE,CAAC;CAChC;AAED,wBAAgB,YAAY,CAC1B,WAAW,EAAE,YAAY,EAAE,EAC3B,aAAa,EAAE,kBAAkB,EAAE,EACnC,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,YAAY,EAAE,CA+ChB"}
@@ -0,0 +1,47 @@
1
+ export function hybridSearch(bm25Results, vectorResults, opts) {
2
+ const bm25Weight = opts?.bm25Weight ?? 1.0;
3
+ const vectorWeight = opts?.vectorWeight ?? 1.0;
4
+ const k = opts?.k ?? 60;
5
+ const merged = new Map();
6
+ // Process BM25 results
7
+ for (let rank = 0; rank < bm25Results.length; rank++) {
8
+ const r = bm25Results[rank];
9
+ const rrfScore = bm25Weight * (1 / (k + rank + 1));
10
+ const existing = merged.get(r.path);
11
+ if (existing) {
12
+ existing.score += rrfScore;
13
+ existing.snippet = existing.snippet ?? r.snippet;
14
+ existing.sources.push('bm25');
15
+ }
16
+ else {
17
+ merged.set(r.path, {
18
+ path: r.path,
19
+ score: rrfScore,
20
+ snippet: r.snippet,
21
+ sources: ['bm25'],
22
+ });
23
+ }
24
+ }
25
+ // Process vector results
26
+ for (let rank = 0; rank < vectorResults.length; rank++) {
27
+ const r = vectorResults[rank];
28
+ const rrfScore = vectorWeight * (1 / (k + rank + 1));
29
+ const existing = merged.get(r.path);
30
+ if (existing) {
31
+ existing.score += rrfScore;
32
+ existing.sources.push('vector');
33
+ }
34
+ else {
35
+ merged.set(r.path, {
36
+ path: r.path,
37
+ score: rrfScore,
38
+ sources: ['vector'],
39
+ });
40
+ }
41
+ }
42
+ // Sort by combined score descending
43
+ const results = Array.from(merged.values());
44
+ results.sort((a, b) => b.score - a.score);
45
+ return results;
46
+ }
47
+ //# sourceMappingURL=rerank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rerank.js","sourceRoot":"","sources":["../../../src/mcp/rerank.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,YAAY,CAC1B,WAA2B,EAC3B,aAAmC,EACnC,IAAiE;IAEjE,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,GAAG,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,GAAG,CAAC;IAC/C,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IAExB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE/C,uBAAuB;IACvB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACrD,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC;YAC3B,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC;YACjD,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;gBACjB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,QAAQ;gBACf,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,OAAO,EAAE,CAAC,MAAM,CAAC;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACvD,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC;YAC3B,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;gBACjB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,QAAQ;gBACf,OAAO,EAAE,CAAC,QAAQ,CAAC;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,oCAAoC;IACpC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ApiPermission } from '../types.js';
2
+ /**
3
+ * Check if a file path matches a scope pattern.
4
+ * Scopes use glob-like patterns:
5
+ * - "*" matches everything
6
+ * - "skills/*" matches paths starting with "skills/" or containing "/skills/"
7
+ * - "memories/*" matches paths containing "memory/" or ending with "MEMORY.md"
8
+ * - Multiple scopes comma-separated: "skills/*,memories/*"
9
+ */
10
+ export declare function matchesScope(filePath: string, scope: string): boolean;
11
+ /**
12
+ * Check if a permission level satisfies a required permission.
13
+ * "read-write" satisfies both "read" and "read-write" requirements.
14
+ * "read" only satisfies "read" requirements.
15
+ */
16
+ export declare function hasPermission(granted: ApiPermission, required: ApiPermission): boolean;
17
+ /**
18
+ * Determine the required permission for a tool name.
19
+ */
20
+ export declare function requiredPermission(toolName: string): ApiPermission;
21
+ /**
22
+ * Extract the file path that a tool invocation accesses.
23
+ * Returns null if the tool doesn't access a specific file (e.g., list-skills, search-memory).
24
+ */
25
+ export declare function extractFilePath(toolName: string, args: Record<string, unknown>): string | null;
26
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/mcp/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAkCrE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAGT;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAGlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAWf"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Check if a file path matches a scope pattern.
3
+ * Scopes use glob-like patterns:
4
+ * - "*" matches everything
5
+ * - "skills/*" matches paths starting with "skills/" or containing "/skills/"
6
+ * - "memories/*" matches paths containing "memory/" or ending with "MEMORY.md"
7
+ * - Multiple scopes comma-separated: "skills/*,memories/*"
8
+ */
9
+ export function matchesScope(filePath, scope) {
10
+ if (!scope || scope.trim() === '')
11
+ return false;
12
+ const patterns = scope.split(',').map((s) => s.trim()).filter(Boolean);
13
+ for (const pattern of patterns) {
14
+ if (pattern === '*')
15
+ return true;
16
+ // Strip trailing "/*" or "/" to get the prefix
17
+ const prefix = pattern.replace(/\/\*$/, '').replace(/\/$/, '');
18
+ if (prefix === 'memories') {
19
+ // Special case: "memories/*" matches memory-related paths
20
+ if (filePath.includes('memory/') ||
21
+ filePath.includes('memory\\') ||
22
+ filePath.endsWith('MEMORY.md')) {
23
+ return true;
24
+ }
25
+ }
26
+ // Direct prefix match: "skills/*" matches "skills/my-skill/SKILL.md"
27
+ if (filePath.startsWith(prefix + '/') || filePath === prefix) {
28
+ return true;
29
+ }
30
+ // Also match nested paths: "openclaw/skills/..." matches "skills/*"
31
+ if (filePath.includes('/' + prefix + '/')) {
32
+ return true;
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ /**
38
+ * Check if a permission level satisfies a required permission.
39
+ * "read-write" satisfies both "read" and "read-write" requirements.
40
+ * "read" only satisfies "read" requirements.
41
+ */
42
+ export function hasPermission(granted, required) {
43
+ if (required === 'read')
44
+ return true; // both 'read' and 'read-write' satisfy 'read'
45
+ return granted === 'read-write';
46
+ }
47
+ /**
48
+ * Determine the required permission for a tool name.
49
+ */
50
+ export function requiredPermission(toolName) {
51
+ if (toolName === 'write-memory')
52
+ return 'read-write';
53
+ return 'read';
54
+ }
55
+ /**
56
+ * Extract the file path that a tool invocation accesses.
57
+ * Returns null if the tool doesn't access a specific file (e.g., list-skills, search-memory).
58
+ */
59
+ export function extractFilePath(toolName, args) {
60
+ switch (toolName) {
61
+ case 'read-memory':
62
+ return args.file ?? null;
63
+ case 'write-memory':
64
+ return args.file ?? null;
65
+ case 'read-skill':
66
+ return args.skill ? `skills/${args.skill}/SKILL.md` : null;
67
+ default:
68
+ return null; // list/search tools don't target specific files
69
+ }
70
+ }
71
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../../src/mcp/scope.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,KAAa;IAC1D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAEhD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAEjC,+CAA+C;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAE/D,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,0DAA0D;YAC1D,IACE,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAC5B,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAC7B,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAC9B,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,qEAAqE;QACrE,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oEAAoE;QACpE,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAsB,EACtB,QAAuB;IAEvB,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,CAAC,8CAA8C;IACpF,OAAO,OAAO,KAAK,YAAY,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,IAAI,QAAQ,KAAK,cAAc;QAAE,OAAO,YAAY,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAA6B;IAE7B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,aAAa;YAChB,OAAQ,IAAI,CAAC,IAAe,IAAI,IAAI,CAAC;QACvC,KAAK,cAAc;YACjB,OAAQ,IAAI,CAAC,IAAe,IAAI,IAAI,CAAC;QACvC,KAAK,YAAY;YACf,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D;YACE,OAAO,IAAI,CAAC,CAAC,gDAAgD;IACjE,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface SearchResult {
2
+ path: string;
3
+ snippet: string;
4
+ score: number;
5
+ }
6
+ export declare class SearchIndex {
7
+ private db;
8
+ constructor(dbPath: string);
9
+ indexFile(path: string, content: string): void;
10
+ removeFromIndex(path: string): void;
11
+ search(query: string, limit?: number): SearchResult[];
12
+ rebuildIndex(vaultPath: string): Promise<void>;
13
+ getIndexedFiles(): string[];
14
+ close(): void;
15
+ private sanitizeQuery;
16
+ private collectMdFiles;
17
+ }
18
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/mcp/search.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAiB1B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAY9C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQnC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,YAAY,EAAE;IA4BnD,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD,eAAe,IAAI,MAAM,EAAE;IAO3B,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,aAAa;YAUP,cAAc;CAqB7B"}