vemora 0.1.0-alpha.15

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 (254) hide show
  1. package/README.md +851 -0
  2. package/dist/cli.d.ts +16 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +682 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/ask.d.ts +14 -0
  7. package/dist/commands/ask.d.ts.map +1 -0
  8. package/dist/commands/ask.js +137 -0
  9. package/dist/commands/ask.js.map +1 -0
  10. package/dist/commands/audit.d.ts +17 -0
  11. package/dist/commands/audit.d.ts.map +1 -0
  12. package/dist/commands/audit.js +398 -0
  13. package/dist/commands/audit.js.map +1 -0
  14. package/dist/commands/brief.d.ts +16 -0
  15. package/dist/commands/brief.d.ts.map +1 -0
  16. package/dist/commands/brief.js +84 -0
  17. package/dist/commands/brief.js.map +1 -0
  18. package/dist/commands/chat.d.ts +7 -0
  19. package/dist/commands/chat.d.ts.map +1 -0
  20. package/dist/commands/chat.js +155 -0
  21. package/dist/commands/chat.js.map +1 -0
  22. package/dist/commands/context.d.ts +63 -0
  23. package/dist/commands/context.d.ts.map +1 -0
  24. package/dist/commands/context.js +794 -0
  25. package/dist/commands/context.js.map +1 -0
  26. package/dist/commands/dead-code.d.ts +15 -0
  27. package/dist/commands/dead-code.d.ts.map +1 -0
  28. package/dist/commands/dead-code.js +206 -0
  29. package/dist/commands/dead-code.js.map +1 -0
  30. package/dist/commands/deps.d.ts +20 -0
  31. package/dist/commands/deps.d.ts.map +1 -0
  32. package/dist/commands/deps.js +138 -0
  33. package/dist/commands/deps.js.map +1 -0
  34. package/dist/commands/focus.d.ts +8 -0
  35. package/dist/commands/focus.d.ts.map +1 -0
  36. package/dist/commands/focus.js +310 -0
  37. package/dist/commands/focus.js.map +1 -0
  38. package/dist/commands/index.d.ts +10 -0
  39. package/dist/commands/index.d.ts.map +1 -0
  40. package/dist/commands/index.js +366 -0
  41. package/dist/commands/index.js.map +1 -0
  42. package/dist/commands/init-agent.d.ts +23 -0
  43. package/dist/commands/init-agent.d.ts.map +1 -0
  44. package/dist/commands/init-agent.js +384 -0
  45. package/dist/commands/init-agent.js.map +1 -0
  46. package/dist/commands/init.d.ts +2 -0
  47. package/dist/commands/init.d.ts.map +1 -0
  48. package/dist/commands/init.js +122 -0
  49. package/dist/commands/init.js.map +1 -0
  50. package/dist/commands/knowledge.d.ts +14 -0
  51. package/dist/commands/knowledge.d.ts.map +1 -0
  52. package/dist/commands/knowledge.js +115 -0
  53. package/dist/commands/knowledge.js.map +1 -0
  54. package/dist/commands/plan.d.ts +24 -0
  55. package/dist/commands/plan.d.ts.map +1 -0
  56. package/dist/commands/plan.js +867 -0
  57. package/dist/commands/plan.js.map +1 -0
  58. package/dist/commands/query.d.ts +39 -0
  59. package/dist/commands/query.d.ts.map +1 -0
  60. package/dist/commands/query.js +392 -0
  61. package/dist/commands/query.js.map +1 -0
  62. package/dist/commands/remember.d.ts +11 -0
  63. package/dist/commands/remember.d.ts.map +1 -0
  64. package/dist/commands/remember.js +267 -0
  65. package/dist/commands/remember.js.map +1 -0
  66. package/dist/commands/report.d.ts +10 -0
  67. package/dist/commands/report.d.ts.map +1 -0
  68. package/dist/commands/report.js +243 -0
  69. package/dist/commands/report.js.map +1 -0
  70. package/dist/commands/status.d.ts +2 -0
  71. package/dist/commands/status.d.ts.map +1 -0
  72. package/dist/commands/status.js +127 -0
  73. package/dist/commands/status.js.map +1 -0
  74. package/dist/commands/summarize.d.ts +14 -0
  75. package/dist/commands/summarize.d.ts.map +1 -0
  76. package/dist/commands/summarize.js +170 -0
  77. package/dist/commands/summarize.js.map +1 -0
  78. package/dist/commands/triage.d.ts +33 -0
  79. package/dist/commands/triage.d.ts.map +1 -0
  80. package/dist/commands/triage.js +419 -0
  81. package/dist/commands/triage.js.map +1 -0
  82. package/dist/commands/usages.d.ts +14 -0
  83. package/dist/commands/usages.d.ts.map +1 -0
  84. package/dist/commands/usages.js +236 -0
  85. package/dist/commands/usages.js.map +1 -0
  86. package/dist/core/config.d.ts +35 -0
  87. package/dist/core/config.d.ts.map +1 -0
  88. package/dist/core/config.js +159 -0
  89. package/dist/core/config.js.map +1 -0
  90. package/dist/core/types.d.ts +287 -0
  91. package/dist/core/types.d.ts.map +1 -0
  92. package/dist/core/types.js +4 -0
  93. package/dist/core/types.js.map +1 -0
  94. package/dist/embeddings/factory.d.ts +9 -0
  95. package/dist/embeddings/factory.d.ts.map +1 -0
  96. package/dist/embeddings/factory.js +26 -0
  97. package/dist/embeddings/factory.js.map +1 -0
  98. package/dist/embeddings/noop.d.ts +17 -0
  99. package/dist/embeddings/noop.d.ts.map +1 -0
  100. package/dist/embeddings/noop.js +22 -0
  101. package/dist/embeddings/noop.js.map +1 -0
  102. package/dist/embeddings/ollama.d.ts +11 -0
  103. package/dist/embeddings/ollama.d.ts.map +1 -0
  104. package/dist/embeddings/ollama.js +49 -0
  105. package/dist/embeddings/ollama.js.map +1 -0
  106. package/dist/embeddings/openai.d.ts +10 -0
  107. package/dist/embeddings/openai.d.ts.map +1 -0
  108. package/dist/embeddings/openai.js +67 -0
  109. package/dist/embeddings/openai.js.map +1 -0
  110. package/dist/embeddings/provider.d.ts +19 -0
  111. package/dist/embeddings/provider.d.ts.map +1 -0
  112. package/dist/embeddings/provider.js +3 -0
  113. package/dist/embeddings/provider.js.map +1 -0
  114. package/dist/indexer/callgraph.d.ts +16 -0
  115. package/dist/indexer/callgraph.d.ts.map +1 -0
  116. package/dist/indexer/callgraph.js +154 -0
  117. package/dist/indexer/callgraph.js.map +1 -0
  118. package/dist/indexer/chunkBySlidingWindow.d.ts +6 -0
  119. package/dist/indexer/chunkBySlidingWindow.d.ts.map +1 -0
  120. package/dist/indexer/chunkBySlidingWindow.js +30 -0
  121. package/dist/indexer/chunkBySlidingWindow.js.map +1 -0
  122. package/dist/indexer/chunkBySymbols.d.ts +7 -0
  123. package/dist/indexer/chunkBySymbols.d.ts.map +1 -0
  124. package/dist/indexer/chunkBySymbols.js +57 -0
  125. package/dist/indexer/chunkBySymbols.js.map +1 -0
  126. package/dist/indexer/chunker.d.ts +15 -0
  127. package/dist/indexer/chunker.d.ts.map +1 -0
  128. package/dist/indexer/chunker.js +26 -0
  129. package/dist/indexer/chunker.js.map +1 -0
  130. package/dist/indexer/classHeader.d.ts +7 -0
  131. package/dist/indexer/classHeader.d.ts.map +1 -0
  132. package/dist/indexer/classHeader.js +37 -0
  133. package/dist/indexer/classHeader.js.map +1 -0
  134. package/dist/indexer/deps.d.ts +66 -0
  135. package/dist/indexer/deps.d.ts.map +1 -0
  136. package/dist/indexer/deps.js +412 -0
  137. package/dist/indexer/deps.js.map +1 -0
  138. package/dist/indexer/hasher.d.ts +17 -0
  139. package/dist/indexer/hasher.d.ts.map +1 -0
  140. package/dist/indexer/hasher.js +38 -0
  141. package/dist/indexer/hasher.js.map +1 -0
  142. package/dist/indexer/parser.d.ts +18 -0
  143. package/dist/indexer/parser.d.ts.map +1 -0
  144. package/dist/indexer/parser.js +355 -0
  145. package/dist/indexer/parser.js.map +1 -0
  146. package/dist/indexer/scanner.d.ts +18 -0
  147. package/dist/indexer/scanner.d.ts.map +1 -0
  148. package/dist/indexer/scanner.js +37 -0
  149. package/dist/indexer/scanner.js.map +1 -0
  150. package/dist/indexer/strategy.d.ts +11 -0
  151. package/dist/indexer/strategy.d.ts.map +1 -0
  152. package/dist/indexer/strategy.js +15 -0
  153. package/dist/indexer/strategy.js.map +1 -0
  154. package/dist/indexer/tests.d.ts +15 -0
  155. package/dist/indexer/tests.d.ts.map +1 -0
  156. package/dist/indexer/tests.js +68 -0
  157. package/dist/indexer/tests.js.map +1 -0
  158. package/dist/indexer/todos.d.ts +9 -0
  159. package/dist/indexer/todos.d.ts.map +1 -0
  160. package/dist/indexer/todos.js +29 -0
  161. package/dist/indexer/todos.js.map +1 -0
  162. package/dist/llm/anthropic.d.ts +8 -0
  163. package/dist/llm/anthropic.d.ts.map +1 -0
  164. package/dist/llm/anthropic.js +76 -0
  165. package/dist/llm/anthropic.js.map +1 -0
  166. package/dist/llm/claude-code.d.ts +37 -0
  167. package/dist/llm/claude-code.d.ts.map +1 -0
  168. package/dist/llm/claude-code.js +97 -0
  169. package/dist/llm/claude-code.js.map +1 -0
  170. package/dist/llm/factory.d.ts +7 -0
  171. package/dist/llm/factory.d.ts.map +1 -0
  172. package/dist/llm/factory.js +47 -0
  173. package/dist/llm/factory.js.map +1 -0
  174. package/dist/llm/ollama.d.ts +8 -0
  175. package/dist/llm/ollama.d.ts.map +1 -0
  176. package/dist/llm/ollama.js +83 -0
  177. package/dist/llm/ollama.js.map +1 -0
  178. package/dist/llm/openai.d.ts +8 -0
  179. package/dist/llm/openai.d.ts.map +1 -0
  180. package/dist/llm/openai.js +68 -0
  181. package/dist/llm/openai.js.map +1 -0
  182. package/dist/llm/provider.d.ts +35 -0
  183. package/dist/llm/provider.d.ts.map +1 -0
  184. package/dist/llm/provider.js +3 -0
  185. package/dist/llm/provider.js.map +1 -0
  186. package/dist/search/bm25.d.ts +3 -0
  187. package/dist/search/bm25.d.ts.map +1 -0
  188. package/dist/search/bm25.js +104 -0
  189. package/dist/search/bm25.js.map +1 -0
  190. package/dist/search/formatter.d.ts +43 -0
  191. package/dist/search/formatter.d.ts.map +1 -0
  192. package/dist/search/formatter.js +208 -0
  193. package/dist/search/formatter.js.map +1 -0
  194. package/dist/search/hybrid.d.ts +10 -0
  195. package/dist/search/hybrid.d.ts.map +1 -0
  196. package/dist/search/hybrid.js +53 -0
  197. package/dist/search/hybrid.js.map +1 -0
  198. package/dist/search/merge.d.ts +33 -0
  199. package/dist/search/merge.d.ts.map +1 -0
  200. package/dist/search/merge.js +158 -0
  201. package/dist/search/merge.js.map +1 -0
  202. package/dist/search/mmr.d.ts +23 -0
  203. package/dist/search/mmr.d.ts.map +1 -0
  204. package/dist/search/mmr.js +95 -0
  205. package/dist/search/mmr.js.map +1 -0
  206. package/dist/search/rerank.d.ts +12 -0
  207. package/dist/search/rerank.d.ts.map +1 -0
  208. package/dist/search/rerank.js +113 -0
  209. package/dist/search/rerank.js.map +1 -0
  210. package/dist/search/signature.d.ts +42 -0
  211. package/dist/search/signature.d.ts.map +1 -0
  212. package/dist/search/signature.js +112 -0
  213. package/dist/search/signature.js.map +1 -0
  214. package/dist/search/vector.d.ts +41 -0
  215. package/dist/search/vector.d.ts.map +1 -0
  216. package/dist/search/vector.js +185 -0
  217. package/dist/search/vector.js.map +1 -0
  218. package/dist/storage/cache.d.ts +30 -0
  219. package/dist/storage/cache.d.ts.map +1 -0
  220. package/dist/storage/cache.js +160 -0
  221. package/dist/storage/cache.js.map +1 -0
  222. package/dist/storage/knowledge.d.ts +23 -0
  223. package/dist/storage/knowledge.d.ts.map +1 -0
  224. package/dist/storage/knowledge.js +81 -0
  225. package/dist/storage/knowledge.js.map +1 -0
  226. package/dist/storage/planSession.d.ts +39 -0
  227. package/dist/storage/planSession.d.ts.map +1 -0
  228. package/dist/storage/planSession.js +78 -0
  229. package/dist/storage/planSession.js.map +1 -0
  230. package/dist/storage/repository.d.ts +27 -0
  231. package/dist/storage/repository.d.ts.map +1 -0
  232. package/dist/storage/repository.js +95 -0
  233. package/dist/storage/repository.js.map +1 -0
  234. package/dist/storage/session.d.ts +38 -0
  235. package/dist/storage/session.d.ts.map +1 -0
  236. package/dist/storage/session.js +100 -0
  237. package/dist/storage/session.js.map +1 -0
  238. package/dist/storage/summaries.d.ts +19 -0
  239. package/dist/storage/summaries.d.ts.map +1 -0
  240. package/dist/storage/summaries.js +66 -0
  241. package/dist/storage/summaries.js.map +1 -0
  242. package/dist/storage/usage.d.ts +39 -0
  243. package/dist/storage/usage.d.ts.map +1 -0
  244. package/dist/storage/usage.js +55 -0
  245. package/dist/storage/usage.js.map +1 -0
  246. package/dist/utils/git.d.ts +20 -0
  247. package/dist/utils/git.d.ts.map +1 -0
  248. package/dist/utils/git.js +49 -0
  249. package/dist/utils/git.js.map +1 -0
  250. package/dist/utils/tokenizer.d.ts +32 -0
  251. package/dist/utils/tokenizer.d.ts.map +1 -0
  252. package/dist/utils/tokenizer.js +66 -0
  253. package/dist/utils/tokenizer.js.map +1 -0
  254. package/package.json +71 -0
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SessionStorage = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const config_1 = require("../core/config");
11
+ // ─── Constants ────────────────────────────────────────────────────────────────
12
+ /** Idle duration after which a session is considered expired (30 min) */
13
+ const SESSION_TIMEOUT_MS = 30 * 60 * 1000;
14
+ const SESSION_FILE = "session.json";
15
+ // ─── Storage ──────────────────────────────────────────────────────────────────
16
+ /**
17
+ * Manages per-project session memory stored in the local developer cache.
18
+ *
19
+ * The session tracks which chunk IDs have been returned to the LLM so that
20
+ * subsequent queries can skip already-seen chunks. Sessions auto-expire after
21
+ * 30 minutes of idle time.
22
+ *
23
+ * Stored in ~/.vemora-cache/<projectId>/session.json — never in the repo.
24
+ */
25
+ class SessionStorage {
26
+ filePath;
27
+ constructor(projectId) {
28
+ const dir = (0, config_1.getLocalCacheDir)(projectId);
29
+ this.filePath = path_1.default.join(dir, SESSION_FILE);
30
+ }
31
+ load() {
32
+ if (!fs_1.default.existsSync(this.filePath))
33
+ return null;
34
+ try {
35
+ return JSON.parse(fs_1.default.readFileSync(this.filePath, "utf-8"));
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /**
42
+ * Returns the active session, or creates a new one if expired or absent.
43
+ * A session expires after SESSION_TIMEOUT_MS of inactivity.
44
+ */
45
+ loadOrCreate() {
46
+ const existing = this.load();
47
+ if (existing) {
48
+ const idle = Date.now() - new Date(existing.lastActiveAt).getTime();
49
+ if (idle < 0 || idle < SESSION_TIMEOUT_MS)
50
+ return existing;
51
+ }
52
+ return this.newSession();
53
+ }
54
+ newSession() {
55
+ return {
56
+ sessionId: crypto_1.default.randomBytes(8).toString("hex"),
57
+ lastActiveAt: new Date().toISOString(),
58
+ seenChunkIds: [],
59
+ };
60
+ }
61
+ saveState(state) {
62
+ const dir = path_1.default.dirname(this.filePath);
63
+ if (!fs_1.default.existsSync(dir))
64
+ fs_1.default.mkdirSync(dir, { recursive: true });
65
+ const tmp = this.filePath + ".tmp";
66
+ fs_1.default.writeFileSync(tmp, JSON.stringify(state), "utf-8");
67
+ fs_1.default.renameSync(tmp, this.filePath);
68
+ }
69
+ /** Resets the session to a clean state (new session ID, empty seen list). */
70
+ reset() {
71
+ const fresh = this.newSession();
72
+ this.saveState(fresh);
73
+ return fresh;
74
+ }
75
+ /**
76
+ * Adds chunk IDs to the seen set and refreshes the session timestamp.
77
+ * Creates or continues the current session as needed.
78
+ */
79
+ markSeen(chunkIds) {
80
+ const state = this.loadOrCreate();
81
+ const seen = new Set(state.seenChunkIds);
82
+ for (const id of chunkIds)
83
+ seen.add(id);
84
+ state.seenChunkIds = Array.from(seen);
85
+ state.lastActiveAt = new Date().toISOString();
86
+ this.saveState(state);
87
+ }
88
+ /** Returns the set of chunk IDs seen in the current (unexpired) session. */
89
+ getSeenIds() {
90
+ const state = this.load();
91
+ if (!state)
92
+ return new Set();
93
+ const idle = Date.now() - new Date(state.lastActiveAt).getTime();
94
+ if (idle >= SESSION_TIMEOUT_MS)
95
+ return new Set();
96
+ return new Set(state.seenChunkIds);
97
+ }
98
+ }
99
+ exports.SessionStorage = SessionStorage;
100
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/storage/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { FileSummaryIndex, ProjectSummary } from "../core/types";
2
+ /**
3
+ * Reads and writes LLM-generated summary files stored in .vemora/summaries/.
4
+ * These files are committed to git so the whole team shares the same summaries.
5
+ */
6
+ export declare class SummaryStorage {
7
+ private summariesDir;
8
+ constructor(rootDir: string);
9
+ loadFileSummaries(): FileSummaryIndex;
10
+ saveFileSummaries(index: FileSummaryIndex): void;
11
+ loadProjectSummary(): ProjectSummary | null;
12
+ saveProjectSummary(summary: ProjectSummary): void;
13
+ hasFileSummaries(): boolean;
14
+ hasProjectSummary(): boolean;
15
+ getSummariesDir(): string;
16
+ private readJson;
17
+ private writeJson;
18
+ }
19
+ //# sourceMappingURL=summaries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summaries.d.ts","sourceRoot":"","sources":["../../src/storage/summaries.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEtE;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,OAAO,EAAE,MAAM;IAM3B,iBAAiB,IAAI,gBAAgB;IAOrC,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAMhD,kBAAkB,IAAI,cAAc,GAAG,IAAI;IAM3C,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAMjD,gBAAgB,IAAI,OAAO;IAI3B,iBAAiB,IAAI,OAAO;IAI5B,eAAe,IAAI,MAAM;IAMzB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,SAAS;CAOlB"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SummaryStorage = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const config_1 = require("../core/config");
10
+ /**
11
+ * Reads and writes LLM-generated summary files stored in .vemora/summaries/.
12
+ * These files are committed to git so the whole team shares the same summaries.
13
+ */
14
+ class SummaryStorage {
15
+ summariesDir;
16
+ constructor(rootDir) {
17
+ this.summariesDir = path_1.default.join(rootDir, config_1.AI_MEMORY_DIR, config_1.SUMMARIES_DIR);
18
+ }
19
+ // ─── File Summaries ──────────────────────────────────────────────────────────
20
+ loadFileSummaries() {
21
+ return this.readJson(path_1.default.join(this.summariesDir, config_1.FILE_SUMMARIES_JSON), {});
22
+ }
23
+ saveFileSummaries(index) {
24
+ this.writeJson(path_1.default.join(this.summariesDir, config_1.FILE_SUMMARIES_JSON), index);
25
+ }
26
+ // ─── Project Summary ─────────────────────────────────────────────────────────
27
+ loadProjectSummary() {
28
+ const p = path_1.default.join(this.summariesDir, config_1.PROJECT_SUMMARY_JSON);
29
+ if (!fs_1.default.existsSync(p))
30
+ return null;
31
+ return this.readJson(p, null);
32
+ }
33
+ saveProjectSummary(summary) {
34
+ this.writeJson(path_1.default.join(this.summariesDir, config_1.PROJECT_SUMMARY_JSON), summary);
35
+ }
36
+ // ─── Status helpers ───────────────────────────────────────────────────────────
37
+ hasFileSummaries() {
38
+ return fs_1.default.existsSync(path_1.default.join(this.summariesDir, config_1.FILE_SUMMARIES_JSON));
39
+ }
40
+ hasProjectSummary() {
41
+ return fs_1.default.existsSync(path_1.default.join(this.summariesDir, config_1.PROJECT_SUMMARY_JSON));
42
+ }
43
+ getSummariesDir() {
44
+ return this.summariesDir;
45
+ }
46
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
47
+ readJson(filePath, fallback) {
48
+ if (!fs_1.default.existsSync(filePath))
49
+ return fallback;
50
+ try {
51
+ return JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
52
+ }
53
+ catch {
54
+ return fallback;
55
+ }
56
+ }
57
+ writeJson(filePath, data) {
58
+ const dir = path_1.default.dirname(filePath);
59
+ fs_1.default.mkdirSync(dir, { recursive: true });
60
+ const tmp = filePath + ".tmp";
61
+ fs_1.default.writeFileSync(tmp, JSON.stringify(data), "utf-8");
62
+ fs_1.default.renameSync(tmp, filePath);
63
+ }
64
+ }
65
+ exports.SummaryStorage = SummaryStorage;
66
+ //# sourceMappingURL=summaries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summaries.js","sourceRoot":"","sources":["../../src/storage/summaries.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,2CAKwB;AAGxB;;;GAGG;AACH,MAAa,cAAc;IACjB,YAAY,CAAS;IAE7B,YAAY,OAAe;QACzB,IAAI,CAAC,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAa,EAAE,sBAAa,CAAC,CAAC;IACvE,CAAC;IAED,gFAAgF;IAEhF,iBAAiB;QACf,OAAO,IAAI,CAAC,QAAQ,CAClB,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,4BAAmB,CAAC,EACjD,EAAE,CACH,CAAC;IACJ,CAAC;IAED,iBAAiB,CAAC,KAAuB;QACvC,IAAI,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,4BAAmB,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,gFAAgF;IAEhF,kBAAkB;QAChB,MAAM,CAAC,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,6BAAoB,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAiB,CAAC,EAAE,IAAiC,CAAC,CAAC;IAC7E,CAAC;IAED,kBAAkB,CAAC,OAAuB;QACxC,IAAI,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,6BAAoB,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,iFAAiF;IAEjF,gBAAgB;QACd,OAAO,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,4BAAmB,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,iBAAiB;QACf,OAAO,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,6BAAoB,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,gFAAgF;IAExE,QAAQ,CAAI,QAAgB,EAAE,QAAW;QAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC9C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAM,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,QAAgB,EAAE,IAAa;QAC/C,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,QAAQ,GAAG,MAAM,CAAC;QAC9B,YAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACrD,YAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC/B,CAAC;CACF;AAhED,wCAgEC"}
@@ -0,0 +1,39 @@
1
+ export interface UsageEvent {
2
+ /** ISO timestamp of the query */
3
+ ts: string;
4
+ command: "query" | "context" | "ask";
5
+ /** Query text, truncated to 120 chars */
6
+ query?: string;
7
+ searchType: "vector" | "bm25" | "hybrid" | "symbol" | "none";
8
+ format?: string;
9
+ /** Top-K requested */
10
+ topK: number;
11
+ /** Chunks actually returned to the caller */
12
+ resultsReturned: number;
13
+ /** Estimated tokens in returned chunks */
14
+ tokensReturned: number;
15
+ /** Tokens saved by semantic deduplication (0 if dedup didn't fire) */
16
+ tokensSavedDedup: number;
17
+ /** Tokens saved by session filter (0 if --session not active) */
18
+ tokensSavedSession: number;
19
+ /** Tokens saved by budget cap (0 if --budget not set) */
20
+ tokensSavedBudget: number;
21
+ /** Wall-clock milliseconds from search start to results ready */
22
+ durationMs?: number;
23
+ /** Up to 3 unique file paths present in the returned chunks */
24
+ topFiles?: string[];
25
+ }
26
+ /**
27
+ * Append-only log of usage events stored in the local developer cache.
28
+ * Never committed to git — per-developer analytics only.
29
+ *
30
+ * Stored in ~/.vemora-cache/<projectId>/usage.log.json
31
+ */
32
+ export declare class UsageStorage {
33
+ private filePath;
34
+ constructor(projectId: string);
35
+ load(): UsageEvent[];
36
+ append(event: UsageEvent): void;
37
+ clear(): void;
38
+ }
39
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/storage/usage.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC;IACrC,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAUD;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAEb,SAAS,EAAE,MAAM;IAK7B,IAAI,IAAI,UAAU,EAAE;IASpB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAa/B,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.UsageStorage = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const config_1 = require("../core/config");
10
+ // ─── Constants ────────────────────────────────────────────────────────────────
11
+ const USAGE_FILE = "usage.log.json";
12
+ /** Maximum events to retain (rolling buffer) */
13
+ const MAX_EVENTS = 2000;
14
+ // ─── Storage ──────────────────────────────────────────────────────────────────
15
+ /**
16
+ * Append-only log of usage events stored in the local developer cache.
17
+ * Never committed to git — per-developer analytics only.
18
+ *
19
+ * Stored in ~/.vemora-cache/<projectId>/usage.log.json
20
+ */
21
+ class UsageStorage {
22
+ filePath;
23
+ constructor(projectId) {
24
+ const dir = (0, config_1.getLocalCacheDir)(projectId);
25
+ this.filePath = path_1.default.join(dir, USAGE_FILE);
26
+ }
27
+ load() {
28
+ if (!fs_1.default.existsSync(this.filePath))
29
+ return [];
30
+ try {
31
+ return JSON.parse(fs_1.default.readFileSync(this.filePath, "utf-8"));
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+ append(event) {
38
+ const events = this.load();
39
+ events.push(event);
40
+ // Keep only the most recent MAX_EVENTS
41
+ const pruned = events.length > MAX_EVENTS ? events.slice(-MAX_EVENTS) : events;
42
+ const dir = path_1.default.dirname(this.filePath);
43
+ if (!fs_1.default.existsSync(dir))
44
+ fs_1.default.mkdirSync(dir, { recursive: true });
45
+ const tmp = this.filePath + ".tmp";
46
+ fs_1.default.writeFileSync(tmp, JSON.stringify(pruned), "utf-8");
47
+ fs_1.default.renameSync(tmp, this.filePath);
48
+ }
49
+ clear() {
50
+ if (fs_1.default.existsSync(this.filePath))
51
+ fs_1.default.unlinkSync(this.filePath);
52
+ }
53
+ }
54
+ exports.UsageStorage = UsageStorage;
55
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/storage/usage.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,2CAAkD;AA8BlD,iFAAiF;AAEjF,MAAM,UAAU,GAAG,gBAAgB,CAAC;AACpC,gDAAgD;AAChD,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAa,YAAY;IACf,QAAQ,CAAS;IAEzB,YAAY,SAAiB;QAC3B,MAAM,GAAG,GAAG,IAAA,yBAAgB,EAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI;QACF,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAiB,CAAC;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAiB;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,uCAAuC;QACvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAE/E,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;QACnC,YAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;QACvD,YAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,KAAK;QACH,IAAI,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;CACF;AAjCD,oCAiCC"}
@@ -0,0 +1,20 @@
1
+ export interface GitCommit {
2
+ sha: string;
3
+ message: string;
4
+ author: string;
5
+ date: string;
6
+ }
7
+ /**
8
+ * Returns the N most recent git commits that touched a file.
9
+ * Returns [] if git is unavailable, the file has no history, or rootDir is not
10
+ * inside a git repository.
11
+ *
12
+ * Uses --follow so renames/moves are tracked across history.
13
+ */
14
+ /**
15
+ * Returns the list of files changed since a given git ref (commit, branch, tag).
16
+ * Returns [] if git is unavailable or the ref is invalid.
17
+ */
18
+ export declare function getChangedFiles(since: string, rootDir: string): string[];
19
+ export declare function getFileGitHistory(rootDir: string, relPath: string, maxCommits?: number): GitCommit[];
20
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQxE;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,SAAI,GACb,SAAS,EAAE,CA8Bb"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getChangedFiles = getChangedFiles;
4
+ exports.getFileGitHistory = getFileGitHistory;
5
+ const child_process_1 = require("child_process");
6
+ /**
7
+ * Returns the N most recent git commits that touched a file.
8
+ * Returns [] if git is unavailable, the file has no history, or rootDir is not
9
+ * inside a git repository.
10
+ *
11
+ * Uses --follow so renames/moves are tracked across history.
12
+ */
13
+ /**
14
+ * Returns the list of files changed since a given git ref (commit, branch, tag).
15
+ * Returns [] if git is unavailable or the ref is invalid.
16
+ */
17
+ function getChangedFiles(since, rootDir) {
18
+ const result = (0, child_process_1.spawnSync)("git", ["diff", "--name-only", since, "--", "."], { cwd: rootDir, encoding: "utf-8" });
19
+ if (result.status !== 0 || !result.stdout?.trim())
20
+ return [];
21
+ return result.stdout.trim().split("\n").filter(Boolean);
22
+ }
23
+ function getFileGitHistory(rootDir, relPath, maxCommits = 5) {
24
+ const SEP = "\x1f";
25
+ const result = (0, child_process_1.spawnSync)("git", [
26
+ "log",
27
+ `--max-count=${maxCommits}`,
28
+ `--format=%H${SEP}%s${SEP}%an${SEP}%ai`,
29
+ "--follow",
30
+ "--",
31
+ relPath,
32
+ ], { cwd: rootDir, encoding: "utf-8" });
33
+ if (result.status !== 0 || !result.stdout?.trim())
34
+ return [];
35
+ return result.stdout
36
+ .trim()
37
+ .split("\n")
38
+ .filter(Boolean)
39
+ .map((line) => {
40
+ const [sha, message, author, date] = line.split(SEP);
41
+ return {
42
+ sha: (sha ?? "").slice(0, 8),
43
+ message: (message ?? "").trim(),
44
+ author: (author ?? "").trim(),
45
+ date: (date ?? "").slice(0, 10),
46
+ };
47
+ });
48
+ }
49
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":";;AAoBA,0CAQC;AAED,8CAkCC;AAhED,iDAA0C;AAS1C;;;;;;GAMG;AACH;;;GAGG;AACH,SAAgB,eAAe,CAAC,KAAa,EAAE,OAAe;IAC5D,MAAM,MAAM,GAAG,IAAA,yBAAS,EACtB,KAAK,EACL,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,EACzC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CACpC,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,SAAgB,iBAAiB,CAC/B,OAAe,EACf,OAAe,EACf,UAAU,GAAG,CAAC;IAEd,MAAM,GAAG,GAAG,MAAM,CAAC;IACnB,MAAM,MAAM,GAAG,IAAA,yBAAS,EACtB,KAAK,EACL;QACE,KAAK;QACL,eAAe,UAAU,EAAE;QAC3B,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK;QACvC,UAAU;QACV,IAAI;QACJ,OAAO;KACR,EACD,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CACpC,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAE7D,OAAO,MAAM,CAAC,MAAM;SACjB,IAAI,EAAE;SACN,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrD,OAAO;YACL,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YAC/B,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YAC7B,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SAChC,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { SearchResult } from "../core/types";
2
+ /** Sums the estimated token count across a list of search results. */
3
+ export declare function sumResultTokens(results: SearchResult[]): number;
4
+ /**
5
+ * Heuristic-based token counting.
6
+ *
7
+ * Exact token counts depend on the model's tokenizer (e.g. Tiktoken for OpenAI,
8
+ * LlamaTokenizer for Mistral/Ollama). For a general CLI comparison, a conservative
9
+ * heuristic of ~3.2 characters per token is standard for code-heavy content.
10
+ */
11
+ export declare function countTokensHeuristic(text: string): number;
12
+ /**
13
+ * Returns a formatted string with token count and size in KB.
14
+ */
15
+ export declare function formatTokenStats(text: string): string;
16
+ /**
17
+ * Truncates a string to fit within a token budget.
18
+ * Always includes at least a small prefix even if the budget is tiny.
19
+ */
20
+ export declare function truncateToTokenBudget(text: string, budget: number): {
21
+ text: string;
22
+ truncated: boolean;
23
+ };
24
+ /**
25
+ * Filters a ranked list of SearchResults to fit within a token budget.
26
+ *
27
+ * Iterates in score order, accumulating chunk token counts until the budget
28
+ * would be exceeded. The first result is always included even if it alone
29
+ * exceeds the budget (never return empty when results exist).
30
+ */
31
+ export declare function applyTokenBudget(results: SearchResult[], budget: number): SearchResult[];
32
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../../src/utils/tokenizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAMxG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EAAE,EACvB,MAAM,EAAE,MAAM,GACb,YAAY,EAAE,CAYhB"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sumResultTokens = sumResultTokens;
4
+ exports.countTokensHeuristic = countTokensHeuristic;
5
+ exports.formatTokenStats = formatTokenStats;
6
+ exports.truncateToTokenBudget = truncateToTokenBudget;
7
+ exports.applyTokenBudget = applyTokenBudget;
8
+ /** Sums the estimated token count across a list of search results. */
9
+ function sumResultTokens(results) {
10
+ return results.reduce((n, r) => n + countTokensHeuristic(r.chunk.content), 0);
11
+ }
12
+ /**
13
+ * Heuristic-based token counting.
14
+ *
15
+ * Exact token counts depend on the model's tokenizer (e.g. Tiktoken for OpenAI,
16
+ * LlamaTokenizer for Mistral/Ollama). For a general CLI comparison, a conservative
17
+ * heuristic of ~3.2 characters per token is standard for code-heavy content.
18
+ */
19
+ function countTokensHeuristic(text) {
20
+ if (!text)
21
+ return 0;
22
+ return Math.ceil(text.length / 3.2);
23
+ }
24
+ /**
25
+ * Returns a formatted string with token count and size in KB.
26
+ */
27
+ function formatTokenStats(text) {
28
+ const tokens = countTokensHeuristic(text);
29
+ const kb = (Buffer.byteLength(text, "utf8") / 1024).toFixed(2);
30
+ return `${tokens.toLocaleString()} tokens (~${kb} KB)`;
31
+ }
32
+ /**
33
+ * Truncates a string to fit within a token budget.
34
+ * Always includes at least a small prefix even if the budget is tiny.
35
+ */
36
+ function truncateToTokenBudget(text, budget) {
37
+ if (budget <= 0)
38
+ return { text, truncated: false };
39
+ const tokens = countTokensHeuristic(text);
40
+ if (tokens <= budget)
41
+ return { text, truncated: false };
42
+ const maxChars = Math.floor(budget * 3.2);
43
+ return { text: text.slice(0, maxChars), truncated: true };
44
+ }
45
+ /**
46
+ * Filters a ranked list of SearchResults to fit within a token budget.
47
+ *
48
+ * Iterates in score order, accumulating chunk token counts until the budget
49
+ * would be exceeded. The first result is always included even if it alone
50
+ * exceeds the budget (never return empty when results exist).
51
+ */
52
+ function applyTokenBudget(results, budget) {
53
+ if (budget <= 0)
54
+ return results;
55
+ let tokens = 0;
56
+ const filtered = [];
57
+ for (const r of results) {
58
+ const t = countTokensHeuristic(r.chunk.content);
59
+ if (filtered.length === 0 || tokens + t <= budget) {
60
+ tokens += t;
61
+ filtered.push(r);
62
+ }
63
+ }
64
+ return filtered;
65
+ }
66
+ //# sourceMappingURL=tokenizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../src/utils/tokenizer.ts"],"names":[],"mappings":";;AAGA,0CAEC;AASD,oDAGC;AAKD,4CAIC;AAMD,sDAMC;AASD,4CAeC;AA5DD,sEAAsE;AACtE,SAAgB,eAAe,CAAC,OAAuB;IACrD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,aAAa,EAAE,MAAM,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,IAAY,EAAE,MAAc;IAChE,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,IAAI,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAC9B,OAAuB,EACvB,MAAc;IAEd,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IAChC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;YAClD,MAAM,IAAI,CAAC,CAAC;YACZ,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "vemora",
3
+ "version": "0.1.0-alpha.15",
4
+ "description": "Repository-local memory system for LLM-assisted development",
5
+ "type": "commonjs",
6
+ "author": "Maku <makuma85@gmail.com>",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/maku85/vemora.git"
11
+ },
12
+ "keywords": [
13
+ "llm",
14
+ "memory",
15
+ "semantic search",
16
+ "codebase",
17
+ "rag",
18
+ "ai",
19
+ "typescript",
20
+ "nodejs"
21
+ ],
22
+ "homepage": "https://github.com/maku85/vemora",
23
+ "bugs": {
24
+ "url": "https://github.com/maku85/vemora/issues"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "files": [
30
+ "dist/",
31
+ "README.md"
32
+ ],
33
+ "bin": {
34
+ "vemora": "./dist/cli.js"
35
+ },
36
+ "main": "./dist/cli.js",
37
+ "dependencies": {
38
+ "chalk": "^4.1.2",
39
+ "chokidar": "^5.0.0",
40
+ "commander": "^12.1.0",
41
+ "fast-glob": "^3.3.2",
42
+ "hnsw": "^1.1.1",
43
+ "micromatch": "^4.0.8",
44
+ "ora": "^5.4.1"
45
+ },
46
+ "optionalDependencies": {
47
+ "@anthropic-ai/sdk": "^0.78.0",
48
+ "@xenova/transformers": "^2.17.2",
49
+ "openai": "^4.67.0",
50
+ "tree-sitter": "^0.21.1",
51
+ "tree-sitter-javascript": "^0.21.4",
52
+ "tree-sitter-typescript": "^0.21.2"
53
+ },
54
+ "devDependencies": {
55
+ "@biomejs/biome": "^2.4.6",
56
+ "@types/node": "^20.16.0",
57
+ "rimraf": "^6.0.1",
58
+ "ts-node": "^10.9.2",
59
+ "typescript": "^5.6.2"
60
+ },
61
+ "scripts": {
62
+ "build": "tsc",
63
+ "build:watch": "tsc --watch",
64
+ "dev": "ts-node src/cli.ts",
65
+ "clean": "rimraf dist",
66
+ "format": "biome format --write src/",
67
+ "lint": "biome check src/",
68
+ "lint:fix": "biome check --write src/",
69
+ "release": "node scripts/release.js"
70
+ }
71
+ }