agcel 1.0.4 → 2.0.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 (293) hide show
  1. package/README.md +40 -47
  2. package/dist/cli/commands/create.d.ts +4 -0
  3. package/dist/cli/commands/create.d.ts.map +1 -0
  4. package/dist/cli/commands/create.js +68 -0
  5. package/dist/cli/commands/create.js.map +1 -0
  6. package/dist/cli/commands/init.d.ts +3 -0
  7. package/dist/cli/commands/init.d.ts.map +1 -0
  8. package/dist/cli/commands/init.js +98 -0
  9. package/dist/cli/commands/init.js.map +1 -0
  10. package/dist/cli/commands/install.d.ts +3 -0
  11. package/dist/cli/commands/install.d.ts.map +1 -0
  12. package/dist/cli/commands/install.helpers.d.ts +15 -0
  13. package/dist/cli/commands/install.helpers.d.ts.map +1 -0
  14. package/dist/cli/commands/install.helpers.js +47 -0
  15. package/dist/cli/commands/install.helpers.js.map +1 -0
  16. package/dist/cli/commands/install.helpers.test.d.ts +2 -0
  17. package/dist/cli/commands/install.helpers.test.d.ts.map +1 -0
  18. package/dist/cli/commands/install.helpers.test.js +18 -0
  19. package/dist/cli/commands/install.helpers.test.js.map +1 -0
  20. package/dist/cli/commands/install.js +74 -0
  21. package/dist/cli/commands/install.js.map +1 -0
  22. package/dist/cli/commands/pulse.d.ts +4 -0
  23. package/dist/cli/commands/pulse.d.ts.map +1 -0
  24. package/dist/cli/commands/pulse.js +48 -0
  25. package/dist/cli/commands/pulse.js.map +1 -0
  26. package/dist/cli/commands/pulse.test.d.ts +2 -0
  27. package/dist/cli/commands/pulse.test.d.ts.map +1 -0
  28. package/dist/cli/commands/pulse.test.js +19 -0
  29. package/dist/cli/commands/pulse.test.js.map +1 -0
  30. package/dist/cli/commands/suggest.d.ts +3 -0
  31. package/dist/cli/commands/suggest.d.ts.map +1 -0
  32. package/dist/cli/commands/suggest.js +32 -0
  33. package/dist/cli/commands/suggest.js.map +1 -0
  34. package/dist/cli/index.d.ts +3 -0
  35. package/dist/cli/index.d.ts.map +1 -0
  36. package/dist/cli/index.js +20 -0
  37. package/dist/cli/index.js.map +1 -0
  38. package/dist/cli/research-hints.d.ts +5 -0
  39. package/dist/cli/research-hints.d.ts.map +1 -0
  40. package/dist/cli/research-hints.js +109 -0
  41. package/dist/cli/research-hints.js.map +1 -0
  42. package/dist/cli/research-hints.test.d.ts +2 -0
  43. package/dist/cli/research-hints.test.d.ts.map +1 -0
  44. package/dist/cli/research-hints.test.js +50 -0
  45. package/dist/cli/research-hints.test.js.map +1 -0
  46. package/dist/core/agcel-config.d.ts +27 -0
  47. package/dist/core/agcel-config.d.ts.map +1 -0
  48. package/dist/core/agcel-config.js +4 -0
  49. package/dist/core/agcel-config.js.map +1 -0
  50. package/dist/core/build-rag-engine.d.ts +12 -0
  51. package/dist/core/build-rag-engine.d.ts.map +1 -0
  52. package/dist/core/build-rag-engine.js +24 -0
  53. package/dist/core/build-rag-engine.js.map +1 -0
  54. package/dist/core/build-rag-engine.test.d.ts +2 -0
  55. package/dist/core/build-rag-engine.test.d.ts.map +1 -0
  56. package/dist/core/build-rag-engine.test.js +34 -0
  57. package/dist/core/build-rag-engine.test.js.map +1 -0
  58. package/dist/core/chroma-rag.d.ts +20 -0
  59. package/dist/core/chroma-rag.d.ts.map +1 -0
  60. package/dist/core/chroma-rag.js +108 -0
  61. package/dist/core/chroma-rag.js.map +1 -0
  62. package/dist/core/context-hygiene.d.ts +12 -0
  63. package/dist/core/context-hygiene.d.ts.map +1 -0
  64. package/dist/core/context-hygiene.js +43 -0
  65. package/dist/core/context-hygiene.js.map +1 -0
  66. package/dist/core/context-hygiene.test.d.ts +2 -0
  67. package/dist/core/context-hygiene.test.d.ts.map +1 -0
  68. package/dist/core/context-hygiene.test.js +18 -0
  69. package/dist/core/context-hygiene.test.js.map +1 -0
  70. package/dist/core/context.d.ts +44 -0
  71. package/dist/core/context.d.ts.map +1 -0
  72. package/dist/core/context.js +114 -0
  73. package/dist/core/context.js.map +1 -0
  74. package/dist/core/conversation-routing.d.ts +10 -0
  75. package/dist/core/conversation-routing.d.ts.map +1 -0
  76. package/dist/core/conversation-routing.js +27 -0
  77. package/dist/core/conversation-routing.js.map +1 -0
  78. package/dist/core/conversation-routing.test.d.ts +2 -0
  79. package/dist/core/conversation-routing.test.d.ts.map +1 -0
  80. package/dist/core/conversation-routing.test.js +29 -0
  81. package/dist/core/conversation-routing.test.js.map +1 -0
  82. package/dist/core/guardrails.d.ts +26 -0
  83. package/dist/core/guardrails.d.ts.map +1 -0
  84. package/dist/core/guardrails.js +76 -0
  85. package/dist/core/guardrails.js.map +1 -0
  86. package/dist/core/guardrails.test.d.ts +2 -0
  87. package/dist/core/guardrails.test.d.ts.map +1 -0
  88. package/dist/core/guardrails.test.js +35 -0
  89. package/dist/core/guardrails.test.js.map +1 -0
  90. package/dist/core/intent.d.ts +22 -0
  91. package/dist/core/intent.d.ts.map +1 -0
  92. package/dist/core/intent.js +79 -0
  93. package/dist/core/intent.js.map +1 -0
  94. package/dist/core/intent.test.d.ts +2 -0
  95. package/dist/core/intent.test.d.ts.map +1 -0
  96. package/dist/core/intent.test.js +43 -0
  97. package/dist/core/intent.test.js.map +1 -0
  98. package/dist/core/local-rag.d.ts +17 -0
  99. package/dist/core/local-rag.d.ts.map +1 -0
  100. package/dist/core/local-rag.js +74 -0
  101. package/dist/core/local-rag.js.map +1 -0
  102. package/dist/core/local-rag.test.d.ts +2 -0
  103. package/dist/core/local-rag.test.d.ts.map +1 -0
  104. package/dist/core/local-rag.test.js +47 -0
  105. package/dist/core/local-rag.test.js.map +1 -0
  106. package/dist/core/orchestrator.d.ts +47 -0
  107. package/dist/core/orchestrator.d.ts.map +1 -0
  108. package/dist/core/orchestrator.js +138 -0
  109. package/dist/core/orchestrator.js.map +1 -0
  110. package/dist/core/orchestrator.test.d.ts +2 -0
  111. package/dist/core/orchestrator.test.d.ts.map +1 -0
  112. package/dist/core/orchestrator.test.js +118 -0
  113. package/dist/core/orchestrator.test.js.map +1 -0
  114. package/dist/core/pulse.d.ts +13 -0
  115. package/dist/core/pulse.d.ts.map +1 -0
  116. package/dist/core/pulse.js +29 -0
  117. package/dist/core/pulse.js.map +1 -0
  118. package/dist/core/pulse.test.d.ts +2 -0
  119. package/dist/core/pulse.test.d.ts.map +1 -0
  120. package/dist/core/pulse.test.js +18 -0
  121. package/dist/core/pulse.test.js.map +1 -0
  122. package/dist/core/rag-metadata.d.ts +5 -0
  123. package/dist/core/rag-metadata.d.ts.map +1 -0
  124. package/dist/core/rag-metadata.js +13 -0
  125. package/dist/core/rag-metadata.js.map +1 -0
  126. package/dist/core/rag-metadata.test.d.ts +2 -0
  127. package/dist/core/rag-metadata.test.d.ts.map +1 -0
  128. package/dist/core/rag-metadata.test.js +12 -0
  129. package/dist/core/rag-metadata.test.js.map +1 -0
  130. package/dist/core/rag-types.d.ts +18 -0
  131. package/dist/core/rag-types.d.ts.map +1 -0
  132. package/dist/core/rag-types.js +2 -0
  133. package/dist/core/rag-types.js.map +1 -0
  134. package/dist/core/read-agcel-config.d.ts +3 -0
  135. package/dist/core/read-agcel-config.d.ts.map +1 -0
  136. package/dist/core/read-agcel-config.js +13 -0
  137. package/dist/core/read-agcel-config.js.map +1 -0
  138. package/dist/core/registry.d.ts +9 -0
  139. package/dist/core/registry.d.ts.map +1 -0
  140. package/dist/core/registry.js +75 -0
  141. package/dist/core/registry.js.map +1 -0
  142. package/dist/core/registry.test.d.ts +2 -0
  143. package/dist/core/registry.test.d.ts.map +1 -0
  144. package/dist/core/registry.test.js +128 -0
  145. package/dist/core/registry.test.js.map +1 -0
  146. package/dist/core/schema.d.ts +51 -0
  147. package/dist/core/schema.d.ts.map +1 -0
  148. package/dist/core/schema.js +31 -0
  149. package/dist/core/schema.js.map +1 -0
  150. package/dist/core/summarizer.d.ts +23 -0
  151. package/dist/core/summarizer.d.ts.map +1 -0
  152. package/dist/core/summarizer.js +66 -0
  153. package/dist/core/summarizer.js.map +1 -0
  154. package/dist/core/text-similarity.d.ts +7 -0
  155. package/dist/core/text-similarity.d.ts.map +1 -0
  156. package/dist/core/text-similarity.js +35 -0
  157. package/dist/core/text-similarity.js.map +1 -0
  158. package/dist/core/text-similarity.test.d.ts +2 -0
  159. package/dist/core/text-similarity.test.d.ts.map +1 -0
  160. package/dist/core/text-similarity.test.js +11 -0
  161. package/dist/core/text-similarity.test.js.map +1 -0
  162. package/dist/docs-site.test.d.ts +2 -0
  163. package/dist/docs-site.test.d.ts.map +1 -0
  164. package/dist/docs-site.test.js +19 -0
  165. package/dist/docs-site.test.js.map +1 -0
  166. package/dist/index.d.ts +8 -0
  167. package/dist/index.d.ts.map +1 -0
  168. package/dist/index.js +8 -39
  169. package/dist/index.js.map +1 -0
  170. package/dist/providers/adapter.d.ts +23 -0
  171. package/dist/providers/adapter.d.ts.map +1 -0
  172. package/dist/providers/adapter.js +9 -0
  173. package/dist/providers/adapter.js.map +1 -0
  174. package/dist/providers/chatgpt.d.ts +13 -0
  175. package/dist/providers/chatgpt.d.ts.map +1 -0
  176. package/dist/providers/chatgpt.js +33 -0
  177. package/dist/providers/chatgpt.js.map +1 -0
  178. package/dist/providers/chatgpt.test.d.ts +2 -0
  179. package/dist/providers/chatgpt.test.d.ts.map +1 -0
  180. package/dist/providers/chatgpt.test.js +23 -0
  181. package/dist/providers/chatgpt.test.js.map +1 -0
  182. package/dist/providers/claude.d.ts +13 -0
  183. package/dist/providers/claude.d.ts.map +1 -0
  184. package/dist/providers/claude.js +48 -0
  185. package/dist/providers/claude.js.map +1 -0
  186. package/dist/providers/cursor.d.ts +14 -0
  187. package/dist/providers/cursor.d.ts.map +1 -0
  188. package/dist/providers/cursor.js +47 -0
  189. package/dist/providers/cursor.js.map +1 -0
  190. package/dist/providers/gemini.d.ts +13 -0
  191. package/dist/providers/gemini.d.ts.map +1 -0
  192. package/dist/providers/gemini.js +42 -0
  193. package/dist/providers/gemini.js.map +1 -0
  194. package/dist/providers/index.d.ts +5 -0
  195. package/dist/providers/index.d.ts.map +1 -0
  196. package/dist/providers/index.js +18 -0
  197. package/dist/providers/index.js.map +1 -0
  198. package/dist/server/index.d.ts +2 -0
  199. package/dist/server/index.d.ts.map +1 -0
  200. package/dist/server/index.js +288 -154
  201. package/dist/server/index.js.map +1 -0
  202. package/package.json +62 -52
  203. package/.agent/workflows/api-gen.md +0 -63
  204. package/.agent/workflows/architect.md +0 -44
  205. package/.agent/workflows/brainstorm.md +0 -227
  206. package/.agent/workflows/build.md +0 -38
  207. package/.agent/workflows/changelog.md +0 -55
  208. package/.agent/workflows/checkpoint.md +0 -142
  209. package/.agent/workflows/commit.md +0 -227
  210. package/.agent/workflows/debug.md +0 -61
  211. package/.agent/workflows/deploy.md +0 -80
  212. package/.agent/workflows/doc.md +0 -251
  213. package/.agent/workflows/execute-plan.md +0 -229
  214. package/.agent/workflows/feature.md +0 -259
  215. package/.agent/workflows/fix.md +0 -327
  216. package/.agent/workflows/help.md +0 -67
  217. package/.agent/workflows/index.md +0 -152
  218. package/.agent/workflows/load.md +0 -116
  219. package/.agent/workflows/mode.md +0 -174
  220. package/.agent/workflows/optimize.md +0 -57
  221. package/.agent/workflows/plan.md +0 -341
  222. package/.agent/workflows/pr.md +0 -78
  223. package/.agent/workflows/product-plan.md +0 -36
  224. package/.agent/workflows/production-deploy.md +0 -39
  225. package/.agent/workflows/refactor.md +0 -67
  226. package/.agent/workflows/research.md +0 -120
  227. package/.agent/workflows/review.md +0 -348
  228. package/.agent/workflows/security-scan.md +0 -60
  229. package/.agent/workflows/ship.md +0 -225
  230. package/.agent/workflows/spawn.md +0 -181
  231. package/.agent/workflows/status.md +0 -63
  232. package/.agent/workflows/tdd.md +0 -143
  233. package/.agent/workflows/test.md +0 -344
  234. package/.agent/workflows/verify.md +0 -35
  235. package/LICENSE +0 -21
  236. package/dist/commands/init.js +0 -147
  237. package/dist/commands/list.js +0 -43
  238. package/dist/commands/uninstall.js +0 -70
  239. package/dist/utils/index.js +0 -28
  240. package/skills/api-security-best-practices/SKILL.md +0 -291
  241. package/skills/api-security-best-practices/references/examples.md +0 -617
  242. package/skills/architecture/SKILL.md +0 -59
  243. package/skills/architecture/context-discovery.md +0 -43
  244. package/skills/architecture/examples.md +0 -94
  245. package/skills/architecture/pattern-selection.md +0 -68
  246. package/skills/architecture/patterns-reference.md +0 -50
  247. package/skills/architecture/trade-off-analysis.md +0 -77
  248. package/skills/aws-serverless/SKILL.md +0 -327
  249. package/skills/brainstorming/SKILL.md +0 -234
  250. package/skills/c4-context/SKILL.md +0 -154
  251. package/skills/ci-cd-engineer/SKILL.md +0 -50
  252. package/skills/code-auditing/SKILL.md +0 -55
  253. package/skills/copywriting/SKILL.md +0 -248
  254. package/skills/database-engineer/SKILL.md +0 -47
  255. package/skills/doc-coauthoring/SKILL.md +0 -379
  256. package/skills/docker-expert/SKILL.md +0 -412
  257. package/skills/langgraph/SKILL.md +0 -291
  258. package/skills/postgresql/SKILL.md +0 -73
  259. package/skills/pricing-strategy/SKILL.md +0 -360
  260. package/skills/product-manager/SKILL.md +0 -57
  261. package/skills/prompt-engineer/README.md +0 -659
  262. package/skills/prompt-engineer/SKILL.md +0 -256
  263. package/skills/python-patterns/SKILL.md +0 -445
  264. package/skills/qa-engineer/SKILL.md +0 -42
  265. package/skills/rag-engineer/SKILL.md +0 -94
  266. package/skills/react-patterns/SKILL.md +0 -202
  267. package/skills/secure-refactoring/SKILL.md +0 -54
  268. package/skills/security-documentation/SKILL.md +0 -53
  269. package/skills/senior-architect/SKILL.md +0 -213
  270. package/skills/senior-architect/references/architecture_patterns.md +0 -103
  271. package/skills/senior-architect/references/system_design_workflows.md +0 -103
  272. package/skills/senior-architect/references/tech_decision_guide.md +0 -103
  273. package/skills/senior-architect/scripts/architecture_diagram_generator.py +0 -114
  274. package/skills/senior-architect/scripts/dependency_analyzer.py +0 -114
  275. package/skills/senior-architect/scripts/project_architect.py +0 -114
  276. package/skills/seo-audit/SKILL.md +0 -491
  277. package/skills/sql-injection-testing/SKILL.md +0 -452
  278. package/skills/test-driven-development/SKILL.md +0 -375
  279. package/skills/test-driven-development/testing-anti-patterns.md +0 -299
  280. package/skills/test-fixing/SKILL.md +0 -123
  281. package/skills/testing-patterns/SKILL.md +0 -263
  282. package/skills/typescript-expert/SKILL.md +0 -202
  283. package/skills/typescript-expert/references/advanced-topics.md +0 -252
  284. package/skills/typescript-expert/references/tsconfig-strict.json +0 -92
  285. package/skills/typescript-expert/references/typescript-cheatsheet.md +0 -383
  286. package/skills/typescript-expert/references/utility-types.ts +0 -335
  287. package/skills/typescript-expert/scripts/ts_diagnostic.py +0 -203
  288. package/skills/ui-ux-designer/SKILL.md +0 -46
  289. package/skills/vercel-deployment/SKILL.md +0 -83
  290. package/skills/vulnerability-scanner/SKILL.md +0 -280
  291. package/skills/vulnerability-scanner/checklists.md +0 -121
  292. package/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
  293. package/skills/writing-plans/SKILL.md +0 -120
@@ -0,0 +1,17 @@
1
+ import type { IRagEngine, RagSearchResult } from './rag-types.js';
2
+ /**
3
+ * Local JSON-backed RAG: TF-IDF-like token overlap scoring (no external services).
4
+ */
5
+ export declare class LocalRagEngine implements IRagEngine {
6
+ private documents;
7
+ private readonly indexPath;
8
+ constructor(basePath?: string);
9
+ initialize(): Promise<void>;
10
+ addDocument(id: string, content: string, metadata?: Record<string, string>): Promise<void>;
11
+ query(queryText: string, topK?: number, metadataFilter?: Record<string, string>): Promise<RagSearchResult[]>;
12
+ removeDocument(id: string): Promise<void>;
13
+ getDocumentCount(): Promise<number>;
14
+ private loadIndex;
15
+ private saveIndex;
16
+ }
17
+ //# sourceMappingURL=local-rag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-rag.d.ts","sourceRoot":"","sources":["../../src/core/local-rag.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIlE;;GAEG;AACH,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,SAAS,CAAgF;IACjG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,QAAQ,CAAC,EAAE,MAAM;IAIvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9F,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,MAAU,EAChB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;IA6BvB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;YAI3B,SAAS;YAUT,SAAS;CAIxB"}
@@ -0,0 +1,74 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { cosineSimilarityMaps, tokenizeForSimilarity } from './text-similarity.js';
4
+ import { recencyScoreMultiplier } from './rag-metadata.js';
5
+ /**
6
+ * Local JSON-backed RAG: TF-IDF-like token overlap scoring (no external services).
7
+ */
8
+ export class LocalRagEngine {
9
+ documents = [];
10
+ indexPath;
11
+ constructor(basePath) {
12
+ this.indexPath = basePath || path.join(process.cwd(), '.agcel', 'rag');
13
+ }
14
+ async initialize() {
15
+ await fs.mkdir(this.indexPath, { recursive: true });
16
+ await this.loadIndex();
17
+ }
18
+ async addDocument(id, content, metadata = {}) {
19
+ const existing = this.documents.findIndex(d => d.id === id);
20
+ if (existing >= 0) {
21
+ this.documents[existing] = { id, content, metadata };
22
+ }
23
+ else {
24
+ this.documents.push({ id, content, metadata });
25
+ }
26
+ await this.saveIndex();
27
+ }
28
+ async query(queryText, topK = 5, metadataFilter) {
29
+ const queryTerms = tokenizeForSimilarity(queryText);
30
+ let pool = this.documents;
31
+ if (metadataFilter && Object.keys(metadataFilter).length > 0) {
32
+ pool = pool.filter((d) => Object.entries(metadataFilter).every(([k, v]) => d.metadata[k] === v));
33
+ }
34
+ const scored = pool.map((doc) => {
35
+ const metaBlob = Object.entries(doc.metadata)
36
+ .map(([k, v]) => `${k} ${v}`)
37
+ .join(' ');
38
+ const blob = `${doc.content}\n${metaBlob}`;
39
+ const docTerms = tokenizeForSimilarity(blob);
40
+ let score = cosineSimilarityMaps(queryTerms, docTerms);
41
+ score *= recencyScoreMultiplier(doc.metadata.updatedAt);
42
+ return {
43
+ id: doc.id,
44
+ content: doc.content,
45
+ score,
46
+ metadata: { ...doc.metadata }
47
+ };
48
+ });
49
+ scored.sort((a, b) => b.score - a.score);
50
+ return scored.slice(0, topK);
51
+ }
52
+ async removeDocument(id) {
53
+ this.documents = this.documents.filter(d => d.id !== id);
54
+ await this.saveIndex();
55
+ }
56
+ async getDocumentCount() {
57
+ return this.documents.length;
58
+ }
59
+ async loadIndex() {
60
+ try {
61
+ const indexFile = path.join(this.indexPath, 'index.json');
62
+ const data = await fs.readFile(indexFile, 'utf-8');
63
+ this.documents = JSON.parse(data);
64
+ }
65
+ catch {
66
+ this.documents = [];
67
+ }
68
+ }
69
+ async saveIndex() {
70
+ const indexFile = path.join(this.indexPath, 'index.json');
71
+ await fs.writeFile(indexFile, JSON.stringify(this.documents, null, 2));
72
+ }
73
+ }
74
+ //# sourceMappingURL=local-rag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-rag.js","sourceRoot":"","sources":["../../src/core/local-rag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local-rag.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-rag.test.d.ts","sourceRoot":"","sources":["../../src/core/local-rag.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { LocalRagEngine } from './local-rag.js';
6
+ describe('LocalRagEngine', () => {
7
+ let tmpDir;
8
+ afterEach(async () => {
9
+ if (tmpDir) {
10
+ await fs.rm(tmpDir, { recursive: true, force: true });
11
+ }
12
+ });
13
+ it('Given indexed docs about Python when querying python topic then higher-scoring doc is first', async () => {
14
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'agcel-rag-'));
15
+ const ragPath = path.join(tmpDir, 'rag');
16
+ const engine = new LocalRagEngine(ragPath);
17
+ await engine.initialize();
18
+ await engine.addDocument('a', 'Notes about cooking pasta and sauces.');
19
+ await engine.addDocument('b', 'Python testing with pytest and fixtures.');
20
+ const results = await engine.query('python testing pytest', 2);
21
+ expect(results.length).toBeGreaterThanOrEqual(1);
22
+ expect(results[0]?.id).toBe('b');
23
+ expect(results[0]?.score).toBeGreaterThan(0);
24
+ });
25
+ it('Given same id when adding again then document is replaced', async () => {
26
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'agcel-rag-'));
27
+ const engine = new LocalRagEngine(path.join(tmpDir, 'rag'));
28
+ await engine.initialize();
29
+ await engine.addDocument('x', 'first');
30
+ await engine.addDocument('x', 'second version');
31
+ const count = await engine.getDocumentCount();
32
+ expect(count).toBe(1);
33
+ const q = await engine.query('second version', 1);
34
+ expect(q[0]?.content).toBe('second version');
35
+ });
36
+ it('Given metadata filter when querying then only matching documents are returned', async () => {
37
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'agcel-rag-'));
38
+ const engine = new LocalRagEngine(path.join(tmpDir, 'rag'));
39
+ await engine.initialize();
40
+ await engine.addDocument('a', 'alpha project notes', { source: 'a' });
41
+ await engine.addDocument('b', 'beta project notes', { source: 'b' });
42
+ const filtered = await engine.query('project', 5, { source: 'b' });
43
+ expect(filtered).toHaveLength(1);
44
+ expect(filtered[0]?.id).toBe('b');
45
+ });
46
+ });
47
+ //# sourceMappingURL=local-rag.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-rag.test.js","sourceRoot":"","sources":["../../src/core/local-rag.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { Agent, Guardrail } from './schema.js';
2
+ import { Registry } from './registry.js';
3
+ import { IntentEngine } from './intent.js';
4
+ import { ContextManager } from './context.js';
5
+ import { type ConversationTurn } from './conversation-routing.js';
6
+ import { GuardrailValidator, type ValidationResult } from './guardrails.js';
7
+ export interface RouteQueryOptions {
8
+ /** Prior turns (oldest first). Combined with the current query for intent and context. */
9
+ conversationHistory?: ConversationTurn[];
10
+ /** Name of the agent used on the previous turn; used to report `agentSwitched`. */
11
+ previousAgentName?: string | null;
12
+ /** When set, validate this text against the resolved agent guardrails. */
13
+ draftOutput?: string;
14
+ /** When true, failed validation (error-severity rules) sets `guardrailsBlocked`. */
15
+ strictGuardrailsOnDraft?: boolean;
16
+ }
17
+ export interface RouteQueryResult {
18
+ agent: Agent | null;
19
+ confidence: number;
20
+ suggestion: string | null;
21
+ context: string;
22
+ assembledPrompt: string;
23
+ guardrails: Guardrail[];
24
+ /** True when `previousAgentName` was set and differs from the selected agent name (including null). */
25
+ agentSwitched: boolean;
26
+ /** Text passed to intent detection (may include conversation history). */
27
+ routingQuery: string;
28
+ /** Agent skill names with no matching registry entry. */
29
+ missingSkills: string[];
30
+ /** Human-readable issues (for example missing skills). */
31
+ warnings: string[];
32
+ guardrailValidation?: ValidationResult;
33
+ guardrailReport?: string;
34
+ guardrailRevisionHint?: string;
35
+ /** True when strict guardrail mode is on and the draft failed validation. */
36
+ guardrailsBlocked?: boolean;
37
+ }
38
+ export declare class Orchestrator {
39
+ private registry;
40
+ private intentEngine;
41
+ private contextManager;
42
+ private guardrailValidator;
43
+ constructor(registry?: Registry, intentEngine?: IntentEngine, contextManager?: ContextManager, guardrailValidator?: GuardrailValidator);
44
+ initialize(): Promise<void>;
45
+ routeQuery(query: string, options?: RouteQueryOptions): Promise<RouteQueryResult>;
46
+ }
47
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAS,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,0FAA0F;IAC1F,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACzC,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,uGAAuG;IACvG,aAAa,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAkED,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,kBAAkB;gBAHlB,QAAQ,GAAE,QAAyB,EACnC,YAAY,GAAE,YAAiC,EAC/C,cAAc,GAAE,cAAqC,EACrD,kBAAkB,GAAE,kBAA6C;IAGrE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,UAAU,CACd,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC;CAmF7B"}
@@ -0,0 +1,138 @@
1
+ import { Registry } from './registry.js';
2
+ import { IntentEngine } from './intent.js';
3
+ import { ContextManager } from './context.js';
4
+ import { buildRoutingQuery } from './conversation-routing.js';
5
+ import { GuardrailValidator } from './guardrails.js';
6
+ function buildRevisionHint(result) {
7
+ const errs = result.violations.filter((v) => v.severity === 'error');
8
+ if (errs.length === 0)
9
+ return undefined;
10
+ return ('Address these guardrail errors and revise the draft: ' +
11
+ errs.map((e) => `${e.description} (${e.detail})`).join('; '));
12
+ }
13
+ function collectGuardrails(agent, skills) {
14
+ if (!agent)
15
+ return [];
16
+ const all = [...(agent.guardrails ?? [])];
17
+ for (const skillName of agent.skills) {
18
+ const skill = skills.find(s => s.name === skillName);
19
+ if (skill?.guardrails)
20
+ all.push(...skill.guardrails);
21
+ }
22
+ return all;
23
+ }
24
+ function assemblePrompt(parts) {
25
+ const lines = [];
26
+ if (!parts.agent) {
27
+ if (parts.context.trim()) {
28
+ lines.push('Context:\n' + parts.context.trim());
29
+ }
30
+ if (parts.warnings?.length) {
31
+ lines.push(`Warnings:\n${parts.warnings.map(w => `- ${w}`).join('\n')}`.trim());
32
+ }
33
+ return lines.join('\n\n').trim();
34
+ }
35
+ lines.push(`Agent: ${parts.agent.name}`);
36
+ lines.push(`Role:\n${parts.agent.role}`.trim());
37
+ if (parts.skills.length > 0) {
38
+ const skillsText = parts.skills
39
+ .map(s => `Skill: ${s.name}\n${s.systemPrompt}`.trim())
40
+ .join('\n\n');
41
+ lines.push(`Skills:\n${skillsText}`.trim());
42
+ }
43
+ if (parts.context.trim()) {
44
+ lines.push(`Context:\n${parts.context.trim()}`.trim());
45
+ }
46
+ if (parts.missingSkills && parts.missingSkills.length > 0) {
47
+ lines.push(`Notes:\nMissing registry skills (listed on the agent but no skill file matched): ${parts.missingSkills.join(', ')}. Add markdown or JSON under .agcel/registry/skills/ or run \`agcel create-skill\`.`.trim());
48
+ }
49
+ if (parts.warnings?.length) {
50
+ lines.push(`Warnings:\n${parts.warnings.map(w => `- ${w}`).join('\n')}`.trim());
51
+ }
52
+ return lines.join('\n\n').trim();
53
+ }
54
+ export class Orchestrator {
55
+ registry;
56
+ intentEngine;
57
+ contextManager;
58
+ guardrailValidator;
59
+ constructor(registry = new Registry(), intentEngine = new IntentEngine(), contextManager = new ContextManager(), guardrailValidator = new GuardrailValidator()) {
60
+ this.registry = registry;
61
+ this.intentEngine = intentEngine;
62
+ this.contextManager = contextManager;
63
+ this.guardrailValidator = guardrailValidator;
64
+ }
65
+ async initialize() {
66
+ await this.contextManager.initialize();
67
+ }
68
+ async routeQuery(query, options) {
69
+ const [agents, allSkills] = await Promise.all([
70
+ this.registry.loadAgents(),
71
+ this.registry.loadSkills()
72
+ ]);
73
+ const routingQuery = buildRoutingQuery(query, options?.conversationHistory);
74
+ const intent = this.intentEngine.detectIntent(routingQuery, agents, {
75
+ latestUserTurn: query.trim()
76
+ });
77
+ const agent = intent.bestAgent;
78
+ const resolvedSkills = agent
79
+ ? agent.skills.map(name => allSkills.find(s => s.name === name)).filter((s) => s !== undefined)
80
+ : [];
81
+ const missingSkills = agent
82
+ ? agent.skills.filter((name) => !allSkills.some((s) => s.name === name))
83
+ : [];
84
+ const warnings = [];
85
+ if (missingSkills.length > 0) {
86
+ warnings.push(`Skills not loaded from registry: ${missingSkills.join(', ')}`);
87
+ }
88
+ const context = (await this.contextManager.getContext(routingQuery)) || '';
89
+ const guardrails = collectGuardrails(agent, allSkills);
90
+ const assembledPrompt = assemblePrompt({
91
+ agent,
92
+ skills: resolvedSkills,
93
+ context,
94
+ missingSkills,
95
+ warnings
96
+ });
97
+ const prev = options?.previousAgentName ?? null;
98
+ const currentName = agent?.name ?? null;
99
+ const agentSwitched = prev !== null &&
100
+ prev !== '' &&
101
+ (currentName === null ? true : currentName !== prev);
102
+ const draft = options?.draftOutput?.trim();
103
+ let guardrailValidation;
104
+ let guardrailReport;
105
+ let guardrailRevisionHint;
106
+ if (draft && agent && guardrails.length > 0) {
107
+ guardrailValidation = this.guardrailValidator.validate(draft, guardrails);
108
+ guardrailReport = this.guardrailValidator.formatReport(guardrailValidation);
109
+ guardrailRevisionHint = buildRevisionHint(guardrailValidation);
110
+ }
111
+ const guardrailsBlocked = guardrailValidation !== undefined &&
112
+ Boolean(options?.strictGuardrailsOnDraft) &&
113
+ !guardrailValidation.passed;
114
+ return {
115
+ agent,
116
+ confidence: intent.confidence,
117
+ suggestion: intent.suggestion,
118
+ context,
119
+ assembledPrompt,
120
+ guardrails,
121
+ agentSwitched,
122
+ routingQuery,
123
+ missingSkills,
124
+ warnings,
125
+ ...(guardrailValidation !== undefined
126
+ ? {
127
+ guardrailValidation,
128
+ guardrailReport: guardrailReport,
129
+ ...(guardrailRevisionHint !== undefined
130
+ ? { guardrailRevisionHint }
131
+ : {}),
132
+ guardrailsBlocked
133
+ }
134
+ : {})
135
+ };
136
+ }
137
+ }
138
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/core/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=orchestrator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.test.d.ts","sourceRoot":"","sources":["../../src/core/orchestrator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Orchestrator } from './orchestrator.js';
3
+ import { IntentEngine } from './intent.js';
4
+ import { GuardrailValidator } from './guardrails.js';
5
+ class FakeIntentEngine {
6
+ detectIntent(query, agents) {
7
+ const lower = query.toLowerCase();
8
+ const best = agents.find(a => lower.includes('python') &&
9
+ (a.name === 'backend-developer' || a.name.includes('python'))) ?? agents[0] ?? null;
10
+ return { bestAgent: best, confidence: best ? 1 : 0, suggestion: null };
11
+ }
12
+ }
13
+ class FakeRegistry {
14
+ agents;
15
+ skills;
16
+ constructor(agents, skills) {
17
+ this.agents = agents;
18
+ this.skills = skills;
19
+ }
20
+ async loadAgents() {
21
+ return this.agents;
22
+ }
23
+ async loadSkills() {
24
+ return this.skills;
25
+ }
26
+ }
27
+ class FakeContextManager {
28
+ async initialize() {
29
+ return;
30
+ }
31
+ async getContext(_query) {
32
+ return 'Some relevant context.';
33
+ }
34
+ }
35
+ describe('Orchestrator', () => {
36
+ it('Given matching query when routing then returns agent, context, and assembled prompt', async () => {
37
+ const agents = [
38
+ { name: 'backend-developer', description: 'Python Java Node backend', role: 'Be a backend dev', skills: ['python'] },
39
+ { name: 'web-designer', description: 'Web designer', role: 'Be a designer', skills: ['design'] }
40
+ ];
41
+ const skills = [
42
+ { name: 'python', description: 'Python skill', systemPrompt: 'Use Python.', tools: [] }
43
+ ];
44
+ const orchestrator = new Orchestrator(new FakeRegistry(agents, skills), new FakeIntentEngine(), new FakeContextManager());
45
+ const result = await orchestrator.routeQuery('Need help with python testing');
46
+ expect(result.agent?.name).toBe('backend-developer');
47
+ expect(result.context).toContain('relevant context');
48
+ expect(result.assembledPrompt).toContain('Agent: backend-developer');
49
+ expect(result.assembledPrompt).toContain('Skill: python');
50
+ expect(result.assembledPrompt).toContain('Context:');
51
+ expect(result.agentSwitched).toBe(false);
52
+ expect(result.routingQuery).toBe('Need help with python testing');
53
+ expect(result.missingSkills).toEqual([]);
54
+ expect(result.warnings).toEqual([]);
55
+ });
56
+ it('Given evolving conversation toward Python when routing with history then selects python agent and reports switch', async () => {
57
+ const agents = [
58
+ {
59
+ name: 'python-expert',
60
+ description: 'Python backend asyncio django debugging',
61
+ role: 'Senior Python engineer for APIs and tracebacks',
62
+ skills: ['python']
63
+ },
64
+ {
65
+ name: 'ui-expert',
66
+ description: 'Figma mockups React frontend layout design',
67
+ role: 'Product designer for UI and visual design',
68
+ skills: ['design']
69
+ }
70
+ ];
71
+ const skills = [
72
+ { name: 'python', description: 'Py', systemPrompt: 'Use Python.', tools: [] },
73
+ { name: 'design', description: 'UI', systemPrompt: 'Use design.', tools: [] }
74
+ ];
75
+ const orchestrator = new Orchestrator(new FakeRegistry(agents, skills), new IntentEngine(0.25), new FakeContextManager());
76
+ const first = await orchestrator.routeQuery('Create a Figma mockup for the dashboard');
77
+ expect(first.agent?.name).toBe('ui-expert');
78
+ expect(first.agentSwitched).toBe(false);
79
+ const second = await orchestrator.routeQuery('Ignore that, the Django view is throwing a traceback', {
80
+ conversationHistory: [
81
+ { role: 'user', content: 'Create a Figma mockup for the dashboard' },
82
+ { role: 'assistant', content: 'Here is a layout concept.' }
83
+ ],
84
+ previousAgentName: first.agent?.name ?? null
85
+ });
86
+ expect(second.agent?.name).toBe('python-expert');
87
+ expect(second.agentSwitched).toBe(true);
88
+ expect(second.routingQuery).toContain('Django');
89
+ expect(second.routingQuery).toContain('Figma');
90
+ });
91
+ it('Given draft breaking guardrails when strict validation then guardrailsBlocked is true', async () => {
92
+ const agents = [
93
+ {
94
+ name: 'safe-agent',
95
+ description: 'Safe',
96
+ role: 'Be safe',
97
+ skills: [],
98
+ guardrails: [
99
+ {
100
+ id: 'no-secret',
101
+ description: 'Do not leak secret marker',
102
+ severity: 'error',
103
+ forbiddenTerms: ['TOPSECRET']
104
+ }
105
+ ]
106
+ }
107
+ ];
108
+ const orchestrator = new Orchestrator(new FakeRegistry(agents, []), new FakeIntentEngine(), new FakeContextManager(), new GuardrailValidator());
109
+ const result = await orchestrator.routeQuery('hello', {
110
+ draftOutput: 'This contains TOPSECRET',
111
+ strictGuardrailsOnDraft: true
112
+ });
113
+ expect(result.guardrailValidation?.passed).toBe(false);
114
+ expect(result.guardrailsBlocked).toBe(true);
115
+ expect(result.guardrailRevisionHint).toBeDefined();
116
+ });
117
+ });
118
+ //# sourceMappingURL=orchestrator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../../src/core/orchestrator.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { SummarizationService } from './summarizer.js';
2
+ export interface PulseInput {
3
+ timestampIso: string;
4
+ changedFiles: string[];
5
+ diffStat: string;
6
+ gitHead?: string;
7
+ }
8
+ export declare class PulseService {
9
+ private readonly summarizer;
10
+ constructor(summarizer?: SummarizationService);
11
+ buildMemo(input: PulseInput): string;
12
+ }
13
+ //# sourceMappingURL=pulse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.d.ts","sourceRoot":"","sources":["../../src/core/pulse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,GAAE,oBAAoD;IAE7F,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;CAqBrC"}
@@ -0,0 +1,29 @@
1
+ import { SummarizationService } from './summarizer.js';
2
+ export class PulseService {
3
+ summarizer;
4
+ constructor(summarizer = new SummarizationService(800)) {
5
+ this.summarizer = summarizer;
6
+ }
7
+ buildMemo(input) {
8
+ const lines = [
9
+ 'Project Pulse',
10
+ `Time: ${input.timestampIso}`,
11
+ ...(input.gitHead ? [`HEAD: ${input.gitHead}`] : [])
12
+ ];
13
+ if (input.changedFiles.length > 0) {
14
+ lines.push('', 'Changed files:');
15
+ for (const f of input.changedFiles.slice(0, 200))
16
+ lines.push(`- ${f}`);
17
+ if (input.changedFiles.length > 200)
18
+ lines.push(`- ...and ${input.changedFiles.length - 200} more`);
19
+ }
20
+ if (input.diffStat.trim()) {
21
+ lines.push('', 'Diff stat:', input.diffStat.trim());
22
+ }
23
+ const memo = lines.join('\n');
24
+ if (this.summarizer.exceedsBudget(memo))
25
+ return this.summarizer.summarize(memo);
26
+ return memo;
27
+ }
28
+ }
29
+ //# sourceMappingURL=pulse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.js","sourceRoot":"","sources":["../../src/core/pulse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AASvD,MAAM,OAAO,YAAY;IACM;IAA7B,YAA6B,aAAmC,IAAI,oBAAoB,CAAC,GAAG,CAAC;QAAhE,eAAU,GAAV,UAAU,CAAsD;IAAG,CAAC;IAEjG,SAAS,CAAC,KAAiB;QACzB,MAAM,KAAK,GAAa;YACtB,eAAe;YACf,SAAS,KAAK,CAAC,YAAY,EAAE;YAC7B,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACrD,CAAC;QAEF,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvE,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,GAAG;gBAAE,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC;QACtG,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pulse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.test.d.ts","sourceRoot":"","sources":["../../src/core/pulse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { PulseService } from './pulse.js';
3
+ describe('PulseService', () => {
4
+ it('Given changes when building memo then includes timestamp and file list', () => {
5
+ const svc = new PulseService();
6
+ const memo = svc.buildMemo({
7
+ timestampIso: '2026-03-27T00:00:00.000Z',
8
+ changedFiles: ['src/a.ts', 'src/b.ts'],
9
+ diffStat: '2 files changed, 10 insertions(+), 1 deletion(-)',
10
+ gitHead: 'abc123 test'
11
+ });
12
+ expect(memo).toContain('Project Pulse');
13
+ expect(memo).toContain('Time: 2026-03-27T00:00:00.000Z');
14
+ expect(memo).toContain('- src/a.ts');
15
+ expect(memo).toContain('Diff stat:');
16
+ });
17
+ });
18
+ //# sourceMappingURL=pulse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse.test.js","sourceRoot":"","sources":["../../src/core/pulse.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC;YACzB,YAAY,EAAE,0BAA0B;YACxC,YAAY,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;YACtC,QAAQ,EAAE,kDAAkD;YAC5D,OAAO,EAAE,aAAa;SACvB,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Optional recency boost for RAG hits using ISO metadata `updatedAt`.
3
+ */
4
+ export declare function recencyScoreMultiplier(updatedAt?: string): number;
5
+ //# sourceMappingURL=rag-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-metadata.d.ts","sourceRoot":"","sources":["../../src/core/rag-metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAMjE"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Optional recency boost for RAG hits using ISO metadata `updatedAt`.
3
+ */
4
+ export function recencyScoreMultiplier(updatedAt) {
5
+ if (!updatedAt)
6
+ return 1;
7
+ const t = Date.parse(updatedAt);
8
+ if (Number.isNaN(t))
9
+ return 1;
10
+ const days = (Date.now() - t) / (86400 * 1000);
11
+ return 1 + 0.15 * Math.exp(-Math.max(0, days) / 14);
12
+ }
13
+ //# sourceMappingURL=rag-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-metadata.js","sourceRoot":"","sources":["../../src/core/rag-metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAkB;IACvD,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rag-metadata.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-metadata.test.d.ts","sourceRoot":"","sources":["../../src/core/rag-metadata.test.ts"],"names":[],"mappings":""}