@saleem11kh/repomem 0.3.1 → 0.5.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 (57) hide show
  1. package/README.md +655 -212
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +230 -14
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config/config.d.ts +20 -0
  6. package/dist/config/config.d.ts.map +1 -1
  7. package/dist/config/config.js +1 -0
  8. package/dist/config/config.js.map +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +10 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/store/adr.d.ts +22 -0
  13. package/dist/store/adr.d.ts.map +1 -0
  14. package/dist/store/adr.js +201 -0
  15. package/dist/store/adr.js.map +1 -0
  16. package/dist/store/capture.d.ts +39 -0
  17. package/dist/store/capture.d.ts.map +1 -0
  18. package/dist/store/capture.js +148 -0
  19. package/dist/store/capture.js.map +1 -0
  20. package/dist/store/embeddings.d.ts +34 -0
  21. package/dist/store/embeddings.d.ts.map +1 -0
  22. package/dist/store/embeddings.js +250 -0
  23. package/dist/store/embeddings.js.map +1 -0
  24. package/dist/store/file-store.d.ts +26 -1
  25. package/dist/store/file-store.d.ts.map +1 -1
  26. package/dist/store/file-store.js +105 -16
  27. package/dist/store/file-store.js.map +1 -1
  28. package/dist/store/git.d.ts +46 -0
  29. package/dist/store/git.d.ts.map +1 -0
  30. package/dist/store/git.js +131 -0
  31. package/dist/store/git.js.map +1 -0
  32. package/dist/store/profile.d.ts +18 -0
  33. package/dist/store/profile.d.ts.map +1 -0
  34. package/dist/store/profile.js +345 -0
  35. package/dist/store/profile.js.map +1 -0
  36. package/dist/tools/mem-context.d.ts.map +1 -1
  37. package/dist/tools/mem-context.js +249 -33
  38. package/dist/tools/mem-context.js.map +1 -1
  39. package/dist/tools/mem-handoff.d.ts.map +1 -1
  40. package/dist/tools/mem-handoff.js +53 -5
  41. package/dist/tools/mem-handoff.js.map +1 -1
  42. package/dist/tools/mem-save.d.ts +5 -0
  43. package/dist/tools/mem-save.d.ts.map +1 -1
  44. package/dist/tools/mem-save.js +60 -2
  45. package/dist/tools/mem-save.js.map +1 -1
  46. package/dist/tools/mem-search.d.ts.map +1 -1
  47. package/dist/tools/mem-search.js +26 -14
  48. package/dist/tools/mem-search.js.map +1 -1
  49. package/dist/tools/session.d.ts +40 -0
  50. package/dist/tools/session.d.ts.map +1 -0
  51. package/dist/tools/session.js +159 -0
  52. package/dist/tools/session.js.map +1 -0
  53. package/dist/tools/util.d.ts +8 -1
  54. package/dist/tools/util.d.ts.map +1 -1
  55. package/dist/tools/util.js +7 -0
  56. package/dist/tools/util.js.map +1 -1
  57. package/package.json +1 -1
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.findAdrs = findAdrs;
37
+ exports.importAdrs = importAdrs;
38
+ /**
39
+ * Import Architecture Decision Records that a repo already has.
40
+ *
41
+ * A project with docs/adr/0001-use-postgres.md is not a project without
42
+ * decisions — it is a project whose decisions repomem cannot see. These are
43
+ * already structured and already authored, so they are copied in directly. No
44
+ * model, no distillation, no judgement required.
45
+ *
46
+ * Prose docs (README, ARCHITECTURE) still need an agent to distil — that is what
47
+ * mem_prime is for. This handles only the part that is already decision-shaped.
48
+ */
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const file_store_js_1 = require("./file-store.js");
52
+ // Where ADRs conventionally live. Checked in order; all matches are imported.
53
+ const ADR_DIRS = [
54
+ "docs/adr",
55
+ "docs/adrs",
56
+ "docs/decisions",
57
+ "docs/architecture/decisions",
58
+ "adr",
59
+ "adrs",
60
+ "decisions",
61
+ "rfcs",
62
+ "docs/rfcs",
63
+ ];
64
+ const MAX_ADRS = 50;
65
+ const MAX_BODY_CHARS = 8000;
66
+ /** First markdown H1, else a title derived from the filename. */
67
+ function titleOf(raw, filename) {
68
+ const h1 = raw.match(/^#\s+(.+)$/m);
69
+ if (h1)
70
+ return h1[1].trim();
71
+ return filename
72
+ .replace(/\.md$/i, "")
73
+ .replace(/^\d+[-_]/, "")
74
+ .replace(/[-_]+/g, " ")
75
+ .trim();
76
+ }
77
+ /** MADR and Nygard both record a status line; missing is fine. */
78
+ function statusOf(raw) {
79
+ const fm = raw.match(/^status:\s*(.+)$/im);
80
+ if (fm)
81
+ return fm[1].trim().replace(/^["']|["']$/g, "");
82
+ const heading = raw.match(/^##\s*Status\s*\n+([^\n#]+)/im);
83
+ return heading ? heading[1].trim() : "";
84
+ }
85
+ function dateOf(raw, filePath) {
86
+ const fm = raw.match(/^date:\s*(\d{4}-\d{2}-\d{2})/im);
87
+ if (fm)
88
+ return fm[1];
89
+ const inText = raw.match(/\b(\d{4}-\d{2}-\d{2})\b/);
90
+ if (inText)
91
+ return inText[1];
92
+ try {
93
+ return new Date(fs.statSync(filePath).mtime).toISOString().slice(0, 10);
94
+ }
95
+ catch {
96
+ return "1970-01-01";
97
+ }
98
+ }
99
+ /** Strip YAML front matter so the imported body starts at real content. */
100
+ function stripFrontMatter(raw) {
101
+ if (!raw.startsWith("---"))
102
+ return raw;
103
+ const end = raw.indexOf("\n---", 3);
104
+ if (end === -1)
105
+ return raw;
106
+ const after = raw.indexOf("\n", end + 1);
107
+ return after === -1 ? "" : raw.slice(after + 1);
108
+ }
109
+ /** Find ADR-shaped markdown files anywhere the ecosystem conventionally puts them. */
110
+ function findAdrs(projectRoot) {
111
+ const found = [];
112
+ const seen = new Set();
113
+ for (const dir of ADR_DIRS) {
114
+ const abs = path.join(projectRoot, dir);
115
+ let entries;
116
+ try {
117
+ entries = fs.readdirSync(abs);
118
+ }
119
+ catch {
120
+ continue;
121
+ }
122
+ for (const name of entries.sort()) {
123
+ if (found.length >= MAX_ADRS)
124
+ return found;
125
+ if (!/\.md$/i.test(name))
126
+ continue;
127
+ // Index and template files are scaffolding, not decisions.
128
+ if (/^(readme|index|template|_template|0000)/i.test(name))
129
+ continue;
130
+ const filePath = path.join(abs, name);
131
+ const raw = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : "";
132
+ if (!raw.trim())
133
+ continue;
134
+ const rel = path.join(dir, name).replace(/\\/g, "/");
135
+ if (seen.has(rel))
136
+ continue;
137
+ seen.add(rel);
138
+ found.push({
139
+ rel,
140
+ title: titleOf(raw, name),
141
+ status: statusOf(raw),
142
+ date: dateOf(raw, filePath),
143
+ body: stripFrontMatter(raw).trim().slice(0, MAX_BODY_CHARS),
144
+ });
145
+ }
146
+ }
147
+ return found;
148
+ }
149
+ function slugify(title) {
150
+ return (title
151
+ .toLowerCase()
152
+ .replace(/[^a-z0-9]+/g, "-")
153
+ .replace(/^-+|-+$/g, "")
154
+ .slice(0, 60) || "adr");
155
+ }
156
+ /** Source paths already imported, read back from `source:` front matter. */
157
+ function importedSources(projectRoot) {
158
+ const sources = new Set();
159
+ for (const filename of (0, file_store_js_1.listFiles)("decisions", projectRoot)) {
160
+ const raw = (0, file_store_js_1.readFile)("decisions", filename, projectRoot) ?? "";
161
+ const m = raw.match(/^source:\s*(.+)$/m);
162
+ if (m)
163
+ sources.add(m[1].trim());
164
+ }
165
+ return sources;
166
+ }
167
+ /**
168
+ * Copy discovered ADRs into decisions/. Each imported entry records `source:`,
169
+ * so re-running is safe: an ADR already imported is skipped rather than
170
+ * duplicated. Entries are marked `generated: true` — they are derived, and a
171
+ * human editing them would lose the edit on the next import.
172
+ */
173
+ function importAdrs(projectRoot) {
174
+ const already = importedSources(projectRoot);
175
+ const imported = [];
176
+ let skipped = 0;
177
+ for (const adr of findAdrs(projectRoot)) {
178
+ if (already.has(adr.rel)) {
179
+ skipped += 1;
180
+ continue;
181
+ }
182
+ const filename = `${adr.date}-${slugify(adr.title)}.md`;
183
+ const summary = adr.status
184
+ ? `${adr.status} — imported from ${adr.rel}`
185
+ : `Imported from ${adr.rel}`;
186
+ const front = [
187
+ "---",
188
+ `date: ${adr.date}`,
189
+ `summary: ${summary}`,
190
+ "tags: [adr, imported]",
191
+ `source: ${adr.rel}`,
192
+ "generated: true",
193
+ "---",
194
+ "",
195
+ ].join("\n");
196
+ (0, file_store_js_1.writeFile)("decisions", filename, `${front}# ${adr.title}\n\n${adr.body}\n`, {}, projectRoot);
197
+ imported.push(`decisions/${filename}`);
198
+ }
199
+ return { imported, skipped };
200
+ }
201
+ //# sourceMappingURL=adr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adr.js","sourceRoot":"","sources":["../../src/store/adr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export interface CaptureMarker {
2
+ at: string;
3
+ /** Digest of the uncommitted file set at the last capture. */
4
+ fingerprint: string;
5
+ /**
6
+ * HEAD at the last capture. Commits are counted as `head..HEAD`, which is
7
+ * exact — `--since` only resolves to the minute, so a commit made in the same
8
+ * minute as the marker looks new on every later run.
9
+ */
10
+ head?: string;
11
+ }
12
+ export declare function readMarker(projectRoot: string): CaptureMarker;
13
+ /**
14
+ * Record that capture ran. The cache is gitignored — a marker is local state
15
+ * about this machine, not memory to share with the team.
16
+ */
17
+ export declare function writeMarker(projectRoot: string, marker: CaptureMarker): void;
18
+ export interface CapturePlan {
19
+ since: string;
20
+ summary: string;
21
+ /** False when there is nothing new — capture must then write nothing at all. */
22
+ worthWriting: boolean;
23
+ /** Marker to persist once the capture has been written. */
24
+ marker: CaptureMarker;
25
+ }
26
+ /**
27
+ * What an unattended capture would record.
28
+ *
29
+ * Commits are events: anything inside the window is new by definition. Uncommitted
30
+ * files are *state* — they survive from one capture to the next, so writing a
31
+ * session every time any exist would fill sessions/ with near-identical files.
32
+ * They therefore only justify a capture when the set has actually changed, which
33
+ * is what the fingerprint tracks.
34
+ *
35
+ * A summary assembled from git facts is a poor substitute for one written with
36
+ * judgement, so it says so plainly rather than pretending to understand the work.
37
+ */
38
+ export declare function planCapture(projectRoot: string, now?: Date): CapturePlan;
39
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/store/capture.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAc7D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAQ5E;AAOD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,YAAY,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,MAAM,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,WAAW,CAqCpF"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readMarker = readMarker;
37
+ exports.writeMarker = writeMarker;
38
+ exports.planCapture = planCapture;
39
+ /**
40
+ * Unattended session capture.
41
+ *
42
+ * repomem's oldest gap is that nothing is recorded unless someone remembers to
43
+ * ask. MCP servers are passive, so the fix cannot live in the server — it has to
44
+ * be something the harness fires. `repomem capture` is that something: a
45
+ * standalone command an agent hook (or a cron, or a shell alias) can run to
46
+ * record what happened, with no model in the loop.
47
+ *
48
+ * It runs in its own process, so it has no session to measure from. A marker
49
+ * under .repomem/.cache/ records when it last ran, and that becomes the window.
50
+ */
51
+ const crypto = __importStar(require("crypto"));
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const file_store_js_1 = require("./file-store.js");
55
+ const git_js_1 = require("./git.js");
56
+ const MARKER = "last-capture.json";
57
+ /** First run has no marker. Look back far enough to catch a day's work. */
58
+ const COLD_START_HOURS = 12;
59
+ function cacheDir(projectRoot) {
60
+ return path.join((0, file_store_js_1.getRepomemRoot)(projectRoot), ".cache");
61
+ }
62
+ /** Format for git's --since and our own front matter: "YYYY-MM-DD HH:MM". */
63
+ function stamp(d) {
64
+ const pad = (n) => String(n).padStart(2, "0");
65
+ return (`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
66
+ `${pad(d.getHours())}:${pad(d.getMinutes())}`);
67
+ }
68
+ function readMarker(projectRoot) {
69
+ try {
70
+ const raw = fs.readFileSync(path.join(cacheDir(projectRoot), MARKER), "utf8");
71
+ const parsed = JSON.parse(raw);
72
+ if (parsed.at) {
73
+ return { at: parsed.at, fingerprint: parsed.fingerprint ?? "", head: parsed.head };
74
+ }
75
+ }
76
+ catch {
77
+ /* never captured here, or the marker is unreadable */
78
+ }
79
+ return {
80
+ at: stamp(new Date(Date.now() - COLD_START_HOURS * 60 * 60 * 1000)),
81
+ fingerprint: "",
82
+ };
83
+ }
84
+ /**
85
+ * Record that capture ran. The cache is gitignored — a marker is local state
86
+ * about this machine, not memory to share with the team.
87
+ */
88
+ function writeMarker(projectRoot, marker) {
89
+ const dir = cacheDir(projectRoot);
90
+ fs.mkdirSync(dir, { recursive: true });
91
+ const gitignore = path.join(dir, ".gitignore");
92
+ if (!fs.existsSync(gitignore)) {
93
+ fs.writeFileSync(gitignore, "# repomem local cache — do not commit\n*\n", "utf8");
94
+ }
95
+ fs.writeFileSync(path.join(dir, MARKER), JSON.stringify(marker, null, 2) + "\n", "utf8");
96
+ }
97
+ function fingerprintOf(changed) {
98
+ if (!changed.length)
99
+ return "";
100
+ return crypto.createHash("sha1").update([...changed].sort().join("\n")).digest("hex");
101
+ }
102
+ /**
103
+ * What an unattended capture would record.
104
+ *
105
+ * Commits are events: anything inside the window is new by definition. Uncommitted
106
+ * files are *state* — they survive from one capture to the next, so writing a
107
+ * session every time any exist would fill sessions/ with near-identical files.
108
+ * They therefore only justify a capture when the set has actually changed, which
109
+ * is what the fingerprint tracks.
110
+ *
111
+ * A summary assembled from git facts is a poor substitute for one written with
112
+ * judgement, so it says so plainly rather than pretending to understand the work.
113
+ */
114
+ function planCapture(projectRoot, now = new Date()) {
115
+ const previous = readMarker(projectRoot);
116
+ const activity = (0, git_js_1.activitySince)(previous.at, projectRoot, previous.head);
117
+ const fingerprint = fingerprintOf(activity?.changed ?? []);
118
+ const marker = {
119
+ at: stamp(now),
120
+ fingerprint,
121
+ head: (0, git_js_1.headHash)(projectRoot) ?? undefined,
122
+ };
123
+ if (!activity)
124
+ return { since: previous.at, summary: "", worthWriting: false, marker };
125
+ const newCommits = activity.commits.length > 0;
126
+ const changedSet = activity.changed.length > 0 && fingerprint !== previous.fingerprint;
127
+ if (!newCommits && !changedSet) {
128
+ return { since: previous.at, summary: "", worthWriting: false, marker };
129
+ }
130
+ const parts = [];
131
+ if (activity.commits.length) {
132
+ const n = activity.commits.length + activity.moreCommits;
133
+ parts.push(`${n} commit${n === 1 ? "" : "s"}`);
134
+ }
135
+ if (activity.changed.length) {
136
+ const n = activity.changed.length + activity.moreChanged;
137
+ parts.push(`${n} file${n === 1 ? "" : "s"} left uncommitted`);
138
+ }
139
+ return {
140
+ since: previous.at,
141
+ summary: `Auto-captured from git — ${parts.join(", ")}` +
142
+ `${activity.branch ? ` on ${activity.branch}` : ""}. ` +
143
+ "No summary was written by hand, so the intent behind this work is not recorded.",
144
+ worthWriting: true,
145
+ marker,
146
+ };
147
+ }
148
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/store/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { SemanticConfig } from "../config/config.js";
2
+ export interface EmbeddingCache {
3
+ /** Which provider and model produced these vectors; a change invalidates all. */
4
+ signature: string;
5
+ entries: Record<string, {
6
+ hash: string;
7
+ vector: number[];
8
+ }>;
9
+ }
10
+ export declare function readCache(projectRoot: string): EmbeddingCache | null;
11
+ export declare function embed(text: string, config: SemanticConfig): Promise<number[]>;
12
+ export declare function cosine(a: number[], b: number[]): number;
13
+ export interface IndexResult {
14
+ embedded: number;
15
+ reused: number;
16
+ removed: number;
17
+ failed: string[];
18
+ }
19
+ /**
20
+ * Bring the vector cache up to date. Only entries whose content hash changed are
21
+ * re-embedded, so a second run over an unchanged repo makes no provider calls.
22
+ */
23
+ export declare function buildIndex(projectRoot: string, config: SemanticConfig): Promise<IndexResult>;
24
+ /**
25
+ * Cosine similarity of every cached entry against the query, keyed "type/filename".
26
+ *
27
+ * Returns an empty map — never throws — when semantic search is off, the cache is
28
+ * missing or stale, or the provider is unreachable. Search degrading to BM25 is
29
+ * always better than search failing.
30
+ */
31
+ export declare function semanticScores(query: string, projectRoot: string, config: SemanticConfig): Promise<Map<string, number>>;
32
+ /** Scale scores to 0–1 so lexical and semantic ranks can be blended fairly. */
33
+ export declare function normalise(scores: Map<string, number>): Map<string, number>;
34
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/store/embeddings.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAQrD,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D;AAcD,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAQpE;AAiED,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAInF;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAYvD;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,WAAW,CAAC,CAyCtB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiB9B;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAO1E"}