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,249 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, join, resolve as resolvePath } from 'node:path';
|
|
3
|
+
import { ulid } from 'ulid';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
6
|
+
import { loadConfig } from '../config.js';
|
|
7
|
+
import { openDb } from '../core/db.js';
|
|
8
|
+
import { MemoryStore } from '../core/store.js';
|
|
9
|
+
import { generateIndex } from '../core/index_gen.js';
|
|
10
|
+
import { extract, anthropicCaller, estimateTokensSaved, } from '../core/extractor.js';
|
|
11
|
+
import { resolveProjectId, projectNameFromCwd } from '../core/project_id.js';
|
|
12
|
+
import { countTokens } from '../core/tokens.js';
|
|
13
|
+
import { projectDir } from '../config.js';
|
|
14
|
+
import { parseTranscript, renderTurns, extractPromptResponsePairs } from '../core/transcript.js';
|
|
15
|
+
import { PromptCache, hashPrompt } from '../core/cache.js';
|
|
16
|
+
import { fingerprintFiles } from '../core/fingerprint.js';
|
|
17
|
+
import { ensureEmbedderConfigured } from '../core/embeddings_bootstrap.js';
|
|
18
|
+
import { embedMissing } from '../core/reindex.js';
|
|
19
|
+
import { FileFingerprintStore, matchesAnyGlob, statFile, summarizeFile, summaryHash, } from '../core/file_summary.js';
|
|
20
|
+
import { writeMemoryMarkdown, memoriesDir } from '../core/memory_files.js';
|
|
21
|
+
export const HookPayloadSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
session_id: z.string().optional(),
|
|
24
|
+
cwd: z.string().optional(),
|
|
25
|
+
project_id: z.string().optional(),
|
|
26
|
+
transcript: z.string().optional(),
|
|
27
|
+
transcript_path: z.string().optional(),
|
|
28
|
+
// Claude Code includes these; we ignore them here but allow passthrough.
|
|
29
|
+
hook_event_name: z.string().optional(),
|
|
30
|
+
})
|
|
31
|
+
.refine((v) => v.transcript !== undefined || v.transcript_path !== undefined, {
|
|
32
|
+
message: 'Either `transcript` or `transcript_path` is required',
|
|
33
|
+
});
|
|
34
|
+
export async function readToEnd(stream) {
|
|
35
|
+
// Claude Code sends the hook payload as a single JSON blob with no
|
|
36
|
+
// trailing newline. Read to EOF; don't try to split on lines.
|
|
37
|
+
const chunks = [];
|
|
38
|
+
for await (const chunk of stream) {
|
|
39
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
40
|
+
}
|
|
41
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
42
|
+
}
|
|
43
|
+
function resolveTranscript(payload) {
|
|
44
|
+
const raw = payload.transcript !== undefined
|
|
45
|
+
? payload.transcript
|
|
46
|
+
: payload.transcript_path !== undefined
|
|
47
|
+
? readFileSync(payload.transcript_path, 'utf8')
|
|
48
|
+
: (() => {
|
|
49
|
+
throw new Error('Unreachable: schema requires one of transcript | transcript_path');
|
|
50
|
+
})();
|
|
51
|
+
const turns = parseTranscript(raw);
|
|
52
|
+
// If the parser found structured turns, render them compactly for the extractor.
|
|
53
|
+
// Otherwise fall back to the raw string (plain-text transcript fixtures etc.).
|
|
54
|
+
return { text: turns.length > 0 ? renderTurns(turns) : raw, turns };
|
|
55
|
+
}
|
|
56
|
+
function populateCache(db, turns, opts) {
|
|
57
|
+
const cache = new PromptCache(db);
|
|
58
|
+
const pairs = extractPromptResponsePairs(turns);
|
|
59
|
+
let inserted = 0;
|
|
60
|
+
for (const pair of pairs) {
|
|
61
|
+
if (pair.prompt.trim().length === 0 || pair.response.trim().length === 0)
|
|
62
|
+
continue;
|
|
63
|
+
const { fingerprint } = fingerprintFiles(pair.files_touched, { cwd: opts.cwd });
|
|
64
|
+
cache.put({
|
|
65
|
+
prompt_hash: hashPrompt(pair.prompt),
|
|
66
|
+
prompt_text: pair.prompt,
|
|
67
|
+
response: pair.response,
|
|
68
|
+
model: opts.model,
|
|
69
|
+
context_fingerprint: fingerprint,
|
|
70
|
+
files_touched: pair.files_touched,
|
|
71
|
+
});
|
|
72
|
+
inserted += 1;
|
|
73
|
+
}
|
|
74
|
+
return inserted;
|
|
75
|
+
}
|
|
76
|
+
function collectSessionFiles(turns) {
|
|
77
|
+
const set = new Set();
|
|
78
|
+
for (const t of turns) {
|
|
79
|
+
for (const f of t.files_touched ?? [])
|
|
80
|
+
set.add(f);
|
|
81
|
+
}
|
|
82
|
+
return [...set];
|
|
83
|
+
}
|
|
84
|
+
async function populateFileSummaries(db, turns, opts) {
|
|
85
|
+
const paths = collectSessionFiles(turns);
|
|
86
|
+
if (paths.length === 0)
|
|
87
|
+
return 0;
|
|
88
|
+
const store = new FileFingerprintStore(db);
|
|
89
|
+
const { exclude_globs, min_file_size_tokens } = opts.config.file_gating;
|
|
90
|
+
let generated = 0;
|
|
91
|
+
for (const path of paths) {
|
|
92
|
+
if (matchesAnyGlob(path, exclude_globs))
|
|
93
|
+
continue;
|
|
94
|
+
const stat = statFile(path, { cwd: opts.cwd });
|
|
95
|
+
if (!stat || stat.tokens < min_file_size_tokens)
|
|
96
|
+
continue;
|
|
97
|
+
const existing = store.get(opts.projectId, path);
|
|
98
|
+
if (existing && existing.content_hash === stat.contentHash && existing.summary)
|
|
99
|
+
continue;
|
|
100
|
+
const abs = isAbsolute(path) ? path : resolvePath(opts.cwd, path);
|
|
101
|
+
let contents;
|
|
102
|
+
try {
|
|
103
|
+
contents = readFileSync(abs, 'utf8');
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const { summary } = await summarizeFile(path, contents, {
|
|
110
|
+
model: opts.config.extraction.model,
|
|
111
|
+
caller: opts.caller,
|
|
112
|
+
});
|
|
113
|
+
store.upsert({
|
|
114
|
+
project_id: opts.projectId,
|
|
115
|
+
path,
|
|
116
|
+
content_hash: stat.contentHash,
|
|
117
|
+
mtime: stat.mtime,
|
|
118
|
+
tokens: stat.tokens,
|
|
119
|
+
summary,
|
|
120
|
+
summary_hash: summaryHash(summary),
|
|
121
|
+
});
|
|
122
|
+
generated += 1;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
console.error(`[somtum] summarize ${path} failed: ${err.message}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return generated;
|
|
129
|
+
}
|
|
130
|
+
export async function runPostSession(payload, opts = {}) {
|
|
131
|
+
const parsed = HookPayloadSchema.parse(payload);
|
|
132
|
+
const cwd = opts.cwd ?? parsed.cwd ?? process.cwd();
|
|
133
|
+
const config = opts.config ?? loadConfig({ cwd });
|
|
134
|
+
const projectId = parsed.project_id ?? resolveProjectId(cwd);
|
|
135
|
+
const projectName = opts.projectName ?? projectNameFromCwd(cwd);
|
|
136
|
+
const sessionId = parsed.session_id ?? ulid();
|
|
137
|
+
const ownsDb = opts.db === undefined;
|
|
138
|
+
const dir = opts.dbPath ? undefined : projectDir(projectId);
|
|
139
|
+
const dbPath = opts.dbPath ?? join(dir, 'db.sqlite');
|
|
140
|
+
const indexPath = opts.indexPath ?? join(dir ?? '.', 'index.md');
|
|
141
|
+
const db = opts.db ?? openDb({ path: dbPath });
|
|
142
|
+
try {
|
|
143
|
+
const store = new MemoryStore(db);
|
|
144
|
+
const resolved = resolveTranscript(parsed);
|
|
145
|
+
const transcript = resolved.text;
|
|
146
|
+
const transcriptTokens = countTokens(transcript);
|
|
147
|
+
const caller = opts.caller ??
|
|
148
|
+
anthropicCaller(new Anthropic({ apiKey: process.env['ANTHROPIC_API_KEY'] ?? '' }));
|
|
149
|
+
const outcome = await extract(transcript, caller, {
|
|
150
|
+
model: config.extraction.model,
|
|
151
|
+
maxObservations: config.extraction.max_observations_per_session,
|
|
152
|
+
maxRetries: config.extraction.max_retries,
|
|
153
|
+
});
|
|
154
|
+
const total = outcome.observations.length;
|
|
155
|
+
// Divide extraction cost across observations so per-observation tokens_spent adds up.
|
|
156
|
+
const perObsSpend = total > 0 ? Math.floor(outcome.tokensSpent / total) : 0;
|
|
157
|
+
const memDir = memoriesDir(opts.dbPath ? opts.dbPath.replace(/db\.sqlite$/, '') : projectDir(projectId));
|
|
158
|
+
let inserted = 0;
|
|
159
|
+
for (const obs of outcome.observations) {
|
|
160
|
+
const saved = estimateTokensSaved(transcriptTokens, obs, total);
|
|
161
|
+
const stored = store.insert({
|
|
162
|
+
project_id: projectId,
|
|
163
|
+
session_id: sessionId,
|
|
164
|
+
kind: obs.kind,
|
|
165
|
+
title: obs.title,
|
|
166
|
+
body: obs.body,
|
|
167
|
+
files: obs.files,
|
|
168
|
+
tags: obs.tags,
|
|
169
|
+
tokens_saved: saved,
|
|
170
|
+
tokens_spent: perObsSpend,
|
|
171
|
+
}, { redactPatterns: config.privacy.redact_patterns });
|
|
172
|
+
// Write the human-readable markdown mirror (SPEC.md §5.2).
|
|
173
|
+
try {
|
|
174
|
+
writeMemoryMarkdown(stored, memDir);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Non-fatal: SQLite is the source of truth.
|
|
178
|
+
}
|
|
179
|
+
inserted += 1;
|
|
180
|
+
}
|
|
181
|
+
const tokensSavedTotal = store.totalTokensSaved(projectId);
|
|
182
|
+
const cacheEntriesAdded = config.cache.enabled
|
|
183
|
+
? populateCache(db, resolved.turns, { cwd, model: config.extraction.model })
|
|
184
|
+
: 0;
|
|
185
|
+
let embeddingsAdded = 0;
|
|
186
|
+
if (config.retrieval.embeddings.enabled) {
|
|
187
|
+
ensureEmbedderConfigured(config);
|
|
188
|
+
try {
|
|
189
|
+
const r = await embedMissing(db, projectId);
|
|
190
|
+
embeddingsAdded = r.embedded;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
console.error(`[somtum] embedding failed: ${err.message}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const summariesGenerated = config.file_gating.enabled
|
|
197
|
+
? await populateFileSummaries(db, resolved.turns, { cwd, projectId, config, caller })
|
|
198
|
+
: 0;
|
|
199
|
+
generateIndex({
|
|
200
|
+
projectName,
|
|
201
|
+
projectId,
|
|
202
|
+
totalTokensSaved: tokensSavedTotal,
|
|
203
|
+
store,
|
|
204
|
+
outputPath: indexPath,
|
|
205
|
+
now: opts.now ?? Date.now(),
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
projectId,
|
|
209
|
+
inserted,
|
|
210
|
+
tokensSpent: outcome.tokensSpent,
|
|
211
|
+
tokensSavedTotal,
|
|
212
|
+
indexPath,
|
|
213
|
+
cacheEntriesAdded,
|
|
214
|
+
embeddingsAdded,
|
|
215
|
+
summariesGenerated,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
if (ownsDb)
|
|
220
|
+
db.close();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
export async function main() {
|
|
224
|
+
try {
|
|
225
|
+
const raw = await readToEnd(process.stdin);
|
|
226
|
+
const payload = HookPayloadSchema.parse(JSON.parse(raw));
|
|
227
|
+
const result = await runPostSession(payload);
|
|
228
|
+
// Hooks communicate via stdout; keep output structured.
|
|
229
|
+
console.log(JSON.stringify({
|
|
230
|
+
ok: true,
|
|
231
|
+
inserted: result.inserted,
|
|
232
|
+
cache_entries_added: result.cacheEntriesAdded,
|
|
233
|
+
summaries_generated: result.summariesGenerated,
|
|
234
|
+
tokens_spent_estimated: result.tokensSpent,
|
|
235
|
+
tokens_saved_total_estimated: result.tokensSavedTotal,
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
console.error(`[somtum] post_session failed: ${err.message}`);
|
|
240
|
+
// Exit 0: hook failures should never break the user's session.
|
|
241
|
+
process.exit(0);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Only run when invoked as a script, not when imported by tests.
|
|
245
|
+
const isDirectRun = import.meta.url === `file://${process.argv[1]}`;
|
|
246
|
+
if (isDirectRun) {
|
|
247
|
+
void main();
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=post_session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post_session.js","sourceRoot":"","sources":["../../src/hooks/post_session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type DB } from '../core/db.js';
|
|
3
|
+
import type { Config } from '../core/schema.js';
|
|
4
|
+
export declare const PrePromptPayloadSchema: z.ZodEffects<z.ZodObject<{
|
|
5
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
6
|
+
user_prompt: z.ZodOptional<z.ZodString>;
|
|
7
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
8
|
+
project_id: z.ZodOptional<z.ZodString>;
|
|
9
|
+
hook_event_name: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
project_id?: string | undefined;
|
|
12
|
+
cwd?: string | undefined;
|
|
13
|
+
hook_event_name?: string | undefined;
|
|
14
|
+
prompt?: string | undefined;
|
|
15
|
+
user_prompt?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
project_id?: string | undefined;
|
|
18
|
+
cwd?: string | undefined;
|
|
19
|
+
hook_event_name?: string | undefined;
|
|
20
|
+
prompt?: string | undefined;
|
|
21
|
+
user_prompt?: string | undefined;
|
|
22
|
+
}>, {
|
|
23
|
+
project_id?: string | undefined;
|
|
24
|
+
cwd?: string | undefined;
|
|
25
|
+
hook_event_name?: string | undefined;
|
|
26
|
+
prompt?: string | undefined;
|
|
27
|
+
user_prompt?: string | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
project_id?: string | undefined;
|
|
30
|
+
cwd?: string | undefined;
|
|
31
|
+
hook_event_name?: string | undefined;
|
|
32
|
+
prompt?: string | undefined;
|
|
33
|
+
user_prompt?: string | undefined;
|
|
34
|
+
}>;
|
|
35
|
+
export type PrePromptPayload = z.infer<typeof PrePromptPayloadSchema>;
|
|
36
|
+
export interface PrePromptOptions {
|
|
37
|
+
db?: DB;
|
|
38
|
+
dbPath?: string;
|
|
39
|
+
cwd?: string;
|
|
40
|
+
config?: Config;
|
|
41
|
+
projectId?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface PrePromptOutput {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
hit: boolean;
|
|
46
|
+
matchKind?: 'exact' | 'fuzzy';
|
|
47
|
+
similarity?: number;
|
|
48
|
+
reason?: 'no-hit' | 'fingerprint-mismatch' | 'cache-disabled';
|
|
49
|
+
hookSpecificOutput?: {
|
|
50
|
+
hookEventName: 'UserPromptSubmit';
|
|
51
|
+
additionalContext: string;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export declare function runPrePrompt(payload: PrePromptPayload, opts?: PrePromptOptions): Promise<PrePromptOutput>;
|
|
55
|
+
//# sourceMappingURL=pre_prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre_prompt.d.ts","sourceRoot":"","sources":["../../src/hooks/pre_prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAU,KAAK,EAAE,EAAE,MAAM,eAAe,CAAC;AAMhD,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,mBAAmB,CAAC;AAI5D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU/B,CAAC;AAEL,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,QAAQ,GAAG,sBAAsB,GAAG,gBAAgB,CAAC;IAC9D,kBAAkB,CAAC,EAAE;QACnB,aAAa,EAAE,kBAAkB,CAAC;QAClC,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AASD,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,EACzB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,eAAe,CAAC,CAwE1B"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { loadConfig, projectDir } from '../config.js';
|
|
4
|
+
import { openDb } from '../core/db.js';
|
|
5
|
+
import { PromptCache, hashPrompt } from '../core/cache.js';
|
|
6
|
+
import { fingerprintFiles } from '../core/fingerprint.js';
|
|
7
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
8
|
+
import { ensureEmbedderConfigured } from '../core/embeddings_bootstrap.js';
|
|
9
|
+
import { getEmbedder, isEmbedderReady } from '../core/embeddings.js';
|
|
10
|
+
// Claude Code's UserPromptSubmit hook payload. We accept both `prompt`
|
|
11
|
+
// (newer shape) and `user_prompt` (older) to tolerate version drift.
|
|
12
|
+
export const PrePromptPayloadSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
prompt: z.string().optional(),
|
|
15
|
+
user_prompt: z.string().optional(),
|
|
16
|
+
cwd: z.string().optional(),
|
|
17
|
+
project_id: z.string().optional(),
|
|
18
|
+
hook_event_name: z.string().optional(),
|
|
19
|
+
})
|
|
20
|
+
.refine((v) => v.prompt !== undefined || v.user_prompt !== undefined, {
|
|
21
|
+
message: 'Either `prompt` or `user_prompt` is required',
|
|
22
|
+
});
|
|
23
|
+
const MAX_INJECTED_CHARS = 4000;
|
|
24
|
+
function clampContext(text) {
|
|
25
|
+
if (text.length <= MAX_INJECTED_CHARS)
|
|
26
|
+
return text;
|
|
27
|
+
return `${text.slice(0, MAX_INJECTED_CHARS)}\n… [truncated]`;
|
|
28
|
+
}
|
|
29
|
+
export async function runPrePrompt(payload, opts = {}) {
|
|
30
|
+
const parsed = PrePromptPayloadSchema.parse(payload);
|
|
31
|
+
const prompt = parsed.prompt ?? parsed.user_prompt ?? '';
|
|
32
|
+
if (prompt.trim().length === 0)
|
|
33
|
+
return { ok: true, hit: false, reason: 'no-hit' };
|
|
34
|
+
const cwd = opts.cwd ?? parsed.cwd ?? process.cwd();
|
|
35
|
+
const config = opts.config ?? loadConfig({ cwd });
|
|
36
|
+
if (!config.cache.enabled)
|
|
37
|
+
return { ok: true, hit: false, reason: 'cache-disabled' };
|
|
38
|
+
const projectId = opts.projectId ?? parsed.project_id ?? resolveProjectId(cwd);
|
|
39
|
+
const ownsDb = opts.db === undefined;
|
|
40
|
+
const dbPath = opts.dbPath ?? join(projectDir(projectId), 'db.sqlite');
|
|
41
|
+
const db = opts.db ?? openDb({ path: dbPath });
|
|
42
|
+
try {
|
|
43
|
+
const cache = new PromptCache(db);
|
|
44
|
+
// Try exact match first — it's free.
|
|
45
|
+
let hit = cache.lookupByHash(hashPrompt(prompt));
|
|
46
|
+
let matchKind = 'exact';
|
|
47
|
+
let similarity;
|
|
48
|
+
// Fall back to fuzzy match when enabled and we have an embedder available.
|
|
49
|
+
if (!hit && config.cache.fuzzy_match && config.retrieval.embeddings.enabled) {
|
|
50
|
+
ensureEmbedderConfigured(config);
|
|
51
|
+
if (isEmbedderReady()) {
|
|
52
|
+
try {
|
|
53
|
+
const embedder = await getEmbedder();
|
|
54
|
+
const fuzzy = await cache.lookupFuzzy(prompt, embedder, config.cache.fuzzy_threshold);
|
|
55
|
+
if (fuzzy) {
|
|
56
|
+
hit = fuzzy.entry;
|
|
57
|
+
matchKind = 'fuzzy';
|
|
58
|
+
similarity = fuzzy.similarity;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// A failing embedder should never block Claude Code; fall through to miss.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!hit)
|
|
67
|
+
return { ok: true, hit: false, reason: 'no-hit' };
|
|
68
|
+
// Re-hash the files that were touched when this response was captured.
|
|
69
|
+
// If any content has changed, the cached response is stale.
|
|
70
|
+
const current = fingerprintFiles(hit.files_touched, { cwd }).fingerprint;
|
|
71
|
+
if (current !== hit.context_fingerprint) {
|
|
72
|
+
cache.invalidate(hit.id);
|
|
73
|
+
return { ok: true, hit: false, reason: 'fingerprint-mismatch' };
|
|
74
|
+
}
|
|
75
|
+
cache.touch(hit.id);
|
|
76
|
+
const header = matchKind === 'fuzzy' && similarity !== undefined
|
|
77
|
+
? `[somtum-cache: fuzzy match sim=${similarity.toFixed(3)}]`
|
|
78
|
+
: `[somtum-cache]`;
|
|
79
|
+
const context = clampContext(`${header} A previous response addressed a matching prompt:\n---\n${hit.response}\n---\nUse it if still applicable; otherwise answer fresh.`);
|
|
80
|
+
const out = {
|
|
81
|
+
ok: true,
|
|
82
|
+
hit: true,
|
|
83
|
+
matchKind,
|
|
84
|
+
hookSpecificOutput: {
|
|
85
|
+
hookEventName: 'UserPromptSubmit',
|
|
86
|
+
additionalContext: context,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
if (similarity !== undefined)
|
|
90
|
+
out.similarity = similarity;
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
if (ownsDb)
|
|
95
|
+
db.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=pre_prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre_prompt.js","sourceRoot":"","sources":["../../src/hooks/pre_prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type DB } from '../core/db.js';
|
|
3
|
+
import type { Config } from '../core/schema.js';
|
|
4
|
+
export declare const PreReadPayloadSchema: z.ZodObject<{
|
|
5
|
+
tool_name: z.ZodOptional<z.ZodString>;
|
|
6
|
+
tool_input: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
file_path: z.ZodOptional<z.ZodString>;
|
|
8
|
+
notebook_path: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
10
|
+
file_path: z.ZodOptional<z.ZodString>;
|
|
11
|
+
notebook_path: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
13
|
+
file_path: z.ZodOptional<z.ZodString>;
|
|
14
|
+
notebook_path: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.ZodTypeAny, "passthrough">>>;
|
|
16
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
17
|
+
project_id: z.ZodOptional<z.ZodString>;
|
|
18
|
+
hook_event_name: z.ZodOptional<z.ZodString>;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
project_id?: string | undefined;
|
|
21
|
+
cwd?: string | undefined;
|
|
22
|
+
hook_event_name?: string | undefined;
|
|
23
|
+
tool_name?: string | undefined;
|
|
24
|
+
tool_input?: z.objectOutputType<{
|
|
25
|
+
file_path: z.ZodOptional<z.ZodString>;
|
|
26
|
+
notebook_path: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
project_id?: string | undefined;
|
|
30
|
+
cwd?: string | undefined;
|
|
31
|
+
hook_event_name?: string | undefined;
|
|
32
|
+
tool_name?: string | undefined;
|
|
33
|
+
tool_input?: z.objectInputType<{
|
|
34
|
+
file_path: z.ZodOptional<z.ZodString>;
|
|
35
|
+
notebook_path: z.ZodOptional<z.ZodString>;
|
|
36
|
+
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
37
|
+
}>;
|
|
38
|
+
export type PreReadPayload = z.infer<typeof PreReadPayloadSchema>;
|
|
39
|
+
export interface PreReadOptions {
|
|
40
|
+
db?: DB;
|
|
41
|
+
dbPath?: string;
|
|
42
|
+
cwd?: string;
|
|
43
|
+
config?: Config;
|
|
44
|
+
projectId?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface PreReadOutput {
|
|
47
|
+
ok: boolean;
|
|
48
|
+
gated: boolean;
|
|
49
|
+
reason?: 'gating-disabled' | 'wrong-tool' | 'no-path' | 'file-missing' | 'excluded' | 'below-threshold' | 'no-summary' | 'stale-summary';
|
|
50
|
+
hookSpecificOutput?: {
|
|
51
|
+
hookEventName: 'PreToolUse';
|
|
52
|
+
additionalContext: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export declare function runPreRead(payload: PreReadPayload, opts?: PreReadOptions): PreReadOutput;
|
|
56
|
+
//# sourceMappingURL=pre_read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre_read.d.ts","sourceRoot":"","sources":["../../src/hooks/pre_read.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAU,KAAK,EAAE,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EACH,iBAAiB,GACjB,YAAY,GACZ,SAAS,GACT,cAAc,GACd,UAAU,GACV,iBAAiB,GACjB,YAAY,GACZ,eAAe,CAAC;IACpB,kBAAkB,CAAC,EAAE;QACnB,aAAa,EAAE,YAAY,CAAC;QAC5B,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH;AAYD,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,GAAE,cAAmB,GAAG,aAAa,CA8C5F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { loadConfig, projectDir } from '../config.js';
|
|
4
|
+
import { openDb } from '../core/db.js';
|
|
5
|
+
import { resolveProjectId } from '../core/project_id.js';
|
|
6
|
+
import { FileFingerprintStore, statFile, matchesAnyGlob } from '../core/file_summary.js';
|
|
7
|
+
// Claude Code's PreToolUse payload. We only care about file_path-bearing
|
|
8
|
+
// tools (Read, Edit). Anything else passes through.
|
|
9
|
+
export const PreReadPayloadSchema = z.object({
|
|
10
|
+
tool_name: z.string().optional(),
|
|
11
|
+
tool_input: z
|
|
12
|
+
.object({
|
|
13
|
+
file_path: z.string().optional(),
|
|
14
|
+
notebook_path: z.string().optional(),
|
|
15
|
+
})
|
|
16
|
+
.passthrough()
|
|
17
|
+
.optional(),
|
|
18
|
+
cwd: z.string().optional(),
|
|
19
|
+
project_id: z.string().optional(),
|
|
20
|
+
hook_event_name: z.string().optional(),
|
|
21
|
+
});
|
|
22
|
+
const GATEABLE_TOOLS = new Set(['Read', 'Edit']);
|
|
23
|
+
function buildContextMessage(path, summary, tokens) {
|
|
24
|
+
return `[somtum-cache] Cached summary of ${path} (~${tokens} tokens in full):
|
|
25
|
+
---
|
|
26
|
+
${summary}
|
|
27
|
+
---
|
|
28
|
+
This summary is fresh as of the current file content. Use it if it answers the question; otherwise still proceed with the Read.`;
|
|
29
|
+
}
|
|
30
|
+
export function runPreRead(payload, opts = {}) {
|
|
31
|
+
const parsed = PreReadPayloadSchema.parse(payload);
|
|
32
|
+
const cwd = opts.cwd ?? parsed.cwd ?? process.cwd();
|
|
33
|
+
const config = opts.config ?? loadConfig({ cwd });
|
|
34
|
+
if (!config.file_gating.enabled)
|
|
35
|
+
return { ok: true, gated: false, reason: 'gating-disabled' };
|
|
36
|
+
if (!parsed.tool_name || !GATEABLE_TOOLS.has(parsed.tool_name)) {
|
|
37
|
+
return { ok: true, gated: false, reason: 'wrong-tool' };
|
|
38
|
+
}
|
|
39
|
+
const path = parsed.tool_input?.file_path;
|
|
40
|
+
if (!path)
|
|
41
|
+
return { ok: true, gated: false, reason: 'no-path' };
|
|
42
|
+
if (matchesAnyGlob(path, config.file_gating.exclude_globs)) {
|
|
43
|
+
return { ok: true, gated: false, reason: 'excluded' };
|
|
44
|
+
}
|
|
45
|
+
const stat = statFile(path, { cwd });
|
|
46
|
+
if (!stat)
|
|
47
|
+
return { ok: true, gated: false, reason: 'file-missing' };
|
|
48
|
+
if (stat.tokens < config.file_gating.min_file_size_tokens) {
|
|
49
|
+
return { ok: true, gated: false, reason: 'below-threshold' };
|
|
50
|
+
}
|
|
51
|
+
const projectId = opts.projectId ?? parsed.project_id ?? resolveProjectId(cwd);
|
|
52
|
+
const ownsDb = opts.db === undefined;
|
|
53
|
+
const dbPath = opts.dbPath ?? join(projectDir(projectId), 'db.sqlite');
|
|
54
|
+
const db = opts.db ?? openDb({ path: dbPath });
|
|
55
|
+
try {
|
|
56
|
+
const store = new FileFingerprintStore(db);
|
|
57
|
+
const fp = store.get(projectId, path);
|
|
58
|
+
if (!fp || !fp.summary)
|
|
59
|
+
return { ok: true, gated: false, reason: 'no-summary' };
|
|
60
|
+
if (fp.content_hash !== stat.contentHash) {
|
|
61
|
+
return { ok: true, gated: false, reason: 'stale-summary' };
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
ok: true,
|
|
65
|
+
gated: true,
|
|
66
|
+
hookSpecificOutput: {
|
|
67
|
+
hookEventName: 'PreToolUse',
|
|
68
|
+
additionalContext: buildContextMessage(path, fp.summary, stat.tokens),
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
if (ownsDb)
|
|
74
|
+
db.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=pre_read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre_read.js","sourceRoot":"","sources":["../../src/hooks/pre_read.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { openDb, runMigrations, appliedVersions, hasFts5 } from './core/db.js';
|
|
2
|
+
export { MemoryStore } from './core/store.js';
|
|
3
|
+
export { PromptCache, hashPrompt, normalizePrompt, CACHE_FINGERPRINT_VERSION, } from './core/cache.js';
|
|
4
|
+
export { Bm25Retriever } from './core/retriever/bm25.js';
|
|
5
|
+
export type { Retriever, RetrievalResult, SearchOptions } from './core/retriever/types.js';
|
|
6
|
+
export { extract, anthropicCaller, estimateTokensSaved } from './core/extractor.js';
|
|
7
|
+
export type { LlmCaller, ExtractOptions, ExtractionOutcome } from './core/extractor.js';
|
|
8
|
+
export { countTokens, sumTokens } from './core/tokens.js';
|
|
9
|
+
export { redact, redactAll, REDACTION_PLACEHOLDER } from './core/privacy.js';
|
|
10
|
+
export { renderIndex, generateIndex } from './core/index_gen.js';
|
|
11
|
+
export { runPostSession, HookPayloadSchema } from './hooks/post_session.js';
|
|
12
|
+
export { resolveProjectId, projectNameFromCwd } from './core/project_id.js';
|
|
13
|
+
export { loadConfig, projectDir, ensureGlobalDir, GLOBAL_DIR, GLOBAL_CONFIG_PATH, } from './config.js';
|
|
14
|
+
export * from './core/schema.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,WAAW,EACX,UAAU,EACV,eAAe,EACf,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACpF,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,UAAU,EACV,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Public API for embedding Somtum in other tools.
|
|
2
|
+
// Intentionally narrow; grow it deliberately as needs emerge.
|
|
3
|
+
export { openDb, runMigrations, appliedVersions, hasFts5 } from './core/db.js';
|
|
4
|
+
export { MemoryStore } from './core/store.js';
|
|
5
|
+
export { PromptCache, hashPrompt, normalizePrompt, CACHE_FINGERPRINT_VERSION, } from './core/cache.js';
|
|
6
|
+
export { Bm25Retriever } from './core/retriever/bm25.js';
|
|
7
|
+
export { extract, anthropicCaller, estimateTokensSaved } from './core/extractor.js';
|
|
8
|
+
export { countTokens, sumTokens } from './core/tokens.js';
|
|
9
|
+
export { redact, redactAll, REDACTION_PLACEHOLDER } from './core/privacy.js';
|
|
10
|
+
export { renderIndex, generateIndex } from './core/index_gen.js';
|
|
11
|
+
export { runPostSession, HookPayloadSchema } from './hooks/post_session.js';
|
|
12
|
+
export { resolveProjectId, projectNameFromCwd } from './core/project_id.js';
|
|
13
|
+
export { loadConfig, projectDir, ensureGlobalDir, GLOBAL_DIR, GLOBAL_CONFIG_PATH, } from './config.js';
|
|
14
|
+
export * from './core/schema.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,8DAA8D;AAE9D,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,WAAW,EACX,UAAU,EACV,eAAe,EACf,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEpF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,UAAU,EACV,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type DB } from '../core/db.js';
|
|
3
|
+
import type { Config } from '../core/schema.js';
|
|
4
|
+
import { type ToolContext } from './tools.js';
|
|
5
|
+
export interface BuildOptions {
|
|
6
|
+
db?: DB;
|
|
7
|
+
dbPath?: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
config?: Config;
|
|
10
|
+
projectId?: string;
|
|
11
|
+
}
|
|
12
|
+
interface BuildResult {
|
|
13
|
+
server: McpServer;
|
|
14
|
+
context: ToolContext;
|
|
15
|
+
close: () => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function buildServer(opts?: BuildOptions): BuildResult;
|
|
18
|
+
export declare function runMcpServer(opts?: BuildOptions): Promise<void>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAU,KAAK,EAAE,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAaL,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AA0BD,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,WAAW,CAkHhE;AAED,wBAAsB,YAAY,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE"}
|