@code-rag/core 0.1.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 (347) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/auth/audit-log.d.ts +35 -0
  4. package/dist/auth/audit-log.js +110 -0
  5. package/dist/auth/audit-log.js.map +1 -0
  6. package/dist/auth/audit-log.test.d.ts +1 -0
  7. package/dist/auth/audit-log.test.js +261 -0
  8. package/dist/auth/audit-log.test.js.map +1 -0
  9. package/dist/auth/index.d.ts +6 -0
  10. package/dist/auth/index.js +5 -0
  11. package/dist/auth/index.js.map +1 -0
  12. package/dist/auth/oidc-provider.d.ts +49 -0
  13. package/dist/auth/oidc-provider.js +358 -0
  14. package/dist/auth/oidc-provider.js.map +1 -0
  15. package/dist/auth/oidc-provider.test.d.ts +1 -0
  16. package/dist/auth/oidc-provider.test.js +520 -0
  17. package/dist/auth/oidc-provider.test.js.map +1 -0
  18. package/dist/auth/rbac.d.ts +29 -0
  19. package/dist/auth/rbac.js +75 -0
  20. package/dist/auth/rbac.js.map +1 -0
  21. package/dist/auth/rbac.test.d.ts +1 -0
  22. package/dist/auth/rbac.test.js +224 -0
  23. package/dist/auth/rbac.test.js.map +1 -0
  24. package/dist/auth/saml-provider.d.ts +51 -0
  25. package/dist/auth/saml-provider.js +355 -0
  26. package/dist/auth/saml-provider.js.map +1 -0
  27. package/dist/auth/saml-provider.test.d.ts +1 -0
  28. package/dist/auth/saml-provider.test.js +422 -0
  29. package/dist/auth/saml-provider.test.js.map +1 -0
  30. package/dist/auth/types.d.ts +81 -0
  31. package/dist/auth/types.js +11 -0
  32. package/dist/auth/types.js.map +1 -0
  33. package/dist/auth/types.test.d.ts +1 -0
  34. package/dist/auth/types.test.js +147 -0
  35. package/dist/auth/types.test.js.map +1 -0
  36. package/dist/backlog/ab-reference-scanner.d.ts +10 -0
  37. package/dist/backlog/ab-reference-scanner.js +22 -0
  38. package/dist/backlog/ab-reference-scanner.js.map +1 -0
  39. package/dist/backlog/ab-reference-scanner.test.d.ts +1 -0
  40. package/dist/backlog/ab-reference-scanner.test.js +83 -0
  41. package/dist/backlog/ab-reference-scanner.test.js.map +1 -0
  42. package/dist/backlog/azure-devops-provider.d.ts +59 -0
  43. package/dist/backlog/azure-devops-provider.js +283 -0
  44. package/dist/backlog/azure-devops-provider.js.map +1 -0
  45. package/dist/backlog/backlog-provider.d.ts +13 -0
  46. package/dist/backlog/backlog-provider.js +6 -0
  47. package/dist/backlog/backlog-provider.js.map +1 -0
  48. package/dist/backlog/backlog-provider.test.d.ts +1 -0
  49. package/dist/backlog/backlog-provider.test.js +426 -0
  50. package/dist/backlog/backlog-provider.test.js.map +1 -0
  51. package/dist/backlog/clickup-provider.d.ts +55 -0
  52. package/dist/backlog/clickup-provider.js +301 -0
  53. package/dist/backlog/clickup-provider.js.map +1 -0
  54. package/dist/backlog/clickup-provider.test.d.ts +1 -0
  55. package/dist/backlog/clickup-provider.test.js +426 -0
  56. package/dist/backlog/clickup-provider.test.js.map +1 -0
  57. package/dist/backlog/clickup-reference-scanner.d.ts +10 -0
  58. package/dist/backlog/clickup-reference-scanner.js +32 -0
  59. package/dist/backlog/clickup-reference-scanner.js.map +1 -0
  60. package/dist/backlog/clickup-reference-scanner.test.d.ts +1 -0
  61. package/dist/backlog/clickup-reference-scanner.test.js +92 -0
  62. package/dist/backlog/clickup-reference-scanner.test.js.map +1 -0
  63. package/dist/backlog/code-linker.d.ts +63 -0
  64. package/dist/backlog/code-linker.js +90 -0
  65. package/dist/backlog/code-linker.js.map +1 -0
  66. package/dist/backlog/code-linker.test.d.ts +1 -0
  67. package/dist/backlog/code-linker.test.js +325 -0
  68. package/dist/backlog/code-linker.test.js.map +1 -0
  69. package/dist/backlog/index.d.ts +14 -0
  70. package/dist/backlog/index.js +8 -0
  71. package/dist/backlog/index.js.map +1 -0
  72. package/dist/backlog/jira-provider.d.ts +60 -0
  73. package/dist/backlog/jira-provider.js +272 -0
  74. package/dist/backlog/jira-provider.js.map +1 -0
  75. package/dist/backlog/jira-provider.test.d.ts +1 -0
  76. package/dist/backlog/jira-provider.test.js +449 -0
  77. package/dist/backlog/jira-provider.test.js.map +1 -0
  78. package/dist/backlog/jira-reference-scanner.d.ts +11 -0
  79. package/dist/backlog/jira-reference-scanner.js +26 -0
  80. package/dist/backlog/jira-reference-scanner.js.map +1 -0
  81. package/dist/backlog/jira-reference-scanner.test.d.ts +1 -0
  82. package/dist/backlog/jira-reference-scanner.test.js +127 -0
  83. package/dist/backlog/jira-reference-scanner.test.js.map +1 -0
  84. package/dist/backlog/types.d.ts +22 -0
  85. package/dist/backlog/types.js +1 -0
  86. package/dist/backlog/types.js.map +1 -0
  87. package/dist/chunker/ast-chunker.d.ts +45 -0
  88. package/dist/chunker/ast-chunker.js +292 -0
  89. package/dist/chunker/ast-chunker.js.map +1 -0
  90. package/dist/chunker/ast-chunker.test.d.ts +1 -0
  91. package/dist/chunker/ast-chunker.test.js +391 -0
  92. package/dist/chunker/ast-chunker.test.js.map +1 -0
  93. package/dist/chunker/chunker.d.ts +8 -0
  94. package/dist/chunker/chunker.js +1 -0
  95. package/dist/chunker/chunker.js.map +1 -0
  96. package/dist/chunker/index.d.ts +3 -0
  97. package/dist/chunker/index.js +2 -0
  98. package/dist/chunker/index.js.map +1 -0
  99. package/dist/config/config-parser.d.ts +15 -0
  100. package/dist/config/config-parser.js +283 -0
  101. package/dist/config/config-parser.js.map +1 -0
  102. package/dist/config/config-parser.test.d.ts +1 -0
  103. package/dist/config/config-parser.test.js +699 -0
  104. package/dist/config/config-parser.test.js.map +1 -0
  105. package/dist/docs/confluence-provider.d.ts +121 -0
  106. package/dist/docs/confluence-provider.js +459 -0
  107. package/dist/docs/confluence-provider.js.map +1 -0
  108. package/dist/docs/confluence-provider.test.d.ts +1 -0
  109. package/dist/docs/confluence-provider.test.js +765 -0
  110. package/dist/docs/confluence-provider.test.js.map +1 -0
  111. package/dist/docs/index.d.ts +4 -0
  112. package/dist/docs/index.js +2 -0
  113. package/dist/docs/index.js.map +1 -0
  114. package/dist/docs/sharepoint-provider.d.ts +150 -0
  115. package/dist/docs/sharepoint-provider.js +637 -0
  116. package/dist/docs/sharepoint-provider.js.map +1 -0
  117. package/dist/docs/sharepoint-provider.test.d.ts +1 -0
  118. package/dist/docs/sharepoint-provider.test.js +873 -0
  119. package/dist/docs/sharepoint-provider.test.js.map +1 -0
  120. package/dist/embedding/bm25-index.d.ts +12 -0
  121. package/dist/embedding/bm25-index.js +89 -0
  122. package/dist/embedding/bm25-index.js.map +1 -0
  123. package/dist/embedding/bm25-index.test.d.ts +1 -0
  124. package/dist/embedding/bm25-index.test.js +289 -0
  125. package/dist/embedding/bm25-index.test.js.map +1 -0
  126. package/dist/embedding/hybrid-search.d.ts +13 -0
  127. package/dist/embedding/hybrid-search.js +124 -0
  128. package/dist/embedding/hybrid-search.js.map +1 -0
  129. package/dist/embedding/hybrid-search.test.d.ts +1 -0
  130. package/dist/embedding/hybrid-search.test.js +266 -0
  131. package/dist/embedding/hybrid-search.test.js.map +1 -0
  132. package/dist/embedding/index.d.ts +11 -0
  133. package/dist/embedding/index.js +7 -0
  134. package/dist/embedding/index.js.map +1 -0
  135. package/dist/embedding/lancedb-store.d.ts +21 -0
  136. package/dist/embedding/lancedb-store.js +172 -0
  137. package/dist/embedding/lancedb-store.js.map +1 -0
  138. package/dist/embedding/lancedb-store.test.d.ts +1 -0
  139. package/dist/embedding/lancedb-store.test.js +268 -0
  140. package/dist/embedding/lancedb-store.test.js.map +1 -0
  141. package/dist/embedding/model-lifecycle-manager.d.ts +83 -0
  142. package/dist/embedding/model-lifecycle-manager.js +419 -0
  143. package/dist/embedding/model-lifecycle-manager.js.map +1 -0
  144. package/dist/embedding/model-lifecycle-manager.test.d.ts +1 -0
  145. package/dist/embedding/model-lifecycle-manager.test.js +642 -0
  146. package/dist/embedding/model-lifecycle-manager.test.js.map +1 -0
  147. package/dist/embedding/ollama-embedding-provider.d.ts +16 -0
  148. package/dist/embedding/ollama-embedding-provider.js +74 -0
  149. package/dist/embedding/ollama-embedding-provider.js.map +1 -0
  150. package/dist/embedding/ollama-embedding-provider.test.d.ts +1 -0
  151. package/dist/embedding/ollama-embedding-provider.test.js +198 -0
  152. package/dist/embedding/ollama-embedding-provider.test.js.map +1 -0
  153. package/dist/embedding/openai-compatible-embedding-provider.d.ts +19 -0
  154. package/dist/embedding/openai-compatible-embedding-provider.js +108 -0
  155. package/dist/embedding/openai-compatible-embedding-provider.js.map +1 -0
  156. package/dist/embedding/openai-compatible-embedding-provider.test.d.ts +1 -0
  157. package/dist/embedding/openai-compatible-embedding-provider.test.js +456 -0
  158. package/dist/embedding/openai-compatible-embedding-provider.test.js.map +1 -0
  159. package/dist/embedding/qdrant-store.d.ts +28 -0
  160. package/dist/embedding/qdrant-store.js +174 -0
  161. package/dist/embedding/qdrant-store.js.map +1 -0
  162. package/dist/embedding/qdrant-store.test.d.ts +1 -0
  163. package/dist/embedding/qdrant-store.test.js +359 -0
  164. package/dist/embedding/qdrant-store.test.js.map +1 -0
  165. package/dist/enrichment/index.d.ts +4 -0
  166. package/dist/enrichment/index.js +2 -0
  167. package/dist/enrichment/index.js.map +1 -0
  168. package/dist/enrichment/nl-enricher.d.ts +16 -0
  169. package/dist/enrichment/nl-enricher.js +47 -0
  170. package/dist/enrichment/nl-enricher.js.map +1 -0
  171. package/dist/enrichment/nl-enricher.test.d.ts +1 -0
  172. package/dist/enrichment/nl-enricher.test.js +154 -0
  173. package/dist/enrichment/nl-enricher.test.js.map +1 -0
  174. package/dist/enrichment/ollama-client.d.ts +18 -0
  175. package/dist/enrichment/ollama-client.js +55 -0
  176. package/dist/enrichment/ollama-client.js.map +1 -0
  177. package/dist/enrichment/ollama-client.test.d.ts +1 -0
  178. package/dist/enrichment/ollama-client.test.js +129 -0
  179. package/dist/enrichment/ollama-client.test.js.map +1 -0
  180. package/dist/git/git-client.d.ts +22 -0
  181. package/dist/git/git-client.js +6 -0
  182. package/dist/git/git-client.js.map +1 -0
  183. package/dist/git/git-client.test.d.ts +1 -0
  184. package/dist/git/git-client.test.js +200 -0
  185. package/dist/git/git-client.test.js.map +1 -0
  186. package/dist/git/ignore-filter.d.ts +2 -0
  187. package/dist/git/ignore-filter.js +31 -0
  188. package/dist/git/ignore-filter.js.map +1 -0
  189. package/dist/git/ignore-filter.test.d.ts +1 -0
  190. package/dist/git/ignore-filter.test.js +87 -0
  191. package/dist/git/ignore-filter.test.js.map +1 -0
  192. package/dist/git/index.d.ts +4 -0
  193. package/dist/git/index.js +3 -0
  194. package/dist/git/index.js.map +1 -0
  195. package/dist/git/simple-git-client.d.ts +12 -0
  196. package/dist/git/simple-git-client.js +138 -0
  197. package/dist/git/simple-git-client.js.map +1 -0
  198. package/dist/graph/cross-repo-resolver.d.ts +50 -0
  199. package/dist/graph/cross-repo-resolver.js +315 -0
  200. package/dist/graph/cross-repo-resolver.js.map +1 -0
  201. package/dist/graph/cross-repo-resolver.test.d.ts +1 -0
  202. package/dist/graph/cross-repo-resolver.test.js +548 -0
  203. package/dist/graph/cross-repo-resolver.test.js.map +1 -0
  204. package/dist/graph/dependency-graph.d.ts +44 -0
  205. package/dist/graph/dependency-graph.js +108 -0
  206. package/dist/graph/dependency-graph.js.map +1 -0
  207. package/dist/graph/dependency-graph.test.d.ts +1 -0
  208. package/dist/graph/dependency-graph.test.js +276 -0
  209. package/dist/graph/dependency-graph.test.js.map +1 -0
  210. package/dist/graph/graph-builder.d.ts +11 -0
  211. package/dist/graph/graph-builder.js +113 -0
  212. package/dist/graph/graph-builder.js.map +1 -0
  213. package/dist/graph/graph-builder.test.d.ts +1 -0
  214. package/dist/graph/graph-builder.test.js +178 -0
  215. package/dist/graph/graph-builder.test.js.map +1 -0
  216. package/dist/graph/import-resolver.d.ts +11 -0
  217. package/dist/graph/import-resolver.js +199 -0
  218. package/dist/graph/import-resolver.js.map +1 -0
  219. package/dist/graph/import-resolver.test.d.ts +1 -0
  220. package/dist/graph/import-resolver.test.js +282 -0
  221. package/dist/graph/import-resolver.test.js.map +1 -0
  222. package/dist/graph/index.d.ts +7 -0
  223. package/dist/graph/index.js +4 -0
  224. package/dist/graph/index.js.map +1 -0
  225. package/dist/index.d.ts +31 -0
  226. package/dist/index.js +15 -0
  227. package/dist/index.js.map +1 -0
  228. package/dist/indexer/file-scanner.d.ts +34 -0
  229. package/dist/indexer/file-scanner.js +69 -0
  230. package/dist/indexer/file-scanner.js.map +1 -0
  231. package/dist/indexer/file-scanner.test.d.ts +1 -0
  232. package/dist/indexer/file-scanner.test.js +110 -0
  233. package/dist/indexer/file-scanner.test.js.map +1 -0
  234. package/dist/indexer/file-watcher.d.ts +79 -0
  235. package/dist/indexer/file-watcher.js +148 -0
  236. package/dist/indexer/incremental-indexer.d.ts +67 -0
  237. package/dist/indexer/incremental-indexer.js +142 -0
  238. package/dist/indexer/incremental-indexer.js.map +1 -0
  239. package/dist/indexer/incremental-indexer.test.d.ts +1 -0
  240. package/dist/indexer/incremental-indexer.test.js +266 -0
  241. package/dist/indexer/incremental-indexer.test.js.map +1 -0
  242. package/dist/indexer/index-check.d.ts +22 -0
  243. package/dist/indexer/index-check.js +74 -0
  244. package/dist/indexer/index-check.js.map +1 -0
  245. package/dist/indexer/index-check.test.d.ts +1 -0
  246. package/dist/indexer/index-check.test.js +100 -0
  247. package/dist/indexer/index-check.test.js.map +1 -0
  248. package/dist/indexer/index-state.d.ts +61 -0
  249. package/dist/indexer/index-state.js +82 -0
  250. package/dist/indexer/index-state.js.map +1 -0
  251. package/dist/indexer/index-state.test.d.ts +1 -0
  252. package/dist/indexer/index-state.test.js +140 -0
  253. package/dist/indexer/index-state.test.js.map +1 -0
  254. package/dist/indexer/index.d.ts +12 -0
  255. package/dist/indexer/index.js +6 -0
  256. package/dist/indexer/index.js.map +1 -0
  257. package/dist/indexer/multi-repo-indexer.d.ts +63 -0
  258. package/dist/indexer/multi-repo-indexer.js +144 -0
  259. package/dist/indexer/multi-repo-indexer.js.map +1 -0
  260. package/dist/indexer/multi-repo-indexer.test.d.ts +1 -0
  261. package/dist/indexer/multi-repo-indexer.test.js +238 -0
  262. package/dist/indexer/multi-repo-indexer.test.js.map +1 -0
  263. package/dist/parser/index.d.ts +4 -0
  264. package/dist/parser/index.js +3 -0
  265. package/dist/parser/index.js.map +1 -0
  266. package/dist/parser/language-registry.d.ts +46 -0
  267. package/dist/parser/language-registry.js +219 -0
  268. package/dist/parser/language-registry.js.map +1 -0
  269. package/dist/parser/language-registry.test.d.ts +1 -0
  270. package/dist/parser/language-registry.test.js +225 -0
  271. package/dist/parser/language-registry.test.js.map +1 -0
  272. package/dist/parser/markdown-parser.d.ts +124 -0
  273. package/dist/parser/markdown-parser.js +487 -0
  274. package/dist/parser/markdown-parser.js.map +1 -0
  275. package/dist/parser/markdown-parser.test.d.ts +1 -0
  276. package/dist/parser/markdown-parser.test.js +600 -0
  277. package/dist/parser/markdown-parser.test.js.map +1 -0
  278. package/dist/parser/tree-sitter-parser.d.ts +32 -0
  279. package/dist/parser/tree-sitter-parser.js +146 -0
  280. package/dist/parser/tree-sitter-parser.js.map +1 -0
  281. package/dist/retrieval/context-expander.d.ts +51 -0
  282. package/dist/retrieval/context-expander.js +218 -0
  283. package/dist/retrieval/context-expander.js.map +1 -0
  284. package/dist/retrieval/context-expander.test.d.ts +1 -0
  285. package/dist/retrieval/context-expander.test.js +339 -0
  286. package/dist/retrieval/context-expander.test.js.map +1 -0
  287. package/dist/retrieval/cross-encoder-reranker.d.ts +16 -0
  288. package/dist/retrieval/cross-encoder-reranker.js +90 -0
  289. package/dist/retrieval/cross-encoder-reranker.js.map +1 -0
  290. package/dist/retrieval/cross-encoder-reranker.test.d.ts +1 -0
  291. package/dist/retrieval/cross-encoder-reranker.test.js +305 -0
  292. package/dist/retrieval/cross-encoder-reranker.test.js.map +1 -0
  293. package/dist/retrieval/index.d.ts +8 -0
  294. package/dist/retrieval/index.js +4 -0
  295. package/dist/retrieval/index.js.map +1 -0
  296. package/dist/retrieval/query-analyzer.d.ts +29 -0
  297. package/dist/retrieval/query-analyzer.js +238 -0
  298. package/dist/retrieval/query-analyzer.js.map +1 -0
  299. package/dist/retrieval/query-analyzer.test.d.ts +1 -0
  300. package/dist/retrieval/query-analyzer.test.js +236 -0
  301. package/dist/retrieval/query-analyzer.test.js.map +1 -0
  302. package/dist/retrieval/token-budget.d.ts +51 -0
  303. package/dist/retrieval/token-budget.js +141 -0
  304. package/dist/retrieval/token-budget.js.map +1 -0
  305. package/dist/retrieval/token-budget.test.d.ts +1 -0
  306. package/dist/retrieval/token-budget.test.js +404 -0
  307. package/dist/retrieval/token-budget.test.js.map +1 -0
  308. package/dist/storage/azure-blob-provider.d.ts +19 -0
  309. package/dist/storage/azure-blob-provider.js +199 -0
  310. package/dist/storage/azure-blob-provider.js.map +1 -0
  311. package/dist/storage/azure-blob-provider.test.d.ts +1 -0
  312. package/dist/storage/azure-blob-provider.test.js +250 -0
  313. package/dist/storage/azure-blob-provider.test.js.map +1 -0
  314. package/dist/storage/gcs-provider.d.ts +22 -0
  315. package/dist/storage/gcs-provider.js +241 -0
  316. package/dist/storage/gcs-provider.js.map +1 -0
  317. package/dist/storage/gcs-provider.test.d.ts +1 -0
  318. package/dist/storage/gcs-provider.test.js +299 -0
  319. package/dist/storage/gcs-provider.test.js.map +1 -0
  320. package/dist/storage/index.d.ts +5 -0
  321. package/dist/storage/index.js +4 -0
  322. package/dist/storage/index.js.map +1 -0
  323. package/dist/storage/s3-provider.d.ts +21 -0
  324. package/dist/storage/s3-provider.js +220 -0
  325. package/dist/storage/s3-provider.js.map +1 -0
  326. package/dist/storage/s3-provider.test.d.ts +1 -0
  327. package/dist/storage/s3-provider.test.js +329 -0
  328. package/dist/storage/s3-provider.test.js.map +1 -0
  329. package/dist/storage/types.d.ts +65 -0
  330. package/dist/storage/types.js +12 -0
  331. package/dist/storage/types.js.map +1 -0
  332. package/dist/types/chunk.d.ts +32 -0
  333. package/dist/types/chunk.js +1 -0
  334. package/dist/types/chunk.js.map +1 -0
  335. package/dist/types/config.d.ts +71 -0
  336. package/dist/types/config.js +1 -0
  337. package/dist/types/config.js.map +1 -0
  338. package/dist/types/index.d.ts +5 -0
  339. package/dist/types/index.js +1 -0
  340. package/dist/types/index.js.map +1 -0
  341. package/dist/types/provider.d.ts +54 -0
  342. package/dist/types/provider.js +36 -0
  343. package/dist/types/provider.js.map +1 -0
  344. package/dist/types/search.d.ts +27 -0
  345. package/dist/types/search.js +1 -0
  346. package/dist/types/search.js.map +1 -0
  347. package/package.json +70 -0
@@ -0,0 +1,404 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { TokenBudgetOptimizer } from './token-budget.js';
3
+ function makeSearchResult(chunkId, overrides = {}) {
4
+ return {
5
+ chunkId,
6
+ content: `content of ${chunkId}`,
7
+ nlSummary: `summary of ${chunkId}`,
8
+ score: 0.9,
9
+ method: 'hybrid',
10
+ metadata: {
11
+ chunkType: 'function',
12
+ name: chunkId,
13
+ declarations: [],
14
+ imports: [],
15
+ exports: [],
16
+ },
17
+ chunk: {
18
+ id: chunkId,
19
+ content: `content of ${chunkId}`,
20
+ nlSummary: `summary of ${chunkId}`,
21
+ filePath: `src/${chunkId}.ts`,
22
+ startLine: 1,
23
+ endLine: 10,
24
+ language: 'typescript',
25
+ metadata: {
26
+ chunkType: 'function',
27
+ name: chunkId,
28
+ declarations: [],
29
+ imports: [],
30
+ exports: [],
31
+ },
32
+ },
33
+ ...overrides,
34
+ };
35
+ }
36
+ function makeRelatedChunk(chunkId, relationship = 'imports', distance = 1) {
37
+ return {
38
+ chunk: makeSearchResult(chunkId),
39
+ relationship,
40
+ distance,
41
+ };
42
+ }
43
+ function makeExpandedContext(overrides = {}) {
44
+ return {
45
+ primaryResults: [
46
+ makeSearchResult('primary1', { score: 0.95 }),
47
+ makeSearchResult('primary2', { score: 0.85 }),
48
+ ],
49
+ relatedChunks: [
50
+ makeRelatedChunk('related1', 'imports', 1),
51
+ makeRelatedChunk('related2', 'imported_by', 2),
52
+ ],
53
+ graphExcerpt: {
54
+ nodes: ['primary1', 'primary2', 'related1', 'related2'],
55
+ edges: [
56
+ { from: 'primary1', to: 'related1', type: 'imports' },
57
+ { from: 'related2', to: 'primary2', type: 'imports' },
58
+ ],
59
+ },
60
+ ...overrides,
61
+ };
62
+ }
63
+ describe('TokenBudgetOptimizer', () => {
64
+ describe('constructor', () => {
65
+ it('should use default config when none provided', () => {
66
+ const optimizer = new TokenBudgetOptimizer();
67
+ // Validate by checking estimateTokens works
68
+ expect(optimizer.estimateTokens('hello')).toBe(2);
69
+ });
70
+ it('should merge partial config with defaults', () => {
71
+ const optimizer = new TokenBudgetOptimizer({ maxTokens: 4000 });
72
+ // The optimizer should work with partial config
73
+ const result = optimizer.assemble(makeExpandedContext());
74
+ expect(result).toBeDefined();
75
+ });
76
+ });
77
+ describe('estimateTokens', () => {
78
+ it('should estimate tokens as text.length / 4', () => {
79
+ const optimizer = new TokenBudgetOptimizer();
80
+ expect(optimizer.estimateTokens('abcd')).toBe(1);
81
+ expect(optimizer.estimateTokens('abcdefgh')).toBe(2);
82
+ expect(optimizer.estimateTokens('abc')).toBe(1); // ceil(3/4) = 1
83
+ });
84
+ it('should return 0 for empty string', () => {
85
+ const optimizer = new TokenBudgetOptimizer();
86
+ expect(optimizer.estimateTokens('')).toBe(0);
87
+ });
88
+ it('should round up fractional tokens', () => {
89
+ const optimizer = new TokenBudgetOptimizer();
90
+ // 5 chars / 4 = 1.25 -> ceil = 2
91
+ expect(optimizer.estimateTokens('abcde')).toBe(2);
92
+ });
93
+ });
94
+ describe('assemble', () => {
95
+ it('should produce a content string with sections', () => {
96
+ const optimizer = new TokenBudgetOptimizer();
97
+ const result = optimizer.assemble(makeExpandedContext());
98
+ expect(result.content).toContain('## Primary Results');
99
+ expect(result.content).toContain('## Related Context');
100
+ expect(result.content).toContain('## Dependency Graph');
101
+ });
102
+ it('should include primary chunk content', () => {
103
+ const optimizer = new TokenBudgetOptimizer();
104
+ const result = optimizer.assemble(makeExpandedContext());
105
+ expect(result.content).toContain('content of primary1');
106
+ expect(result.content).toContain('content of primary2');
107
+ });
108
+ it('should include related chunk content', () => {
109
+ const optimizer = new TokenBudgetOptimizer();
110
+ const result = optimizer.assemble(makeExpandedContext());
111
+ expect(result.content).toContain('content of related1');
112
+ });
113
+ it('should include file path headers for primary chunks', () => {
114
+ const optimizer = new TokenBudgetOptimizer();
115
+ const result = optimizer.assemble(makeExpandedContext());
116
+ expect(result.content).toContain('File: src/primary1.ts');
117
+ });
118
+ it('should include relationship labels for related chunks', () => {
119
+ const optimizer = new TokenBudgetOptimizer();
120
+ const result = optimizer.assemble(makeExpandedContext());
121
+ expect(result.content).toContain('[imports');
122
+ });
123
+ it('should include graph excerpt', () => {
124
+ const optimizer = new TokenBudgetOptimizer();
125
+ const result = optimizer.assemble(makeExpandedContext());
126
+ expect(result.content).toContain('primary1 --[imports]--> related1');
127
+ });
128
+ it('should sort primary results by score descending', () => {
129
+ const expanded = makeExpandedContext({
130
+ primaryResults: [
131
+ makeSearchResult('low', { score: 0.3 }),
132
+ makeSearchResult('high', { score: 0.99 }),
133
+ makeSearchResult('mid', { score: 0.6 }),
134
+ ],
135
+ });
136
+ const optimizer = new TokenBudgetOptimizer();
137
+ const result = optimizer.assemble(expanded);
138
+ // high (0.99) should come before mid (0.6) which should come before low (0.3)
139
+ const highIdx = result.content.indexOf('content of high');
140
+ const midIdx = result.content.indexOf('content of mid');
141
+ const lowIdx = result.content.indexOf('content of low');
142
+ expect(highIdx).toBeLessThan(midIdx);
143
+ expect(midIdx).toBeLessThan(lowIdx);
144
+ });
145
+ it('should sort related chunks by distance ascending', () => {
146
+ const expanded = makeExpandedContext({
147
+ relatedChunks: [
148
+ makeRelatedChunk('far', 'imports', 3),
149
+ makeRelatedChunk('near', 'imports', 1),
150
+ makeRelatedChunk('mid', 'imports', 2),
151
+ ],
152
+ });
153
+ const optimizer = new TokenBudgetOptimizer();
154
+ const result = optimizer.assemble(expanded);
155
+ const nearIdx = result.content.indexOf('content of near');
156
+ const midIdx = result.content.indexOf('content of mid');
157
+ const farIdx = result.content.indexOf('content of far');
158
+ expect(nearIdx).toBeLessThan(midIdx);
159
+ expect(midIdx).toBeLessThan(farIdx);
160
+ });
161
+ it('should set truncated=false when everything fits', () => {
162
+ const optimizer = new TokenBudgetOptimizer({ maxTokens: 100000 });
163
+ const result = optimizer.assemble(makeExpandedContext());
164
+ expect(result.truncated).toBe(false);
165
+ });
166
+ it('should return included primary chunks', () => {
167
+ const optimizer = new TokenBudgetOptimizer();
168
+ const expanded = makeExpandedContext();
169
+ const result = optimizer.assemble(expanded);
170
+ expect(result.primaryChunks.length).toBeGreaterThan(0);
171
+ expect(result.primaryChunks.length).toBeLessThanOrEqual(expanded.primaryResults.length);
172
+ });
173
+ it('should return included related chunks', () => {
174
+ const optimizer = new TokenBudgetOptimizer();
175
+ const expanded = makeExpandedContext();
176
+ const result = optimizer.assemble(expanded);
177
+ expect(result.relatedChunks.length).toBeGreaterThanOrEqual(0);
178
+ expect(result.relatedChunks.length).toBeLessThanOrEqual(expanded.relatedChunks.length);
179
+ });
180
+ it('should report token count', () => {
181
+ const optimizer = new TokenBudgetOptimizer();
182
+ const result = optimizer.assemble(makeExpandedContext());
183
+ expect(result.tokenCount).toBeGreaterThan(0);
184
+ });
185
+ });
186
+ describe('budget overflow handling', () => {
187
+ it('should truncate primary results when budget is very small', () => {
188
+ const optimizer = new TokenBudgetOptimizer({
189
+ maxTokens: 100,
190
+ reserveForAnswer: 0,
191
+ primaryWeight: 1.0,
192
+ relatedWeight: 0,
193
+ graphWeight: 0,
194
+ });
195
+ // Create many large primary results
196
+ const bigResults = Array.from({ length: 20 }, (_, i) => makeSearchResult(`chunk${i}`, {
197
+ score: 0.9 - i * 0.01,
198
+ content: 'x'.repeat(200), // Each chunk ~50 tokens
199
+ }));
200
+ const expanded = makeExpandedContext({
201
+ primaryResults: bigResults,
202
+ relatedChunks: [],
203
+ graphExcerpt: { nodes: [], edges: [] },
204
+ });
205
+ const result = optimizer.assemble(expanded);
206
+ expect(result.primaryChunks.length).toBeLessThan(bigResults.length);
207
+ expect(result.truncated).toBe(true);
208
+ });
209
+ it('should truncate related chunks when budget is limited', () => {
210
+ const optimizer = new TokenBudgetOptimizer({
211
+ maxTokens: 200,
212
+ reserveForAnswer: 0,
213
+ primaryWeight: 0.5,
214
+ relatedWeight: 0.5,
215
+ graphWeight: 0,
216
+ });
217
+ const manyRelated = Array.from({ length: 20 }, (_, i) => makeRelatedChunk(`rel${i}`, 'imports', i + 1));
218
+ const expanded = makeExpandedContext({
219
+ primaryResults: [makeSearchResult('p1', { score: 0.9, content: 'short' })],
220
+ relatedChunks: manyRelated,
221
+ graphExcerpt: { nodes: [], edges: [] },
222
+ });
223
+ const result = optimizer.assemble(expanded);
224
+ expect(result.relatedChunks.length).toBeLessThan(manyRelated.length);
225
+ expect(result.truncated).toBe(true);
226
+ });
227
+ it('should skip graph excerpt when budget is exhausted', () => {
228
+ const optimizer = new TokenBudgetOptimizer({
229
+ maxTokens: 100,
230
+ reserveForAnswer: 0,
231
+ primaryWeight: 0.9,
232
+ relatedWeight: 0.09,
233
+ graphWeight: 0.01, // Only 1 token for graph
234
+ });
235
+ const expanded = makeExpandedContext({
236
+ primaryResults: [makeSearchResult('p1', { score: 0.9, content: 'short' })],
237
+ relatedChunks: [],
238
+ graphExcerpt: {
239
+ nodes: ['a', 'b', 'c', 'd', 'e'],
240
+ edges: [
241
+ { from: 'a', to: 'b', type: 'imports' },
242
+ { from: 'b', to: 'c', type: 'imports' },
243
+ { from: 'c', to: 'd', type: 'imports' },
244
+ ],
245
+ },
246
+ });
247
+ const result = optimizer.assemble(expanded);
248
+ // Graph is too large for 1 token, so it should be excluded and truncated=true
249
+ expect(result.truncated).toBe(true);
250
+ });
251
+ });
252
+ describe('empty inputs', () => {
253
+ it('should handle empty expanded context', () => {
254
+ const optimizer = new TokenBudgetOptimizer();
255
+ const result = optimizer.assemble({
256
+ primaryResults: [],
257
+ relatedChunks: [],
258
+ graphExcerpt: { nodes: [], edges: [] },
259
+ });
260
+ expect(result.content).toBe('');
261
+ expect(result.primaryChunks).toHaveLength(0);
262
+ expect(result.relatedChunks).toHaveLength(0);
263
+ expect(result.tokenCount).toBe(0);
264
+ expect(result.truncated).toBe(false);
265
+ });
266
+ it('should handle context with only primary results', () => {
267
+ const optimizer = new TokenBudgetOptimizer();
268
+ const result = optimizer.assemble({
269
+ primaryResults: [makeSearchResult('p1')],
270
+ relatedChunks: [],
271
+ graphExcerpt: { nodes: [], edges: [] },
272
+ });
273
+ expect(result.content).toContain('## Primary Results');
274
+ expect(result.content).not.toContain('## Related Context');
275
+ expect(result.content).not.toContain('## Dependency Graph');
276
+ });
277
+ it('should handle context with only related chunks', () => {
278
+ const optimizer = new TokenBudgetOptimizer();
279
+ const result = optimizer.assemble({
280
+ primaryResults: [],
281
+ relatedChunks: [makeRelatedChunk('r1')],
282
+ graphExcerpt: { nodes: [], edges: [] },
283
+ });
284
+ expect(result.content).not.toContain('## Primary Results');
285
+ expect(result.content).toContain('## Related Context');
286
+ });
287
+ });
288
+ describe('budget allocation', () => {
289
+ it('should respect custom weight allocation', () => {
290
+ const optimizer = new TokenBudgetOptimizer({
291
+ maxTokens: 10000,
292
+ reserveForAnswer: 0,
293
+ primaryWeight: 1.0,
294
+ relatedWeight: 0,
295
+ graphWeight: 0,
296
+ });
297
+ const expanded = makeExpandedContext();
298
+ const result = optimizer.assemble(expanded);
299
+ // With 0 weight for related and graph, they should be empty
300
+ expect(result.relatedChunks).toHaveLength(0);
301
+ expect(result.content).not.toContain('## Related Context');
302
+ expect(result.content).not.toContain('## Dependency Graph');
303
+ });
304
+ it('should reserve tokens for answer', () => {
305
+ // With maxTokens=200, reserveForAnswer=190, only 10 tokens available
306
+ const optimizer = new TokenBudgetOptimizer({
307
+ maxTokens: 200,
308
+ reserveForAnswer: 190,
309
+ primaryWeight: 1.0,
310
+ relatedWeight: 0,
311
+ graphWeight: 0,
312
+ });
313
+ const bigResults = Array.from({ length: 10 }, (_, i) => makeSearchResult(`chunk${i}`, {
314
+ score: 0.9,
315
+ content: 'x'.repeat(100),
316
+ }));
317
+ const result = optimizer.assemble({
318
+ primaryResults: bigResults,
319
+ relatedChunks: [],
320
+ graphExcerpt: { nodes: [], edges: [] },
321
+ });
322
+ // Very limited budget should restrict how many primary results fit
323
+ expect(result.primaryChunks.length).toBeLessThan(bigResults.length);
324
+ });
325
+ });
326
+ describe('formatting', () => {
327
+ it('should format primary chunks with name and type', () => {
328
+ const optimizer = new TokenBudgetOptimizer();
329
+ const result = optimizer.assemble(makeExpandedContext({
330
+ primaryResults: [
331
+ makeSearchResult('myFunc', {
332
+ score: 0.9,
333
+ metadata: {
334
+ chunkType: 'function',
335
+ name: 'myFunc',
336
+ declarations: [],
337
+ imports: [],
338
+ exports: [],
339
+ },
340
+ }),
341
+ ],
342
+ }));
343
+ expect(result.content).toContain('### myFunc (function)');
344
+ });
345
+ it('should format related chunks with relationship and distance', () => {
346
+ const optimizer = new TokenBudgetOptimizer();
347
+ const result = optimizer.assemble(makeExpandedContext({
348
+ primaryResults: [],
349
+ relatedChunks: [
350
+ makeRelatedChunk('helper', 'imported_by', 2),
351
+ ],
352
+ }));
353
+ expect(result.content).toContain('[imported_by, distance=2]');
354
+ });
355
+ it('should format graph excerpt with node list and edges', () => {
356
+ const optimizer = new TokenBudgetOptimizer();
357
+ const result = optimizer.assemble(makeExpandedContext({
358
+ primaryResults: [],
359
+ relatedChunks: [],
360
+ graphExcerpt: {
361
+ nodes: ['A', 'B'],
362
+ edges: [{ from: 'A', to: 'B', type: 'imports' }],
363
+ },
364
+ }));
365
+ expect(result.content).toContain('Nodes: A, B');
366
+ expect(result.content).toContain('A --[imports]--> B');
367
+ });
368
+ it('should wrap code in code blocks', () => {
369
+ const optimizer = new TokenBudgetOptimizer();
370
+ const result = optimizer.assemble(makeExpandedContext({
371
+ primaryResults: [makeSearchResult('p1', { score: 0.9 })],
372
+ }));
373
+ expect(result.content).toContain('```');
374
+ });
375
+ it('should include line numbers in file path when available', () => {
376
+ const optimizer = new TokenBudgetOptimizer();
377
+ const result = optimizer.assemble(makeExpandedContext({
378
+ primaryResults: [
379
+ makeSearchResult('p1', {
380
+ score: 0.9,
381
+ chunk: {
382
+ id: 'p1',
383
+ content: 'code',
384
+ nlSummary: 'summary',
385
+ filePath: 'src/foo.ts',
386
+ startLine: 10,
387
+ endLine: 20,
388
+ language: 'typescript',
389
+ metadata: {
390
+ chunkType: 'function',
391
+ name: 'p1',
392
+ declarations: [],
393
+ imports: [],
394
+ exports: [],
395
+ },
396
+ },
397
+ }),
398
+ ],
399
+ }));
400
+ expect(result.content).toContain('[L10-20]');
401
+ });
402
+ });
403
+ });
404
+ //# sourceMappingURL=token-budget.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.test.js","sourceRoot":"","sources":["../../src/retrieval/token-budget.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAIzD,SAAS,gBAAgB,CACvB,OAAe,EACf,YAAmC,EAAE;IAErC,OAAO;QACL,OAAO;QACP,OAAO,EAAE,cAAc,OAAO,EAAE;QAChC,SAAS,EAAE,cAAc,OAAO,EAAE;QAClC,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE;YACR,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,OAAO;YACb,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,EAAE;SACZ;QACD,KAAK,EAAE;YACL,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,cAAc,OAAO,EAAE;YAChC,SAAS,EAAE,cAAc,OAAO,EAAE;YAClC,QAAQ,EAAE,OAAO,OAAO,KAAK;YAC7B,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE;gBACR,SAAS,EAAE,UAAU;gBACrB,IAAI,EAAE,OAAO;gBACb,YAAY,EAAE,EAAE;gBAChB,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,EAAE;aACZ;SACF;QACD,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,OAAe,EACf,eAA6C,SAAS,EACtD,QAAQ,GAAG,CAAC;IAEZ,OAAO;QACL,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC;QAChC,YAAY;QACZ,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,YAAsC,EAAE;IAExC,OAAO;QACL,cAAc,EAAE;YACd,gBAAgB,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAC7C,gBAAgB,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SAC9C;QACD,aAAa,EAAE;YACb,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YAC1C,gBAAgB,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;SAC/C;QACD,YAAY,EAAE;YACZ,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;YACvD,KAAK,EAAE;gBACL,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE;gBACrD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE;aACtD;SACF;QACD,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,4CAA4C;YAC5C,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,gDAAgD;YAChD,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,iCAAiC;YACjC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;YACxD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,QAAQ,GAAG,mBAAmB,CAAC;gBACnC,cAAc,EAAE;oBACd,gBAAgB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;oBACvC,gBAAgB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;oBACzC,gBAAgB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;iBACxC;aACF,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,8EAA8E;YAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACxD,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,QAAQ,GAAG,mBAAmB,CAAC;gBACnC,aAAa,EAAE;oBACb,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;oBACrC,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBACtC,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;iBACtC;aACF,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACxD,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,mBAAmB,CACrD,QAAQ,CAAC,cAAc,CAAC,MAAM,CAC/B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,mBAAmB,CACrD,QAAQ,CAAC,aAAa,CAAC,MAAM,CAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAEzD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,SAAS,EAAE,GAAG;gBACd,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,CAAC;gBAChB,WAAW,EAAE,CAAC;aACf,CAAC,CAAC;YAEH,oCAAoC;YACpC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrD,gBAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAC5B,KAAK,EAAE,GAAG,GAAG,CAAC,GAAG,IAAI;gBACrB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,wBAAwB;aACnD,CAAC,CACH,CAAC;YAEF,MAAM,QAAQ,GAAG,mBAAmB,CAAC;gBACnC,cAAc,EAAE,UAAU;gBAC1B,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACpE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,SAAS,EAAE,GAAG;gBACd,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,GAAG;gBAClB,WAAW,EAAE,CAAC;aACf,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACtD,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,CAC9C,CAAC;YAEF,MAAM,QAAQ,GAAG,mBAAmB,CAAC;gBACnC,cAAc,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC1E,aAAa,EAAE,WAAW;gBAC1B,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACrE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,SAAS,EAAE,GAAG;gBACd,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,IAAI;gBACnB,WAAW,EAAE,IAAI,EAAE,yBAAyB;aAC7C,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,mBAAmB,CAAC;gBACnC,cAAc,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC1E,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE;oBACZ,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;oBAChC,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE;wBACvC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE;wBACvC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE;qBACxC;iBACF;aACF,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC5C,8EAA8E;YAC9E,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;gBAChC,cAAc,EAAE,EAAE;gBAClB,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;gBAChC,cAAc,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACxC,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;gBAChC,cAAc,EAAE,EAAE;gBAClB,aAAa,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,SAAS,EAAE,KAAK;gBAChB,gBAAgB,EAAE,CAAC;gBACnB,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,CAAC;gBAChB,WAAW,EAAE,CAAC;aACf,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE5C,4DAA4D;YAC5D,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,qEAAqE;YACrE,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,SAAS,EAAE,GAAG;gBACd,gBAAgB,EAAE,GAAG;gBACrB,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,CAAC;gBAChB,WAAW,EAAE,CAAC;aACf,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrD,gBAAgB,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAC5B,KAAK,EAAE,GAAG;gBACV,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;aACzB,CAAC,CACH,CAAC;YAEF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;gBAChC,cAAc,EAAE,UAAU;gBAC1B,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;aACvC,CAAC,CAAC;YAEH,mEAAmE;YACnE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAC/B,mBAAmB,CAAC;gBAClB,cAAc,EAAE;oBACd,gBAAgB,CAAC,QAAQ,EAAE;wBACzB,KAAK,EAAE,GAAG;wBACV,QAAQ,EAAE;4BACR,SAAS,EAAE,UAAU;4BACrB,IAAI,EAAE,QAAQ;4BACd,YAAY,EAAE,EAAE;4BAChB,OAAO,EAAE,EAAE;4BACX,OAAO,EAAE,EAAE;yBACZ;qBACF,CAAC;iBACH;aACF,CAAC,CACH,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAC/B,mBAAmB,CAAC;gBAClB,cAAc,EAAE,EAAE;gBAClB,aAAa,EAAE;oBACb,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;iBAC7C;aACF,CAAC,CACH,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAC/B,mBAAmB,CAAC;gBAClB,cAAc,EAAE,EAAE;gBAClB,aAAa,EAAE,EAAE;gBACjB,YAAY,EAAE;oBACZ,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;oBACjB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;iBACjD;aACF,CAAC,CACH,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAC/B,mBAAmB,CAAC;gBAClB,cAAc,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;aACzD,CAAC,CACH,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAC/B,mBAAmB,CAAC;gBAClB,cAAc,EAAE;oBACd,gBAAgB,CAAC,IAAI,EAAE;wBACrB,KAAK,EAAE,GAAG;wBACV,KAAK,EAAE;4BACL,EAAE,EAAE,IAAI;4BACR,OAAO,EAAE,MAAM;4BACf,SAAS,EAAE,SAAS;4BACpB,QAAQ,EAAE,YAAY;4BACtB,SAAS,EAAE,EAAE;4BACb,OAAO,EAAE,EAAE;4BACX,QAAQ,EAAE,YAAY;4BACtB,QAAQ,EAAE;gCACR,SAAS,EAAE,UAAU;gCACrB,IAAI,EAAE,IAAI;gCACV,YAAY,EAAE,EAAE;gCAChB,OAAO,EAAE,EAAE;gCACX,OAAO,EAAE,EAAE;6BACZ;yBACF;qBACF,CAAC;iBACH;aACF,CAAC,CACH,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type Result } from 'neverthrow';
2
+ import type { CloudStorageProvider, AzureBlobConfig } from './types.js';
3
+ import { StorageError } from './types.js';
4
+ /**
5
+ * Cloud storage provider for Azure Blob Storage.
6
+ * Uses node:https with Shared Key authentication — no external SDK dependency.
7
+ */
8
+ export declare class AzureBlobStorageProvider implements CloudStorageProvider {
9
+ private readonly config;
10
+ private readonly host;
11
+ constructor(config: AzureBlobConfig);
12
+ upload(key: string, data: Buffer): Promise<Result<void, StorageError>>;
13
+ download(key: string): Promise<Result<Buffer, StorageError>>;
14
+ delete(key: string): Promise<Result<void, StorageError>>;
15
+ list(prefix: string): Promise<Result<readonly string[], StorageError>>;
16
+ exists(key: string): Promise<Result<boolean, StorageError>>;
17
+ getUrl(key: string): Result<string, StorageError>;
18
+ private azureRequest;
19
+ }
@@ -0,0 +1,199 @@
1
+ import { ok, err } from 'neverthrow';
2
+ import { request as httpsRequest } from 'node:https';
3
+ import { createHmac } from 'node:crypto';
4
+ import { StorageError } from './types.js';
5
+ // ---------------------------------------------------------------------------
6
+ // Azure Storage Shared Key helpers
7
+ // ---------------------------------------------------------------------------
8
+ function buildAuthorizationHeader(config, method, path, headers, queryParams) {
9
+ const contentLength = headers['content-length'] ?? '';
10
+ const contentType = headers['content-type'] ?? '';
11
+ // Build canonicalized headers (x-ms-*)
12
+ const msHeaders = Object.entries(headers)
13
+ .filter(([k]) => k.startsWith('x-ms-'))
14
+ .sort(([a], [b]) => a.localeCompare(b))
15
+ .map(([k, v]) => `${k}:${v}`)
16
+ .join('\n');
17
+ // Build canonicalized resource
18
+ let canonicalizedResource = `/${config.accountName}${path}`;
19
+ if (queryParams) {
20
+ const params = new URLSearchParams(queryParams);
21
+ const sortedParams = [...params.entries()].sort(([a], [b]) => a.localeCompare(b));
22
+ for (const [key, value] of sortedParams) {
23
+ canonicalizedResource += `\n${key}:${value}`;
24
+ }
25
+ }
26
+ // StringToSign for SharedKey
27
+ // https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key
28
+ const stringToSign = [
29
+ method, // VERB
30
+ '', // Content-Encoding
31
+ '', // Content-Language
32
+ contentLength, // Content-Length
33
+ '', // Content-MD5
34
+ contentType, // Content-Type
35
+ '', // Date
36
+ '', // If-Modified-Since
37
+ '', // If-Match
38
+ '', // If-None-Match
39
+ '', // If-Unmodified-Since
40
+ '', // Range
41
+ msHeaders, // CanonicalizedHeaders
42
+ canonicalizedResource, // CanonicalizedResource
43
+ ].join('\n');
44
+ const key = Buffer.from(config.accountKey, 'base64');
45
+ const signature = createHmac('sha256', key).update(stringToSign, 'utf-8').digest('base64');
46
+ return `SharedKey ${config.accountName}:${signature}`;
47
+ }
48
+ function formatRfc1123(date) {
49
+ return date.toUTCString();
50
+ }
51
+ // ---------------------------------------------------------------------------
52
+ // AzureBlobStorageProvider
53
+ // ---------------------------------------------------------------------------
54
+ /**
55
+ * Cloud storage provider for Azure Blob Storage.
56
+ * Uses node:https with Shared Key authentication — no external SDK dependency.
57
+ */
58
+ export class AzureBlobStorageProvider {
59
+ config;
60
+ host;
61
+ constructor(config) {
62
+ this.config = config;
63
+ this.host = `${config.accountName}.blob.core.windows.net`;
64
+ }
65
+ // -----------------------------------------------------------------------
66
+ // Public API
67
+ // -----------------------------------------------------------------------
68
+ async upload(key, data) {
69
+ try {
70
+ await this.azureRequest('PUT', key, data);
71
+ return ok(undefined);
72
+ }
73
+ catch (error) {
74
+ return err(new StorageError(`Azure upload failed for "${key}": ${errorMessage(error)}`));
75
+ }
76
+ }
77
+ async download(key) {
78
+ try {
79
+ const body = await this.azureRequest('GET', key);
80
+ return ok(body);
81
+ }
82
+ catch (error) {
83
+ return err(new StorageError(`Azure download failed for "${key}": ${errorMessage(error)}`));
84
+ }
85
+ }
86
+ async delete(key) {
87
+ try {
88
+ await this.azureRequest('DELETE', key);
89
+ return ok(undefined);
90
+ }
91
+ catch (error) {
92
+ return err(new StorageError(`Azure delete failed for "${key}": ${errorMessage(error)}`));
93
+ }
94
+ }
95
+ async list(prefix) {
96
+ try {
97
+ const query = `restype=container&comp=list&prefix=${encodeURIComponent(prefix)}`;
98
+ const body = await this.azureRequest('GET', '', undefined, query);
99
+ const xml = body.toString('utf-8');
100
+ const names = extractBlobNames(xml);
101
+ return ok(names);
102
+ }
103
+ catch (error) {
104
+ return err(new StorageError(`Azure list failed for prefix "${prefix}": ${errorMessage(error)}`));
105
+ }
106
+ }
107
+ async exists(key) {
108
+ try {
109
+ await this.azureRequest('HEAD', key);
110
+ return ok(true);
111
+ }
112
+ catch (error) {
113
+ const msg = errorMessage(error);
114
+ if (msg.includes('404') || msg.includes('BlobNotFound')) {
115
+ return ok(false);
116
+ }
117
+ return err(new StorageError(`Azure exists check failed for "${key}": ${msg}`));
118
+ }
119
+ }
120
+ getUrl(key) {
121
+ return ok(`https://${this.host}/${this.config.containerName}/${encodeURIComponent(key)}`);
122
+ }
123
+ // -----------------------------------------------------------------------
124
+ // Internal
125
+ // -----------------------------------------------------------------------
126
+ async azureRequest(method, blobName, body, query) {
127
+ const now = new Date();
128
+ const dateStr = formatRfc1123(now);
129
+ const apiVersion = '2023-11-03';
130
+ const path = blobName
131
+ ? `/${this.config.containerName}/${blobName}`
132
+ : `/${this.config.containerName}`;
133
+ const headers = {
134
+ 'x-ms-date': dateStr,
135
+ 'x-ms-version': apiVersion,
136
+ 'x-ms-blob-type': 'BlockBlob',
137
+ };
138
+ if (body && method === 'PUT') {
139
+ headers['content-length'] = body.length.toString();
140
+ headers['content-type'] = 'application/octet-stream';
141
+ }
142
+ const authorization = buildAuthorizationHeader(this.config, method, path, headers, query);
143
+ return new Promise((resolve, reject) => {
144
+ const fullPath = query ? `${path}?${query}` : path;
145
+ const req = httpsRequest({
146
+ hostname: this.host,
147
+ path: fullPath,
148
+ method,
149
+ headers: {
150
+ ...headers,
151
+ authorization,
152
+ },
153
+ }, (res) => {
154
+ const chunks = [];
155
+ res.on('data', (chunk) => chunks.push(chunk));
156
+ res.on('end', () => {
157
+ const responseBody = Buffer.concat(chunks);
158
+ const statusCode = res.statusCode ?? 0;
159
+ if (statusCode >= 200 && statusCode < 300) {
160
+ resolve(responseBody);
161
+ }
162
+ else if (method === 'HEAD' && statusCode === 404) {
163
+ reject(new Error('404 BlobNotFound'));
164
+ }
165
+ else {
166
+ reject(new Error(`Azure responded with status ${statusCode}: ${responseBody.toString('utf-8')}`));
167
+ }
168
+ });
169
+ });
170
+ req.on('error', reject);
171
+ if (body) {
172
+ req.write(body);
173
+ }
174
+ req.end();
175
+ });
176
+ }
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // Helpers
180
+ // ---------------------------------------------------------------------------
181
+ function errorMessage(error) {
182
+ return error instanceof Error ? error.message : String(error);
183
+ }
184
+ /**
185
+ * Extract <Name>...</Name> values from Azure List Blobs XML response.
186
+ */
187
+ function extractBlobNames(xml) {
188
+ const names = [];
189
+ const regex = /<Name>([^<]+)<\/Name>/g;
190
+ let match = regex.exec(xml);
191
+ while (match) {
192
+ const name = match[1];
193
+ if (name !== undefined) {
194
+ names.push(name);
195
+ }
196
+ match = regex.exec(xml);
197
+ }
198
+ return names;
199
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-blob-provider.js","sourceRoot":"","sources":["../../src/storage/azure-blob-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAe,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E,SAAS,wBAAwB,CAC/B,MAAuB,EACvB,MAAc,EACd,IAAY,EACZ,OAA+B,EAC/B,WAAoB;IAEpB,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAElD,uCAAuC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;SACtC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,+BAA+B;IAC/B,IAAI,qBAAqB,GAAG,IAAI,MAAM,CAAC,WAAW,GAAG,IAAI,EAAE,CAAC;IAC5D,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC;YACxC,qBAAqB,IAAI,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,uFAAuF;IACvF,MAAM,YAAY,GAAG;QACnB,MAAM,EAAgB,OAAO;QAC7B,EAAE,EAAoB,mBAAmB;QACzC,EAAE,EAAoB,mBAAmB;QACzC,aAAa,EAAS,iBAAiB;QACvC,EAAE,EAAoB,cAAc;QACpC,WAAW,EAAW,eAAe;QACrC,EAAE,EAAoB,OAAO;QAC7B,EAAE,EAAoB,oBAAoB;QAC1C,EAAE,EAAoB,WAAW;QACjC,EAAE,EAAoB,gBAAgB;QACtC,EAAE,EAAoB,sBAAsB;QAC5C,EAAE,EAAoB,QAAQ;QAC9B,SAAS,EAAa,uBAAuB;QAC7C,qBAAqB,EAAE,wBAAwB;KAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE3F,OAAO,aAAa,MAAM,CAAC,WAAW,IAAI,SAAS,EAAE,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,IAAU;IAC/B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAClB,MAAM,CAAkB;IACxB,IAAI,CAAS;IAE9B,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,GAAG,MAAM,CAAC,WAAW,wBAAwB,CAAC;IAC5D,CAAC;IAED,0EAA0E;IAC1E,aAAa;IACb,0EAA0E;IAE1E,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,IAAY;QACpC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,IAAI,YAAY,CAAC,4BAA4B,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjD,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,IAAI,YAAY,CAAC,8BAA8B,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACvC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,IAAI,YAAY,CAAC,4BAA4B,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,sCAAsC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;YACjF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;YAClE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,IAAI,YAAY,CAAC,iCAAiC,MAAM,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACrC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YAChC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACxD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;YACD,OAAO,GAAG,CAAC,IAAI,YAAY,CAAC,kCAAkC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,EAAE,CAAC,WAAW,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,0EAA0E;IAC1E,WAAW;IACX,0EAA0E;IAElE,KAAK,CAAC,YAAY,CACxB,MAAc,EACd,QAAgB,EAChB,IAAa,EACb,KAAc;QAEd,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,YAAY,CAAC;QAEhC,MAAM,IAAI,GAAG,QAAQ;YACnB,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,EAAE;YAC7C,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAEpC,MAAM,OAAO,GAA2B;YACtC,WAAW,EAAE,OAAO;YACpB,cAAc,EAAE,UAAU;YAC1B,gBAAgB,EAAE,WAAW;SAC9B,CAAC;QAEF,IAAI,IAAI,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnD,OAAO,CAAC,cAAc,CAAC,GAAG,0BAA0B,CAAC;QACvD,CAAC;QAED,MAAM,aAAa,GAAG,wBAAwB,CAC5C,IAAI,CAAC,MAAM,EACX,MAAM,EACN,IAAI,EACJ,OAAO,EACP,KAAK,CACN,CAAC;QAEF,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAEnD,MAAM,GAAG,GAAG,YAAY,CACtB;gBACE,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,IAAI,EAAE,QAAQ;gBACd,MAAM;gBACN,OAAO,EAAE;oBACP,GAAG,OAAO;oBACV,aAAa;iBACd;aACF,EACD,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,MAAM,GAAa,EAAE,CAAC;gBAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC3C,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC;oBACvC,IAAI,UAAU,IAAI,GAAG,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;wBAC1C,OAAO,CAAC,YAAY,CAAC,CAAC;oBACxB,CAAC;yBAAM,IAAI,MAAM,KAAK,MAAM,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;wBACnD,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,UAAU,KAAK,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;oBACpG,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CACF,CAAC;YAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAExB,IAAI,IAAI,EAAE,CAAC;gBACT,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;YACD,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,wBAAwB,CAAC;IACvC,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}