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,18 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { deduplicateLines, deduplicateRetrievalBlocks } from './context-hygiene.js';
3
+ describe('deduplicateRetrievalBlocks', () => {
4
+ it('Given duplicate RAG chunks when deduping then only one copy remains', () => {
5
+ const dup = 'Same chunk text here.';
6
+ const text = [dup, dup, 'unique'].join('\n\n---\n\n');
7
+ const out = deduplicateRetrievalBlocks(text);
8
+ expect(out.split('\n\n---\n\n').filter(Boolean).length).toBe(2);
9
+ expect(out).toContain('unique');
10
+ });
11
+ });
12
+ describe('deduplicateLines', () => {
13
+ it('Given repeated paragraphs when deduping then order is preserved', () => {
14
+ const text = 'A\n\nB\n\nA\n\nC';
15
+ expect(deduplicateLines(text)).toBe('A\n\nB\n\nC');
16
+ });
17
+ });
18
+ //# sourceMappingURL=context-hygiene.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-hygiene.test.js","sourceRoot":"","sources":["../../src/core/context-hygiene.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC3B,MAAM,sBAAsB,CAAC;AAE9B,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,GAAG,GAAG,uBAAuB,CAAC;QACpC,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,kBAAkB,CAAC;QAChC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { type RagEngineMode } from './build-rag-engine.js';
2
+ import type { IRagEngine } from './rag-types.js';
3
+ import { SummarizationService } from './summarizer.js';
4
+ /**
5
+ * Context Manager (CM).
6
+ * Orchestrates what goes into the prompt by querying the RAG engine
7
+ * and applying summarization when context is too long.
8
+ * Falls back to MEMORY.md when RAG is not available.
9
+ */
10
+ export declare class ContextManager {
11
+ private rag;
12
+ private readonly summarizer;
13
+ private readonly memoryPath;
14
+ private ragEnabled;
15
+ private ragMode;
16
+ private readonly basePath;
17
+ private ragMetadataFilter;
18
+ constructor(options?: {
19
+ basePath?: string;
20
+ maxTokens?: number;
21
+ });
22
+ initialize(): Promise<void>;
23
+ /**
24
+ * Retrieve relevant context for a given query.
25
+ */
26
+ getContext(query: string): Promise<string>;
27
+ /**
28
+ * Ingest a document into the knowledge base.
29
+ */
30
+ ingest(id: string, content: string, metadata?: Record<string, string>): Promise<void>;
31
+ /**
32
+ * Write a summary/memo to MEMORY.md (fallback when RAG is unavailable).
33
+ */
34
+ appendToMemory(title: string, content: string): Promise<void>;
35
+ /**
36
+ * Read the MEMORY.md fallback file.
37
+ */
38
+ readMemoryFile(): Promise<string>;
39
+ isRagEnabled(): boolean;
40
+ getRagMode(): RagEngineMode | null;
41
+ getRag(): IRagEngine | null;
42
+ getSummarizer(): SummarizationService;
43
+ }
44
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAIvD;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAAqC;gBAElD,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAMzD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBjC;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBhD;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/F;;OAEG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnE;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAQvC,YAAY,IAAI,OAAO;IAIvB,UAAU,IAAI,aAAa,GAAG,IAAI;IAIlC,MAAM,IAAI,UAAU,GAAG,IAAI;IAI3B,aAAa,IAAI,oBAAoB;CAGtC"}
@@ -0,0 +1,114 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { buildRagEngine } from './build-rag-engine.js';
4
+ import { SummarizationService } from './summarizer.js';
5
+ import { readAgcelConfig } from './read-agcel-config.js';
6
+ import { deduplicateRetrievalBlocks } from './context-hygiene.js';
7
+ /**
8
+ * Context Manager (CM).
9
+ * Orchestrates what goes into the prompt by querying the RAG engine
10
+ * and applying summarization when context is too long.
11
+ * Falls back to MEMORY.md when RAG is not available.
12
+ */
13
+ export class ContextManager {
14
+ rag = null;
15
+ summarizer;
16
+ memoryPath;
17
+ ragEnabled = false;
18
+ ragMode = null;
19
+ basePath;
20
+ ragMetadataFilter;
21
+ constructor(options) {
22
+ this.basePath = options?.basePath || process.cwd();
23
+ this.summarizer = new SummarizationService(options?.maxTokens);
24
+ this.memoryPath = path.join(this.basePath, 'MEMORY.md');
25
+ }
26
+ async initialize() {
27
+ const config = await readAgcelConfig(this.basePath);
28
+ this.ragMetadataFilter = config.ragQueryMetadataFilter;
29
+ if (config.ragEnabled === false) {
30
+ this.ragEnabled = false;
31
+ this.rag = null;
32
+ this.ragMode = null;
33
+ return;
34
+ }
35
+ try {
36
+ const { engine, mode } = await buildRagEngine(this.basePath, config);
37
+ this.rag = engine;
38
+ this.ragMode = mode;
39
+ this.ragEnabled = true;
40
+ }
41
+ catch {
42
+ this.ragEnabled = false;
43
+ this.rag = null;
44
+ this.ragMode = null;
45
+ }
46
+ }
47
+ /**
48
+ * Retrieve relevant context for a given query.
49
+ */
50
+ async getContext(query) {
51
+ if (this.ragEnabled && this.rag) {
52
+ const filter = this.ragMetadataFilter && Object.keys(this.ragMetadataFilter).length > 0
53
+ ? this.ragMetadataFilter
54
+ : undefined;
55
+ const results = await this.rag.query(query, 5, filter);
56
+ let context = results.map(r => r.content).join('\n\n---\n\n');
57
+ context = deduplicateRetrievalBlocks(context);
58
+ if (this.summarizer.exceedsBudget(context)) {
59
+ return deduplicateRetrievalBlocks(this.summarizer.summarize(context));
60
+ }
61
+ return context;
62
+ }
63
+ const mem = await this.readMemoryFile();
64
+ return mem ? deduplicateRetrievalBlocks(mem) : '';
65
+ }
66
+ /**
67
+ * Ingest a document into the knowledge base.
68
+ */
69
+ async ingest(id, content, metadata = {}) {
70
+ if (this.ragEnabled && this.rag) {
71
+ await this.rag.addDocument(id, content, metadata);
72
+ }
73
+ else {
74
+ await this.appendToMemory(id, content);
75
+ }
76
+ }
77
+ /**
78
+ * Write a summary/memo to MEMORY.md (fallback when RAG is unavailable).
79
+ */
80
+ async appendToMemory(title, content) {
81
+ const timestamp = new Date().toISOString();
82
+ const entry = `\n## ${title}\n_${timestamp}_\n\n${content}\n`;
83
+ try {
84
+ await fs.appendFile(this.memoryPath, entry);
85
+ }
86
+ catch {
87
+ await fs.writeFile(this.memoryPath, `# AgCEL Memory\n${entry}`);
88
+ }
89
+ }
90
+ /**
91
+ * Read the MEMORY.md fallback file.
92
+ */
93
+ async readMemoryFile() {
94
+ try {
95
+ return await fs.readFile(this.memoryPath, 'utf-8');
96
+ }
97
+ catch {
98
+ return '';
99
+ }
100
+ }
101
+ isRagEnabled() {
102
+ return this.ragEnabled;
103
+ }
104
+ getRagMode() {
105
+ return this.ragMode;
106
+ }
107
+ getRag() {
108
+ return this.rag;
109
+ }
110
+ getSummarizer() {
111
+ return this.summarizer;
112
+ }
113
+ }
114
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Builds the text used for intent detection and RAG when a conversation
3
+ * is in progress, so agent selection can change as the topic evolves.
4
+ */
5
+ export type ConversationTurn = {
6
+ role: 'user' | 'assistant' | string;
7
+ content: string;
8
+ };
9
+ export declare function buildRoutingQuery(currentQuery: string, history: ConversationTurn[] | undefined, maxChars?: number): string;
10
+ //# sourceMappingURL=conversation-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-routing.d.ts","sourceRoot":"","sources":["../../src/core/conversation-routing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,gBAAgB,EAAE,GAAG,SAAS,EACvC,QAAQ,GAAE,MAA0B,GACnC,MAAM,CAuBR"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Builds the text used for intent detection and RAG when a conversation
3
+ * is in progress, so agent selection can change as the topic evolves.
4
+ */
5
+ const DEFAULT_MAX_CHARS = 8000;
6
+ export function buildRoutingQuery(currentQuery, history, maxChars = DEFAULT_MAX_CHARS) {
7
+ const trimmed = currentQuery.trim();
8
+ if (!history?.length) {
9
+ return trimmed;
10
+ }
11
+ const parts = [];
12
+ for (const turn of history) {
13
+ const label = turn.role === 'user'
14
+ ? 'User'
15
+ : turn.role === 'assistant'
16
+ ? 'Assistant'
17
+ : String(turn.role);
18
+ parts.push(`${label}: ${turn.content.trim()}`);
19
+ }
20
+ parts.push(`User: ${trimmed}`);
21
+ let combined = parts.join('\n\n');
22
+ if (combined.length > maxChars) {
23
+ combined = combined.slice(-maxChars);
24
+ }
25
+ return combined;
26
+ }
27
+ //# sourceMappingURL=conversation-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-routing.js","sourceRoot":"","sources":["../../src/core/conversation-routing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,MAAM,UAAU,iBAAiB,CAC/B,YAAoB,EACpB,OAAuC,EACvC,WAAmB,iBAAiB;IAEpC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IACpC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,MAAM;YAClB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW;gBACzB,CAAC,CAAC,WAAW;gBACb,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IAE/B,IAAI,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC/B,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=conversation-routing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-routing.test.d.ts","sourceRoot":"","sources":["../../src/core/conversation-routing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildRoutingQuery } from './conversation-routing.js';
3
+ describe('buildRoutingQuery', () => {
4
+ it('Given no history when building routing query then returns the current query only', () => {
5
+ const q = ' fix the bug ';
6
+ expect(buildRoutingQuery(q, undefined)).toBe('fix the bug');
7
+ expect(buildRoutingQuery(q, [])).toBe('fix the bug');
8
+ });
9
+ it('Given prior turns when building routing query then concatenates roles and caps length', () => {
10
+ const history = [
11
+ { role: 'user', content: 'Need React layout help' },
12
+ { role: 'assistant', content: 'Here is a wireframe idea.' }
13
+ ];
14
+ const out = buildRoutingQuery('Now the Python API returns 500', history);
15
+ expect(out).toContain('User: Need React layout help');
16
+ expect(out).toContain('Assistant: Here is a wireframe idea.');
17
+ expect(out).toContain('User: Now the Python API returns 500');
18
+ });
19
+ it('Given combined text exceeds maxChars when building then keeps the suffix', () => {
20
+ const filler = 'x'.repeat(100);
21
+ const history = [{ role: 'user', content: filler }];
22
+ const current = 'END_MARKER_UNIQUE';
23
+ const max = 200;
24
+ const out = buildRoutingQuery(current, history, max);
25
+ expect(out.length).toBeLessThanOrEqual(max);
26
+ expect(out).toContain('END_MARKER_UNIQUE');
27
+ });
28
+ });
29
+ //# sourceMappingURL=conversation-routing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-routing.test.js","sourceRoot":"","sources":["../../src/core/conversation-routing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,CAAC,GAAG,iBAAiB,CAAC;QAC5B,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE;QAC/F,MAAM,OAAO,GAAG;YACd,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,wBAAwB,EAAE;YAC5D,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,2BAA2B,EAAE;SACrE,CAAC;QACF,MAAM,GAAG,GAAG,iBAAiB,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,mBAAmB,CAAC;QACpC,MAAM,GAAG,GAAG,GAAG,CAAC;QAChB,MAAM,GAAG,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { Guardrail } from './schema.js';
2
+ export interface ValidationResult {
3
+ passed: boolean;
4
+ violations: Violation[];
5
+ }
6
+ export interface Violation {
7
+ guardrailId: string;
8
+ severity: 'error' | 'warning';
9
+ description: string;
10
+ detail: string;
11
+ }
12
+ /**
13
+ * Validates agent output against a set of guardrails.
14
+ * - 'error' violations cause the validation to fail.
15
+ * - 'warning' violations are flagged but don't block.
16
+ */
17
+ export declare class GuardrailValidator {
18
+ validate(output: string, guardrails: Guardrail[]): ValidationResult;
19
+ /**
20
+ * Format violations into a human-readable report.
21
+ */
22
+ formatReport(result: ValidationResult): string;
23
+ private checkPattern;
24
+ private checkForbiddenTerms;
25
+ }
26
+ //# sourceMappingURL=guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,gBAAgB;IA6BnE;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;IAmB9C,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,mBAAmB;CAa5B"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Validates agent output against a set of guardrails.
3
+ * - 'error' violations cause the validation to fail.
4
+ * - 'warning' violations are flagged but don't block.
5
+ */
6
+ export class GuardrailValidator {
7
+ validate(output, guardrails) {
8
+ const violations = [];
9
+ for (const rule of guardrails) {
10
+ // Pattern check
11
+ if (rule.pattern) {
12
+ this.checkPattern(output, rule, violations);
13
+ }
14
+ // Forbidden terms check
15
+ if (rule.forbiddenTerms) {
16
+ this.checkForbiddenTerms(output, rule, violations);
17
+ }
18
+ // Max length check
19
+ if (rule.maxLength !== undefined && output.length > rule.maxLength) {
20
+ violations.push({
21
+ guardrailId: rule.id,
22
+ severity: rule.severity,
23
+ description: rule.description,
24
+ detail: `Output length (${output.length}) exceeds max (${rule.maxLength}).`
25
+ });
26
+ }
27
+ }
28
+ const hasErrors = violations.some(v => v.severity === 'error');
29
+ return { passed: !hasErrors, violations };
30
+ }
31
+ /**
32
+ * Format violations into a human-readable report.
33
+ */
34
+ formatReport(result) {
35
+ if (result.violations.length === 0) {
36
+ return 'All guardrails passed.';
37
+ }
38
+ const lines = [
39
+ result.passed ? 'Guardrail warnings:' : 'Guardrail violations (output blocked):'
40
+ ];
41
+ for (const v of result.violations) {
42
+ lines.push(` [${v.severity}] [${v.guardrailId}] ${v.description}`, ` ${v.detail}`);
43
+ }
44
+ return lines.join('\n');
45
+ }
46
+ checkPattern(output, rule, violations) {
47
+ if (!rule.pattern)
48
+ return;
49
+ const regex = new RegExp(rule.pattern, 'gi');
50
+ const matches = output.match(regex);
51
+ if (!matches)
52
+ return;
53
+ violations.push({
54
+ guardrailId: rule.id,
55
+ severity: rule.severity,
56
+ description: rule.description,
57
+ detail: `Pattern "${rule.pattern}" matched ${matches.length} time(s).`
58
+ });
59
+ }
60
+ checkForbiddenTerms(output, rule, violations) {
61
+ if (!rule.forbiddenTerms)
62
+ return;
63
+ const lowerOutput = output.toLowerCase();
64
+ for (const term of rule.forbiddenTerms) {
65
+ if (!lowerOutput.includes(term.toLowerCase()))
66
+ continue;
67
+ violations.push({
68
+ guardrailId: rule.id,
69
+ severity: rule.severity,
70
+ description: rule.description,
71
+ detail: `Forbidden term "${term}" detected.`
72
+ });
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=guardrails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../src/core/guardrails.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=guardrails.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.test.d.ts","sourceRoot":"","sources":["../../src/core/guardrails.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { GuardrailValidator } from './guardrails.js';
3
+ describe('GuardrailValidator', () => {
4
+ it('Given clean output when validating then passes with no violations', () => {
5
+ const validator = new GuardrailValidator();
6
+ const guardrails = [
7
+ { id: 'G1', description: 'No profanity allowed', severity: 'error', forbiddenTerms: ['badword'] }
8
+ ];
9
+ const result = validator.validate('All good here.', guardrails);
10
+ expect(result.passed).toBe(true);
11
+ expect(result.violations).toHaveLength(0);
12
+ });
13
+ it('Given forbidden term when validating then fails with error violation', () => {
14
+ const validator = new GuardrailValidator();
15
+ const guardrails = [
16
+ { id: 'G1', description: 'No profanity allowed', severity: 'error', forbiddenTerms: ['badword'] }
17
+ ];
18
+ const result = validator.validate('This contains a badword.', guardrails);
19
+ expect(result.passed).toBe(false);
20
+ expect(result.violations).toHaveLength(1);
21
+ expect(result.violations[0]?.guardrailId).toBe('G1');
22
+ expect(result.violations[0]?.severity).toBe('error');
23
+ });
24
+ it('Given maxLength warning when validating then passes with warning violation', () => {
25
+ const validator = new GuardrailValidator();
26
+ const guardrails = [
27
+ { id: 'G2', description: 'Output must be concise', severity: 'warning', maxLength: 10 }
28
+ ];
29
+ const result = validator.validate('This is too long.', guardrails);
30
+ expect(result.passed).toBe(true);
31
+ expect(result.violations).toHaveLength(1);
32
+ expect(result.violations[0]?.severity).toBe('warning');
33
+ });
34
+ });
35
+ //# sourceMappingURL=guardrails.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.test.js","sourceRoot":"","sources":["../../src/core/guardrails.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGrD,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAgB;YAC9B,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE;SAClG,CAAC;QAEF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;QAEhE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAgB;YAC9B,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE;SAClG,CAAC;QAEF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,0BAA0B,EAAE,UAAU,CAAC,CAAC;QAE1E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAgB;YAC9B,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,wBAAwB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;SACxF,CAAC;QAEF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;QAEnE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { Agent } from './schema.js';
2
+ export interface IntentResult {
3
+ bestAgent: Agent | null;
4
+ confidence: number;
5
+ /** When confidence is below threshold, this contains a suggestion */
6
+ suggestion: string | null;
7
+ }
8
+ /** Score how well `lowerText` matches an agent (lowercased query text). */
9
+ export declare function scoreAgentAgainstText(lowerText: string, agent: Agent): number;
10
+ export declare function agentSemanticProfile(agent: Agent): string;
11
+ export interface DetectIntentOptions {
12
+ /** Latest user message; weighted extra vs `query` so routing can follow topic shifts. */
13
+ latestUserTurn?: string;
14
+ /** Multiplier for `scoreAgentAgainstText(latest, agent)` (default 3). */
15
+ latestTurnWeight?: number;
16
+ }
17
+ export declare class IntentEngine {
18
+ private threshold;
19
+ constructor(threshold?: number);
20
+ detectIntent(query: string, agents: Agent[], options?: DetectIntentOptions): IntentResult;
21
+ }
22
+ //# sourceMappingURL=intent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAoB7E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,mBAAmB;IAClC,yFAAyF;IACzF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,GAAE,MAA6B;IAIpD,YAAY,CACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,EAAE,EACf,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY;CAqDhB"}
@@ -0,0 +1,79 @@
1
+ import { textCosineSimilarity } from './text-similarity.js';
2
+ const CONFIDENCE_THRESHOLD = 0.5;
3
+ /** Score how well `lowerText` matches an agent (lowercased query text). */
4
+ export function scoreAgentAgainstText(lowerText, agent) {
5
+ let score = 0;
6
+ if (lowerText.includes(agent.name.toLowerCase()))
7
+ score += 10;
8
+ const roleWords = agent.role.toLowerCase().split(/\s+/);
9
+ for (const word of roleWords) {
10
+ if (word.length > 3 && lowerText.includes(word))
11
+ score += 2;
12
+ }
13
+ const descWords = agent.description.toLowerCase().split(/\s+/);
14
+ for (const word of descWords) {
15
+ if (word.length > 3 && lowerText.includes(word))
16
+ score += 1;
17
+ }
18
+ for (const skill of agent.skills) {
19
+ if (lowerText.includes(skill.toLowerCase()))
20
+ score += 5;
21
+ }
22
+ return score;
23
+ }
24
+ export function agentSemanticProfile(agent) {
25
+ return [agent.name, agent.description, agent.role, ...agent.skills].join(' ');
26
+ }
27
+ export class IntentEngine {
28
+ threshold;
29
+ constructor(threshold = CONFIDENCE_THRESHOLD) {
30
+ this.threshold = threshold;
31
+ }
32
+ detectIntent(query, agents, options) {
33
+ if (agents.length === 0) {
34
+ return {
35
+ bestAgent: null,
36
+ confidence: 0,
37
+ suggestion: 'No agents registered. Run `agcel create-agent` to create one, or provide skill keywords to help AgCEL build one for you.'
38
+ };
39
+ }
40
+ let bestAgent = agents[0];
41
+ let maxScore = 0;
42
+ const lowerQuery = query.toLowerCase();
43
+ const latest = options?.latestUserTurn?.toLowerCase().trim() ?? '';
44
+ const latestWeight = options?.latestTurnWeight ?? 3;
45
+ const useRecencyBoost = Boolean(latest && latest !== lowerQuery);
46
+ for (const agent of agents) {
47
+ const profile = agentSemanticProfile(agent).toLowerCase();
48
+ let score = scoreAgentAgainstText(lowerQuery, agent);
49
+ score += textCosineSimilarity(lowerQuery, profile) * 24;
50
+ if (useRecencyBoost) {
51
+ score += scoreAgentAgainstText(latest, agent) * latestWeight;
52
+ score += textCosineSimilarity(latest, profile) * latestWeight * 8;
53
+ }
54
+ if (score > maxScore) {
55
+ maxScore = score;
56
+ bestAgent = agent;
57
+ }
58
+ }
59
+ const confidenceDivisor = useRecencyBoost ? 95 : 38;
60
+ const confidence = Math.min(maxScore / confidenceDivisor, 1);
61
+ if (confidence < this.threshold) {
62
+ return {
63
+ bestAgent: confidence > 0 ? bestAgent : null,
64
+ confidence,
65
+ suggestion: [
66
+ `Low confidence (${(confidence * 100).toFixed(0)}%) - no agent is a strong match for this query.`,
67
+ `Available agents: ${agents.map(a => a.name).join(', ')}`,
68
+ `Suggestion: Run \`agcel suggest "<your query>"\` for next steps, \`agcel create-agent --research\` to build a persona with best-practice hints, or \`agcel create-skill\` for a new skill bundle.`
69
+ ].join('\n')
70
+ };
71
+ }
72
+ return {
73
+ bestAgent,
74
+ confidence,
75
+ suggestion: null
76
+ };
77
+ }
78
+ }
79
+ //# sourceMappingURL=intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=intent.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.test.d.ts","sourceRoot":"","sources":["../../src/core/intent.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { IntentEngine, scoreAgentAgainstText } from './intent.js';
3
+ const pythonAgent = {
4
+ name: 'python-expert',
5
+ description: 'Python django asyncio debugging',
6
+ role: 'Python engineer for APIs and servers',
7
+ skills: ['python']
8
+ };
9
+ const uiAgent = {
10
+ name: 'ui-expert',
11
+ description: 'Figma mockups React layout design',
12
+ role: 'Designer for UI and product visuals',
13
+ skills: ['design']
14
+ };
15
+ describe('IntentEngine', () => {
16
+ it('Given only the current query when detecting intent then behavior matches single-shot routing', () => {
17
+ const engine = new IntentEngine(0.25);
18
+ const agents = [pythonAgent, uiAgent];
19
+ const q = 'Need a Figma mockup for onboarding';
20
+ const combined = q;
21
+ const withRecency = engine.detectIntent(combined, agents, {
22
+ latestUserTurn: q
23
+ });
24
+ const without = engine.detectIntent(combined, agents);
25
+ expect(withRecency.bestAgent?.name).toBe(without.bestAgent?.name);
26
+ });
27
+ it('Given long prior UI thread when latest turn is Python then best agent follows the latest turn', () => {
28
+ const engine = new IntentEngine(0.25);
29
+ const agents = [pythonAgent, uiAgent];
30
+ const routing = 'User: Build a Figma dashboard mockup\n\nAssistant: Here are frames.\n\nUser: Fix the Django 500 in our Python API';
31
+ const result = engine.detectIntent(routing, agents, {
32
+ latestUserTurn: 'Fix the Django 500 in our Python API'
33
+ });
34
+ expect(result.bestAgent?.name).toBe('python-expert');
35
+ });
36
+ });
37
+ describe('scoreAgentAgainstText', () => {
38
+ it('Given django in text when scoring python agent then returns a positive score', () => {
39
+ const s = scoreAgentAgainstText('debug django view', pythonAgent);
40
+ expect(s).toBeGreaterThan(0);
41
+ });
42
+ });
43
+ //# sourceMappingURL=intent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.test.js","sourceRoot":"","sources":["../../src/core/intent.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGlE,MAAM,WAAW,GAAU;IACzB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,iCAAiC;IAC9C,IAAI,EAAE,sCAAsC;IAC5C,MAAM,EAAE,CAAC,QAAQ,CAAC;CACnB,CAAC;AAEF,MAAM,OAAO,GAAU;IACrB,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,mCAAmC;IAChD,IAAI,EAAE,qCAAqC;IAC3C,MAAM,EAAE,CAAC,QAAQ,CAAC;CACnB,CAAC;AAEF,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,8FAA8F,EAAE,GAAG,EAAE;QACtG,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,oCAAoC,CAAC;QAC/C,MAAM,QAAQ,GAAG,CAAC,CAAC;QACnB,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE;YACxD,cAAc,EAAE,CAAC;SAClB,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+FAA+F,EAAE,GAAG,EAAE;QACvG,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,OAAO,GACX,mHAAmH,CAAC;QACtH,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE;YAClD,cAAc,EAAE,sCAAsC;SACvD,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,CAAC,GAAG,qBAAqB,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QAClE,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}