somtum 0.1.2
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 +663 -0
- package/README.md +459 -0
- package/dist/cli/config_cmd.d.ts +10 -0
- package/dist/cli/config_cmd.d.ts.map +1 -0
- package/dist/cli/config_cmd.js +96 -0
- package/dist/cli/config_cmd.js.map +1 -0
- package/dist/cli/doctor.d.ts +17 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +169 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/edit.d.ts +4 -0
- package/dist/cli/edit.d.ts.map +1 -0
- package/dist/cli/edit.js +63 -0
- package/dist/cli/edit.js.map +1 -0
- package/dist/cli/export.d.ts +19 -0
- package/dist/cli/export.d.ts.map +1 -0
- package/dist/cli/export.js +84 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/forget.d.ts +11 -0
- package/dist/cli/forget.d.ts.map +1 -0
- package/dist/cli/forget.js +32 -0
- package/dist/cli/forget.js.map +1 -0
- package/dist/cli/hook.d.ts +2 -0
- package/dist/cli/hook.d.ts.map +1 -0
- package/dist/cli/hook.js +66 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/import.d.ts +18 -0
- package/dist/cli/import.d.ts.map +1 -0
- package/dist/cli/import.js +90 -0
- package/dist/cli/import.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +223 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +24 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +144 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/purge.d.ts +16 -0
- package/dist/cli/purge.d.ts.map +1 -0
- package/dist/cli/purge.js +69 -0
- package/dist/cli/purge.js.map +1 -0
- package/dist/cli/rebuild.d.ts +15 -0
- package/dist/cli/rebuild.d.ts.map +1 -0
- package/dist/cli/rebuild.js +41 -0
- package/dist/cli/rebuild.js.map +1 -0
- package/dist/cli/reindex.d.ts +6 -0
- package/dist/cli/reindex.d.ts.map +1 -0
- package/dist/cli/reindex.js +47 -0
- package/dist/cli/reindex.js.map +1 -0
- package/dist/cli/search.d.ts +16 -0
- package/dist/cli/search.d.ts.map +1 -0
- package/dist/cli/search.js +62 -0
- package/dist/cli/search.js.map +1 -0
- package/dist/cli/show.d.ts +12 -0
- package/dist/cli/show.d.ts.map +1 -0
- package/dist/cli/show.js +49 -0
- package/dist/cli/show.js.map +1 -0
- package/dist/cli/stats.d.ts +27 -0
- package/dist/cli/stats.d.ts.map +1 -0
- package/dist/cli/stats.js +80 -0
- package/dist/cli/stats.js.map +1 -0
- package/dist/cli/sync.d.ts +18 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +138 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +52 -0
- package/dist/config.js.map +1 -0
- package/dist/core/cache.d.ts +29 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +137 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/db.d.ts +12 -0
- package/dist/core/db.d.ts.map +1 -0
- package/dist/core/db.js +80 -0
- package/dist/core/db.js.map +1 -0
- package/dist/core/embeddings.d.ts +15 -0
- package/dist/core/embeddings.d.ts.map +1 -0
- package/dist/core/embeddings.js +74 -0
- package/dist/core/embeddings.js.map +1 -0
- package/dist/core/embeddings_bootstrap.d.ts +3 -0
- package/dist/core/embeddings_bootstrap.d.ts.map +1 -0
- package/dist/core/embeddings_bootstrap.js +16 -0
- package/dist/core/embeddings_bootstrap.js.map +1 -0
- package/dist/core/embeddings_xenova.d.ts +3 -0
- package/dist/core/embeddings_xenova.d.ts.map +1 -0
- package/dist/core/embeddings_xenova.js +28 -0
- package/dist/core/embeddings_xenova.js.map +1 -0
- package/dist/core/extractor.d.ts +27 -0
- package/dist/core/extractor.d.ts.map +1 -0
- package/dist/core/extractor.js +133 -0
- package/dist/core/extractor.js.map +1 -0
- package/dist/core/file_summary.d.ts +33 -0
- package/dist/core/file_summary.d.ts.map +1 -0
- package/dist/core/file_summary.js +127 -0
- package/dist/core/file_summary.js.map +1 -0
- package/dist/core/fingerprint.d.ts +13 -0
- package/dist/core/fingerprint.d.ts.map +1 -0
- package/dist/core/fingerprint.js +36 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/index_gen.d.ts +16 -0
- package/dist/core/index_gen.d.ts.map +1 -0
- package/dist/core/index_gen.js +173 -0
- package/dist/core/index_gen.js.map +1 -0
- package/dist/core/memory_files.d.ts +4 -0
- package/dist/core/memory_files.d.ts.map +1 -0
- package/dist/core/memory_files.js +36 -0
- package/dist/core/memory_files.js.map +1 -0
- package/dist/core/privacy.d.ts +9 -0
- package/dist/core/privacy.d.ts.map +1 -0
- package/dist/core/privacy.js +32 -0
- package/dist/core/privacy.js.map +1 -0
- package/dist/core/project_id.d.ts +3 -0
- package/dist/core/project_id.d.ts.map +1 -0
- package/dist/core/project_id.js +31 -0
- package/dist/core/project_id.js.map +1 -0
- package/dist/core/reindex.d.ts +10 -0
- package/dist/core/reindex.d.ts.map +1 -0
- package/dist/core/reindex.js +40 -0
- package/dist/core/reindex.js.map +1 -0
- package/dist/core/retrieval_stats.d.ts +22 -0
- package/dist/core/retrieval_stats.d.ts.map +1 -0
- package/dist/core/retrieval_stats.js +56 -0
- package/dist/core/retrieval_stats.js.map +1 -0
- package/dist/core/retriever/bm25.d.ts +15 -0
- package/dist/core/retriever/bm25.d.ts.map +1 -0
- package/dist/core/retriever/bm25.js +51 -0
- package/dist/core/retriever/bm25.js.map +1 -0
- package/dist/core/retriever/embeddings.d.ts +9 -0
- package/dist/core/retriever/embeddings.d.ts.map +1 -0
- package/dist/core/retriever/embeddings.js +34 -0
- package/dist/core/retriever/embeddings.js.map +1 -0
- package/dist/core/retriever/factory.d.ts +6 -0
- package/dist/core/retriever/factory.d.ts.map +1 -0
- package/dist/core/retriever/factory.js +53 -0
- package/dist/core/retriever/factory.js.map +1 -0
- package/dist/core/retriever/hybrid.d.ts +14 -0
- package/dist/core/retriever/hybrid.d.ts.map +1 -0
- package/dist/core/retriever/hybrid.js +52 -0
- package/dist/core/retriever/hybrid.js.map +1 -0
- package/dist/core/retriever/llm_index.d.ts +18 -0
- package/dist/core/retriever/llm_index.d.ts.map +1 -0
- package/dist/core/retriever/llm_index.js +90 -0
- package/dist/core/retriever/llm_index.js.map +1 -0
- package/dist/core/retriever/types.d.ts +16 -0
- package/dist/core/retriever/types.d.ts.map +1 -0
- package/dist/core/retriever/types.js +2 -0
- package/dist/core/retriever/types.js.map +1 -0
- package/dist/core/schema.d.ts +470 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +153 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/store.d.ts +35 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +172 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/tokens.d.ts +3 -0
- package/dist/core/tokens.d.ts.map +1 -0
- package/dist/core/tokens.js +12 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/core/transcript.d.ts +16 -0
- package/dist/core/transcript.d.ts.map +1 -0
- package/dist/core/transcript.js +128 -0
- package/dist/core/transcript.js.map +1 -0
- package/dist/db/migrations/001_init.sql +90 -0
- package/dist/db/migrations/002_cache_files.sql +6 -0
- package/dist/db/migrations/003_retrieval_stats.sql +17 -0
- package/dist/hooks/post_session.d.ts +65 -0
- package/dist/hooks/post_session.d.ts.map +1 -0
- package/dist/hooks/post_session.js +249 -0
- package/dist/hooks/post_session.js.map +1 -0
- package/dist/hooks/pre_prompt.d.ts +55 -0
- package/dist/hooks/pre_prompt.d.ts.map +1 -0
- package/dist/hooks/pre_prompt.js +98 -0
- package/dist/hooks/pre_prompt.js.map +1 -0
- package/dist/hooks/pre_read.d.ts +56 -0
- package/dist/hooks/pre_read.d.ts.map +1 -0
- package/dist/hooks/pre_read.js +77 -0
- package/dist/hooks/pre_read.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +20 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +128 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +72 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +153 -0
- package/dist/mcp/tools.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RetrievalResult } from '../core/retriever/types.js';
|
|
2
|
+
export declare function runSearch(opts: {
|
|
3
|
+
query: string;
|
|
4
|
+
k?: number;
|
|
5
|
+
strategy?: string;
|
|
6
|
+
cwd?: string;
|
|
7
|
+
dbPath?: string;
|
|
8
|
+
projectId?: string;
|
|
9
|
+
}): Promise<RetrievalResult[]>;
|
|
10
|
+
export declare function searchCommand(query: string, options?: {
|
|
11
|
+
strategy?: string;
|
|
12
|
+
k?: number;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
cwd?: string;
|
|
15
|
+
}): Promise<number>;
|
|
16
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/cli/search.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AASlE,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAuB7B;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E,OAAO,CAAC,MAAM,CAAC,CAkCjB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { openDb } from '../core/db.js';
|
|
3
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
4
|
+
import { loadConfig, projectDir } from '../config.js';
|
|
5
|
+
import { makeRetriever } from '../core/retriever/factory.js';
|
|
6
|
+
import { RetrievalStrategy as RetrievalStrategyEnum } from '../core/schema.js';
|
|
7
|
+
function snippet(body, max = 160) {
|
|
8
|
+
const single = body.replace(/\s+/g, ' ').trim();
|
|
9
|
+
return single.length <= max ? single : `${single.slice(0, max - 1)}…`;
|
|
10
|
+
}
|
|
11
|
+
export async function runSearch(opts) {
|
|
12
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
13
|
+
const config = loadConfig({ cwd });
|
|
14
|
+
const k = opts.k ?? config.retrieval.k;
|
|
15
|
+
const projectId = opts.projectId ?? resolveProjectId(cwd);
|
|
16
|
+
const dbPath = opts.dbPath ?? join(projectDir(projectId), 'db.sqlite');
|
|
17
|
+
// Resolve strategy: prefer explicit arg → config default
|
|
18
|
+
const strategyRaw = opts.strategy ?? config.retrieval.strategy;
|
|
19
|
+
const strategyParsed = RetrievalStrategyEnum.safeParse(strategyRaw);
|
|
20
|
+
const strategy = strategyParsed.success ? strategyParsed.data : 'bm25';
|
|
21
|
+
if (strategyParsed.success && strategyRaw !== strategy) {
|
|
22
|
+
console.warn(`[somtum] unknown strategy "${strategyRaw}", falling back to bm25`);
|
|
23
|
+
}
|
|
24
|
+
const db = openDb({ path: dbPath });
|
|
25
|
+
try {
|
|
26
|
+
const retriever = makeRetriever(strategy, db, config);
|
|
27
|
+
return await retriever.search(opts.query, { k, projectId });
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
db.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function searchCommand(query, options = {}) {
|
|
34
|
+
const cwd = options.cwd ?? process.cwd();
|
|
35
|
+
const searchOpts = { query, cwd };
|
|
36
|
+
if (options.k !== undefined)
|
|
37
|
+
searchOpts.k = options.k;
|
|
38
|
+
if (options.strategy !== undefined)
|
|
39
|
+
searchOpts.strategy = options.strategy;
|
|
40
|
+
const results = await runSearch(searchOpts);
|
|
41
|
+
if (options.json) {
|
|
42
|
+
console.log(JSON.stringify(results.map((r) => ({
|
|
43
|
+
id: r.id,
|
|
44
|
+
score: r.score,
|
|
45
|
+
source: r.source,
|
|
46
|
+
title: r.observation.title,
|
|
47
|
+
kind: r.observation.kind,
|
|
48
|
+
files: r.observation.files,
|
|
49
|
+
})), null, 2));
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
if (results.length === 0) {
|
|
53
|
+
console.log('no matches');
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
for (const r of results) {
|
|
57
|
+
console.log(`${r.id} [${r.observation.kind}] ${r.observation.title} (${r.source}: ${r.score.toFixed(3)})`);
|
|
58
|
+
console.log(` ${snippet(r.observation.body)}`);
|
|
59
|
+
}
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/cli/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Observation } from '../core/schema.js';
|
|
2
|
+
export declare function runShow(opts: {
|
|
3
|
+
id: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
dbPath?: string;
|
|
6
|
+
projectId?: string;
|
|
7
|
+
}): Observation | null;
|
|
8
|
+
export declare function showCommand(id: string, options?: {
|
|
9
|
+
json?: boolean;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}): number;
|
|
12
|
+
//# sourceMappingURL=show.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/cli/show.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,WAAW,GAAG,IAAI,CAWrB;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CA4B9F"}
|
package/dist/cli/show.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { openDb } from '../core/db.js';
|
|
3
|
+
import { MemoryStore } from '../core/store.js';
|
|
4
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
5
|
+
import { projectDir } from '../config.js';
|
|
6
|
+
export function runShow(opts) {
|
|
7
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
8
|
+
const projectId = opts.projectId ?? resolveProjectId(cwd);
|
|
9
|
+
const dbPath = opts.dbPath ?? join(projectDir(projectId), 'db.sqlite');
|
|
10
|
+
const db = openDb({ path: dbPath });
|
|
11
|
+
try {
|
|
12
|
+
const store = new MemoryStore(db);
|
|
13
|
+
return store.get(opts.id);
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
db.close();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function showCommand(id, options = {}) {
|
|
20
|
+
const obs = runShow({ id, cwd: options.cwd ?? process.cwd() });
|
|
21
|
+
if (!obs) {
|
|
22
|
+
console.error(`no observation with id ${id}`);
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
if (options.json) {
|
|
26
|
+
// embedding is a Buffer; serialize length not contents
|
|
27
|
+
const { embedding, ...rest } = obs;
|
|
28
|
+
const serializable = { ...rest, embedding_bytes: embedding ? embedding.length : null };
|
|
29
|
+
console.log(JSON.stringify(serializable, null, 2));
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
console.log(`id: ${obs.id}`);
|
|
33
|
+
console.log(`project: ${obs.project_id}`);
|
|
34
|
+
console.log(`session: ${obs.session_id}`);
|
|
35
|
+
console.log(`kind: ${obs.kind}`);
|
|
36
|
+
console.log(`created: ${new Date(obs.created_at).toISOString()}`);
|
|
37
|
+
if (obs.files.length > 0)
|
|
38
|
+
console.log(`files: ${obs.files.join(', ')}`);
|
|
39
|
+
if (obs.tags.length > 0)
|
|
40
|
+
console.log(`tags: ${obs.tags.join(', ')}`);
|
|
41
|
+
console.log(`saved est: ${obs.tokens_saved} tokens`);
|
|
42
|
+
console.log(`spent est: ${obs.tokens_spent} tokens`);
|
|
43
|
+
console.log('');
|
|
44
|
+
console.log(`# ${obs.title}`);
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log(obs.body);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=show.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/cli/show.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface StatsSnapshot {
|
|
2
|
+
project_id: string;
|
|
3
|
+
memories: number;
|
|
4
|
+
by_kind: Record<string, number>;
|
|
5
|
+
cache_entries: number;
|
|
6
|
+
cache_hits: number;
|
|
7
|
+
cache_misses: number;
|
|
8
|
+
cache_hit_rate: number | null;
|
|
9
|
+
retrieval_by_strategy: Array<{
|
|
10
|
+
strategy: string;
|
|
11
|
+
call_count: number;
|
|
12
|
+
}>;
|
|
13
|
+
tokens_saved_estimated: number;
|
|
14
|
+
tokens_spent_estimated: number;
|
|
15
|
+
net_estimated: number;
|
|
16
|
+
breakeven_ratio_estimated: number | null;
|
|
17
|
+
}
|
|
18
|
+
export declare function collectStats(opts?: {
|
|
19
|
+
cwd?: string;
|
|
20
|
+
dbPath?: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
}): StatsSnapshot;
|
|
23
|
+
export declare function statsCommand(options?: {
|
|
24
|
+
json?: boolean;
|
|
25
|
+
cwd?: string;
|
|
26
|
+
}): number;
|
|
27
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/cli/stats.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,CA8B5G;AAiCD,wBAAgB,YAAY,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAQnF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { openDb } from '../core/db.js';
|
|
3
|
+
import { MemoryStore } from '../core/store.js';
|
|
4
|
+
import { PromptCache } from '../core/cache.js';
|
|
5
|
+
import { RetrievalStatsStore } from '../core/retrieval_stats.js';
|
|
6
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
7
|
+
import { projectDir } from '../config.js';
|
|
8
|
+
export function collectStats(opts = {}) {
|
|
9
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
10
|
+
const projectId = opts.projectId ?? resolveProjectId(cwd);
|
|
11
|
+
const dbPath = opts.dbPath ?? join(projectDir(projectId), 'db.sqlite');
|
|
12
|
+
const db = openDb({ path: dbPath });
|
|
13
|
+
try {
|
|
14
|
+
const store = new MemoryStore(db);
|
|
15
|
+
const cache = new PromptCache(db);
|
|
16
|
+
const statsStore = new RetrievalStatsStore(db);
|
|
17
|
+
const saved = store.totalTokensSaved(projectId);
|
|
18
|
+
const spent = store.totalTokensSpent(projectId);
|
|
19
|
+
const cacheHits = statsStore.getCacheHitSummary(projectId);
|
|
20
|
+
const retrievalBreakdown = statsStore.getRetrievalBreakdown(projectId);
|
|
21
|
+
return {
|
|
22
|
+
project_id: projectId,
|
|
23
|
+
memories: store.countByProject(projectId),
|
|
24
|
+
by_kind: store.countByKind(projectId),
|
|
25
|
+
cache_entries: cache.count(),
|
|
26
|
+
cache_hits: cacheHits.hit_count,
|
|
27
|
+
cache_misses: cacheHits.miss_count,
|
|
28
|
+
cache_hit_rate: cacheHits.hit_rate,
|
|
29
|
+
retrieval_by_strategy: retrievalBreakdown,
|
|
30
|
+
tokens_saved_estimated: saved,
|
|
31
|
+
tokens_spent_estimated: spent,
|
|
32
|
+
net_estimated: saved - spent,
|
|
33
|
+
breakeven_ratio_estimated: spent > 0 ? Number((saved / spent).toFixed(2)) : null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
db.close();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function printHuman(s) {
|
|
41
|
+
console.log(`project ${s.project_id}`);
|
|
42
|
+
console.log(`memories ${s.memories}`);
|
|
43
|
+
for (const [k, n] of Object.entries(s.by_kind)) {
|
|
44
|
+
if (n > 0)
|
|
45
|
+
console.log(` ${k.padEnd(15)} ${n}`);
|
|
46
|
+
}
|
|
47
|
+
console.log(`cache entries ${s.cache_entries}`);
|
|
48
|
+
console.log(`cache hits ${s.cache_hits}`);
|
|
49
|
+
console.log(`cache misses ${s.cache_misses}`);
|
|
50
|
+
const hitRate = s.cache_hit_rate !== null ? `${(s.cache_hit_rate * 100).toFixed(1)}%` : 'n/a';
|
|
51
|
+
console.log(`cache hit rate ${hitRate}`);
|
|
52
|
+
if (s.retrieval_by_strategy.length > 0) {
|
|
53
|
+
console.log(`retrieval calls by strategy:`);
|
|
54
|
+
for (const r of s.retrieval_by_strategy) {
|
|
55
|
+
console.log(` ${r.strategy.padEnd(12)} ${r.call_count}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
console.log(`tokens saved ${s.tokens_saved_estimated} (estimated)`);
|
|
59
|
+
console.log(`tokens spent ${s.tokens_spent_estimated} (estimated)`);
|
|
60
|
+
console.log(`net ${s.net_estimated} (estimated)`);
|
|
61
|
+
const br = s.breakeven_ratio_estimated;
|
|
62
|
+
if (br !== null) {
|
|
63
|
+
const warn = br < 1.5 ? ' — below 1.5x, check `somtum doctor`' : '';
|
|
64
|
+
console.log(`breakeven ${br}x (estimated)${warn}`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(`breakeven n/a (no extraction cost recorded yet)`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function statsCommand(options = {}) {
|
|
71
|
+
const snap = collectStats({ cwd: options.cwd ?? process.cwd() });
|
|
72
|
+
if (options.json) {
|
|
73
|
+
console.log(JSON.stringify(snap, null, 2));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
printHuman(snap);
|
|
77
|
+
}
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/cli/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SyncResult {
|
|
2
|
+
direction: 'push' | 'pull' | 'status';
|
|
3
|
+
local_count: number;
|
|
4
|
+
remote_count: number | null;
|
|
5
|
+
transferred: number;
|
|
6
|
+
remote: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function runSync(opts: {
|
|
9
|
+
direction: 'push' | 'pull' | 'status';
|
|
10
|
+
cwd?: string;
|
|
11
|
+
remote?: string;
|
|
12
|
+
}): Promise<SyncResult>;
|
|
13
|
+
export declare function syncCommand(direction: 'push' | 'pull' | 'status', options?: {
|
|
14
|
+
remote?: string;
|
|
15
|
+
json?: boolean;
|
|
16
|
+
cwd?: string;
|
|
17
|
+
}): Promise<number>;
|
|
18
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AA0CA,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,UAAU,CAAC,CA0EtB;AAED,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,EACrC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9D,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
|
package/dist/cli/sync.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// SSH-based push/pull sync (M6). Transfers observations as JSONL so we can
|
|
2
|
+
// merge rather than overwrite. Conflict rule: if the same ULID already exists
|
|
3
|
+
// locally the remote copy is skipped (ULIDs are unique across machines).
|
|
4
|
+
// Relies on `scp` being available in PATH.
|
|
5
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
6
|
+
import { unlinkSync, existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import { openDb } from '../core/db.js';
|
|
10
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
11
|
+
import { loadConfig, projectDir } from '../config.js';
|
|
12
|
+
import { runExport } from './export.js';
|
|
13
|
+
import { runImport } from './import.js';
|
|
14
|
+
// Parses "user@host:/remote/path" or "host:/remote/path"
|
|
15
|
+
function parseRemote(remote) {
|
|
16
|
+
const colonIdx = remote.indexOf(':');
|
|
17
|
+
if (colonIdx === -1)
|
|
18
|
+
throw new Error(`invalid sync.remote: "${remote}". Expected user@host:/path`);
|
|
19
|
+
return { userHost: remote.slice(0, colonIdx), path: remote.slice(colonIdx + 1) };
|
|
20
|
+
}
|
|
21
|
+
function scpTo(localPath, remote) {
|
|
22
|
+
execFileSync('scp', ['-q', localPath, remote], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
23
|
+
}
|
|
24
|
+
function scpFrom(remote, localPath) {
|
|
25
|
+
execFileSync('scp', ['-q', remote, localPath], { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
26
|
+
}
|
|
27
|
+
function remoteCount(userHost, remotePath) {
|
|
28
|
+
try {
|
|
29
|
+
const out = execSync(`ssh -o BatchMode=yes -o ConnectTimeout=5 ${userHost} "wc -l < '${remotePath}' 2>/dev/null || echo 0"`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
30
|
+
return Number.parseInt(out.trim(), 10);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function runSync(opts) {
|
|
37
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
38
|
+
const config = loadConfig({ cwd });
|
|
39
|
+
const projectId = resolveProjectId(cwd);
|
|
40
|
+
const dbPath = join(projectDir(projectId), 'db.sqlite');
|
|
41
|
+
const remote = opts.remote ?? config.sync.remote;
|
|
42
|
+
if (!remote) {
|
|
43
|
+
throw new Error('sync.remote is not configured. Set it via `somtum config set sync.remote "user@host:/path/.somtum/projects/<id>"`');
|
|
44
|
+
}
|
|
45
|
+
const { userHost, path: remotePath } = parseRemote(remote);
|
|
46
|
+
const remoteJsonl = `${remotePath}/observations.jsonl`;
|
|
47
|
+
const localJsonl = join(projectDir(projectId), 'observations.jsonl');
|
|
48
|
+
const db = openDb({ path: dbPath });
|
|
49
|
+
let localCount;
|
|
50
|
+
try {
|
|
51
|
+
const { MemoryStore } = await import('../core/store.js');
|
|
52
|
+
localCount = new MemoryStore(db).countByProject(projectId);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
db.close();
|
|
56
|
+
}
|
|
57
|
+
if (opts.direction === 'status') {
|
|
58
|
+
const remoteLineCount = remoteCount(userHost, remoteJsonl);
|
|
59
|
+
return {
|
|
60
|
+
direction: 'status',
|
|
61
|
+
local_count: localCount,
|
|
62
|
+
remote_count: remoteLineCount,
|
|
63
|
+
transferred: 0,
|
|
64
|
+
remote,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (opts.direction === 'push') {
|
|
68
|
+
// Export local observations to JSONL then scp to remote.
|
|
69
|
+
runExport({ format: 'jsonl', output: localJsonl, cwd });
|
|
70
|
+
try {
|
|
71
|
+
// Ensure remote directory exists via SSH mkdir.
|
|
72
|
+
execSync(`ssh -o BatchMode=yes ${userHost} "mkdir -p '${remotePath}'"`, { stdio: ['ignore', 'ignore', 'pipe'] });
|
|
73
|
+
scpTo(localJsonl, `${userHost}:${remoteJsonl}`);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
if (existsSync(localJsonl))
|
|
77
|
+
unlinkSync(localJsonl);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
direction: 'push',
|
|
81
|
+
local_count: localCount,
|
|
82
|
+
remote_count: localCount,
|
|
83
|
+
transferred: localCount,
|
|
84
|
+
remote,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// pull: copy remote JSONL locally and merge.
|
|
88
|
+
const tmpPath = join(tmpdir(), `somtum-pull-${projectId}.jsonl`);
|
|
89
|
+
try {
|
|
90
|
+
scpFrom(`${userHost}:${remoteJsonl}`, tmpPath);
|
|
91
|
+
const importResult = runImport({ input: tmpPath, format: 'jsonl', cwd });
|
|
92
|
+
return {
|
|
93
|
+
direction: 'pull',
|
|
94
|
+
local_count: localCount + importResult.imported,
|
|
95
|
+
remote_count: localCount + importResult.imported + importResult.skipped,
|
|
96
|
+
transferred: importResult.imported,
|
|
97
|
+
remote,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
if (existsSync(tmpPath))
|
|
102
|
+
unlinkSync(tmpPath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export async function syncCommand(direction, options = {}) {
|
|
106
|
+
let result;
|
|
107
|
+
try {
|
|
108
|
+
const syncOpts = {
|
|
109
|
+
direction,
|
|
110
|
+
cwd: options.cwd ?? process.cwd(),
|
|
111
|
+
};
|
|
112
|
+
if (options.remote !== undefined)
|
|
113
|
+
syncOpts.remote = options.remote;
|
|
114
|
+
result = await runSync(syncOpts);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
console.error(`sync error: ${err.message}`);
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
if (options.json) {
|
|
121
|
+
console.log(JSON.stringify(result, null, 2));
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
if (direction === 'status') {
|
|
125
|
+
console.log(`local ${result.local_count} observations`);
|
|
126
|
+
const remoteStr = result.remote_count !== null ? String(result.remote_count) : 'unreachable';
|
|
127
|
+
console.log(`remote ${remoteStr} observation lines`);
|
|
128
|
+
console.log(`remote ${result.remote}`);
|
|
129
|
+
}
|
|
130
|
+
else if (direction === 'push') {
|
|
131
|
+
console.log(`pushed ${result.transferred} observations to ${result.remote}`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`pulled ${result.transferred} new observations from ${result.remote}`);
|
|
135
|
+
}
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Config } from './core/schema.js';
|
|
2
|
+
export declare const GLOBAL_DIR: string;
|
|
3
|
+
export declare const GLOBAL_CONFIG_PATH: string;
|
|
4
|
+
export declare const PROJECT_CONFIG_RELATIVE: string;
|
|
5
|
+
export interface LoadOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
global?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadConfig(options?: LoadOptions): Config;
|
|
10
|
+
export declare function ensureGlobalDir(): string;
|
|
11
|
+
export declare function projectDir(projectId: string): string;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,MAAM,EAAoB,MAAM,kBAAkB,CAAC;AAE/E,eAAO,MAAM,UAAU,QAA2D,CAAC;AACnF,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAClE,eAAO,MAAM,uBAAuB,QAAiC,CAAC;AA2BtE,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,WAAgB,GAAG,MAAM,CAS5D;AAED,wBAAgB,eAAe,IAAI,MAAM,CAKxC;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIpD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { ConfigSchema } from './core/schema.js';
|
|
5
|
+
export const GLOBAL_DIR = process.env['SOMTUM_HOME'] ?? join(homedir(), '.somtum');
|
|
6
|
+
export const GLOBAL_CONFIG_PATH = join(GLOBAL_DIR, 'config.json');
|
|
7
|
+
export const PROJECT_CONFIG_RELATIVE = join('.somtum', 'config.json');
|
|
8
|
+
function readJsonIfExists(path) {
|
|
9
|
+
if (!existsSync(path))
|
|
10
|
+
return undefined;
|
|
11
|
+
const raw = readFileSync(path, 'utf8');
|
|
12
|
+
if (raw.trim() === '')
|
|
13
|
+
return undefined;
|
|
14
|
+
return JSON.parse(raw);
|
|
15
|
+
}
|
|
16
|
+
function deepMerge(base, over) {
|
|
17
|
+
if (over === undefined || over === null)
|
|
18
|
+
return base;
|
|
19
|
+
if (typeof base !== 'object' ||
|
|
20
|
+
base === null ||
|
|
21
|
+
Array.isArray(base) ||
|
|
22
|
+
typeof over !== 'object' ||
|
|
23
|
+
Array.isArray(over)) {
|
|
24
|
+
return over;
|
|
25
|
+
}
|
|
26
|
+
const out = { ...base };
|
|
27
|
+
for (const [k, v] of Object.entries(over)) {
|
|
28
|
+
out[k] = deepMerge(base[k], v);
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
export function loadConfig(options = {}) {
|
|
33
|
+
const cwd = options.cwd ?? process.cwd();
|
|
34
|
+
const globalPath = options.global ?? GLOBAL_CONFIG_PATH;
|
|
35
|
+
const globalRaw = (readJsonIfExists(globalPath) ?? {});
|
|
36
|
+
const projectRaw = (readJsonIfExists(join(cwd, PROJECT_CONFIG_RELATIVE)) ?? {});
|
|
37
|
+
const merged = deepMerge(globalRaw, projectRaw);
|
|
38
|
+
return ConfigSchema.parse(merged);
|
|
39
|
+
}
|
|
40
|
+
export function ensureGlobalDir() {
|
|
41
|
+
if (!existsSync(GLOBAL_DIR)) {
|
|
42
|
+
mkdirSync(GLOBAL_DIR, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
return GLOBAL_DIR;
|
|
45
|
+
}
|
|
46
|
+
export function projectDir(projectId) {
|
|
47
|
+
const dir = join(GLOBAL_DIR, 'projects', projectId);
|
|
48
|
+
if (!existsSync(dir))
|
|
49
|
+
mkdirSync(dir, { recursive: true });
|
|
50
|
+
return dir;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DB } from './db.js';
|
|
2
|
+
import { type CacheEntry, type CacheEntryInput } from './schema.js';
|
|
3
|
+
import { type Embedder } from './embeddings.js';
|
|
4
|
+
export declare const CACHE_FINGERPRINT_VERSION = 1;
|
|
5
|
+
export declare function normalizePrompt(prompt: string): string;
|
|
6
|
+
export declare function hashPrompt(prompt: string): string;
|
|
7
|
+
export declare class PromptCache {
|
|
8
|
+
private readonly db;
|
|
9
|
+
constructor(db: DB);
|
|
10
|
+
lookupByHash(promptHash: string): CacheEntry | null;
|
|
11
|
+
put(input: CacheEntryInput & {
|
|
12
|
+
prompt_embedding?: Buffer;
|
|
13
|
+
}): CacheEntry;
|
|
14
|
+
lookupFuzzy(prompt: string, embedder: Embedder, threshold: number): Promise<{
|
|
15
|
+
entry: CacheEntry;
|
|
16
|
+
similarity: number;
|
|
17
|
+
} | null>;
|
|
18
|
+
getById(id: string): CacheEntry | null;
|
|
19
|
+
setPromptEmbedding(id: string, v: Float32Array): void;
|
|
20
|
+
listMissingPromptEmbeddings(): {
|
|
21
|
+
id: string;
|
|
22
|
+
prompt_text: string;
|
|
23
|
+
}[];
|
|
24
|
+
recordFalseHit(id: string): void;
|
|
25
|
+
touch(id: string): void;
|
|
26
|
+
invalidate(id: string): void;
|
|
27
|
+
count(): number;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAoB,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,iBAAiB,CAAC;AAIzB,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAsC3C,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,EAAE;IAEnC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAUnD,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;IA2CjE,WAAW,CACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA4B5D,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAOtC,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,IAAI;IAMrD,2BAA2B,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE;IASpE,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAMhC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQvB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,MAAM;CAMhB"}
|