@mneme-ai/core 0.23.0 → 0.25.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 (54) hide show
  1. package/dist/htc/abstract.d.ts +41 -0
  2. package/dist/htc/abstract.d.ts.map +1 -0
  3. package/dist/htc/abstract.js +97 -0
  4. package/dist/htc/abstract.js.map +1 -0
  5. package/dist/htc/abstract.test.d.ts +2 -0
  6. package/dist/htc/abstract.test.d.ts.map +1 -0
  7. package/dist/htc/abstract.test.js +169 -0
  8. package/dist/htc/abstract.test.js.map +1 -0
  9. package/dist/htc/clusters.d.ts +38 -0
  10. package/dist/htc/clusters.d.ts.map +1 -0
  11. package/dist/htc/clusters.js +103 -0
  12. package/dist/htc/clusters.js.map +1 -0
  13. package/dist/htc/clusters.test.d.ts +2 -0
  14. package/dist/htc/clusters.test.d.ts.map +1 -0
  15. package/dist/htc/clusters.test.js +128 -0
  16. package/dist/htc/clusters.test.js.map +1 -0
  17. package/dist/htc/index.d.ts +16 -0
  18. package/dist/htc/index.d.ts.map +1 -0
  19. package/dist/htc/index.js +16 -0
  20. package/dist/htc/index.js.map +1 -0
  21. package/dist/htc/memoir.d.ts +27 -0
  22. package/dist/htc/memoir.d.ts.map +1 -0
  23. package/dist/htc/memoir.js +50 -0
  24. package/dist/htc/memoir.js.map +1 -0
  25. package/dist/htc/memoir.test.d.ts +2 -0
  26. package/dist/htc/memoir.test.d.ts.map +1 -0
  27. package/dist/htc/memoir.test.js +87 -0
  28. package/dist/htc/memoir.test.js.map +1 -0
  29. package/dist/htc/storage.d.ts +24 -0
  30. package/dist/htc/storage.d.ts.map +1 -0
  31. package/dist/htc/storage.js +170 -0
  32. package/dist/htc/storage.js.map +1 -0
  33. package/dist/htc/storage.test.d.ts +2 -0
  34. package/dist/htc/storage.test.d.ts.map +1 -0
  35. package/dist/htc/storage.test.js +327 -0
  36. package/dist/htc/storage.test.js.map +1 -0
  37. package/dist/htc/types.d.ts +86 -0
  38. package/dist/htc/types.d.ts.map +1 -0
  39. package/dist/htc/types.js +22 -0
  40. package/dist/htc/types.js.map +1 -0
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -0
  44. package/dist/index.js.map +1 -1
  45. package/dist/retrieve/synthesize.d.ts +7 -0
  46. package/dist/retrieve/synthesize.d.ts.map +1 -1
  47. package/dist/retrieve/synthesize.js +31 -1
  48. package/dist/retrieve/synthesize.js.map +1 -1
  49. package/dist/store/schema.d.ts +3 -2
  50. package/dist/store/schema.d.ts.map +1 -1
  51. package/dist/store/schema.js +42 -1
  52. package/dist/store/schema.js.map +1 -1
  53. package/dist/store/sqlite.test.js +1 -1
  54. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clusters.test.js","sourceRoot":"","sources":["../../src/htc/clusters.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Hierarchical Token Cache (HTC) — barrel.
3
+ *
4
+ * Exports:
5
+ * - types.ts — shared types (AbstractResult, ClusterSummary, Memoir, HtcStats, HtcEnricher)
6
+ * - abstract.ts — Layer 1 (~30 tok per commit)
7
+ * - clusters.ts — Layer 2 (~100 tok per cluster)
8
+ * - memoir.ts — Layer 3 (~500 tok per repo)
9
+ * - storage.ts — SQLite read/write helpers
10
+ */
11
+ export * from "./types.js";
12
+ export * from "./abstract.js";
13
+ export * from "./clusters.js";
14
+ export * from "./memoir.js";
15
+ export * from "./storage.js";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/htc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Hierarchical Token Cache (HTC) — barrel.
3
+ *
4
+ * Exports:
5
+ * - types.ts — shared types (AbstractResult, ClusterSummary, Memoir, HtcStats, HtcEnricher)
6
+ * - abstract.ts — Layer 1 (~30 tok per commit)
7
+ * - clusters.ts — Layer 2 (~100 tok per cluster)
8
+ * - memoir.ts — Layer 3 (~500 tok per repo)
9
+ * - storage.ts — SQLite read/write helpers
10
+ */
11
+ export * from "./types.js";
12
+ export * from "./abstract.js";
13
+ export * from "./clusters.js";
14
+ export * from "./memoir.js";
15
+ export * from "./storage.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/htc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * HTC Layer 3 — repo memoir.
3
+ *
4
+ * Single-shot LLM call that turns all cluster summaries into a ~500-token
5
+ * narrative covering: what the repo IS, the major topics + their evolution,
6
+ * and current state + open questions.
7
+ *
8
+ * This is the topmost layer of the cache: 50,000 commits → 500 tokens. The
9
+ * caller pays this cost ONCE per generation; every downstream `mneme ask`
10
+ * can reuse it forever.
11
+ */
12
+ import type { ClusterSummary, HtcEnricher, Memoir } from "./types.js";
13
+ export declare const MEMOIR_SYSTEM_PROMPT: string;
14
+ export interface ClusterDateRange {
15
+ /** Optional ISO date of the cluster's earliest commit (YYYY-MM-DD ok). */
16
+ fromDate?: string;
17
+ /** Optional ISO date of the cluster's latest commit. */
18
+ toDate?: string;
19
+ }
20
+ /**
21
+ * Build the user-side prompt block. Clusters should be passed in the order
22
+ * the caller wants them rendered (typically chronological by fromDate).
23
+ */
24
+ export declare function buildMemoirUserPrompt(clusters: Array<ClusterSummary & ClusterDateRange>): string;
25
+ /** Generate the single-shot repo memoir from cluster summaries. */
26
+ export declare function generateMemoir(clusters: Array<ClusterSummary & ClusterDateRange>, totalCommits: number, enricher: HtcEnricher): Promise<Memoir>;
27
+ //# sourceMappingURL=memoir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoir.d.ts","sourceRoot":"","sources":["../../src/htc/memoir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGtE,eAAO,MAAM,oBAAoB,QAM6B,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,KAAK,CAAC,cAAc,GAAG,gBAAgB,CAAC,GACjD,MAAM,CAYR;AAED,mEAAmE;AACnE,wBAAsB,cAAc,CAClC,QAAQ,EAAE,KAAK,CAAC,cAAc,GAAG,gBAAgB,CAAC,EAClD,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
@@ -0,0 +1,50 @@
1
+ import { estimateTokens } from "./types.js";
2
+ export const MEMOIR_SYSTEM_PROMPT = "Write a ~500-token narrative summary of a codebase based on its topic " +
3
+ "clusters. Output structure:\n" +
4
+ " 1. One opening paragraph: what this repo IS.\n" +
5
+ " 2. 3-5 bullet paragraphs: each major topic + its evolution.\n" +
6
+ " 3. One closing: current state + open questions.\n" +
7
+ "Be specific, concrete, dated where possible. No buzzwords.";
8
+ /**
9
+ * Build the user-side prompt block. Clusters should be passed in the order
10
+ * the caller wants them rendered (typically chronological by fromDate).
11
+ */
12
+ export function buildMemoirUserPrompt(clusters) {
13
+ const lines = ["Topic clusters in chronological order:"];
14
+ for (const c of clusters) {
15
+ const dateRange = c.fromDate && c.toDate
16
+ ? ` (${c.memberHashes.length} commits, dates ${c.fromDate} to ${c.toDate})`
17
+ : ` (${c.memberHashes.length} commits)`;
18
+ lines.push("");
19
+ lines.push(` CLUSTER "${c.label}"${dateRange}:`);
20
+ lines.push(` ${c.summary}`);
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ /** Generate the single-shot repo memoir from cluster summaries. */
25
+ export async function generateMemoir(clusters, totalCommits, enricher) {
26
+ if (clusters.length === 0) {
27
+ throw new Error("Cannot generate memoir from zero clusters; run Layer 2 first.");
28
+ }
29
+ const start = Date.now();
30
+ const result = await enricher.enrich({
31
+ system: MEMOIR_SYSTEM_PROMPT,
32
+ user: buildMemoirUserPrompt(clusters),
33
+ // ~500 tokens target; 800 cap leaves room without inviting tangents.
34
+ maxTokens: 800,
35
+ // Slightly higher than Layer 1/2 — narrative needs a bit of voice.
36
+ temperature: 0.4,
37
+ });
38
+ const generationMs = Date.now() - start;
39
+ const narrative = (result.text ?? "").trim();
40
+ return {
41
+ narrative,
42
+ totalCommits,
43
+ totalClusters: clusters.length,
44
+ tokenCount: estimateTokens(narrative),
45
+ generationMs,
46
+ generator: enricher.name,
47
+ generatedAt: new Date().toISOString(),
48
+ };
49
+ }
50
+ //# sourceMappingURL=memoir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoir.js","sourceRoot":"","sources":["../../src/htc/memoir.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,CAAC,MAAM,oBAAoB,GAC/B,wEAAwE;IACxE,+BAA+B;IAC/B,kDAAkD;IAClD,iEAAiE;IACjE,qDAAqD;IACrD,4DAA4D,CAAC;AAS/D;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkD;IAElD,MAAM,KAAK,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,SAAS,GACb,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM;YACpB,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,mBAAmB,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,MAAM,GAAG;YAC3E,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,WAAW,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,KAAK,IAAI,SAAS,GAAG,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAkD,EAClD,YAAoB,EACpB,QAAqB;IAErB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACnC,MAAM,EAAE,oBAAoB;QAC5B,IAAI,EAAE,qBAAqB,CAAC,QAAQ,CAAC;QACrC,qEAAqE;QACrE,SAAS,EAAE,GAAG;QACd,mEAAmE;QACnE,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IACxC,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7C,OAAO;QACL,SAAS;QACT,YAAY;QACZ,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,UAAU,EAAE,cAAc,CAAC,SAAS,CAAC;QACrC,YAAY;QACZ,SAAS,EAAE,QAAQ,CAAC,IAAI;QACxB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=memoir.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoir.test.d.ts","sourceRoot":"","sources":["../../src/htc/memoir.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { MEMOIR_SYSTEM_PROMPT, buildMemoirUserPrompt, generateMemoir, } from "./memoir.js";
3
+ function mockEnricher(text, name = "mock:test") {
4
+ return {
5
+ name,
6
+ enrich: vi.fn().mockResolvedValue({ text }),
7
+ };
8
+ }
9
+ const sampleClusters = [
10
+ {
11
+ clusterId: "c1",
12
+ label: "auth refactor",
13
+ summary: "Migrated from session cookies to JWT for CDN deploys.",
14
+ memberHashes: ["a", "b", "c"],
15
+ tokenCount: 80,
16
+ generationMs: 1000,
17
+ generator: "test",
18
+ fromDate: "2024-01-01",
19
+ toDate: "2024-03-15",
20
+ },
21
+ {
22
+ clusterId: "c2",
23
+ label: "payment v2",
24
+ summary: "Split monolithic payment.ts into 3 modules.",
25
+ memberHashes: ["d", "e"],
26
+ tokenCount: 60,
27
+ generationMs: 900,
28
+ generator: "test",
29
+ fromDate: "2024-04-01",
30
+ toDate: "2024-06-20",
31
+ },
32
+ ];
33
+ describe("buildMemoirUserPrompt", () => {
34
+ it("renders each cluster with label, member count, and date range", () => {
35
+ const prompt = buildMemoirUserPrompt(sampleClusters);
36
+ expect(prompt).toContain('CLUSTER "auth refactor"');
37
+ expect(prompt).toContain("(3 commits, dates 2024-01-01 to 2024-03-15)");
38
+ expect(prompt).toContain('CLUSTER "payment v2"');
39
+ expect(prompt).toContain("(2 commits, dates 2024-04-01 to 2024-06-20)");
40
+ expect(prompt).toContain("Migrated from session cookies");
41
+ });
42
+ it("falls back to commit count when dates are missing", () => {
43
+ const prompt = buildMemoirUserPrompt([
44
+ {
45
+ clusterId: "c1",
46
+ label: "x",
47
+ summary: "y",
48
+ memberHashes: ["a", "b"],
49
+ tokenCount: 1,
50
+ generationMs: 1,
51
+ generator: "t",
52
+ },
53
+ ]);
54
+ expect(prompt).toContain('CLUSTER "x" (2 commits):');
55
+ expect(prompt).not.toContain("dates");
56
+ });
57
+ });
58
+ describe("generateMemoir", () => {
59
+ it("calls the enricher once and returns Memoir", async () => {
60
+ const enricher = mockEnricher("This repo is a TypeScript library that compresses git history. " +
61
+ "Auth: migrated to JWT. Payment: split for V2. " +
62
+ "Currently shipping v0.24.", "groq:llama-3.3-70b");
63
+ const m = await generateMemoir(sampleClusters, 5, enricher);
64
+ expect(m.totalCommits).toBe(5);
65
+ expect(m.totalClusters).toBe(2);
66
+ expect(m.narrative).toContain("TypeScript");
67
+ expect(m.tokenCount).toBeGreaterThan(0);
68
+ expect(m.generator).toBe("groq:llama-3.3-70b");
69
+ expect(m.generationMs).toBeGreaterThanOrEqual(0);
70
+ expect(enricher.enrich).toHaveBeenCalledTimes(1);
71
+ const call = enricher.enrich.mock.calls[0][0];
72
+ expect(call.system).toBe(MEMOIR_SYSTEM_PROMPT);
73
+ expect(call.user).toContain('CLUSTER "auth refactor"');
74
+ expect(call.maxTokens).toBe(800);
75
+ });
76
+ it("throws when no clusters provided", async () => {
77
+ const enricher = mockEnricher("never called");
78
+ await expect(generateMemoir([], 0, enricher)).rejects.toThrow(/zero clusters/);
79
+ expect(enricher.enrich).not.toHaveBeenCalled();
80
+ });
81
+ it("trims wrapping whitespace from the model's narrative", async () => {
82
+ const enricher = mockEnricher("\n\n the narrative. \n");
83
+ const m = await generateMemoir(sampleClusters, 1, enricher);
84
+ expect(m.narrative).toBe("the narrative.");
85
+ });
86
+ });
87
+ //# sourceMappingURL=memoir.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoir.test.js","sourceRoot":"","sources":["../../src/htc/memoir.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * HTC storage — read/write helpers for the three Hierarchical Token Cache
3
+ * tables (htc_abstracts, htc_clusters, htc_memoir).
4
+ *
5
+ * Pure SQLite wrappers; no LLM calls happen here. The generators in
6
+ * abstract.ts / clusters.ts / memoir.ts produce the typed results, and this
7
+ * module persists + reads them.
8
+ */
9
+ import type { MnemeStore } from "../store/sqlite.js";
10
+ import type { AbstractResult, ClusterSummary, HtcStats, Memoir } from "./types.js";
11
+ import { estimateTokens } from "./types.js";
12
+ export declare function upsertAbstract(store: MnemeStore, a: AbstractResult): void;
13
+ export declare function upsertAbstracts(store: MnemeStore, batch: AbstractResult[]): void;
14
+ export declare function getAbstract(store: MnemeStore, hash: string): AbstractResult | null;
15
+ export declare function getAllAbstracts(store: MnemeStore): Map<string, AbstractResult>;
16
+ /** Delete abstracts older than N days. Returns deleted row count. */
17
+ export declare function deleteOldAbstracts(store: MnemeStore, olderThanDays: number): number;
18
+ export declare function upsertClusterSummary(store: MnemeStore, c: ClusterSummary): void;
19
+ export declare function getAllClusterSummaries(store: MnemeStore): ClusterSummary[];
20
+ export declare function upsertMemoir(store: MnemeStore, m: Memoir): void;
21
+ export declare function getMemoir(store: MnemeStore): Memoir | null;
22
+ export declare function getHtcStats(store: MnemeStore): HtcStats;
23
+ export { estimateTokens };
24
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/htc/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,QAAQ,EACR,MAAM,EACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5C,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,cAAc,GAAG,IAAI,CASzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,CAchF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAyBlF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B9E;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAMnF;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,cAAc,GAAG,IAAI,CAiB/E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,EAAE,CA2B1E;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAgB/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CA0B1D;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAwDvD;AAcD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,170 @@
1
+ import { estimateTokens } from "./types.js";
2
+ /* ─────────────────────── Layer 1 — abstracts ─────────────────────── */
3
+ export function upsertAbstract(store, a) {
4
+ const generatedAt = a.generatedAt ?? new Date().toISOString();
5
+ store.db
6
+ .prepare(`INSERT OR REPLACE INTO htc_abstracts
7
+ (commit_hash, abstract, token_count, generated_at, generator, generation_ms)
8
+ VALUES (?, ?, ?, ?, ?, ?)`)
9
+ .run(a.hash, a.abstract, a.tokenCount, generatedAt, a.generator, a.generationMs);
10
+ }
11
+ export function upsertAbstracts(store, batch) {
12
+ if (batch.length === 0)
13
+ return;
14
+ const stmt = store.db.prepare(`INSERT OR REPLACE INTO htc_abstracts
15
+ (commit_hash, abstract, token_count, generated_at, generator, generation_ms)
16
+ VALUES (?, ?, ?, ?, ?, ?)`);
17
+ const tx = store.db.transaction((items) => {
18
+ for (const a of items) {
19
+ const generatedAt = a.generatedAt ?? new Date().toISOString();
20
+ stmt.run(a.hash, a.abstract, a.tokenCount, generatedAt, a.generator, a.generationMs);
21
+ }
22
+ });
23
+ tx(batch);
24
+ }
25
+ export function getAbstract(store, hash) {
26
+ const row = store.db
27
+ .prepare(`SELECT commit_hash, abstract, token_count, generated_at, generator, generation_ms
28
+ FROM htc_abstracts WHERE commit_hash = ?`)
29
+ .get(hash);
30
+ if (!row)
31
+ return null;
32
+ return {
33
+ hash: row.commit_hash,
34
+ abstract: row.abstract,
35
+ tokenCount: row.token_count,
36
+ generatedAt: row.generated_at,
37
+ generator: row.generator,
38
+ generationMs: row.generation_ms,
39
+ };
40
+ }
41
+ export function getAllAbstracts(store) {
42
+ const rows = store.db
43
+ .prepare(`SELECT commit_hash, abstract, token_count, generated_at, generator, generation_ms
44
+ FROM htc_abstracts`)
45
+ .all();
46
+ const out = new Map();
47
+ for (const r of rows) {
48
+ out.set(r.commit_hash, {
49
+ hash: r.commit_hash,
50
+ abstract: r.abstract,
51
+ tokenCount: r.token_count,
52
+ generatedAt: r.generated_at,
53
+ generator: r.generator,
54
+ generationMs: r.generation_ms,
55
+ });
56
+ }
57
+ return out;
58
+ }
59
+ /** Delete abstracts older than N days. Returns deleted row count. */
60
+ export function deleteOldAbstracts(store, olderThanDays) {
61
+ const cutoff = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000).toISOString();
62
+ const info = store.db
63
+ .prepare("DELETE FROM htc_abstracts WHERE generated_at < ?")
64
+ .run(cutoff);
65
+ return info.changes;
66
+ }
67
+ /* ─────────────────────── Layer 2 — clusters ──────────────────────── */
68
+ export function upsertClusterSummary(store, c) {
69
+ const generatedAt = c.generatedAt ?? new Date().toISOString();
70
+ store.db
71
+ .prepare(`INSERT OR REPLACE INTO htc_clusters
72
+ (cluster_id, label, summary, member_hashes, token_count, generated_at, generator)
73
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
74
+ .run(c.clusterId, c.label, c.summary, JSON.stringify(c.memberHashes), c.tokenCount, generatedAt, c.generator);
75
+ }
76
+ export function getAllClusterSummaries(store) {
77
+ const rows = store.db
78
+ .prepare(`SELECT cluster_id, label, summary, member_hashes, token_count, generated_at, generator
79
+ FROM htc_clusters
80
+ ORDER BY generated_at ASC`)
81
+ .all();
82
+ return rows.map((r) => ({
83
+ clusterId: r.cluster_id,
84
+ label: r.label,
85
+ summary: r.summary,
86
+ memberHashes: safeJsonArray(r.member_hashes),
87
+ tokenCount: r.token_count,
88
+ generatedAt: r.generated_at,
89
+ generator: r.generator,
90
+ // generationMs is per-call telemetry — not persisted (write-only at gen time).
91
+ generationMs: 0,
92
+ }));
93
+ }
94
+ /* ─────────────────────── Layer 3 — memoir ────────────────────────── */
95
+ export function upsertMemoir(store, m) {
96
+ const generatedAt = m.generatedAt ?? new Date().toISOString();
97
+ store.db
98
+ .prepare(`INSERT OR REPLACE INTO htc_memoir
99
+ (id, narrative, total_commits, total_clusters, token_count, generated_at, generator)
100
+ VALUES (1, ?, ?, ?, ?, ?, ?)`)
101
+ .run(m.narrative, m.totalCommits, m.totalClusters, m.tokenCount, generatedAt, m.generator);
102
+ }
103
+ export function getMemoir(store) {
104
+ const row = store.db
105
+ .prepare(`SELECT narrative, total_commits, total_clusters, token_count, generated_at, generator
106
+ FROM htc_memoir WHERE id = 1`)
107
+ .get();
108
+ if (!row)
109
+ return null;
110
+ return {
111
+ narrative: row.narrative,
112
+ totalCommits: row.total_commits,
113
+ totalClusters: row.total_clusters,
114
+ tokenCount: row.token_count,
115
+ generatedAt: row.generated_at,
116
+ generator: row.generator,
117
+ generationMs: 0,
118
+ };
119
+ }
120
+ /* ─────────────────────── Stats ───────────────────────────────────── */
121
+ export function getHtcStats(store) {
122
+ const totalCommits = store.db.prepare("SELECT COUNT(*) AS n FROM commits").get().n;
123
+ const absRow = store.db
124
+ .prepare("SELECT COUNT(*) AS n, COALESCE(SUM(token_count), 0) AS tok FROM htc_abstracts")
125
+ .get();
126
+ const clusterRow = store.db
127
+ .prepare("SELECT COUNT(*) AS n, COALESCE(SUM(token_count), 0) AS tok FROM htc_clusters")
128
+ .get();
129
+ const memoirRow = store.db
130
+ .prepare("SELECT token_count, generated_at FROM htc_memoir WHERE id = 1")
131
+ .get();
132
+ // Estimate raw token cost: subject + body for every commit.
133
+ const rawRow = store.db
134
+ .prepare("SELECT COALESCE(SUM(LENGTH(subject) + LENGTH(body)), 0) AS chars FROM commits")
135
+ .get();
136
+ // Rough chars→tokens conversion: ~4 chars per token.
137
+ const estimatedRawTokens = Math.ceil(rawRow.chars / 4);
138
+ const totalCachedTokens = Number(absRow.tok) + Number(clusterRow.tok) + Number(memoirRow?.token_count ?? 0);
139
+ const memoirGenerated = !!memoirRow;
140
+ let memoirAgeDays;
141
+ if (memoirRow) {
142
+ const ageMs = Date.now() - new Date(memoirRow.generated_at).getTime();
143
+ memoirAgeDays = Math.max(0, Math.floor(ageMs / (24 * 60 * 60 * 1000)));
144
+ }
145
+ const compressionRatio = totalCachedTokens > 0 ? Number((estimatedRawTokens / totalCachedTokens).toFixed(2)) : 0;
146
+ return {
147
+ totalCommits,
148
+ abstractsGenerated: absRow.n,
149
+ abstractsCoverage: totalCommits === 0 ? 0 : Number((absRow.n / totalCommits).toFixed(4)),
150
+ clustersGenerated: clusterRow.n,
151
+ memoirGenerated,
152
+ memoirAgeDays,
153
+ totalCachedTokens,
154
+ estimatedRawTokens,
155
+ compressionRatio,
156
+ };
157
+ }
158
+ /* ─────────────────────── internals ───────────────────────────────── */
159
+ function safeJsonArray(s) {
160
+ try {
161
+ const v = JSON.parse(s);
162
+ return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
163
+ }
164
+ catch {
165
+ return [];
166
+ }
167
+ }
168
+ // Re-export estimateTokens so callers don't need a second import.
169
+ export { estimateTokens };
170
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/htc/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../src/htc/storage.test.ts"],"names":[],"mappings":""}