xtctx 0.3.2

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 (217) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/LICENSE +21 -0
  3. package/README.md +149 -0
  4. package/dist/src/api/routes/config.d.ts +4 -0
  5. package/dist/src/api/routes/config.d.ts.map +1 -0
  6. package/dist/src/api/routes/config.js +61 -0
  7. package/dist/src/api/routes/config.js.map +1 -0
  8. package/dist/src/api/routes/knowledge.d.ts +4 -0
  9. package/dist/src/api/routes/knowledge.d.ts.map +1 -0
  10. package/dist/src/api/routes/knowledge.js +40 -0
  11. package/dist/src/api/routes/knowledge.js.map +1 -0
  12. package/dist/src/api/routes/search.d.ts +7 -0
  13. package/dist/src/api/routes/search.d.ts.map +1 -0
  14. package/dist/src/api/routes/search.js +108 -0
  15. package/dist/src/api/routes/search.js.map +1 -0
  16. package/dist/src/api/routes/sources.d.ts +12 -0
  17. package/dist/src/api/routes/sources.d.ts.map +1 -0
  18. package/dist/src/api/routes/sources.js +70 -0
  19. package/dist/src/api/routes/sources.js.map +1 -0
  20. package/dist/src/api/server.d.ts +26 -0
  21. package/dist/src/api/server.d.ts.map +1 -0
  22. package/dist/src/api/server.js +312 -0
  23. package/dist/src/api/server.js.map +1 -0
  24. package/dist/src/cli/index.d.ts +3 -0
  25. package/dist/src/cli/index.d.ts.map +1 -0
  26. package/dist/src/cli/index.js +58 -0
  27. package/dist/src/cli/index.js.map +1 -0
  28. package/dist/src/cli/ingest.d.ts +6 -0
  29. package/dist/src/cli/ingest.d.ts.map +1 -0
  30. package/dist/src/cli/ingest.js +11 -0
  31. package/dist/src/cli/ingest.js.map +1 -0
  32. package/dist/src/cli/init.d.ts +6 -0
  33. package/dist/src/cli/init.d.ts.map +1 -0
  34. package/dist/src/cli/init.js +105 -0
  35. package/dist/src/cli/init.js.map +1 -0
  36. package/dist/src/cli/serve.d.ts +7 -0
  37. package/dist/src/cli/serve.d.ts.map +1 -0
  38. package/dist/src/cli/serve.js +100 -0
  39. package/dist/src/cli/serve.js.map +1 -0
  40. package/dist/src/cli/sync.d.ts +5 -0
  41. package/dist/src/cli/sync.d.ts.map +1 -0
  42. package/dist/src/cli/sync.js +13 -0
  43. package/dist/src/cli/sync.js.map +1 -0
  44. package/dist/src/compaction/pipeline.d.ts +19 -0
  45. package/dist/src/compaction/pipeline.d.ts.map +1 -0
  46. package/dist/src/compaction/pipeline.js +37 -0
  47. package/dist/src/compaction/pipeline.js.map +1 -0
  48. package/dist/src/compaction/providers/cli.d.ts +13 -0
  49. package/dist/src/compaction/providers/cli.d.ts.map +1 -0
  50. package/dist/src/compaction/providers/cli.js +60 -0
  51. package/dist/src/compaction/providers/cli.js.map +1 -0
  52. package/dist/src/compaction/rule-based.d.ts +8 -0
  53. package/dist/src/compaction/rule-based.d.ts.map +1 -0
  54. package/dist/src/compaction/rule-based.js +120 -0
  55. package/dist/src/compaction/rule-based.js.map +1 -0
  56. package/dist/src/config/loader.d.ts +12 -0
  57. package/dist/src/config/loader.d.ts.map +1 -0
  58. package/dist/src/config/loader.js +76 -0
  59. package/dist/src/config/loader.js.map +1 -0
  60. package/dist/src/config/mappings/claude-code.d.ts +3 -0
  61. package/dist/src/config/mappings/claude-code.d.ts.map +1 -0
  62. package/dist/src/config/mappings/claude-code.js +31 -0
  63. package/dist/src/config/mappings/claude-code.js.map +1 -0
  64. package/dist/src/config/mappings/codex.d.ts +3 -0
  65. package/dist/src/config/mappings/codex.d.ts.map +1 -0
  66. package/dist/src/config/mappings/codex.js +31 -0
  67. package/dist/src/config/mappings/codex.js.map +1 -0
  68. package/dist/src/config/mappings/copilot.d.ts +3 -0
  69. package/dist/src/config/mappings/copilot.d.ts.map +1 -0
  70. package/dist/src/config/mappings/copilot.js +33 -0
  71. package/dist/src/config/mappings/copilot.js.map +1 -0
  72. package/dist/src/config/mappings/cursor.d.ts +3 -0
  73. package/dist/src/config/mappings/cursor.d.ts.map +1 -0
  74. package/dist/src/config/mappings/cursor.js +29 -0
  75. package/dist/src/config/mappings/cursor.js.map +1 -0
  76. package/dist/src/config/sync.d.ts +13 -0
  77. package/dist/src/config/sync.d.ts.map +1 -0
  78. package/dist/src/config/sync.js +96 -0
  79. package/dist/src/config/sync.js.map +1 -0
  80. package/dist/src/ingestion/coordinator.d.ts +37 -0
  81. package/dist/src/ingestion/coordinator.d.ts.map +1 -0
  82. package/dist/src/ingestion/coordinator.js +127 -0
  83. package/dist/src/ingestion/coordinator.js.map +1 -0
  84. package/dist/src/ingestion/daemon.d.ts +17 -0
  85. package/dist/src/ingestion/daemon.d.ts.map +1 -0
  86. package/dist/src/ingestion/daemon.js +35 -0
  87. package/dist/src/ingestion/daemon.js.map +1 -0
  88. package/dist/src/ingestion/watcher.d.ts +19 -0
  89. package/dist/src/ingestion/watcher.d.ts.map +1 -0
  90. package/dist/src/ingestion/watcher.js +70 -0
  91. package/dist/src/ingestion/watcher.js.map +1 -0
  92. package/dist/src/knowledge/autotag.d.ts +3 -0
  93. package/dist/src/knowledge/autotag.d.ts.map +1 -0
  94. package/dist/src/knowledge/autotag.js +24 -0
  95. package/dist/src/knowledge/autotag.js.map +1 -0
  96. package/dist/src/knowledge/dedup.d.ts +7 -0
  97. package/dist/src/knowledge/dedup.d.ts.map +1 -0
  98. package/dist/src/knowledge/dedup.js +15 -0
  99. package/dist/src/knowledge/dedup.js.map +1 -0
  100. package/dist/src/knowledge/repository.d.ts +12 -0
  101. package/dist/src/knowledge/repository.d.ts.map +1 -0
  102. package/dist/src/knowledge/repository.js +74 -0
  103. package/dist/src/knowledge/repository.js.map +1 -0
  104. package/dist/src/mcp/server.d.ts +31 -0
  105. package/dist/src/mcp/server.d.ts.map +1 -0
  106. package/dist/src/mcp/server.js +323 -0
  107. package/dist/src/mcp/server.js.map +1 -0
  108. package/dist/src/mcp/tools/config.d.ts +36 -0
  109. package/dist/src/mcp/tools/config.d.ts.map +1 -0
  110. package/dist/src/mcp/tools/config.js +54 -0
  111. package/dist/src/mcp/tools/config.js.map +1 -0
  112. package/dist/src/mcp/tools/knowledge.d.ts +17 -0
  113. package/dist/src/mcp/tools/knowledge.d.ts.map +1 -0
  114. package/dist/src/mcp/tools/knowledge.js +46 -0
  115. package/dist/src/mcp/tools/knowledge.js.map +1 -0
  116. package/dist/src/mcp/tools/search.d.ts +22 -0
  117. package/dist/src/mcp/tools/search.d.ts.map +1 -0
  118. package/dist/src/mcp/tools/search.js +30 -0
  119. package/dist/src/mcp/tools/search.js.map +1 -0
  120. package/dist/src/mcp/tools/sessions.d.ts +38 -0
  121. package/dist/src/mcp/tools/sessions.d.ts.map +1 -0
  122. package/dist/src/mcp/tools/sessions.js +55 -0
  123. package/dist/src/mcp/tools/sessions.js.map +1 -0
  124. package/dist/src/mcp/tools/write.d.ts +38 -0
  125. package/dist/src/mcp/tools/write.d.ts.map +1 -0
  126. package/dist/src/mcp/tools/write.js +97 -0
  127. package/dist/src/mcp/tools/write.js.map +1 -0
  128. package/dist/src/runtime/ingestion.d.ts +17 -0
  129. package/dist/src/runtime/ingestion.d.ts.map +1 -0
  130. package/dist/src/runtime/ingestion.js +106 -0
  131. package/dist/src/runtime/ingestion.js.map +1 -0
  132. package/dist/src/runtime/services.d.ts +46 -0
  133. package/dist/src/runtime/services.d.ts.map +1 -0
  134. package/dist/src/runtime/services.js +227 -0
  135. package/dist/src/runtime/services.js.map +1 -0
  136. package/dist/src/scrapers/base.d.ts +10 -0
  137. package/dist/src/scrapers/base.d.ts.map +1 -0
  138. package/dist/src/scrapers/base.js +34 -0
  139. package/dist/src/scrapers/base.js.map +1 -0
  140. package/dist/src/scrapers/claude-code.d.ts +16 -0
  141. package/dist/src/scrapers/claude-code.d.ts.map +1 -0
  142. package/dist/src/scrapers/claude-code.js +120 -0
  143. package/dist/src/scrapers/claude-code.js.map +1 -0
  144. package/dist/src/scrapers/codex.d.ts +17 -0
  145. package/dist/src/scrapers/codex.d.ts.map +1 -0
  146. package/dist/src/scrapers/codex.js +179 -0
  147. package/dist/src/scrapers/codex.js.map +1 -0
  148. package/dist/src/scrapers/copilot.d.ts +17 -0
  149. package/dist/src/scrapers/copilot.d.ts.map +1 -0
  150. package/dist/src/scrapers/copilot.js +198 -0
  151. package/dist/src/scrapers/copilot.js.map +1 -0
  152. package/dist/src/scrapers/cursor.d.ts +18 -0
  153. package/dist/src/scrapers/cursor.d.ts.map +1 -0
  154. package/dist/src/scrapers/cursor.js +218 -0
  155. package/dist/src/scrapers/cursor.js.map +1 -0
  156. package/dist/src/scrapers/gemini.d.ts +17 -0
  157. package/dist/src/scrapers/gemini.d.ts.map +1 -0
  158. package/dist/src/scrapers/gemini.js +245 -0
  159. package/dist/src/scrapers/gemini.js.map +1 -0
  160. package/dist/src/scrapers/registry.d.ts +9 -0
  161. package/dist/src/scrapers/registry.d.ts.map +1 -0
  162. package/dist/src/scrapers/registry.js +22 -0
  163. package/dist/src/scrapers/registry.js.map +1 -0
  164. package/dist/src/store/embeddings.d.ts +9 -0
  165. package/dist/src/store/embeddings.d.ts.map +1 -0
  166. package/dist/src/store/embeddings.js +28 -0
  167. package/dist/src/store/embeddings.js.map +1 -0
  168. package/dist/src/store/lance.d.ts +25 -0
  169. package/dist/src/store/lance.d.ts.map +1 -0
  170. package/dist/src/store/lance.js +74 -0
  171. package/dist/src/store/lance.js.map +1 -0
  172. package/dist/src/store/search.d.ts +18 -0
  173. package/dist/src/store/search.d.ts.map +1 -0
  174. package/dist/src/store/search.js +55 -0
  175. package/dist/src/store/search.js.map +1 -0
  176. package/dist/src/types/compaction.d.ts +29 -0
  177. package/dist/src/types/compaction.d.ts.map +1 -0
  178. package/dist/src/types/compaction.js +2 -0
  179. package/dist/src/types/compaction.js.map +1 -0
  180. package/dist/src/types/config.d.ts +45 -0
  181. package/dist/src/types/config.d.ts.map +1 -0
  182. package/dist/src/types/config.js +2 -0
  183. package/dist/src/types/config.js.map +1 -0
  184. package/dist/src/types/context.d.ts +33 -0
  185. package/dist/src/types/context.d.ts.map +1 -0
  186. package/dist/src/types/context.js +18 -0
  187. package/dist/src/types/context.js.map +1 -0
  188. package/dist/src/types/index.d.ts +5 -0
  189. package/dist/src/types/index.d.ts.map +1 -0
  190. package/dist/src/types/index.js +5 -0
  191. package/dist/src/types/index.js.map +1 -0
  192. package/dist/src/types/scraper.d.ts +70 -0
  193. package/dist/src/types/scraper.d.ts.map +1 -0
  194. package/dist/src/types/scraper.js +2 -0
  195. package/dist/src/types/scraper.js.map +1 -0
  196. package/dist/src/utils/retry.d.ts +11 -0
  197. package/dist/src/utils/retry.d.ts.map +1 -0
  198. package/dist/src/utils/retry.js +46 -0
  199. package/dist/src/utils/retry.js.map +1 -0
  200. package/dist/src/utils/shutdown.d.ts +25 -0
  201. package/dist/src/utils/shutdown.d.ts.map +1 -0
  202. package/dist/src/utils/shutdown.js +56 -0
  203. package/dist/src/utils/shutdown.js.map +1 -0
  204. package/dist/web/apple-touch-icon.png +0 -0
  205. package/dist/web/assets/index-Nuadr5ox.css +1 -0
  206. package/dist/web/assets/index-aA0u8eXA.js +3504 -0
  207. package/dist/web/assets/primeicons-C6QP2o4f.woff2 +0 -0
  208. package/dist/web/assets/primeicons-DMOk5skT.eot +0 -0
  209. package/dist/web/assets/primeicons-Dr5RGzOO.svg +345 -0
  210. package/dist/web/assets/primeicons-MpK4pl85.ttf +0 -0
  211. package/dist/web/assets/primeicons-WjwUDZjB.woff +0 -0
  212. package/dist/web/favicon.ico +0 -0
  213. package/dist/web/favicon.svg +21 -0
  214. package/dist/web/index.html +21 -0
  215. package/dist/web/site.webmanifest +19 -0
  216. package/dist/web/vite.svg +1 -0
  217. package/package.json +69 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,122 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on Keep a Changelog, and this project follows Semantic Versioning.
6
+ This file is maintained automatically by Release Please.
7
+
8
+ ## [0.3.2](https://github.com/fstubner/xtctx/compare/xtctx-v0.3.1...xtctx-v0.3.2) (2026-02-26)
9
+
10
+
11
+ ### Documentation
12
+
13
+ * add root AGENTS guide for repository automation ([1439030](https://github.com/fstubner/xtctx/commit/1439030dfc458cf88f9a7e3abf7f925d678aa1ab))
14
+
15
+
16
+ ### Miscellaneous
17
+
18
+ * deploy landing site to github pages ([6ddecd1](https://github.com/fstubner/xtctx/commit/6ddecd1828e6f3e2ba60200ba8a4dc659e629e73))
19
+ * deploy landing site to GitHub Pages ([4fbbfdc](https://github.com/fstubner/xtctx/commit/4fbbfdc1ffadd615e444ab865afa8196ee2f6466))
20
+
21
+ ## [0.3.1](https://github.com/fstubner/xtctx/compare/xtctx-v0.3.0...xtctx-v0.3.1) (2026-02-26)
22
+
23
+
24
+ ### Miscellaneous
25
+
26
+ * auto-enable merge for release-please prs ([8028118](https://github.com/fstubner/xtctx/commit/80281187525971817d238d8c6c93e67309e01d69))
27
+ * auto-enable merge for release-please PRs ([7c8535f](https://github.com/fstubner/xtctx/commit/7c8535ff7858111fa570bc528c457e29e99c5098))
28
+
29
+ ## [0.3.0](https://github.com/fstubner/xtctx/compare/xtctx-v0.2.0...xtctx-v0.3.0) (2026-02-26)
30
+
31
+
32
+ ### Features
33
+
34
+ * make API security config file first and refresh README ([bac9c3b](https://github.com/fstubner/xtctx/commit/bac9c3bfa44e0b0c4a080f2fcf42550c1e21ef29))
35
+ * make API security config file first and refresh README ([8625dba](https://github.com/fstubner/xtctx/commit/8625dba6383cd416ae6d45790bfe67e5eac0eaad))
36
+
37
+ ## [0.2.0](https://github.com/fstubner/xtctx/compare/xtctx-v0.1.0...xtctx-v0.2.0) (2026-02-25)
38
+
39
+
40
+ ### Features
41
+
42
+ * add api security hardening and owasp checklist ([5660c52](https://github.com/fstubner/xtctx/commit/5660c52591cfcacd1611cfa914e31435d2747c80))
43
+ * add API server and Phase 9 Vue web UI ([775543e](https://github.com/fstubner/xtctx/commit/775543e93720c24786abbeb3089e0393eeffa904))
44
+ * add auto-tagging for file references and domain classification ([fc27a52](https://github.com/fstubner/xtctx/commit/fc27a52de6edad9cd1b29dd3ee6685d9eb3db4b5))
45
+ * add Claude Code conversation scraper ([ba01b58](https://github.com/fstubner/xtctx/commit/ba01b583bfe440e6c274024961dd3472908a923c))
46
+ * add CLI compaction provider ([e5f38f8](https://github.com/fstubner/xtctx/commit/e5f38f87a51d5352bf46e741694fa7a70933d8dd))
47
+ * add CLI entrypoints and MCP serve command ([866052c](https://github.com/fstubner/xtctx/commit/866052c79c5e2d85aa7f391dcb260e83cd765e5b))
48
+ * add core type definitions ([c8dba56](https://github.com/fstubner/xtctx/commit/c8dba5614b83c7521638da67d7c0e664fb4434d1))
49
+ * add deduplication with similarity-based supercession ([7023c92](https://github.com/fstubner/xtctx/commit/7023c920fa8b294e5cc9500a456748ecc5cc06bf))
50
+ * add hybrid search with reciprocal rank fusion ([830dbe7](https://github.com/fstubner/xtctx/commit/830dbe78ea30dd3c5679e1b9c998150861d57a93))
51
+ * add ingestion coordinator, watcher, and daemon ([92a4553](https://github.com/fstubner/xtctx/commit/92a455311683f28b1a4cbdfbef6a8662cbb04faa))
52
+ * add knowledge repository with YAML file persistence ([52c2e5c](https://github.com/fstubner/xtctx/commit/52c2e5cbf8100364a17036daad9e24dd090a38b6))
53
+ * add LanceDB vector store wrapper ([4f10d46](https://github.com/fstubner/xtctx/commit/4f10d463c48dc916fe5ad8ca1eb2bea73c736927))
54
+ * add local embedding service using MiniLM ([dc66f51](https://github.com/fstubner/xtctx/commit/dc66f51b48200b5fb6a42c42be246edd311b7464))
55
+ * add MCP server scaffold with all tool definitions ([fa3554f](https://github.com/fstubner/xtctx/commit/fa3554fa5f424448eb3cab339e6a6c23707cb21e))
56
+ * add phase 12 landing page ([791f535](https://github.com/fstubner/xtctx/commit/791f53561146f5858ea7de458b084e9d14d6ce5b))
57
+ * add phase 13 multi-tool scrapers ([f81c2fb](https://github.com/fstubner/xtctx/commit/f81c2fb2406a98e554ae2246cbd96ffdd4571a78))
58
+ * add rule-based compaction pipeline ([7e5d58d](https://github.com/fstubner/xtctx/commit/7e5d58d4fd86cb5eb777021a5e6943b86c07cee8))
59
+ * add scraper registry and state management ([9859e2d](https://github.com/fstubner/xtctx/commit/9859e2d49c1678c85e0d824cd87a372aeaae9f63))
60
+ * automate releases and bundle web ui in npm package ([3d6ecac](https://github.com/fstubner/xtctx/commit/3d6ecac4db0e88d594e6d5c4e17d9c245d74999b))
61
+ * implement MCP tool handlers ([71c6ab5](https://github.com/fstubner/xtctx/commit/71c6ab5f97dde0d0dc63759d4b7014adc0ef78f3))
62
+ * implement phase 10 config sync ([dc2661a](https://github.com/fstubner/xtctx/commit/dc2661a58af83f4fafaa008bf8f0b796631341da))
63
+ * implement phase 14 hardening and release tooling ([4590f38](https://github.com/fstubner/xtctx/commit/4590f38d26d6ad80fb4737cf721796df68fae307))
64
+ * wire ingestion runtime into serve and ingest commands ([89dd876](https://github.com/fstubner/xtctx/commit/89dd876cd8de12617220e7a2e1167dd4bce8c1b5))
65
+
66
+
67
+ ### Bug Fixes
68
+
69
+ * allow release-please prs to trigger ci ([fc00a77](https://github.com/fstubner/xtctx/commit/fc00a77145dbecee8f1a4f80fa3f60b635647738))
70
+ * allow release-please PRs to trigger ci ([c398b12](https://github.com/fstubner/xtctx/commit/c398b12b9273baf13136c16ee7cadca6129a0d10))
71
+ * normalize npm package metadata ([c6cf81f](https://github.com/fstubner/xtctx/commit/c6cf81f45c737d59629b48e850a9c13b6b97566e))
72
+ * normalize npm package metadata ([5553c78](https://github.com/fstubner/xtctx/commit/5553c78f9cf65d4f90d72604b2608d9d5eef40b7))
73
+ * run ci for release-please branches ([97e5111](https://github.com/fstubner/xtctx/commit/97e5111ee098faaaa8dc4f31338183c3b5fb610a))
74
+ * run ci for release-please branches ([90bf917](https://github.com/fstubner/xtctx/commit/90bf9179d05fb103e52036c55648cde422317752))
75
+
76
+
77
+ ### Documentation
78
+
79
+ * add open source governance and release docs ([a9e18f5](https://github.com/fstubner/xtctx/commit/a9e18f51c1c87c2a6d6da241a37d7bf28e058ea3))
80
+ * add phase 14 integration hardening follow-up ([56e7a6e](https://github.com/fstubner/xtctx/commit/56e7a6ee45c0e32fc48940cb319929224a657fb2))
81
+ * add xtctx usage skill guide ([e247258](https://github.com/fstubner/xtctx/commit/e247258de8284297af869a22fb44f1f897001d5b))
82
+
83
+
84
+ ### Miscellaneous
85
+
86
+ * ignore codex local workspace directory ([33af3cb](https://github.com/fstubner/xtctx/commit/33af3cbb99f88a9666c0858922d7984fc18b2408))
87
+ * ignore runtime state directory ([3a8911d](https://github.com/fstubner/xtctx/commit/3a8911dca76787ef8f6724642a85474de566815e))
88
+
89
+ ## [0.1.0] - 2026-02-25
90
+
91
+ ### Added
92
+
93
+ - Core TypeScript project scaffold, tests, and CLI entrypoint.
94
+ - MCP server scaffold and tool handlers:
95
+ - `xtctx_search`
96
+ - `xtctx_recent_sessions`
97
+ - `xtctx_session_detail`
98
+ - `xtctx_project_knowledge`
99
+ - `xtctx_save_*`
100
+ - `xtctx_*_config` handlers
101
+ - Knowledge repository with autotagging and dedup/supersession behaviors.
102
+ - LanceDB-backed vector store + embedding service + hybrid search.
103
+ - Ingestion coordinator, watcher, daemon, and CLI ingestion commands.
104
+ - Rule-based compaction pipeline and external CLI compaction provider.
105
+ - API server and Vue web UI (dashboard/search/knowledge/sources/config pages).
106
+ - Config sync engine generating tool-native managed sections:
107
+ - `.cursorrules`
108
+ - `CLAUDE.md`
109
+ - `AGENTS.md`
110
+ - `.github/copilot-instructions.md`
111
+ - Additional scraper implementations:
112
+ - Claude Code
113
+ - Cursor (SQLite)
114
+ - Codex CLI (JSONL)
115
+ - GitHub Copilot (JSON)
116
+ - Gemini CLI (JSON)
117
+ - Integration hardening:
118
+ - Integration tests for MCP/API/web parity paths
119
+ - Retry and coordinated shutdown utilities
120
+ - CI workflow (Node 20/22)
121
+ - Release verification scripts and packaging allowlist
122
+ - Operator/runbook docs in `README.md`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Felix Stubner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # xtctx
2
+
3
+ [![CI](https://github.com/fstubner/xtctx/actions/workflows/ci.yml/badge.svg)](https://github.com/fstubner/xtctx/actions/workflows/ci.yml)
4
+ [![Release Please](https://github.com/fstubner/xtctx/actions/workflows/release-please.yml/badge.svg)](https://github.com/fstubner/xtctx/actions/workflows/release-please.yml)
5
+ [![Latest Release](https://img.shields.io/github/v/release/fstubner/xtctx?sort=semver)](https://github.com/fstubner/xtctx/releases)
6
+ [![License](https://img.shields.io/github/license/fstubner/xtctx)](LICENSE)
7
+ [![Node >=20](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
8
+
9
+ xtctx is a local-first context runtime for AI coding assistants.
10
+
11
+ It lets Claude Code, Codex, Cursor, Copilot, and Gemini share the same project memory so you can switch tools without re-briefing each session.
12
+
13
+ ## Core Capabilities
14
+
15
+ - Cross-tool retrieval with MCP tools (`xtctx_search`, `xtctx_project_knowledge`, etc.)
16
+ - Durable project knowledge in `.xtctx/knowledge`
17
+ - File-first config sync into tool-native instruction files
18
+ - One runtime process that serves:
19
+ - MCP server
20
+ - HTTP API (`/api/*`)
21
+ - bundled web UI (`/`)
22
+
23
+ ## Knowledge Types
24
+
25
+ xtctx stores structured records as:
26
+
27
+ - `decision`
28
+ - `error_solution`
29
+ - `insight`
30
+ - `convention`
31
+ - `gotcha`
32
+ - `faq`
33
+
34
+ ## Practical Workflow (Tool Handoff)
35
+
36
+ 1. Start in your repo with `xtctx init`.
37
+ 2. Define shared rules in `.xtctx/tool-config/shared.yaml`.
38
+ 3. Run `xtctx sync` to generate managed sections for each tool.
39
+ 4. Start `xtctx serve`.
40
+ 5. At the beginning of every coding session:
41
+ - call `xtctx_search`
42
+ - call `xtctx_project_knowledge`
43
+ 6. After finishing work, write outcomes back with:
44
+ - `xtctx_save_decision`
45
+ - `xtctx_save_error_solution`
46
+ - `xtctx_save_insight`
47
+ - `xtctx_save_faq`
48
+
49
+ This gives a repeatable loop: recall -> implement -> write back.
50
+
51
+ ## Quick Start
52
+
53
+ Install and build:
54
+
55
+ ```bash
56
+ npm ci
57
+ npm --prefix web ci
58
+ npm --prefix landing ci
59
+ npm run build
60
+ ```
61
+
62
+ Initialize project context:
63
+
64
+ ```bash
65
+ npx xtctx init
66
+ ```
67
+
68
+ Sync shared config into tool-native files:
69
+
70
+ ```bash
71
+ npx xtctx sync
72
+ ```
73
+
74
+ Start runtime services:
75
+
76
+ ```bash
77
+ npx xtctx serve
78
+ ```
79
+
80
+ Open:
81
+
82
+ - Runtime web app: `http://127.0.0.1:3232/`
83
+ - Health: `http://127.0.0.1:3232/health`
84
+ - API: `http://127.0.0.1:3232/api/*`
85
+
86
+ Optional full re-index:
87
+
88
+ ```bash
89
+ npx xtctx ingest --full
90
+ ```
91
+
92
+ ## MCP Client Command
93
+
94
+ ```json
95
+ {
96
+ "command": "npx",
97
+ "args": ["xtctx", "serve", "--mcp-only", "--project", "/absolute/path/to/project"]
98
+ }
99
+ ```
100
+
101
+ ## File-First Configuration
102
+
103
+ Primary config source is `.xtctx/config.yaml`.
104
+
105
+ Environment variables are optional explicit overrides only.
106
+
107
+ Security-related overrides:
108
+
109
+ - `XTCTX_API_TOKEN`
110
+ - `XTCTX_ALLOWED_ORIGINS`
111
+ - `XTCTX_ALLOW_LOCALHOST_ORIGINS`
112
+ - `XTCTX_RATE_LIMIT_WINDOW_MS`
113
+ - `XTCTX_RATE_LIMIT_MAX`
114
+
115
+ ## UIs
116
+
117
+ - `web/`: runtime product UI served by `xtctx serve` (dark mode default with toggle)
118
+ - `landing/`: public landing site deployed to GitHub Pages (dark mode default with toggle)
119
+
120
+ Local previews:
121
+
122
+ ```bash
123
+ npm run web:dev
124
+ npm run landing:dev
125
+ npm run landing:preview
126
+ ```
127
+
128
+ ## CLI Commands
129
+
130
+ - `xtctx init [path]`
131
+ - `xtctx serve [--mcp-only] [--project <path>]`
132
+ - `xtctx ingest [--full] [--project <path>]`
133
+ - `xtctx sync [--project <path>]`
134
+
135
+ ## Development
136
+
137
+ Full validation:
138
+
139
+ ```bash
140
+ npm run verify:release
141
+ ```
142
+
143
+ Release automation:
144
+
145
+ - Conventional commits feed Release Please
146
+ - Release PR merge on `main` creates GitHub release
147
+ - GitHub release publication triggers npm publish via OIDC trusted publishing
148
+
149
+ See `CONTRIBUTING.md` and `SECURITY.md` for contributor and security policy details.
@@ -0,0 +1,4 @@
1
+ import { Router } from "express";
2
+ import { type ConfigStore } from "../../mcp/tools/config.js";
3
+ export declare function createConfigRouter(store: ConfigStore): Router;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/api/routes/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAIL,KAAK,WAAW,EAEjB,MAAM,2BAA2B,CAAC;AAEnC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAgD7D"}
@@ -0,0 +1,61 @@
1
+ import { Router } from "express";
2
+ import { createGetConfigHandler, createListConfigsHandler, createToolPreferencesHandler, } from "../../mcp/tools/config.js";
3
+ export function createConfigRouter(store) {
4
+ const router = Router();
5
+ const listConfigs = createListConfigsHandler(store);
6
+ const getConfig = createGetConfigHandler(store);
7
+ const toolPreferences = createToolPreferencesHandler(store);
8
+ router.get("/list", async (req, res, next) => {
9
+ try {
10
+ const type = normalizeListType(req.query.type);
11
+ const result = await listConfigs({ type, format: "json" });
12
+ res.json(result);
13
+ }
14
+ catch (error) {
15
+ next(error);
16
+ }
17
+ });
18
+ router.get("/get", async (req, res, next) => {
19
+ try {
20
+ const type = normalizeConfigType(req.query.type);
21
+ const name = String(req.query.name ?? "");
22
+ if (!type || !name) {
23
+ res.status(400).json({ error: "type and name are required" });
24
+ return;
25
+ }
26
+ const result = await getConfig({ type, name, format: "json" });
27
+ res.json(result);
28
+ }
29
+ catch (error) {
30
+ next(error);
31
+ }
32
+ });
33
+ router.get("/preferences", async (req, res, next) => {
34
+ try {
35
+ const tool = String(req.query.tool ?? "");
36
+ if (!tool) {
37
+ res.status(400).json({ error: "tool is required" });
38
+ return;
39
+ }
40
+ const result = await toolPreferences({ tool, format: "json" });
41
+ res.json(result);
42
+ }
43
+ catch (error) {
44
+ next(error);
45
+ }
46
+ });
47
+ return router;
48
+ }
49
+ function normalizeListType(value) {
50
+ if (value === "skill" || value === "command" || value === "agent" || value === "all") {
51
+ return value;
52
+ }
53
+ return "all";
54
+ }
55
+ function normalizeConfigType(value) {
56
+ if (value === "skill" || value === "command" || value === "agent") {
57
+ return value;
58
+ }
59
+ return null;
60
+ }
61
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/api/routes/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Router } from "express";
2
+ import { type KnowledgeStore } from "../../mcp/tools/knowledge.js";
3
+ export declare function createKnowledgeRouter(knowledge: KnowledgeStore): Router;
4
+ //# sourceMappingURL=knowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../../../src/api/routes/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,8BAA8B,CAAC;AAStC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CA2BvE"}
@@ -0,0 +1,40 @@
1
+ import { Router } from "express";
2
+ import { createProjectKnowledgeHandler, } from "../../mcp/tools/knowledge.js";
3
+ export function createKnowledgeRouter(knowledge) {
4
+ const router = Router();
5
+ const handler = createProjectKnowledgeHandler(knowledge);
6
+ router.get("/", async (req, res, next) => {
7
+ try {
8
+ const query = req.query;
9
+ const type = normalizeType(query.type);
10
+ const format = query.format === "markdown" ? "markdown" : "json";
11
+ const result = await handler({
12
+ type,
13
+ query: query.query,
14
+ format,
15
+ });
16
+ if (format === "markdown" && typeof result === "string") {
17
+ res.type("text/markdown").send(result);
18
+ return;
19
+ }
20
+ res.json(result);
21
+ }
22
+ catch (error) {
23
+ next(error);
24
+ }
25
+ });
26
+ return router;
27
+ }
28
+ function normalizeType(value) {
29
+ if (value === "decision" ||
30
+ value === "error_solution" ||
31
+ value === "insight" ||
32
+ value === "convention" ||
33
+ value === "gotcha" ||
34
+ value === "faq" ||
35
+ value === "all") {
36
+ return value;
37
+ }
38
+ return "all";
39
+ }
40
+ //# sourceMappingURL=knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../../../src/api/routes/knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EACL,6BAA6B,GAE9B,MAAM,8BAA8B,CAAC;AAStC,MAAM,UAAU,qBAAqB,CAAC,SAAyB;IAC7D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,6BAA6B,CAAC,SAAS,CAAC,CAAC;IAEzD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACvC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,GAAG,CAAC,KAAuB,CAAC;YAC1C,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;YACjE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;gBAC3B,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM;aACP,CAAC,CAAC;YAEH,IAAI,MAAM,KAAK,UAAU,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxD,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IACE,KAAK,KAAK,UAAU;QACpB,KAAK,KAAK,gBAAgB;QAC1B,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,YAAY;QACtB,KAAK,KAAK,QAAQ;QAClB,KAAK,KAAK,KAAK;QACf,KAAK,KAAK,KAAK,EACf,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Router } from "express";
2
+ import type { ContextRecord } from "../../types/context.js";
3
+ export interface SearchRouteDependencies {
4
+ knowledgeRecords: () => Promise<ContextRecord[]>;
5
+ }
6
+ export declare function createSearchRouter(deps: SearchRouteDependencies): Router;
7
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/api/routes/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAClD;AAkDD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAkCxE"}
@@ -0,0 +1,108 @@
1
+ import { Router } from "express";
2
+ import { createSearchHandler } from "../../mcp/tools/search.js";
3
+ class KnowledgeSearchRunner {
4
+ knowledgeRecords;
5
+ constructor(knowledgeRecords) {
6
+ this.knowledgeRecords = knowledgeRecords;
7
+ }
8
+ async search(_tableName, query, _mode, limit) {
9
+ const records = await this.knowledgeRecords();
10
+ const needle = query.trim().toLowerCase();
11
+ if (!needle) {
12
+ return [];
13
+ }
14
+ const ranked = records
15
+ .map((record) => {
16
+ const haystack = `${record.title} ${record.body} ${record.domain_tags.join(" ")}`.toLowerCase();
17
+ const score = relevanceScore(needle, haystack);
18
+ return { record, score };
19
+ })
20
+ .filter((item) => item.score > 0)
21
+ .sort((a, b) => b.score - a.score)
22
+ .slice(0, limit);
23
+ return ranked.map(({ record, score }) => ({
24
+ id: record.id,
25
+ text: record.body,
26
+ metadata: JSON.stringify({
27
+ title: record.title,
28
+ type: record.type,
29
+ source_tool: record.source_tool,
30
+ created_at: record.created_at,
31
+ }),
32
+ score,
33
+ fusedScore: score,
34
+ }));
35
+ }
36
+ }
37
+ export function createSearchRouter(deps) {
38
+ const router = Router();
39
+ const runner = new KnowledgeSearchRunner(deps.knowledgeRecords);
40
+ const handler = createSearchHandler(runner);
41
+ router.get("/", async (req, res, next) => {
42
+ try {
43
+ const query = String(req.query.query ?? "");
44
+ const mode = normalizeMode(req.query.mode);
45
+ const limit = clampLimit(req.query.limit);
46
+ const depth = normalizeDepth(req.query.depth);
47
+ const format = "json";
48
+ const result = await handler({ query, mode, limit, depth, format });
49
+ res.json(result);
50
+ }
51
+ catch (error) {
52
+ next(error);
53
+ }
54
+ });
55
+ router.post("/", async (req, res, next) => {
56
+ try {
57
+ const query = String(req.body?.query ?? "");
58
+ const mode = normalizeMode(req.body?.mode);
59
+ const limit = clampLimit(req.body?.limit);
60
+ const depth = normalizeDepth(req.body?.depth);
61
+ const format = "json";
62
+ const result = await handler({ query, mode, limit, depth, format });
63
+ res.json(result);
64
+ }
65
+ catch (error) {
66
+ next(error);
67
+ }
68
+ });
69
+ return router;
70
+ }
71
+ function relevanceScore(needle, haystack) {
72
+ const words = needle.split(/\s+/).filter(Boolean);
73
+ if (words.length === 0) {
74
+ return 0;
75
+ }
76
+ let hits = 0;
77
+ for (const word of words) {
78
+ if (haystack.includes(word)) {
79
+ hits += 1;
80
+ }
81
+ }
82
+ if (hits === 0) {
83
+ return 0;
84
+ }
85
+ const coverage = hits / words.length;
86
+ const exactBonus = haystack.includes(needle) ? 0.25 : 0;
87
+ return Math.min(1, coverage + exactBonus);
88
+ }
89
+ function normalizeMode(value) {
90
+ if (value === "semantic" || value === "keyword") {
91
+ return value;
92
+ }
93
+ return "hybrid";
94
+ }
95
+ function normalizeDepth(value) {
96
+ if (value === "detail" || value === "raw") {
97
+ return value;
98
+ }
99
+ return "summary";
100
+ }
101
+ function clampLimit(value) {
102
+ const parsed = Number(value);
103
+ if (!Number.isFinite(parsed)) {
104
+ return 10;
105
+ }
106
+ return Math.max(1, Math.min(100, Math.floor(parsed)));
107
+ }
108
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/api/routes/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Router } from "express";
2
+ import type { SessionService } from "../../mcp/tools/sessions.js";
3
+ import type { ContextRecord } from "../../types/context.js";
4
+ export interface SourcesRouteDependencies {
5
+ projectRoot: string;
6
+ knowledgeDir: string;
7
+ stateDir: string;
8
+ sessions: SessionService;
9
+ knowledgeRecords: () => Promise<ContextRecord[]>;
10
+ }
11
+ export declare function createSourcesRouter(deps: SourcesRouteDependencies): Router;
12
+ //# sourceMappingURL=sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../../src/api/routes/sources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,gBAAgB,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAClD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,CAuD1E"}
@@ -0,0 +1,70 @@
1
+ import { Router } from "express";
2
+ import { stat } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ export function createSourcesRouter(deps) {
5
+ const router = Router();
6
+ router.get("/", async (_req, res, next) => {
7
+ try {
8
+ const knowledge = await deps.knowledgeRecords();
9
+ const claudeProjectsDir = resolveClaudeProjectsDir();
10
+ const claudeDetected = await isDirectory(claudeProjectsDir);
11
+ const recentSessions = await deps.sessions.listRecentSessions(5);
12
+ res.json({
13
+ projectRoot: deps.projectRoot,
14
+ sources: [
15
+ {
16
+ name: "knowledge",
17
+ kind: "filesystem",
18
+ path: deps.knowledgeDir,
19
+ records: knowledge.length,
20
+ },
21
+ {
22
+ name: "claude-code",
23
+ kind: "scraper",
24
+ path: claudeProjectsDir,
25
+ detected: claudeDetected,
26
+ },
27
+ {
28
+ name: "scraper-state",
29
+ kind: "filesystem",
30
+ path: deps.stateDir,
31
+ },
32
+ ],
33
+ sessions: recentSessions,
34
+ });
35
+ }
36
+ catch (error) {
37
+ next(error);
38
+ }
39
+ });
40
+ router.get("/status", async (_req, res, next) => {
41
+ try {
42
+ const claudeProjectsDir = resolveClaudeProjectsDir();
43
+ const claudeDetected = await isDirectory(claudeProjectsDir);
44
+ const records = await deps.knowledgeRecords();
45
+ res.json({
46
+ ok: true,
47
+ claudeDetected,
48
+ knowledgeRecords: records.length,
49
+ });
50
+ }
51
+ catch (error) {
52
+ next(error);
53
+ }
54
+ });
55
+ return router;
56
+ }
57
+ function resolveClaudeProjectsDir() {
58
+ const home = process.env.USERPROFILE ?? process.env.HOME ?? "";
59
+ return join(home, ".claude", "projects");
60
+ }
61
+ async function isDirectory(path) {
62
+ try {
63
+ const result = await stat(path);
64
+ return result.isDirectory();
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ //# sourceMappingURL=sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../../src/api/routes/sources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,MAAM,UAAU,mBAAmB,CAAC,IAA8B;IAChE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAChD,MAAM,iBAAiB,GAAG,wBAAwB,EAAE,CAAC;YACrD,MAAM,cAAc,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,CAAC;YAC5D,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;YAEjE,GAAG,CAAC,IAAI,CAAC;gBACP,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,WAAW;wBACjB,IAAI,EAAE,YAAY;wBAClB,IAAI,EAAE,IAAI,CAAC,YAAY;wBACvB,OAAO,EAAE,SAAS,CAAC,MAAM;qBAC1B;oBACD;wBACE,IAAI,EAAE,aAAa;wBACnB,IAAI,EAAE,SAAS;wBACf,IAAI,EAAE,iBAAiB;wBACvB,QAAQ,EAAE,cAAc;qBACzB;oBACD;wBACE,IAAI,EAAE,eAAe;wBACrB,IAAI,EAAE,YAAY;wBAClB,IAAI,EAAE,IAAI,CAAC,QAAQ;qBACpB;iBACF;gBACD,QAAQ,EAAE,cAAc;aACzB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9C,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,wBAAwB,EAAE,CAAC;YACrD,MAAM,cAAc,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAE9C,GAAG,CAAC,IAAI,CAAC;gBACP,EAAE,EAAE,IAAI;gBACR,cAAc;gBACd,gBAAgB,EAAE,OAAO,CAAC,MAAM;aACjC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,wBAAwB;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}