openlore 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (634) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +268 -0
  3. package/dist/api/analyze.d.ts +17 -0
  4. package/dist/api/analyze.d.ts.map +1 -0
  5. package/dist/api/analyze.js +143 -0
  6. package/dist/api/analyze.js.map +1 -0
  7. package/dist/api/audit.d.ts +10 -0
  8. package/dist/api/audit.d.ts.map +1 -0
  9. package/dist/api/audit.js +117 -0
  10. package/dist/api/audit.js.map +1 -0
  11. package/dist/api/decisions.d.ts +55 -0
  12. package/dist/api/decisions.d.ts.map +1 -0
  13. package/dist/api/decisions.js +157 -0
  14. package/dist/api/decisions.js.map +1 -0
  15. package/dist/api/drift.d.ts +21 -0
  16. package/dist/api/drift.d.ts.map +1 -0
  17. package/dist/api/drift.js +152 -0
  18. package/dist/api/drift.js.map +1 -0
  19. package/dist/api/generate.d.ts +18 -0
  20. package/dist/api/generate.d.ts.map +1 -0
  21. package/dist/api/generate.js +259 -0
  22. package/dist/api/generate.js.map +1 -0
  23. package/dist/api/index.d.ts +41 -0
  24. package/dist/api/index.d.ts.map +1 -0
  25. package/dist/api/index.js +34 -0
  26. package/dist/api/index.js.map +1 -0
  27. package/dist/api/init.d.ts +18 -0
  28. package/dist/api/init.d.ts.map +1 -0
  29. package/dist/api/init.js +83 -0
  30. package/dist/api/init.js.map +1 -0
  31. package/dist/api/run.d.ts +19 -0
  32. package/dist/api/run.d.ts.map +1 -0
  33. package/dist/api/run.js +312 -0
  34. package/dist/api/run.js.map +1 -0
  35. package/dist/api/specs.d.ts +49 -0
  36. package/dist/api/specs.d.ts.map +1 -0
  37. package/dist/api/specs.js +137 -0
  38. package/dist/api/specs.js.map +1 -0
  39. package/dist/api/types.d.ts +201 -0
  40. package/dist/api/types.d.ts.map +1 -0
  41. package/dist/api/types.js +9 -0
  42. package/dist/api/types.js.map +1 -0
  43. package/dist/api/verify.d.ts +20 -0
  44. package/dist/api/verify.d.ts.map +1 -0
  45. package/dist/api/verify.js +117 -0
  46. package/dist/api/verify.js.map +1 -0
  47. package/dist/cli/commands/analyze.d.ts +30 -0
  48. package/dist/cli/commands/analyze.d.ts.map +1 -0
  49. package/dist/cli/commands/analyze.js +683 -0
  50. package/dist/cli/commands/analyze.js.map +1 -0
  51. package/dist/cli/commands/audit.d.ts +9 -0
  52. package/dist/cli/commands/audit.d.ts.map +1 -0
  53. package/dist/cli/commands/audit.js +98 -0
  54. package/dist/cli/commands/audit.js.map +1 -0
  55. package/dist/cli/commands/decisions.d.ts +16 -0
  56. package/dist/cli/commands/decisions.d.ts.map +1 -0
  57. package/dist/cli/commands/decisions.js +864 -0
  58. package/dist/cli/commands/decisions.js.map +1 -0
  59. package/dist/cli/commands/digest.d.ts +9 -0
  60. package/dist/cli/commands/digest.d.ts.map +1 -0
  61. package/dist/cli/commands/digest.js +61 -0
  62. package/dist/cli/commands/digest.js.map +1 -0
  63. package/dist/cli/commands/doctor.d.ts +9 -0
  64. package/dist/cli/commands/doctor.d.ts.map +1 -0
  65. package/dist/cli/commands/doctor.js +398 -0
  66. package/dist/cli/commands/doctor.js.map +1 -0
  67. package/dist/cli/commands/drift.d.ts +9 -0
  68. package/dist/cli/commands/drift.d.ts.map +1 -0
  69. package/dist/cli/commands/drift.js +550 -0
  70. package/dist/cli/commands/drift.js.map +1 -0
  71. package/dist/cli/commands/generate.d.ts +9 -0
  72. package/dist/cli/commands/generate.d.ts.map +1 -0
  73. package/dist/cli/commands/generate.js +565 -0
  74. package/dist/cli/commands/generate.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +9 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +173 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/mcp.d.ts +2235 -0
  80. package/dist/cli/commands/mcp.d.ts.map +1 -0
  81. package/dist/cli/commands/mcp.js +1384 -0
  82. package/dist/cli/commands/mcp.js.map +1 -0
  83. package/dist/cli/commands/refresh-stories.d.ts +10 -0
  84. package/dist/cli/commands/refresh-stories.d.ts.map +1 -0
  85. package/dist/cli/commands/refresh-stories.js +314 -0
  86. package/dist/cli/commands/refresh-stories.js.map +1 -0
  87. package/dist/cli/commands/run.d.ts +9 -0
  88. package/dist/cli/commands/run.d.ts.map +1 -0
  89. package/dist/cli/commands/run.js +459 -0
  90. package/dist/cli/commands/run.js.map +1 -0
  91. package/dist/cli/commands/setup.d.ts +19 -0
  92. package/dist/cli/commands/setup.d.ts.map +1 -0
  93. package/dist/cli/commands/setup.js +355 -0
  94. package/dist/cli/commands/setup.js.map +1 -0
  95. package/dist/cli/commands/test.d.ts +22 -0
  96. package/dist/cli/commands/test.d.ts.map +1 -0
  97. package/dist/cli/commands/test.js +180 -0
  98. package/dist/cli/commands/test.js.map +1 -0
  99. package/dist/cli/commands/verify.d.ts +9 -0
  100. package/dist/cli/commands/verify.d.ts.map +1 -0
  101. package/dist/cli/commands/verify.js +383 -0
  102. package/dist/cli/commands/verify.js.map +1 -0
  103. package/dist/cli/commands/view.d.ts +13 -0
  104. package/dist/cli/commands/view.d.ts.map +1 -0
  105. package/dist/cli/commands/view.js +547 -0
  106. package/dist/cli/commands/view.js.map +1 -0
  107. package/dist/cli/index.d.ts +9 -0
  108. package/dist/cli/index.d.ts.map +1 -0
  109. package/dist/cli/index.js +118 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/tui-approval.d.ts +11 -0
  112. package/dist/cli/tui-approval.d.ts.map +1 -0
  113. package/dist/cli/tui-approval.js +129 -0
  114. package/dist/cli/tui-approval.js.map +1 -0
  115. package/dist/constants.d.ts +314 -0
  116. package/dist/constants.d.ts.map +1 -0
  117. package/dist/constants.js +382 -0
  118. package/dist/constants.js.map +1 -0
  119. package/dist/core/analyzer/ai-config-generator.d.ts +54 -0
  120. package/dist/core/analyzer/ai-config-generator.d.ts.map +1 -0
  121. package/dist/core/analyzer/ai-config-generator.js +98 -0
  122. package/dist/core/analyzer/ai-config-generator.js.map +1 -0
  123. package/dist/core/analyzer/architecture-writer.d.ts +67 -0
  124. package/dist/core/analyzer/architecture-writer.d.ts.map +1 -0
  125. package/dist/core/analyzer/architecture-writer.js +209 -0
  126. package/dist/core/analyzer/architecture-writer.js.map +1 -0
  127. package/dist/core/analyzer/artifact-generator.d.ts +261 -0
  128. package/dist/core/analyzer/artifact-generator.d.ts.map +1 -0
  129. package/dist/core/analyzer/artifact-generator.js +909 -0
  130. package/dist/core/analyzer/artifact-generator.js.map +1 -0
  131. package/dist/core/analyzer/ast-chunker.d.ts +24 -0
  132. package/dist/core/analyzer/ast-chunker.d.ts.map +1 -0
  133. package/dist/core/analyzer/ast-chunker.js +198 -0
  134. package/dist/core/analyzer/ast-chunker.js.map +1 -0
  135. package/dist/core/analyzer/call-graph.d.ts +162 -0
  136. package/dist/core/analyzer/call-graph.d.ts.map +1 -0
  137. package/dist/core/analyzer/call-graph.js +2040 -0
  138. package/dist/core/analyzer/call-graph.js.map +1 -0
  139. package/dist/core/analyzer/code-shaper.d.ts +33 -0
  140. package/dist/core/analyzer/code-shaper.d.ts.map +1 -0
  141. package/dist/core/analyzer/code-shaper.js +154 -0
  142. package/dist/core/analyzer/code-shaper.js.map +1 -0
  143. package/dist/core/analyzer/codebase-digest.d.ts +40 -0
  144. package/dist/core/analyzer/codebase-digest.d.ts.map +1 -0
  145. package/dist/core/analyzer/codebase-digest.js +195 -0
  146. package/dist/core/analyzer/codebase-digest.js.map +1 -0
  147. package/dist/core/analyzer/cpp-header-resolver.d.ts +30 -0
  148. package/dist/core/analyzer/cpp-header-resolver.d.ts.map +1 -0
  149. package/dist/core/analyzer/cpp-header-resolver.js +71 -0
  150. package/dist/core/analyzer/cpp-header-resolver.js.map +1 -0
  151. package/dist/core/analyzer/dependency-graph.d.ts +230 -0
  152. package/dist/core/analyzer/dependency-graph.d.ts.map +1 -0
  153. package/dist/core/analyzer/dependency-graph.js +752 -0
  154. package/dist/core/analyzer/dependency-graph.js.map +1 -0
  155. package/dist/core/analyzer/duplicate-detector.d.ts +52 -0
  156. package/dist/core/analyzer/duplicate-detector.d.ts.map +1 -0
  157. package/dist/core/analyzer/duplicate-detector.js +289 -0
  158. package/dist/core/analyzer/duplicate-detector.js.map +1 -0
  159. package/dist/core/analyzer/embedding-service.d.ts +56 -0
  160. package/dist/core/analyzer/embedding-service.d.ts.map +1 -0
  161. package/dist/core/analyzer/embedding-service.js +118 -0
  162. package/dist/core/analyzer/embedding-service.js.map +1 -0
  163. package/dist/core/analyzer/env-extractor.d.ts +33 -0
  164. package/dist/core/analyzer/env-extractor.d.ts.map +1 -0
  165. package/dist/core/analyzer/env-extractor.js +196 -0
  166. package/dist/core/analyzer/env-extractor.js.map +1 -0
  167. package/dist/core/analyzer/external-packages.d.ts +20 -0
  168. package/dist/core/analyzer/external-packages.d.ts.map +1 -0
  169. package/dist/core/analyzer/external-packages.js +175 -0
  170. package/dist/core/analyzer/external-packages.js.map +1 -0
  171. package/dist/core/analyzer/file-walker.d.ts +78 -0
  172. package/dist/core/analyzer/file-walker.d.ts.map +1 -0
  173. package/dist/core/analyzer/file-walker.js +532 -0
  174. package/dist/core/analyzer/file-walker.js.map +1 -0
  175. package/dist/core/analyzer/function-registry-trie.d.ts +21 -0
  176. package/dist/core/analyzer/function-registry-trie.d.ts.map +1 -0
  177. package/dist/core/analyzer/function-registry-trie.js +39 -0
  178. package/dist/core/analyzer/function-registry-trie.js.map +1 -0
  179. package/dist/core/analyzer/http-route-parser.d.ts +152 -0
  180. package/dist/core/analyzer/http-route-parser.d.ts.map +1 -0
  181. package/dist/core/analyzer/http-route-parser.js +971 -0
  182. package/dist/core/analyzer/http-route-parser.js.map +1 -0
  183. package/dist/core/analyzer/import-parser.d.ts +100 -0
  184. package/dist/core/analyzer/import-parser.d.ts.map +1 -0
  185. package/dist/core/analyzer/import-parser.js +952 -0
  186. package/dist/core/analyzer/import-parser.js.map +1 -0
  187. package/dist/core/analyzer/import-resolver-bridge.d.ts +25 -0
  188. package/dist/core/analyzer/import-resolver-bridge.d.ts.map +1 -0
  189. package/dist/core/analyzer/import-resolver-bridge.js +99 -0
  190. package/dist/core/analyzer/import-resolver-bridge.js.map +1 -0
  191. package/dist/core/analyzer/index.d.ts +10 -0
  192. package/dist/core/analyzer/index.d.ts.map +1 -0
  193. package/dist/core/analyzer/index.js +10 -0
  194. package/dist/core/analyzer/index.js.map +1 -0
  195. package/dist/core/analyzer/middleware-extractor.d.ts +29 -0
  196. package/dist/core/analyzer/middleware-extractor.d.ts.map +1 -0
  197. package/dist/core/analyzer/middleware-extractor.js +195 -0
  198. package/dist/core/analyzer/middleware-extractor.js.map +1 -0
  199. package/dist/core/analyzer/refactor-analyzer.d.ts +83 -0
  200. package/dist/core/analyzer/refactor-analyzer.d.ts.map +1 -0
  201. package/dist/core/analyzer/refactor-analyzer.js +351 -0
  202. package/dist/core/analyzer/refactor-analyzer.js.map +1 -0
  203. package/dist/core/analyzer/repository-mapper.d.ts +150 -0
  204. package/dist/core/analyzer/repository-mapper.d.ts.map +1 -0
  205. package/dist/core/analyzer/repository-mapper.js +740 -0
  206. package/dist/core/analyzer/repository-mapper.js.map +1 -0
  207. package/dist/core/analyzer/schema-extractor.d.ts +41 -0
  208. package/dist/core/analyzer/schema-extractor.d.ts.map +1 -0
  209. package/dist/core/analyzer/schema-extractor.js +229 -0
  210. package/dist/core/analyzer/schema-extractor.js.map +1 -0
  211. package/dist/core/analyzer/signature-extractor.d.ts +31 -0
  212. package/dist/core/analyzer/signature-extractor.d.ts.map +1 -0
  213. package/dist/core/analyzer/signature-extractor.js +675 -0
  214. package/dist/core/analyzer/signature-extractor.js.map +1 -0
  215. package/dist/core/analyzer/significance-scorer.d.ts +79 -0
  216. package/dist/core/analyzer/significance-scorer.d.ts.map +1 -0
  217. package/dist/core/analyzer/significance-scorer.js +407 -0
  218. package/dist/core/analyzer/significance-scorer.js.map +1 -0
  219. package/dist/core/analyzer/spec-snapshot-generator.d.ts +17 -0
  220. package/dist/core/analyzer/spec-snapshot-generator.d.ts.map +1 -0
  221. package/dist/core/analyzer/spec-snapshot-generator.js +201 -0
  222. package/dist/core/analyzer/spec-snapshot-generator.js.map +1 -0
  223. package/dist/core/analyzer/spec-vector-index.d.ts +68 -0
  224. package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -0
  225. package/dist/core/analyzer/spec-vector-index.js +340 -0
  226. package/dist/core/analyzer/spec-vector-index.js.map +1 -0
  227. package/dist/core/analyzer/subgraph-extractor.d.ts +51 -0
  228. package/dist/core/analyzer/subgraph-extractor.d.ts.map +1 -0
  229. package/dist/core/analyzer/subgraph-extractor.js +147 -0
  230. package/dist/core/analyzer/subgraph-extractor.js.map +1 -0
  231. package/dist/core/analyzer/type-inference-engine.d.ts +23 -0
  232. package/dist/core/analyzer/type-inference-engine.d.ts.map +1 -0
  233. package/dist/core/analyzer/type-inference-engine.js +130 -0
  234. package/dist/core/analyzer/type-inference-engine.js.map +1 -0
  235. package/dist/core/analyzer/ui-component-extractor.d.ts +43 -0
  236. package/dist/core/analyzer/ui-component-extractor.d.ts.map +1 -0
  237. package/dist/core/analyzer/ui-component-extractor.js +245 -0
  238. package/dist/core/analyzer/ui-component-extractor.js.map +1 -0
  239. package/dist/core/analyzer/unified-search.d.ts +116 -0
  240. package/dist/core/analyzer/unified-search.d.ts.map +1 -0
  241. package/dist/core/analyzer/unified-search.js +231 -0
  242. package/dist/core/analyzer/unified-search.js.map +1 -0
  243. package/dist/core/analyzer/vector-index.d.ts +92 -0
  244. package/dist/core/analyzer/vector-index.d.ts.map +1 -0
  245. package/dist/core/analyzer/vector-index.js +451 -0
  246. package/dist/core/analyzer/vector-index.js.map +1 -0
  247. package/dist/core/decisions/consolidator.d.ts +14 -0
  248. package/dist/core/decisions/consolidator.d.ts.map +1 -0
  249. package/dist/core/decisions/consolidator.js +169 -0
  250. package/dist/core/decisions/consolidator.js.map +1 -0
  251. package/dist/core/decisions/extractor.d.ts +26 -0
  252. package/dist/core/decisions/extractor.d.ts.map +1 -0
  253. package/dist/core/decisions/extractor.js +156 -0
  254. package/dist/core/decisions/extractor.js.map +1 -0
  255. package/dist/core/decisions/index.d.ts +19 -0
  256. package/dist/core/decisions/index.d.ts.map +1 -0
  257. package/dist/core/decisions/index.js +16 -0
  258. package/dist/core/decisions/index.js.map +1 -0
  259. package/dist/core/decisions/store.d.ts +36 -0
  260. package/dist/core/decisions/store.d.ts.map +1 -0
  261. package/dist/core/decisions/store.js +109 -0
  262. package/dist/core/decisions/store.js.map +1 -0
  263. package/dist/core/decisions/syncer.d.ts +27 -0
  264. package/dist/core/decisions/syncer.d.ts.map +1 -0
  265. package/dist/core/decisions/syncer.js +214 -0
  266. package/dist/core/decisions/syncer.js.map +1 -0
  267. package/dist/core/decisions/verifier.d.ts +20 -0
  268. package/dist/core/decisions/verifier.d.ts.map +1 -0
  269. package/dist/core/decisions/verifier.js +115 -0
  270. package/dist/core/decisions/verifier.js.map +1 -0
  271. package/dist/core/digest/digest-generator.d.ts +29 -0
  272. package/dist/core/digest/digest-generator.d.ts.map +1 -0
  273. package/dist/core/digest/digest-generator.js +181 -0
  274. package/dist/core/digest/digest-generator.js.map +1 -0
  275. package/dist/core/drift/drift-detector.d.ts +102 -0
  276. package/dist/core/drift/drift-detector.d.ts.map +1 -0
  277. package/dist/core/drift/drift-detector.js +598 -0
  278. package/dist/core/drift/drift-detector.js.map +1 -0
  279. package/dist/core/drift/git-diff.d.ts +60 -0
  280. package/dist/core/drift/git-diff.d.ts.map +1 -0
  281. package/dist/core/drift/git-diff.js +383 -0
  282. package/dist/core/drift/git-diff.js.map +1 -0
  283. package/dist/core/drift/index.d.ts +12 -0
  284. package/dist/core/drift/index.d.ts.map +1 -0
  285. package/dist/core/drift/index.js +9 -0
  286. package/dist/core/drift/index.js.map +1 -0
  287. package/dist/core/drift/spec-mapper.d.ts +73 -0
  288. package/dist/core/drift/spec-mapper.d.ts.map +1 -0
  289. package/dist/core/drift/spec-mapper.js +353 -0
  290. package/dist/core/drift/spec-mapper.js.map +1 -0
  291. package/dist/core/drift/test-suggester.d.ts +18 -0
  292. package/dist/core/drift/test-suggester.d.ts.map +1 -0
  293. package/dist/core/drift/test-suggester.js +107 -0
  294. package/dist/core/drift/test-suggester.js.map +1 -0
  295. package/dist/core/generator/adr-generator.d.ts +32 -0
  296. package/dist/core/generator/adr-generator.d.ts.map +1 -0
  297. package/dist/core/generator/adr-generator.js +192 -0
  298. package/dist/core/generator/adr-generator.js.map +1 -0
  299. package/dist/core/generator/index.d.ts +9 -0
  300. package/dist/core/generator/index.d.ts.map +1 -0
  301. package/dist/core/generator/index.js +12 -0
  302. package/dist/core/generator/index.js.map +1 -0
  303. package/dist/core/generator/mapping-generator.d.ts +54 -0
  304. package/dist/core/generator/mapping-generator.d.ts.map +1 -0
  305. package/dist/core/generator/mapping-generator.js +240 -0
  306. package/dist/core/generator/mapping-generator.js.map +1 -0
  307. package/dist/core/generator/openspec-compat.d.ts +160 -0
  308. package/dist/core/generator/openspec-compat.d.ts.map +1 -0
  309. package/dist/core/generator/openspec-compat.js +524 -0
  310. package/dist/core/generator/openspec-compat.js.map +1 -0
  311. package/dist/core/generator/openspec-format-generator.d.ts +131 -0
  312. package/dist/core/generator/openspec-format-generator.d.ts.map +1 -0
  313. package/dist/core/generator/openspec-format-generator.js +963 -0
  314. package/dist/core/generator/openspec-format-generator.js.map +1 -0
  315. package/dist/core/generator/openspec-writer.d.ts +130 -0
  316. package/dist/core/generator/openspec-writer.d.ts.map +1 -0
  317. package/dist/core/generator/openspec-writer.js +404 -0
  318. package/dist/core/generator/openspec-writer.js.map +1 -0
  319. package/dist/core/generator/prompts.d.ts +35 -0
  320. package/dist/core/generator/prompts.d.ts.map +1 -0
  321. package/dist/core/generator/prompts.js +212 -0
  322. package/dist/core/generator/prompts.js.map +1 -0
  323. package/dist/core/generator/rag-manifest-generator.d.ts +37 -0
  324. package/dist/core/generator/rag-manifest-generator.d.ts.map +1 -0
  325. package/dist/core/generator/rag-manifest-generator.js +134 -0
  326. package/dist/core/generator/rag-manifest-generator.js.map +1 -0
  327. package/dist/core/generator/schemas.d.ts +365 -0
  328. package/dist/core/generator/schemas.d.ts.map +1 -0
  329. package/dist/core/generator/schemas.js +190 -0
  330. package/dist/core/generator/schemas.js.map +1 -0
  331. package/dist/core/generator/spec-pipeline.d.ts +123 -0
  332. package/dist/core/generator/spec-pipeline.d.ts.map +1 -0
  333. package/dist/core/generator/spec-pipeline.js +699 -0
  334. package/dist/core/generator/spec-pipeline.js.map +1 -0
  335. package/dist/core/generator/stages/stage1-survey.d.ts +19 -0
  336. package/dist/core/generator/stages/stage1-survey.d.ts.map +1 -0
  337. package/dist/core/generator/stages/stage1-survey.js +171 -0
  338. package/dist/core/generator/stages/stage1-survey.js.map +1 -0
  339. package/dist/core/generator/stages/stage2-entities.d.ts +11 -0
  340. package/dist/core/generator/stages/stage2-entities.d.ts.map +1 -0
  341. package/dist/core/generator/stages/stage2-entities.js +74 -0
  342. package/dist/core/generator/stages/stage2-entities.js.map +1 -0
  343. package/dist/core/generator/stages/stage3-services.d.ts +11 -0
  344. package/dist/core/generator/stages/stage3-services.d.ts.map +1 -0
  345. package/dist/core/generator/stages/stage3-services.js +85 -0
  346. package/dist/core/generator/stages/stage3-services.js.map +1 -0
  347. package/dist/core/generator/stages/stage4-api.d.ts +11 -0
  348. package/dist/core/generator/stages/stage4-api.d.ts.map +1 -0
  349. package/dist/core/generator/stages/stage4-api.js +72 -0
  350. package/dist/core/generator/stages/stage4-api.js.map +1 -0
  351. package/dist/core/generator/stages/stage5-architecture.d.ts +11 -0
  352. package/dist/core/generator/stages/stage5-architecture.d.ts.map +1 -0
  353. package/dist/core/generator/stages/stage5-architecture.js +75 -0
  354. package/dist/core/generator/stages/stage5-architecture.js.map +1 -0
  355. package/dist/core/generator/stages/stage6-adr.d.ts +8 -0
  356. package/dist/core/generator/stages/stage6-adr.d.ts.map +1 -0
  357. package/dist/core/generator/stages/stage6-adr.js +47 -0
  358. package/dist/core/generator/stages/stage6-adr.js.map +1 -0
  359. package/dist/core/services/chat-agent.d.ts +50 -0
  360. package/dist/core/services/chat-agent.d.ts.map +1 -0
  361. package/dist/core/services/chat-agent.js +369 -0
  362. package/dist/core/services/chat-agent.js.map +1 -0
  363. package/dist/core/services/chat-tools.d.ts +32 -0
  364. package/dist/core/services/chat-tools.d.ts.map +1 -0
  365. package/dist/core/services/chat-tools.js +494 -0
  366. package/dist/core/services/chat-tools.js.map +1 -0
  367. package/dist/core/services/config-manager.d.ts +61 -0
  368. package/dist/core/services/config-manager.d.ts.map +1 -0
  369. package/dist/core/services/config-manager.js +149 -0
  370. package/dist/core/services/config-manager.js.map +1 -0
  371. package/dist/core/services/edge-store.d.ts +57 -0
  372. package/dist/core/services/edge-store.d.ts.map +1 -0
  373. package/dist/core/services/edge-store.js +419 -0
  374. package/dist/core/services/edge-store.js.map +1 -0
  375. package/dist/core/services/gitignore-manager.d.ts +29 -0
  376. package/dist/core/services/gitignore-manager.d.ts.map +1 -0
  377. package/dist/core/services/gitignore-manager.js +95 -0
  378. package/dist/core/services/gitignore-manager.js.map +1 -0
  379. package/dist/core/services/index.d.ts +8 -0
  380. package/dist/core/services/index.d.ts.map +1 -0
  381. package/dist/core/services/index.js +8 -0
  382. package/dist/core/services/index.js.map +1 -0
  383. package/dist/core/services/llm-service.d.ts +379 -0
  384. package/dist/core/services/llm-service.d.ts.map +1 -0
  385. package/dist/core/services/llm-service.js +1553 -0
  386. package/dist/core/services/llm-service.js.map +1 -0
  387. package/dist/core/services/mcp-handlers/analysis.d.ts +127 -0
  388. package/dist/core/services/mcp-handlers/analysis.d.ts.map +1 -0
  389. package/dist/core/services/mcp-handlers/analysis.js +1185 -0
  390. package/dist/core/services/mcp-handlers/analysis.js.map +1 -0
  391. package/dist/core/services/mcp-handlers/change.d.ts +14 -0
  392. package/dist/core/services/mcp-handlers/change.d.ts.map +1 -0
  393. package/dist/core/services/mcp-handlers/change.js +416 -0
  394. package/dist/core/services/mcp-handlers/change.js.map +1 -0
  395. package/dist/core/services/mcp-handlers/decisions.d.ts +16 -0
  396. package/dist/core/services/mcp-handlers/decisions.d.ts.map +1 -0
  397. package/dist/core/services/mcp-handlers/decisions.js +239 -0
  398. package/dist/core/services/mcp-handlers/decisions.js.map +1 -0
  399. package/dist/core/services/mcp-handlers/graph.d.ts +94 -0
  400. package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -0
  401. package/dist/core/services/mcp-handlers/graph.js +693 -0
  402. package/dist/core/services/mcp-handlers/graph.js.map +1 -0
  403. package/dist/core/services/mcp-handlers/orient.d.ts +17 -0
  404. package/dist/core/services/mcp-handlers/orient.d.ts.map +1 -0
  405. package/dist/core/services/mcp-handlers/orient.js +357 -0
  406. package/dist/core/services/mcp-handlers/orient.js.map +1 -0
  407. package/dist/core/services/mcp-handlers/semantic.d.ts +66 -0
  408. package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -0
  409. package/dist/core/services/mcp-handlers/semantic.js +432 -0
  410. package/dist/core/services/mcp-handlers/semantic.js.map +1 -0
  411. package/dist/core/services/mcp-handlers/utils.d.ts +85 -0
  412. package/dist/core/services/mcp-handlers/utils.d.ts.map +1 -0
  413. package/dist/core/services/mcp-handlers/utils.js +262 -0
  414. package/dist/core/services/mcp-handlers/utils.js.map +1 -0
  415. package/dist/core/services/mcp-watcher.d.ts +41 -0
  416. package/dist/core/services/mcp-watcher.d.ts.map +1 -0
  417. package/dist/core/services/mcp-watcher.js +254 -0
  418. package/dist/core/services/mcp-watcher.js.map +1 -0
  419. package/dist/core/services/project-detector.d.ts +32 -0
  420. package/dist/core/services/project-detector.d.ts.map +1 -0
  421. package/dist/core/services/project-detector.js +100 -0
  422. package/dist/core/services/project-detector.js.map +1 -0
  423. package/dist/core/test-generator/coverage-analyzer.d.ts +27 -0
  424. package/dist/core/test-generator/coverage-analyzer.d.ts.map +1 -0
  425. package/dist/core/test-generator/coverage-analyzer.js +285 -0
  426. package/dist/core/test-generator/coverage-analyzer.js.map +1 -0
  427. package/dist/core/test-generator/framework-detector.d.ts +17 -0
  428. package/dist/core/test-generator/framework-detector.d.ts.map +1 -0
  429. package/dist/core/test-generator/framework-detector.js +65 -0
  430. package/dist/core/test-generator/framework-detector.js.map +1 -0
  431. package/dist/core/test-generator/index.d.ts +14 -0
  432. package/dist/core/test-generator/index.d.ts.map +1 -0
  433. package/dist/core/test-generator/index.js +11 -0
  434. package/dist/core/test-generator/index.js.map +1 -0
  435. package/dist/core/test-generator/renderers/catch2.d.ts +8 -0
  436. package/dist/core/test-generator/renderers/catch2.d.ts.map +1 -0
  437. package/dist/core/test-generator/renderers/catch2.js +47 -0
  438. package/dist/core/test-generator/renderers/catch2.js.map +1 -0
  439. package/dist/core/test-generator/renderers/gtest.d.ts +8 -0
  440. package/dist/core/test-generator/renderers/gtest.d.ts.map +1 -0
  441. package/dist/core/test-generator/renderers/gtest.js +45 -0
  442. package/dist/core/test-generator/renderers/gtest.js.map +1 -0
  443. package/dist/core/test-generator/renderers/index.d.ts +20 -0
  444. package/dist/core/test-generator/renderers/index.d.ts.map +1 -0
  445. package/dist/core/test-generator/renderers/index.js +35 -0
  446. package/dist/core/test-generator/renderers/index.js.map +1 -0
  447. package/dist/core/test-generator/renderers/playwright.d.ts +8 -0
  448. package/dist/core/test-generator/renderers/playwright.d.ts.map +1 -0
  449. package/dist/core/test-generator/renderers/playwright.js +44 -0
  450. package/dist/core/test-generator/renderers/playwright.js.map +1 -0
  451. package/dist/core/test-generator/renderers/pytest.d.ts +8 -0
  452. package/dist/core/test-generator/renderers/pytest.d.ts.map +1 -0
  453. package/dist/core/test-generator/renderers/pytest.js +44 -0
  454. package/dist/core/test-generator/renderers/pytest.js.map +1 -0
  455. package/dist/core/test-generator/renderers/shared.d.ts +21 -0
  456. package/dist/core/test-generator/renderers/shared.d.ts.map +1 -0
  457. package/dist/core/test-generator/renderers/shared.js +56 -0
  458. package/dist/core/test-generator/renderers/shared.js.map +1 -0
  459. package/dist/core/test-generator/renderers/vitest.d.ts +8 -0
  460. package/dist/core/test-generator/renderers/vitest.d.ts.map +1 -0
  461. package/dist/core/test-generator/renderers/vitest.js +52 -0
  462. package/dist/core/test-generator/renderers/vitest.js.map +1 -0
  463. package/dist/core/test-generator/scenario-parser.d.ts +33 -0
  464. package/dist/core/test-generator/scenario-parser.d.ts.map +1 -0
  465. package/dist/core/test-generator/scenario-parser.js +244 -0
  466. package/dist/core/test-generator/scenario-parser.js.map +1 -0
  467. package/dist/core/test-generator/test-generator.d.ts +30 -0
  468. package/dist/core/test-generator/test-generator.d.ts.map +1 -0
  469. package/dist/core/test-generator/test-generator.js +174 -0
  470. package/dist/core/test-generator/test-generator.js.map +1 -0
  471. package/dist/core/test-generator/test-writer.d.ts +25 -0
  472. package/dist/core/test-generator/test-writer.d.ts.map +1 -0
  473. package/dist/core/test-generator/test-writer.js +128 -0
  474. package/dist/core/test-generator/test-writer.js.map +1 -0
  475. package/dist/core/test-generator/then-matchers.d.ts +35 -0
  476. package/dist/core/test-generator/then-matchers.d.ts.map +1 -0
  477. package/dist/core/test-generator/then-matchers.js +211 -0
  478. package/dist/core/test-generator/then-matchers.js.map +1 -0
  479. package/dist/core/verifier/index.d.ts +5 -0
  480. package/dist/core/verifier/index.d.ts.map +1 -0
  481. package/dist/core/verifier/index.js +5 -0
  482. package/dist/core/verifier/index.js.map +1 -0
  483. package/dist/core/verifier/verification-engine.d.ts +293 -0
  484. package/dist/core/verifier/verification-engine.d.ts.map +1 -0
  485. package/dist/core/verifier/verification-engine.js +919 -0
  486. package/dist/core/verifier/verification-engine.js.map +1 -0
  487. package/dist/types/index.d.ts +368 -0
  488. package/dist/types/index.d.ts.map +1 -0
  489. package/dist/types/index.js +5 -0
  490. package/dist/types/index.js.map +1 -0
  491. package/dist/types/pipeline.d.ts +167 -0
  492. package/dist/types/pipeline.d.ts.map +1 -0
  493. package/dist/types/pipeline.js +5 -0
  494. package/dist/types/pipeline.js.map +1 -0
  495. package/dist/types/test-generator.d.ts +103 -0
  496. package/dist/types/test-generator.d.ts.map +1 -0
  497. package/dist/types/test-generator.js +17 -0
  498. package/dist/types/test-generator.js.map +1 -0
  499. package/dist/utils/command-helpers.d.ts +68 -0
  500. package/dist/utils/command-helpers.d.ts.map +1 -0
  501. package/dist/utils/command-helpers.js +150 -0
  502. package/dist/utils/command-helpers.js.map +1 -0
  503. package/dist/utils/errors.d.ts +51 -0
  504. package/dist/utils/errors.d.ts.map +1 -0
  505. package/dist/utils/errors.js +129 -0
  506. package/dist/utils/errors.js.map +1 -0
  507. package/dist/utils/logger.d.ts +149 -0
  508. package/dist/utils/logger.d.ts.map +1 -0
  509. package/dist/utils/logger.js +342 -0
  510. package/dist/utils/logger.js.map +1 -0
  511. package/dist/utils/misc.d.ts +10 -0
  512. package/dist/utils/misc.d.ts.map +1 -0
  513. package/dist/utils/misc.js +21 -0
  514. package/dist/utils/misc.js.map +1 -0
  515. package/dist/utils/progress.d.ts +142 -0
  516. package/dist/utils/progress.d.ts.map +1 -0
  517. package/dist/utils/progress.js +283 -0
  518. package/dist/utils/progress.js.map +1 -0
  519. package/dist/utils/prompts.d.ts +53 -0
  520. package/dist/utils/prompts.d.ts.map +1 -0
  521. package/dist/utils/prompts.js +199 -0
  522. package/dist/utils/prompts.js.map +1 -0
  523. package/dist/utils/shutdown.d.ts +89 -0
  524. package/dist/utils/shutdown.d.ts.map +1 -0
  525. package/dist/utils/shutdown.js +238 -0
  526. package/dist/utils/shutdown.js.map +1 -0
  527. package/examples/bmad/README.md +113 -0
  528. package/examples/bmad/agents/architect.md +226 -0
  529. package/examples/bmad/agents/dev-brownfield.md +69 -0
  530. package/examples/bmad/setup/architect.customize.yaml +14 -0
  531. package/examples/bmad/tasks/implement-story.md +254 -0
  532. package/examples/bmad/tasks/onboarding.md +169 -0
  533. package/examples/bmad/tasks/refactor.md +178 -0
  534. package/examples/bmad/tasks/sprint-planning.md +168 -0
  535. package/examples/bmad/templates/story.md +108 -0
  536. package/examples/cline-workflows/openlore-analyze-codebase.md +101 -0
  537. package/examples/cline-workflows/openlore-check-spec-drift.md +102 -0
  538. package/examples/cline-workflows/openlore-execute-refactor.md +212 -0
  539. package/examples/cline-workflows/openlore-implement-feature.md +266 -0
  540. package/examples/cline-workflows/openlore-plan-refactor.md +279 -0
  541. package/examples/cline-workflows/openlore-refactor-codebase.md +16 -0
  542. package/examples/cline-workflows/openlore-write-tests.md +177 -0
  543. package/examples/drift-demo/openspec/config.yaml +14 -0
  544. package/examples/drift-demo/openspec/specs/architecture/spec.md +30 -0
  545. package/examples/drift-demo/openspec/specs/auth/spec.md +71 -0
  546. package/examples/drift-demo/openspec/specs/database/spec.md +33 -0
  547. package/examples/drift-demo/openspec/specs/overview/spec.md +20 -0
  548. package/examples/drift-demo/openspec/specs/projects/spec.md +55 -0
  549. package/examples/drift-demo/openspec/specs/tasks/spec.md +78 -0
  550. package/examples/drift-demo/package.json +21 -0
  551. package/examples/drift-demo/src/auth/auth-middleware.ts +30 -0
  552. package/examples/drift-demo/src/auth/auth-routes.ts +29 -0
  553. package/examples/drift-demo/src/auth/auth-service.ts +45 -0
  554. package/examples/drift-demo/src/database/connection.ts +27 -0
  555. package/examples/drift-demo/src/index.ts +16 -0
  556. package/examples/drift-demo/src/projects/project-model.ts +15 -0
  557. package/examples/drift-demo/src/projects/project-service.ts +34 -0
  558. package/examples/drift-demo/src/tasks/task-model.ts +37 -0
  559. package/examples/drift-demo/src/tasks/task-routes.ts +53 -0
  560. package/examples/drift-demo/src/tasks/task-service.ts +60 -0
  561. package/examples/drift-demo/src/utils/validation.ts +11 -0
  562. package/examples/drift-demo/tests/auth.test.ts +4 -0
  563. package/examples/drift-demo/tests/tasks.test.ts +4 -0
  564. package/examples/drift-demo/tsconfig.json +10 -0
  565. package/examples/drift-test/run-drift-test.sh +1087 -0
  566. package/examples/gsd/README.md +119 -0
  567. package/examples/gsd/commands/gsd/openlore-drift.md +111 -0
  568. package/examples/gsd/commands/gsd/openlore-orient.md +191 -0
  569. package/examples/mistral-vibe/README.md +101 -0
  570. package/examples/mistral-vibe/antipatterns-template.md +18 -0
  571. package/examples/mistral-vibe/skills/openlore-analyze-codebase/SKILL.md +124 -0
  572. package/examples/mistral-vibe/skills/openlore-brainstorm/SKILL.md +379 -0
  573. package/examples/mistral-vibe/skills/openlore-debug/SKILL.md +330 -0
  574. package/examples/mistral-vibe/skills/openlore-execute-refactor/SKILL.md +291 -0
  575. package/examples/mistral-vibe/skills/openlore-generate/SKILL.md +245 -0
  576. package/examples/mistral-vibe/skills/openlore-implement-story/SKILL.md +326 -0
  577. package/examples/mistral-vibe/skills/openlore-plan-refactor/SKILL.md +365 -0
  578. package/examples/mistral-vibe/skills/openlore-review-changes/SKILL.md +128 -0
  579. package/examples/mistral-vibe/skills/openlore-write-tests/SKILL.md +261 -0
  580. package/examples/opencode/agent-guard.ts +170 -0
  581. package/examples/opencode/plugins/anti-laziness.ts +202 -0
  582. package/examples/opencode/plugins/lib/openlore-context-injector-helpers.ts +116 -0
  583. package/examples/opencode/plugins/lib/openlore-decision-extractor-helpers.ts +65 -0
  584. package/examples/opencode/plugins/openlore-context-injector.test.ts +211 -0
  585. package/examples/opencode/plugins/openlore-context-injector.ts +165 -0
  586. package/examples/opencode/plugins/openlore-decision-extractor.test.ts +131 -0
  587. package/examples/opencode/plugins/openlore-decision-extractor.ts +322 -0
  588. package/examples/opencode/plugins/openlore-enforcer.ts +227 -0
  589. package/examples/opencode/prompts/sisyphus-sdd.md +150 -0
  590. package/examples/opencode-skills/openlore-analyze-codebase/SKILL.md +101 -0
  591. package/examples/opencode-skills/openlore-brainstorm/SKILL.md +354 -0
  592. package/examples/opencode-skills/openlore-debug/SKILL.md +291 -0
  593. package/examples/opencode-skills/openlore-execute-refactor/SKILL.md +241 -0
  594. package/examples/opencode-skills/openlore-generate/SKILL.md +236 -0
  595. package/examples/opencode-skills/openlore-implement-story/SKILL.md +251 -0
  596. package/examples/opencode-skills/openlore-plan-refactor/SKILL.md +298 -0
  597. package/examples/opencode-skills/openlore-review-changes/SKILL.md +134 -0
  598. package/examples/opencode-skills/openlore-write-tests/SKILL.md +230 -0
  599. package/examples/openspec-analysis/README.md +59 -0
  600. package/examples/openspec-analysis/SUMMARY.md +72 -0
  601. package/examples/openspec-analysis/config.json +16 -0
  602. package/examples/openspec-analysis/dependencies.mermaid +35 -0
  603. package/examples/openspec-analysis/dependency-graph.json +12116 -0
  604. package/examples/openspec-analysis/llm-context.json +119 -0
  605. package/examples/openspec-analysis/repo-structure.json +871 -0
  606. package/examples/openspec-cli/README.md +67 -0
  607. package/examples/openspec-cli/openspec/config.yaml +26 -0
  608. package/examples/openspec-cli/openspec/specs/architecture/spec.md +178 -0
  609. package/examples/openspec-cli/openspec/specs/artifact-graph/spec.md +143 -0
  610. package/examples/openspec-cli/openspec/specs/cli/spec.md +138 -0
  611. package/examples/openspec-cli/openspec/specs/overview/spec.md +60 -0
  612. package/examples/openspec-cli/openspec/specs/parsing/spec.md +123 -0
  613. package/examples/openspec-cli/openspec/specs/validation/spec.md +108 -0
  614. package/examples/spec-kit/README.md +104 -0
  615. package/examples/spec-kit/commands/drift.md +87 -0
  616. package/examples/spec-kit/commands/orient.md +138 -0
  617. package/examples/spec-kit/extension.yml +54 -0
  618. package/package.json +125 -0
  619. package/src/viewer/InteractiveGraphViewer.jsx +1600 -0
  620. package/src/viewer/app/index.html +17 -0
  621. package/src/viewer/app/main.jsx +13 -0
  622. package/src/viewer/components/ArchitectureView.jsx +177 -0
  623. package/src/viewer/components/ChatPanel.jsx +450 -0
  624. package/src/viewer/components/ClassGraph.jsx +782 -0
  625. package/src/viewer/components/ClusterGraph.jsx +469 -0
  626. package/src/viewer/components/FilterBar.jsx +179 -0
  627. package/src/viewer/components/FlatGraph.jsx +282 -0
  628. package/src/viewer/components/MicroComponents.jsx +85 -0
  629. package/src/viewer/hooks/usePanZoom.js +79 -0
  630. package/src/viewer/utils/constants.js +64 -0
  631. package/src/viewer/utils/graph-helpers.js +303 -0
  632. package/src/viewer/utils/graph-helpers.test.ts +39 -0
  633. package/src/viewer/utils/themes.js +206 -0
  634. package/stubs/tree-sitter-cli-stub/package.json +6 -0
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>openlore · Graph Viewer</title>
7
+ <style>
8
+ html, body { margin: 0; height: 100%; background: #080b18; }
9
+ #root { height: 100%; }
10
+ </style>
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ <script type="module" src="/main.jsx"></script>
15
+ </body>
16
+ </html>
17
+
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import InteractiveGraphViewer from '../InteractiveGraphViewer.jsx';
4
+
5
+ ReactDOM.createRoot(document.getElementById('root')).render(
6
+ <React.StrictMode>
7
+ <InteractiveGraphViewer
8
+ graphUrl="/api/dependency-graph"
9
+ mappingUrl="/api/mapping"
10
+ specUrl="/api/spec"
11
+ />
12
+ </React.StrictMode>
13
+ );
@@ -0,0 +1,177 @@
1
+ import { useState, useMemo } from 'react';
2
+ import { ROLE_COLOR, ROLE_LABEL } from '../utils/constants.js';
3
+ import { computeArchOverview } from '../utils/graph-helpers.js';
4
+
5
+ export function ArchitectureView({ graph, llmCtx, focusedIds }) {
6
+ const overview = useMemo(() => computeArchOverview(graph, llmCtx), [graph, llmCtx]);
7
+ const [hovered, setHovered] = useState(null);
8
+ const focusedClusterIds = useMemo(() => {
9
+ if (!focusedIds?.length || !graph) return null;
10
+ return new Set(graph.nodes.filter(n => focusedIds.includes(n.id)).map(n => n.cluster.id));
11
+ }, [focusedIds, graph]);
12
+
13
+ if (!overview) return <div style={{ color: 'var(--tx-ghost)', padding: 24, fontSize: 11 }}>No graph loaded.</div>;
14
+
15
+ const { summary, clusters, globalEntryPoints, criticalHubs } = overview;
16
+
17
+ const COLS = Math.min(4, clusters.length);
18
+ const BOX_W = 140, BOX_H = 64, GAP_X = 30, GAP_Y = 40;
19
+ const ROWS = Math.ceil(clusters.length / COLS);
20
+ const SVG_W = COLS * (BOX_W + GAP_X) + GAP_X;
21
+ const SVG_H = ROWS * (BOX_H + GAP_Y) + GAP_Y;
22
+
23
+ const pos = {};
24
+ clusters.forEach((cl, i) => {
25
+ const col = i % COLS;
26
+ const row = Math.floor(i / COLS);
27
+ pos[cl.id] = {
28
+ x: GAP_X + col * (BOX_W + GAP_X),
29
+ y: GAP_Y + row * (BOX_H + GAP_Y),
30
+ };
31
+ });
32
+
33
+ const arrows = [];
34
+ clusters.forEach(cl => {
35
+ (cl.dependsOn ?? []).forEach(toId => {
36
+ const from = pos[cl.id];
37
+ const to = pos[toId];
38
+ if (!from || !to) return;
39
+ const fx = from.x + BOX_W / 2, fy = from.y + BOX_H / 2;
40
+ const tx = to.x + BOX_W / 2, ty = to.y + BOX_H / 2;
41
+ const dx = tx - fx, dy = ty - fy;
42
+ const len = Math.sqrt(dx * dx + dy * dy) || 1;
43
+ const sx = fx + (dx / len) * (BOX_W / 2 + 4);
44
+ const sy = fy + (dy / len) * (BOX_H / 2 + 4);
45
+ const ex = tx - (dx / len) * (BOX_W / 2 + 4);
46
+ const ey = ty - (dy / len) * (BOX_H / 2 + 4);
47
+ const isHov = hovered === cl.id || hovered === toId;
48
+ arrows.push(
49
+ <line
50
+ key={`${cl.id}->${toId}`}
51
+ x1={sx} y1={sy} x2={ex} y2={ey}
52
+ stroke={isHov ? 'var(--ac-primary)' : 'var(--ac-arrow)'}
53
+ strokeWidth={isHov ? 1.5 : 1}
54
+ markerEnd="url(#arrowhead)"
55
+ opacity={isHov ? 1 : 0.6}
56
+ />
57
+ );
58
+ });
59
+ });
60
+
61
+ const S = { fontSize: 9, fontFamily: 'inherit' };
62
+
63
+ return (
64
+ <div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
65
+ <div style={{ flex: 1, overflow: 'auto', padding: 12 }}>
66
+ <div style={{ display: 'flex', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
67
+ {[
68
+ ['files', summary.totalFiles],
69
+ ['clusters', summary.totalClusters],
70
+ ['edges', summary.totalEdges],
71
+ summary.cycles > 0 ? ['⚠ cycles', summary.cycles] : null,
72
+ summary.layerViolations > 0 ? ['⚠ violations', summary.layerViolations] : null,
73
+ ].filter(Boolean).map(([l, v]) => (
74
+ <div key={l} style={{ fontSize: 9, color: 'var(--tx-muted)', background: 'var(--bg-raised)', borderRadius: 4, padding: '2px 8px', border: '1px solid var(--bd-muted)' }}>
75
+ <span style={{ color: l.startsWith('⚠') ? '#f97316' : 'var(--tx-primary)' }}>{v}</span> {l}
76
+ </div>
77
+ ))}
78
+ </div>
79
+
80
+ <svg width={SVG_W} height={SVG_H} style={{ display: 'block', minWidth: SVG_W }}>
81
+ <defs>
82
+ <marker id="arrowhead" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
83
+ <path d="M0,0 L0,6 L6,3 z" style={{ fill: 'var(--ac-cluster-arr)' }} />
84
+ </marker>
85
+ </defs>
86
+
87
+ {arrows}
88
+
89
+ {clusters.map(cl => {
90
+ const { x, y } = pos[cl.id] ?? { x: 0, y: 0 };
91
+ const color = ROLE_COLOR[cl.role] ?? '#475569';
92
+ const isHov = hovered === cl.id;
93
+ const isDimmed = focusedClusterIds && !focusedClusterIds.has(cl.id);
94
+ return (
95
+ <g
96
+ key={cl.id}
97
+ onMouseEnter={() => setHovered(cl.id)}
98
+ onMouseLeave={() => setHovered(null)}
99
+ style={{ cursor: 'default' }}
100
+ opacity={isDimmed ? 0.15 : 1}
101
+ >
102
+ <rect
103
+ x={x} y={y} width={BOX_W} height={BOX_H}
104
+ rx={6} ry={6}
105
+ style={{ fill: isHov ? 'var(--bg-hover)' : 'var(--bg-node)' }}
106
+ stroke={isHov ? color : isDimmed ? 'var(--bg-raised)' : 'var(--ac-arrow)'}
107
+ strokeWidth={isHov ? 1.5 : 1}
108
+ />
109
+ <rect x={x} y={y} width={4} height={BOX_H} rx={3} ry={3} fill={color} opacity={0.8} />
110
+ <text x={x + 12} y={y + 18} style={{ fill: 'var(--tx-primary)' }} fontSize={10} fontWeight="600" fontFamily="inherit">
111
+ {cl.name.length > 18 ? cl.name.slice(0, 17) + '…' : cl.name}
112
+ </text>
113
+ <text x={x + 12} y={y + 31} fill={color} fontSize={8} fontFamily="inherit" opacity={0.9}>
114
+ {ROLE_LABEL[cl.role] ?? cl.role}
115
+ </text>
116
+ <text x={x + 12} y={y + 44} style={{ fill: 'var(--tx-dim)' }} fontSize={8} fontFamily="inherit">
117
+ {cl.fileCount} files
118
+ {cl.hubCount > 0 ? ` · ${cl.hubCount} hub${cl.hubCount > 1 ? 's' : ''}` : ''}
119
+ {cl.entryPointCount > 0 ? ` · ${cl.entryPointCount} entry` : ''}
120
+ </text>
121
+ {cl.dependsOn.length > 0 && (
122
+ <text x={x + BOX_W - 6} y={y + 18} style={{ fill: 'var(--tx-dim)' }} fontSize={7} fontFamily="inherit" textAnchor="end">
123
+ →{cl.dependsOn.length}
124
+ </text>
125
+ )}
126
+ </g>
127
+ );
128
+ })}
129
+ </svg>
130
+
131
+ <div style={{ display: 'flex', gap: 12, marginTop: 12, flexWrap: 'wrap' }}>
132
+ {Object.entries(ROLE_LABEL).map(([role, label]) => (
133
+ <div key={role} style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 8, color: 'var(--tx-dim)' }}>
134
+ <div style={{ width: 8, height: 8, borderRadius: 2, background: ROLE_COLOR[role] }} />
135
+ {label}
136
+ </div>
137
+ ))}
138
+ </div>
139
+ </div>
140
+
141
+ <div style={{ width: 220, borderLeft: '1px solid var(--bd-faint)', overflow: 'auto', padding: '12px 10px', flexShrink: 0 }}>
142
+ {globalEntryPoints.length > 0 && (
143
+ <>
144
+ <div style={{ ...S, color: '#4ade80', fontWeight: 600, marginBottom: 6, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
145
+ Entry Points
146
+ </div>
147
+ {globalEntryPoints.map((ep, i) => (
148
+ <div key={i} style={{ marginBottom: 6 }}>
149
+ <div style={{ ...S, color: 'var(--tx-primary)', fontWeight: 600 }}>{ep.name}</div>
150
+ <div style={{ ...S, color: 'var(--tx-dim)', wordBreak: 'break-all' }}>{ep.file}</div>
151
+ </div>
152
+ ))}
153
+ </>
154
+ )}
155
+
156
+ {criticalHubs.length > 0 && (
157
+ <>
158
+ <div style={{ ...S, color: '#f97316', fontWeight: 600, marginBottom: 6, marginTop: 16, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
159
+ Critical Hubs
160
+ </div>
161
+ {criticalHubs.map((hub, i) => (
162
+ <div key={i} style={{ marginBottom: 6 }}>
163
+ <div style={{ ...S, color: 'var(--tx-primary)', fontWeight: 600 }}>{hub.name}</div>
164
+ <div style={{ ...S, color: 'var(--tx-dim)', wordBreak: 'break-all' }}>{hub.file}</div>
165
+ <div style={{ ...S, color: '#f97316', opacity: 0.7 }}>fanIn {hub.fanIn} · fanOut {hub.fanOut}</div>
166
+ </div>
167
+ ))}
168
+ </>
169
+ )}
170
+
171
+ {globalEntryPoints.length === 0 && criticalHubs.length === 0 && (
172
+ <div style={{ ...S, color: 'var(--tx-ghost)' }}>Run <code style={{ color: 'var(--ac-primary)' }}>openlore analyze</code> to populate call graph data.</div>
173
+ )}
174
+ </div>
175
+ </div>
176
+ );
177
+ }
@@ -0,0 +1,450 @@
1
+ import { useState, useRef, useEffect } from 'react';
2
+
3
+ // ============================================================================
4
+ // SIMPLE MARKDOWN RENDERER
5
+ // ============================================================================
6
+
7
+ function escapeHtml(text) {
8
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
9
+ }
10
+
11
+ function renderInline(text) {
12
+ // Escape HTML first to prevent XSS, then apply markdown formatting
13
+ return escapeHtml(text)
14
+ .replace(/`([^`]+)`/g, '<code style="background:var(--bd-muted);padding:1px 4px;border-radius:3px;font-family:JetBrains Mono,monospace;font-size:8px;color:var(--tx-primary)">$1</code>')
15
+ .replace(/\*\*([^*]+)\*\*/g, '<strong style="color:var(--tx-primary)">$1</strong>')
16
+ .replace(/\*([^*]+)\*/g, '<em style="color:var(--tx-secondary)">$1</em>');
17
+ }
18
+
19
+ function MarkdownBlock({ text }) {
20
+ const lines = text.split('\n');
21
+ const elements = [];
22
+ let i = 0;
23
+
24
+ while (i < lines.length) {
25
+ const line = lines[i];
26
+
27
+ // Fenced code block
28
+ if (line.startsWith('```')) {
29
+ const codeLines = [];
30
+ i++;
31
+ while (i < lines.length && !lines[i].startsWith('```')) {
32
+ codeLines.push(lines[i]);
33
+ i++;
34
+ }
35
+ elements.push(
36
+ <pre key={i} style={{
37
+ background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 4,
38
+ padding: '6px 8px', margin: '4px 0', overflowX: 'auto',
39
+ fontSize: 8, color: 'var(--tx-secondary)', fontFamily: 'JetBrains Mono,monospace', lineHeight: 1.5,
40
+ }}>
41
+ {codeLines.join('\n')}
42
+ </pre>
43
+ );
44
+ i++;
45
+ continue;
46
+ }
47
+
48
+ // H3 / H4 headings
49
+ if (/^#{3,4}\s+/.test(line)) {
50
+ const content = line.replace(/^#{3,4}\s+/, '');
51
+ elements.push(
52
+ <div key={i} style={{ fontSize: 9, color: 'var(--ac-primary)', fontWeight: 600, margin: '8px 0 3px', letterSpacing: '0.04em' }}
53
+ dangerouslySetInnerHTML={{ __html: renderInline(content) }} />
54
+ );
55
+ i++;
56
+ continue;
57
+ }
58
+
59
+ // H1 / H2 headings
60
+ if (/^#{1,2}\s+/.test(line)) {
61
+ const content = line.replace(/^#{1,2}\s+/, '');
62
+ elements.push(
63
+ <div key={i} style={{ fontSize: 10, color: 'var(--tx-primary)', fontWeight: 700, margin: '10px 0 4px' }}
64
+ dangerouslySetInnerHTML={{ __html: renderInline(content) }} />
65
+ );
66
+ i++;
67
+ continue;
68
+ }
69
+
70
+ // Bullet list
71
+ if (/^[*-]\s+/.test(line)) {
72
+ const items = [];
73
+ while (i < lines.length && /^[*-]\s+/.test(lines[i])) {
74
+ items.push(lines[i].replace(/^[*-]\s+/, ''));
75
+ i++;
76
+ }
77
+ elements.push(
78
+ <ul key={i} style={{ margin: '3px 0', paddingLeft: 14, listStyle: 'none' }}>
79
+ {items.map((item, j) => (
80
+ <li key={j} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6, position: 'relative', paddingLeft: 8 }}>
81
+ <span style={{ position: 'absolute', left: 0, color: 'var(--ac-primary)' }}>·</span>
82
+ <span dangerouslySetInnerHTML={{ __html: renderInline(item) }} />
83
+ </li>
84
+ ))}
85
+ </ul>
86
+ );
87
+ continue;
88
+ }
89
+
90
+ // Numbered list
91
+ if (/^\d+\.\s+/.test(line)) {
92
+ const items = [];
93
+ while (i < lines.length && /^\d+\.\s+/.test(lines[i])) {
94
+ const match = lines[i].match(/^(\d+)\.\s+(.*)/);
95
+ if (match) items.push({ num: match[1], text: match[2] });
96
+ i++;
97
+ }
98
+ elements.push(
99
+ <ol key={i} style={{ margin: '3px 0', paddingLeft: 0, listStyle: 'none' }}>
100
+ {items.map((item, j) => (
101
+ <li key={j} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6, display: 'flex', gap: 5, margin: '1px 0' }}>
102
+ <span style={{ color: 'var(--ac-primary)', flexShrink: 0, fontVariantNumeric: 'tabular-nums' }}>{item.num}.</span>
103
+ <span dangerouslySetInnerHTML={{ __html: renderInline(item.text) }} />
104
+ </li>
105
+ ))}
106
+ </ol>
107
+ );
108
+ continue;
109
+ }
110
+
111
+ // Horizontal rule
112
+ if (/^---+$/.test(line.trim())) {
113
+ elements.push(<hr key={i} style={{ border: 'none', borderTop: '1px solid var(--bd-muted)', margin: '6px 0' }} />);
114
+ i++;
115
+ continue;
116
+ }
117
+
118
+ // Empty line -> spacer
119
+ if (line.trim() === '') {
120
+ elements.push(<div key={i} style={{ height: 4 }} />);
121
+ i++;
122
+ continue;
123
+ }
124
+
125
+ // Plain paragraph
126
+ elements.push(
127
+ <div key={i} style={{ fontSize: 9, color: 'var(--tx-secondary)', lineHeight: 1.6 }}
128
+ dangerouslySetInnerHTML={{ __html: renderInline(line) }} />
129
+ );
130
+ i++;
131
+ }
132
+
133
+ return <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>{elements}</div>;
134
+ }
135
+
136
+ // ============================================================================
137
+ // TOOL SPINNER
138
+ // ============================================================================
139
+
140
+ function ToolSpinner() {
141
+ const [frame, setFrame] = useState(0);
142
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
143
+ useEffect(() => {
144
+ const id = setInterval(() => setFrame((f) => (f + 1) % frames.length), 80);
145
+ return () => clearInterval(id);
146
+ }, []);
147
+ return <span style={{ color: 'var(--ac-primary)', fontFamily: 'monospace', fontSize: 10, lineHeight: 1 }}>{frames[frame]}</span>;
148
+ }
149
+
150
+ // ============================================================================
151
+ // CHAT PANEL
152
+ // ============================================================================
153
+
154
+ /**
155
+ * ChatPanel -- agentic chatbot panel for the dependency graph viewer.
156
+ *
157
+ * Props:
158
+ * onHighlight(ids: string[]) -- called with dep-graph node IDs to highlight
159
+ * onHighlightPaths(paths: string[])-- called with raw file paths (for class graph)
160
+ * onClose() -- called when the panel is closed
161
+ */
162
+ export function ChatPanel({ onHighlight, onHighlightPaths, onClose, onClearGraph }) {
163
+ const [messages, setMessages] = useState([
164
+ {
165
+ role: 'assistant',
166
+ content:
167
+ 'Hi! Ask me anything about this codebase. For example:\n' +
168
+ '- "What are the most critical functions?"\n' +
169
+ '- "What is the impact of changing the embedding service?"\n' +
170
+ '- "Where would I add a new API endpoint?"',
171
+ },
172
+ ]);
173
+ const [input, setInput] = useState('');
174
+ const [loading, setLoading] = useState(false);
175
+ const [activeTools, setActiveTools] = useState([]); // tools currently running
176
+ const [error, setError] = useState(null);
177
+ const [modelInfo, setModelInfo] = useState(null); // { provider, currentModel, models }
178
+ const bottomRef = useRef(null);
179
+
180
+ useEffect(() => {
181
+ fetch('/api/chat/models')
182
+ .then((r) => r.json())
183
+ .then((data) => {
184
+ if (data.error) console.warn('[chat/models]', data.error);
185
+ else setModelInfo(data);
186
+ })
187
+ .catch((e) => console.warn('[chat/models] fetch failed:', e.message));
188
+ }, []);
189
+
190
+ useEffect(() => {
191
+ bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
192
+ }, [messages, loading, activeTools]);
193
+
194
+ const send = async () => {
195
+ const text = input.trim();
196
+ if (!text || loading) return;
197
+
198
+ const history = messages
199
+ .slice(1) // drop initial greeting
200
+ .map((m) => ({ role: m.role, content: m.content }));
201
+
202
+ setMessages((prev) => [...prev, { role: 'user', content: text }]);
203
+ setInput('');
204
+ setLoading(true);
205
+ setActiveTools([]);
206
+ setError(null);
207
+
208
+ try {
209
+ const res = await fetch('/api/chat', {
210
+ method: 'POST',
211
+ headers: { 'Content-Type': 'application/json' },
212
+ body: JSON.stringify({ message: text, history, model: modelInfo?.currentModel }),
213
+ });
214
+
215
+ if (!res.ok) {
216
+ const err = await res.json().catch(() => ({ error: res.statusText }));
217
+ throw new Error(err.error ?? res.statusText);
218
+ }
219
+
220
+ // Parse SSE stream
221
+ const reader = res.body.getReader();
222
+ const decoder = new TextDecoder();
223
+ let buf = '';
224
+
225
+ while (true) {
226
+ const { done, value } = await reader.read();
227
+ if (done) break;
228
+ buf += decoder.decode(value, { stream: true });
229
+ const parts = buf.split('\n\n');
230
+ buf = parts.pop() ?? '';
231
+ for (const part of parts) {
232
+ const line = part.trim();
233
+ if (!line.startsWith('data:')) continue;
234
+ let evt;
235
+ try { evt = JSON.parse(line.slice(5).trim()); } catch { continue; }
236
+
237
+ if (evt.type === 'tool_start') {
238
+ setActiveTools((prev) => [...prev, evt.name]);
239
+ } else if (evt.type === 'tool_end') {
240
+ setActiveTools((prev) => prev.filter((n) => n !== evt.name));
241
+ } else if (evt.type === 'reply') {
242
+ setMessages((prev) => [...prev, { role: 'assistant', content: evt.reply }]);
243
+ onHighlight(evt.highlightIds ?? []);
244
+ onHighlightPaths?.(evt.filePaths ?? []);
245
+ } else if (evt.type === 'error') {
246
+ throw new Error(evt.error);
247
+ }
248
+ }
249
+ }
250
+ } catch (err) {
251
+ setError(err.message);
252
+ } finally {
253
+ setLoading(false);
254
+ setActiveTools([]);
255
+ }
256
+ };
257
+
258
+ const handleKeyDown = (e) => {
259
+ if (e.key === 'Enter' && !e.shiftKey) {
260
+ e.preventDefault();
261
+ send();
262
+ }
263
+ };
264
+
265
+ const clear = () => {
266
+ setMessages([{ role: 'assistant', content: 'Conversation cleared. What would you like to know?' }]);
267
+ setError(null);
268
+ onClearGraph?.();
269
+ };
270
+
271
+ return (
272
+ <div
273
+ style={{
274
+ width: 340,
275
+ borderLeft: '1px solid var(--bd-faint)',
276
+ background: 'var(--bg-deep)',
277
+ display: 'flex',
278
+ flexDirection: 'column',
279
+ overflow: 'hidden',
280
+ flexShrink: 0,
281
+ }}
282
+ >
283
+ {/* Header */}
284
+ <div
285
+ style={{
286
+ display: 'flex',
287
+ flexDirection: 'column',
288
+ padding: '6px 10px',
289
+ borderBottom: '1px solid var(--bd-faint)',
290
+ flexShrink: 0,
291
+ gap: 5,
292
+ }}
293
+ >
294
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
295
+ <span style={{ fontSize: 9, color: 'var(--ac-primary)', letterSpacing: '0.1em', fontFamily: 'inherit' }}>
296
+ ✦ DIAGRAM CHAT
297
+ </span>
298
+ <div style={{ display: 'flex', gap: 6 }}>
299
+ <button
300
+ onClick={clear}
301
+ title="Clear conversation"
302
+ style={{
303
+ background: 'none', border: '1px solid var(--bd-muted)', borderRadius: 3,
304
+ color: 'var(--tx-ghost)', fontSize: 8, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit',
305
+ }}
306
+ >
307
+ CLEAR
308
+ </button>
309
+ <button
310
+ onClick={onClose}
311
+ title="Close chat"
312
+ style={{
313
+ background: 'none', border: '1px solid var(--bd-muted)', borderRadius: 3,
314
+ color: 'var(--tx-ghost)', fontSize: 10, padding: '2px 6px', cursor: 'pointer', fontFamily: 'inherit', lineHeight: 1,
315
+ }}
316
+ >
317
+ x
318
+ </button>
319
+ </div>
320
+ </div>
321
+ {/* Model selector */}
322
+ {modelInfo && (
323
+ <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
324
+ <span style={{ fontSize: 8, color: 'var(--tx-ghost)', letterSpacing: '0.06em', flexShrink: 0 }}>
325
+ {modelInfo.provider.toUpperCase()}
326
+ </span>
327
+ <select
328
+ value={modelInfo.currentModel}
329
+ onChange={(e) => setModelInfo((prev) => ({ ...prev, currentModel: e.target.value }))}
330
+ style={{
331
+ flex: 1, background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 3,
332
+ color: 'var(--tx-secondary)', fontSize: 8, padding: '2px 4px', fontFamily: 'inherit',
333
+ cursor: 'pointer', outline: 'none',
334
+ }}
335
+ >
336
+ {modelInfo.models.length === 0 && (
337
+ <option value={modelInfo.currentModel}>{modelInfo.currentModel}</option>
338
+ )}
339
+ {modelInfo.models.map((m) => (
340
+ <option key={m} value={m}>{m}</option>
341
+ ))}
342
+ </select>
343
+ </div>
344
+ )}
345
+ </div>
346
+
347
+ {/* Message list */}
348
+ <div
349
+ style={{
350
+ flex: 1, overflowY: 'auto', padding: '8px 10px',
351
+ display: 'flex', flexDirection: 'column', gap: 8,
352
+ }}
353
+ >
354
+ {messages.map((m, i) => (
355
+ <div key={i} style={{ alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start', maxWidth: '96%' }}>
356
+ <div
357
+ style={{
358
+ background: m.role === 'user' ? 'var(--bg-hover)' : 'var(--bg-input)',
359
+ border: `1px solid ${m.role === 'user' ? 'var(--bd-muted)' : 'var(--bd-faint)'}`,
360
+ borderRadius: m.role === 'user' ? '8px 8px 2px 8px' : '8px 8px 8px 2px',
361
+ padding: '6px 10px',
362
+ fontFamily: 'inherit',
363
+ }}
364
+ >
365
+ {m.role === 'user' ? (
366
+ <div style={{ fontSize: 9, color: 'var(--tx-primary)', lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>
367
+ {m.content}
368
+ </div>
369
+ ) : (
370
+ <MarkdownBlock text={m.content} />
371
+ )}
372
+ </div>
373
+ </div>
374
+ ))}
375
+
376
+ {loading && (
377
+ <div style={{ alignSelf: 'flex-start' }}>
378
+ <div style={{
379
+ fontSize: 9, color: 'var(--ac-primary)', background: 'var(--bg-input)',
380
+ border: '1px solid var(--bd-faint)', borderRadius: '8px 8px 8px 2px',
381
+ padding: '6px 10px', fontFamily: 'inherit',
382
+ display: 'flex', flexDirection: 'column', gap: 4,
383
+ }}>
384
+ {activeTools.length === 0 ? (
385
+ <span>thinking...</span>
386
+ ) : (
387
+ activeTools.map((name, i) => (
388
+ <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
389
+ <ToolSpinner />
390
+ <span style={{ color: 'var(--tx-secondary)' }}>{name.replace(/_/g, ' ')}</span>
391
+ </div>
392
+ ))
393
+ )}
394
+ </div>
395
+ </div>
396
+ )}
397
+
398
+ {error && (
399
+ <div style={{
400
+ fontSize: 9, color: 'var(--tx-primary)', background: 'rgba(192,57,43,0.10)',
401
+ border: '1px solid rgba(192,57,43,0.35)', borderRadius: 4,
402
+ padding: '5px 8px', fontFamily: 'inherit',
403
+ }}>
404
+ Error: {error}
405
+ </div>
406
+ )}
407
+
408
+ <div ref={bottomRef} />
409
+ </div>
410
+
411
+ {/* Input area */}
412
+ <div
413
+ style={{
414
+ borderTop: '1px solid var(--bd-faint)', padding: '8px 10px',
415
+ display: 'flex', flexDirection: 'column', gap: 6, flexShrink: 0,
416
+ }}
417
+ >
418
+ <textarea
419
+ value={input}
420
+ onChange={(e) => setInput(e.target.value)}
421
+ onKeyDown={handleKeyDown}
422
+ placeholder="Ask about the codebase... (Enter to send, Shift+Enter for newline)"
423
+ rows={3}
424
+ style={{
425
+ background: 'var(--bg-input)', border: '1px solid var(--bd-muted)', borderRadius: 4,
426
+ color: 'var(--tx-primary)', fontSize: 9, padding: '6px 8px',
427
+ resize: 'none', outline: 'none', fontFamily: 'inherit', lineHeight: 1.4,
428
+ }}
429
+ />
430
+ <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
431
+ <button
432
+ onClick={send}
433
+ disabled={!input.trim() || loading}
434
+ style={{
435
+ background: input.trim() && !loading ? 'var(--bg-select)' : 'transparent',
436
+ border: `1px solid ${input.trim() && !loading ? 'var(--ac-primary)' : 'var(--bd-muted)'}`,
437
+ borderRadius: 4,
438
+ color: input.trim() && !loading ? 'var(--tx-primary)' : 'var(--tx-ghost)',
439
+ fontSize: 8, padding: '4px 12px',
440
+ cursor: input.trim() && !loading ? 'pointer' : 'default',
441
+ fontFamily: 'inherit', letterSpacing: '0.06em',
442
+ }}
443
+ >
444
+ SEND
445
+ </button>
446
+ </div>
447
+ </div>
448
+ </div>
449
+ );
450
+ }