@cloudgrid-io/mcp 0.13.0 → 0.15.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 (364) hide show
  1. package/package.json +1 -1
  2. package/src/corpus/capability-map.md +81 -7
  3. package/src/corpus/templates/_cloudgrid.yaml.reference +228 -0
  4. package/src/corpus/templates/admin-dashboard/cloudgrid.yaml +226 -8
  5. package/src/corpus/templates/admin-dashboard/index.md +3 -0
  6. package/src/corpus/templates/ai-app/cloudgrid.yaml +225 -11
  7. package/src/corpus/templates/ai-app/index.md +3 -11
  8. package/src/corpus/templates/ai-knowledge-base/AGENTS.md +254 -0
  9. package/src/corpus/templates/ai-knowledge-base/README.md +28 -0
  10. package/src/corpus/templates/ai-knowledge-base/cloudgrid.yaml +238 -0
  11. package/src/corpus/templates/ai-knowledge-base/index.md +81 -0
  12. package/src/corpus/templates/analytics-dashboard/README.md +85 -0
  13. package/src/corpus/templates/analytics-dashboard/cloudgrid.yaml +232 -0
  14. package/src/corpus/templates/analytics-dashboard/index.md +316 -0
  15. package/src/corpus/templates/analytics-dashboard/services/web/app/api/events/route.js +60 -0
  16. package/src/corpus/templates/analytics-dashboard/services/web/app/event-form.js +100 -0
  17. package/src/corpus/templates/analytics-dashboard/services/web/app/layout.js +41 -0
  18. package/src/corpus/templates/analytics-dashboard/services/web/app/page.js +54 -0
  19. package/src/corpus/templates/analytics-dashboard/services/web/lib/db.js +32 -0
  20. package/src/corpus/templates/analytics-dashboard/services/web/package.json +16 -0
  21. package/src/corpus/templates/api-dashboard/README.md +84 -0
  22. package/src/corpus/templates/api-dashboard/cloudgrid.yaml +233 -0
  23. package/src/corpus/templates/api-dashboard/index.md +310 -0
  24. package/src/corpus/templates/api-dashboard/services/web/app/api/requests/route.js +62 -0
  25. package/src/corpus/templates/api-dashboard/services/web/app/dashboard.js +156 -0
  26. package/src/corpus/templates/api-dashboard/services/web/app/layout.js +42 -0
  27. package/src/corpus/templates/api-dashboard/services/web/app/page.js +39 -0
  28. package/src/corpus/templates/api-dashboard/services/web/lib/db.js +32 -0
  29. package/src/corpus/templates/api-dashboard/services/web/package.json +16 -0
  30. package/src/corpus/templates/api-docs/cloudgrid.yaml +222 -4
  31. package/src/corpus/templates/api-docs/index.md +3 -5
  32. package/src/corpus/templates/api-service/cloudgrid.yaml +224 -9
  33. package/src/corpus/templates/api-service/index.md +3 -11
  34. package/src/corpus/templates/app-with-data/cloudgrid.yaml +226 -8
  35. package/src/corpus/templates/app-with-data/index.md +3 -8
  36. package/src/corpus/templates/appointment-booking/AGENTS.md +223 -0
  37. package/src/corpus/templates/appointment-booking/README.md +16 -0
  38. package/src/corpus/templates/appointment-booking/cloudgrid.yaml +250 -0
  39. package/src/corpus/templates/appointment-booking/index.md +72 -0
  40. package/src/corpus/templates/approval-workflow/AGENTS.md +170 -0
  41. package/src/corpus/templates/approval-workflow/README.md +12 -0
  42. package/src/corpus/templates/approval-workflow/cloudgrid.yaml +237 -0
  43. package/src/corpus/templates/approval-workflow/index.md +58 -0
  44. package/src/corpus/templates/billing-dashboard/AGENTS.md +199 -0
  45. package/src/corpus/templates/billing-dashboard/README.md +18 -0
  46. package/src/corpus/templates/billing-dashboard/cloudgrid.yaml +235 -0
  47. package/src/corpus/templates/billing-dashboard/index.md +87 -0
  48. package/src/corpus/templates/blog-cms/README.md +94 -0
  49. package/src/corpus/templates/blog-cms/cloudgrid.yaml +233 -0
  50. package/src/corpus/templates/blog-cms/index.md +358 -0
  51. package/src/corpus/templates/blog-cms/services/web/app/admin/admin-editor.js +133 -0
  52. package/src/corpus/templates/blog-cms/services/web/app/admin/page.js +33 -0
  53. package/src/corpus/templates/blog-cms/services/web/app/api/posts/route.js +84 -0
  54. package/src/corpus/templates/blog-cms/services/web/app/layout.js +47 -0
  55. package/src/corpus/templates/blog-cms/services/web/app/page.js +56 -0
  56. package/src/corpus/templates/blog-cms/services/web/app/posts/[slug]/page.js +45 -0
  57. package/src/corpus/templates/blog-cms/services/web/lib/db.js +32 -0
  58. package/src/corpus/templates/blog-cms/services/web/package.json +16 -0
  59. package/src/corpus/templates/booking-system/AGENTS.md +189 -0
  60. package/src/corpus/templates/booking-system/README.md +17 -0
  61. package/src/corpus/templates/booking-system/cloudgrid.yaml +248 -0
  62. package/src/corpus/templates/booking-system/index.md +86 -0
  63. package/src/corpus/templates/calendar-scheduler/AGENTS.md +226 -0
  64. package/src/corpus/templates/calendar-scheduler/README.md +25 -0
  65. package/src/corpus/templates/calendar-scheduler/cloudgrid.yaml +259 -0
  66. package/src/corpus/templates/calendar-scheduler/index.md +85 -0
  67. package/src/corpus/templates/changelog/cloudgrid.yaml +222 -4
  68. package/src/corpus/templates/changelog/index.md +3 -5
  69. package/src/corpus/templates/company-website/README.md +54 -0
  70. package/src/corpus/templates/company-website/cloudgrid.yaml +233 -0
  71. package/src/corpus/templates/company-website/index.html +309 -0
  72. package/src/corpus/templates/company-website/index.md +29 -0
  73. package/src/corpus/templates/course-platform/AGENTS.md +161 -0
  74. package/src/corpus/templates/course-platform/README.md +26 -0
  75. package/src/corpus/templates/course-platform/cloudgrid.yaml +237 -0
  76. package/src/corpus/templates/course-platform/index.md +70 -0
  77. package/src/corpus/templates/crm/cloudgrid.yaml +226 -8
  78. package/src/corpus/templates/crm/index.md +3 -0
  79. package/src/corpus/templates/dashboard/cloudgrid.yaml +228 -4
  80. package/src/corpus/templates/dashboard/index.md +3 -5
  81. package/src/corpus/templates/deck/cloudgrid.yaml +228 -4
  82. package/src/corpus/templates/deck/index.md +3 -5
  83. package/src/corpus/templates/directory/README.md +75 -0
  84. package/src/corpus/templates/directory/cloudgrid.yaml +233 -0
  85. package/src/corpus/templates/directory/index.md +334 -0
  86. package/src/corpus/templates/directory/services/web/app/api/entries/route.js +63 -0
  87. package/src/corpus/templates/directory/services/web/app/directory-list.js +146 -0
  88. package/src/corpus/templates/directory/services/web/app/layout.js +44 -0
  89. package/src/corpus/templates/directory/services/web/app/page.js +38 -0
  90. package/src/corpus/templates/directory/services/web/lib/db.js +32 -0
  91. package/src/corpus/templates/directory/services/web/package.json +16 -0
  92. package/src/corpus/templates/docs-site/cloudgrid.yaml +222 -4
  93. package/src/corpus/templates/docs-site/index.md +3 -5
  94. package/src/corpus/templates/erp/AGENTS.md +116 -0
  95. package/src/corpus/templates/erp/README.md +17 -0
  96. package/src/corpus/templates/erp/cloudgrid.yaml +235 -0
  97. package/src/corpus/templates/erp/index.md +81 -0
  98. package/src/corpus/templates/event-board/README.md +74 -0
  99. package/src/corpus/templates/event-board/cloudgrid.yaml +233 -0
  100. package/src/corpus/templates/event-board/index.md +299 -0
  101. package/src/corpus/templates/event-board/services/web/app/api/events/route.js +61 -0
  102. package/src/corpus/templates/event-board/services/web/app/event-form.js +118 -0
  103. package/src/corpus/templates/event-board/services/web/app/layout.js +39 -0
  104. package/src/corpus/templates/event-board/services/web/app/page.js +34 -0
  105. package/src/corpus/templates/event-board/services/web/lib/db.js +32 -0
  106. package/src/corpus/templates/event-board/services/web/package.json +16 -0
  107. package/src/corpus/templates/expense-tracker/README.md +76 -0
  108. package/src/corpus/templates/expense-tracker/cloudgrid.yaml +233 -0
  109. package/src/corpus/templates/expense-tracker/index.md +305 -0
  110. package/src/corpus/templates/expense-tracker/services/web/app/api/expenses/route.js +61 -0
  111. package/src/corpus/templates/expense-tracker/services/web/app/expense-form.js +145 -0
  112. package/src/corpus/templates/expense-tracker/services/web/app/layout.js +42 -0
  113. package/src/corpus/templates/expense-tracker/services/web/app/page.js +34 -0
  114. package/src/corpus/templates/expense-tracker/services/web/lib/db.js +32 -0
  115. package/src/corpus/templates/expense-tracker/services/web/package.json +16 -0
  116. package/src/corpus/templates/feature-request-board/README.md +87 -0
  117. package/src/corpus/templates/feature-request-board/cloudgrid.yaml +233 -0
  118. package/src/corpus/templates/feature-request-board/index.md +317 -0
  119. package/src/corpus/templates/feature-request-board/services/web/app/api/requests/route.js +92 -0
  120. package/src/corpus/templates/feature-request-board/services/web/app/board.js +91 -0
  121. package/src/corpus/templates/feature-request-board/services/web/app/layout.js +43 -0
  122. package/src/corpus/templates/feature-request-board/services/web/app/page.js +35 -0
  123. package/src/corpus/templates/feature-request-board/services/web/lib/db.js +32 -0
  124. package/src/corpus/templates/feature-request-board/services/web/package.json +16 -0
  125. package/src/corpus/templates/financial-dashboard/README.md +80 -0
  126. package/src/corpus/templates/financial-dashboard/cloudgrid.yaml +233 -0
  127. package/src/corpus/templates/financial-dashboard/index.md +326 -0
  128. package/src/corpus/templates/financial-dashboard/services/web/app/api/entries/route.js +63 -0
  129. package/src/corpus/templates/financial-dashboard/services/web/app/entry-board.js +130 -0
  130. package/src/corpus/templates/financial-dashboard/services/web/app/layout.js +46 -0
  131. package/src/corpus/templates/financial-dashboard/services/web/app/page.js +31 -0
  132. package/src/corpus/templates/financial-dashboard/services/web/lib/db.js +32 -0
  133. package/src/corpus/templates/financial-dashboard/services/web/package.json +16 -0
  134. package/src/corpus/templates/forum/AGENTS.md +196 -0
  135. package/src/corpus/templates/forum/README.md +12 -0
  136. package/src/corpus/templates/forum/cloudgrid.yaml +237 -0
  137. package/src/corpus/templates/forum/index.md +66 -0
  138. package/src/corpus/templates/hr-portal/AGENTS.md +174 -0
  139. package/src/corpus/templates/hr-portal/README.md +14 -0
  140. package/src/corpus/templates/hr-portal/cloudgrid.yaml +237 -0
  141. package/src/corpus/templates/hr-portal/index.md +56 -0
  142. package/src/corpus/templates/internal-tools-portal/AGENTS.md +201 -0
  143. package/src/corpus/templates/internal-tools-portal/README.md +17 -0
  144. package/src/corpus/templates/internal-tools-portal/cloudgrid.yaml +237 -0
  145. package/src/corpus/templates/internal-tools-portal/index.md +62 -0
  146. package/src/corpus/templates/inventory/README.md +71 -0
  147. package/src/corpus/templates/inventory/cloudgrid.yaml +233 -0
  148. package/src/corpus/templates/inventory/index.md +68 -0
  149. package/src/corpus/templates/inventory/services/web/app/api/items/route.js +88 -0
  150. package/src/corpus/templates/inventory/services/web/app/inventory-manager.js +101 -0
  151. package/src/corpus/templates/inventory/services/web/app/layout.js +36 -0
  152. package/src/corpus/templates/inventory/services/web/app/page.js +37 -0
  153. package/src/corpus/templates/inventory/services/web/lib/db.js +32 -0
  154. package/src/corpus/templates/inventory/services/web/package.json +16 -0
  155. package/src/corpus/templates/invoice/README.md +71 -0
  156. package/src/corpus/templates/invoice/cloudgrid.yaml +233 -0
  157. package/src/corpus/templates/invoice/index.md +68 -0
  158. package/src/corpus/templates/invoice/services/web/app/api/invoices/route.js +82 -0
  159. package/src/corpus/templates/invoice/services/web/app/invoice-manager.js +101 -0
  160. package/src/corpus/templates/invoice/services/web/app/layout.js +35 -0
  161. package/src/corpus/templates/invoice/services/web/app/page.js +34 -0
  162. package/src/corpus/templates/invoice/services/web/lib/db.js +32 -0
  163. package/src/corpus/templates/invoice/services/web/package.json +16 -0
  164. package/src/corpus/templates/job-board/README.md +71 -0
  165. package/src/corpus/templates/job-board/cloudgrid.yaml +233 -0
  166. package/src/corpus/templates/job-board/index.md +68 -0
  167. package/src/corpus/templates/job-board/services/web/app/api/jobs/route.js +66 -0
  168. package/src/corpus/templates/job-board/services/web/app/job-board.js +73 -0
  169. package/src/corpus/templates/job-board/services/web/app/layout.js +35 -0
  170. package/src/corpus/templates/job-board/services/web/app/page.js +32 -0
  171. package/src/corpus/templates/job-board/services/web/lib/db.js +32 -0
  172. package/src/corpus/templates/job-board/services/web/package.json +16 -0
  173. package/src/corpus/templates/kanban/cloudgrid.yaml +226 -8
  174. package/src/corpus/templates/kanban/index.md +3 -0
  175. package/src/corpus/templates/landing-page/cloudgrid.yaml +228 -4
  176. package/src/corpus/templates/landing-page/index.md +3 -5
  177. package/src/corpus/templates/lms/AGENTS.md +193 -0
  178. package/src/corpus/templates/lms/README.md +27 -0
  179. package/src/corpus/templates/lms/cloudgrid.yaml +237 -0
  180. package/src/corpus/templates/lms/index.md +79 -0
  181. package/src/corpus/templates/marketplace/AGENTS.md +208 -0
  182. package/src/corpus/templates/marketplace/README.md +22 -0
  183. package/src/corpus/templates/marketplace/cloudgrid.yaml +233 -0
  184. package/src/corpus/templates/marketplace/index.md +76 -0
  185. package/src/corpus/templates/membership-site/AGENTS.md +160 -0
  186. package/src/corpus/templates/membership-site/README.md +18 -0
  187. package/src/corpus/templates/membership-site/cloudgrid.yaml +236 -0
  188. package/src/corpus/templates/membership-site/index.md +66 -0
  189. package/src/corpus/templates/monitoring-dashboard/README.md +84 -0
  190. package/src/corpus/templates/monitoring-dashboard/cloudgrid.yaml +233 -0
  191. package/src/corpus/templates/monitoring-dashboard/index.md +328 -0
  192. package/src/corpus/templates/monitoring-dashboard/services/web/app/api/checks/route.js +76 -0
  193. package/src/corpus/templates/monitoring-dashboard/services/web/app/check-form.js +124 -0
  194. package/src/corpus/templates/monitoring-dashboard/services/web/app/layout.js +44 -0
  195. package/src/corpus/templates/monitoring-dashboard/services/web/app/page.js +49 -0
  196. package/src/corpus/templates/monitoring-dashboard/services/web/lib/db.js +32 -0
  197. package/src/corpus/templates/monitoring-dashboard/services/web/package.json +16 -0
  198. package/src/corpus/templates/online-store/AGENTS.md +153 -0
  199. package/src/corpus/templates/online-store/README.md +16 -0
  200. package/src/corpus/templates/online-store/cloudgrid.yaml +234 -0
  201. package/src/corpus/templates/online-store/index.md +81 -0
  202. package/src/corpus/templates/portfolio/cloudgrid.yaml +222 -4
  203. package/src/corpus/templates/portfolio/index.md +3 -5
  204. package/src/corpus/templates/product-catalog/README.md +74 -0
  205. package/src/corpus/templates/product-catalog/cloudgrid.yaml +232 -0
  206. package/src/corpus/templates/product-catalog/index.md +330 -0
  207. package/src/corpus/templates/product-catalog/services/web/app/api/products/route.js +69 -0
  208. package/src/corpus/templates/product-catalog/services/web/app/catalog.js +153 -0
  209. package/src/corpus/templates/product-catalog/services/web/app/layout.js +49 -0
  210. package/src/corpus/templates/product-catalog/services/web/app/page.js +36 -0
  211. package/src/corpus/templates/product-catalog/services/web/lib/db.js +32 -0
  212. package/src/corpus/templates/product-catalog/services/web/package.json +16 -0
  213. package/src/corpus/templates/product-launch/README.md +46 -0
  214. package/src/corpus/templates/product-launch/cloudgrid.yaml +234 -0
  215. package/src/corpus/templates/product-launch/index.html +320 -0
  216. package/src/corpus/templates/product-launch/index.md +34 -0
  217. package/src/corpus/templates/project-management/README.md +83 -0
  218. package/src/corpus/templates/project-management/cloudgrid.yaml +233 -0
  219. package/src/corpus/templates/project-management/index.md +346 -0
  220. package/src/corpus/templates/project-management/services/web/app/api/projects/route.js +48 -0
  221. package/src/corpus/templates/project-management/services/web/app/api/tasks/route.js +85 -0
  222. package/src/corpus/templates/project-management/services/web/app/board.js +182 -0
  223. package/src/corpus/templates/project-management/services/web/app/layout.js +45 -0
  224. package/src/corpus/templates/project-management/services/web/app/page.js +49 -0
  225. package/src/corpus/templates/project-management/services/web/lib/db.js +32 -0
  226. package/src/corpus/templates/project-management/services/web/package.json +16 -0
  227. package/src/corpus/templates/property-listings/README.md +76 -0
  228. package/src/corpus/templates/property-listings/cloudgrid.yaml +233 -0
  229. package/src/corpus/templates/property-listings/index.md +335 -0
  230. package/src/corpus/templates/property-listings/services/web/app/api/properties/route.js +73 -0
  231. package/src/corpus/templates/property-listings/services/web/app/layout.js +45 -0
  232. package/src/corpus/templates/property-listings/services/web/app/listings.js +152 -0
  233. package/src/corpus/templates/property-listings/services/web/app/page.js +53 -0
  234. package/src/corpus/templates/property-listings/services/web/lib/db.js +32 -0
  235. package/src/corpus/templates/property-listings/services/web/package.json +16 -0
  236. package/src/corpus/templates/quiz-platform/README.md +84 -0
  237. package/src/corpus/templates/quiz-platform/cloudgrid.yaml +233 -0
  238. package/src/corpus/templates/quiz-platform/index.md +313 -0
  239. package/src/corpus/templates/quiz-platform/services/web/app/api/questions/route.js +69 -0
  240. package/src/corpus/templates/quiz-platform/services/web/app/layout.js +47 -0
  241. package/src/corpus/templates/quiz-platform/services/web/app/page.js +37 -0
  242. package/src/corpus/templates/quiz-platform/services/web/app/quiz.js +188 -0
  243. package/src/corpus/templates/quiz-platform/services/web/lib/db.js +32 -0
  244. package/src/corpus/templates/quiz-platform/services/web/package.json +16 -0
  245. package/src/corpus/templates/report/cloudgrid.yaml +228 -4
  246. package/src/corpus/templates/report/index.md +3 -5
  247. package/src/corpus/templates/restaurant-reservations/AGENTS.md +258 -0
  248. package/src/corpus/templates/restaurant-reservations/README.md +17 -0
  249. package/src/corpus/templates/restaurant-reservations/cloudgrid.yaml +258 -0
  250. package/src/corpus/templates/restaurant-reservations/index.md +62 -0
  251. package/src/corpus/templates/revenue-dashboard/README.md +75 -0
  252. package/src/corpus/templates/revenue-dashboard/cloudgrid.yaml +233 -0
  253. package/src/corpus/templates/revenue-dashboard/index.md +307 -0
  254. package/src/corpus/templates/revenue-dashboard/services/web/app/api/sales/route.js +60 -0
  255. package/src/corpus/templates/revenue-dashboard/services/web/app/layout.js +40 -0
  256. package/src/corpus/templates/revenue-dashboard/services/web/app/page.js +87 -0
  257. package/src/corpus/templates/revenue-dashboard/services/web/app/sale-form.js +63 -0
  258. package/src/corpus/templates/revenue-dashboard/services/web/lib/db.js +32 -0
  259. package/src/corpus/templates/revenue-dashboard/services/web/package.json +16 -0
  260. package/src/corpus/templates/saas-marketing/cloudgrid.yaml +222 -4
  261. package/src/corpus/templates/saas-marketing/index.md +3 -5
  262. package/src/corpus/templates/semantic-search/AGENTS.md +192 -0
  263. package/src/corpus/templates/semantic-search/README.md +74 -0
  264. package/src/corpus/templates/semantic-search/cloudgrid.yaml +217 -0
  265. package/src/corpus/templates/semantic-search/index.md +97 -0
  266. package/src/corpus/templates/semantic-search/services/backend/requirements.txt +7 -0
  267. package/src/corpus/templates/semantic-search/services/backend/src/app/__init__.py +0 -0
  268. package/src/corpus/templates/semantic-search/services/backend/src/app/answer.py +90 -0
  269. package/src/corpus/templates/semantic-search/services/backend/src/app/auth.py +65 -0
  270. package/src/corpus/templates/semantic-search/services/backend/src/app/config.py +110 -0
  271. package/src/corpus/templates/semantic-search/services/backend/src/app/db.py +89 -0
  272. package/src/corpus/templates/semantic-search/services/backend/src/app/embeddings.py +44 -0
  273. package/src/corpus/templates/semantic-search/services/backend/src/app/indexing.py +222 -0
  274. package/src/corpus/templates/semantic-search/services/backend/src/app/main.py +259 -0
  275. package/src/corpus/templates/semantic-search/services/backend/src/app/search.py +222 -0
  276. package/src/corpus/templates/semantic-search/services/backend/src/app/source.py +259 -0
  277. package/src/corpus/templates/semantic-search/services/backend/src/main.py +12 -0
  278. package/src/corpus/templates/semantic-search/services/web/index.html +12 -0
  279. package/src/corpus/templates/semantic-search/services/web/package-lock.json +1680 -0
  280. package/src/corpus/templates/semantic-search/services/web/package.json +19 -0
  281. package/src/corpus/templates/semantic-search/services/web/src/App.jsx +55 -0
  282. package/src/corpus/templates/semantic-search/services/web/src/api.js +125 -0
  283. package/src/corpus/templates/semantic-search/services/web/src/components/Dashboard.jsx +61 -0
  284. package/src/corpus/templates/semantic-search/services/web/src/components/ManagerLogin.jsx +39 -0
  285. package/src/corpus/templates/semantic-search/services/web/src/components/SearchView.jsx +166 -0
  286. package/src/corpus/templates/semantic-search/services/web/src/components/Settings.jsx +148 -0
  287. package/src/corpus/templates/semantic-search/services/web/src/main.jsx +10 -0
  288. package/src/corpus/templates/semantic-search/services/web/src/styles.css +78 -0
  289. package/src/corpus/templates/semantic-search/services/web/vite.config.js +10 -0
  290. package/src/corpus/templates/status-page/cloudgrid.yaml +222 -4
  291. package/src/corpus/templates/status-page/index.md +3 -5
  292. package/src/corpus/templates/subscription-management/AGENTS.md +191 -0
  293. package/src/corpus/templates/subscription-management/README.md +21 -0
  294. package/src/corpus/templates/subscription-management/cloudgrid.yaml +236 -0
  295. package/src/corpus/templates/subscription-management/index.md +73 -0
  296. package/src/corpus/templates/task-manager/cloudgrid.yaml +226 -8
  297. package/src/corpus/templates/task-manager/index.md +3 -0
  298. package/src/corpus/templates/ticket-system/README.md +71 -0
  299. package/src/corpus/templates/ticket-system/cloudgrid.yaml +233 -0
  300. package/src/corpus/templates/ticket-system/index.md +68 -0
  301. package/src/corpus/templates/ticket-system/services/web/app/api/tickets/route.js +81 -0
  302. package/src/corpus/templates/ticket-system/services/web/app/layout.js +36 -0
  303. package/src/corpus/templates/ticket-system/services/web/app/page.js +35 -0
  304. package/src/corpus/templates/ticket-system/services/web/app/ticket-queue.js +112 -0
  305. package/src/corpus/templates/ticket-system/services/web/lib/db.js +32 -0
  306. package/src/corpus/templates/ticket-system/services/web/package.json +16 -0
  307. package/src/corpus/templates/time-tracking/README.md +81 -0
  308. package/src/corpus/templates/time-tracking/cloudgrid.yaml +233 -0
  309. package/src/corpus/templates/time-tracking/index.md +298 -0
  310. package/src/corpus/templates/time-tracking/services/web/app/api/entries/route.js +66 -0
  311. package/src/corpus/templates/time-tracking/services/web/app/entry-form.js +106 -0
  312. package/src/corpus/templates/time-tracking/services/web/app/layout.js +39 -0
  313. package/src/corpus/templates/time-tracking/services/web/app/page.js +30 -0
  314. package/src/corpus/templates/time-tracking/services/web/lib/db.js +32 -0
  315. package/src/corpus/templates/time-tracking/services/web/package.json +16 -0
  316. package/src/corpus/templates/travel-booking/AGENTS.md +207 -0
  317. package/src/corpus/templates/travel-booking/README.md +17 -0
  318. package/src/corpus/templates/travel-booking/cloudgrid.yaml +249 -0
  319. package/src/corpus/templates/travel-booking/index.md +88 -0
  320. package/src/corpus/templates/waitlist/cloudgrid.yaml +222 -4
  321. package/src/corpus/templates/waitlist/index.md +3 -5
  322. package/src/corpus/templates/web-app/cloudgrid.yaml +228 -4
  323. package/src/corpus/templates/web-app/index.md +3 -5
  324. package/src/corpus/workflows/ai-knowledge-base.md +137 -0
  325. package/src/corpus/workflows/analytics-dashboard.md +104 -0
  326. package/src/corpus/workflows/api-dashboard.md +102 -0
  327. package/src/corpus/workflows/appointment-booking.md +143 -0
  328. package/src/corpus/workflows/approval-workflow.md +124 -0
  329. package/src/corpus/workflows/billing-dashboard.md +120 -0
  330. package/src/corpus/workflows/blog-cms.md +104 -0
  331. package/src/corpus/workflows/booking-system.md +116 -0
  332. package/src/corpus/workflows/calendar-scheduler.md +134 -0
  333. package/src/corpus/workflows/company-website.md +46 -0
  334. package/src/corpus/workflows/course-platform.md +126 -0
  335. package/src/corpus/workflows/directory.md +101 -0
  336. package/src/corpus/workflows/erp.md +125 -0
  337. package/src/corpus/workflows/event-board.md +102 -0
  338. package/src/corpus/workflows/expense-tracker.md +102 -0
  339. package/src/corpus/workflows/feature-request-board.md +105 -0
  340. package/src/corpus/workflows/financial-dashboard.md +103 -0
  341. package/src/corpus/workflows/forum.md +128 -0
  342. package/src/corpus/workflows/hr-portal.md +115 -0
  343. package/src/corpus/workflows/internal-tools-portal.md +125 -0
  344. package/src/corpus/workflows/inventory.md +101 -0
  345. package/src/corpus/workflows/invoice.md +101 -0
  346. package/src/corpus/workflows/job-board.md +101 -0
  347. package/src/corpus/workflows/lms.md +113 -0
  348. package/src/corpus/workflows/marketplace.md +123 -0
  349. package/src/corpus/workflows/membership-site.md +128 -0
  350. package/src/corpus/workflows/monitoring-dashboard.md +104 -0
  351. package/src/corpus/workflows/online-store.md +114 -0
  352. package/src/corpus/workflows/product-catalog.md +105 -0
  353. package/src/corpus/workflows/product-launch.md +43 -0
  354. package/src/corpus/workflows/project-management.md +106 -0
  355. package/src/corpus/workflows/property-listings.md +101 -0
  356. package/src/corpus/workflows/quiz-platform.md +105 -0
  357. package/src/corpus/workflows/restaurant-reservations.md +123 -0
  358. package/src/corpus/workflows/revenue-dashboard.md +102 -0
  359. package/src/corpus/workflows/semantic-search.md +133 -0
  360. package/src/corpus/workflows/subscription-management.md +141 -0
  361. package/src/corpus/workflows/ticket-system.md +101 -0
  362. package/src/corpus/workflows/time-tracking.md +104 -0
  363. package/src/corpus/workflows/travel-booking.md +115 -0
  364. package/src/tools.js +73 -12
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "semantic-search-web",
3
+ "private": true,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.3.1",
13
+ "react-dom": "^18.3.1"
14
+ },
15
+ "devDependencies": {
16
+ "@vitejs/plugin-react": "^4.3.1",
17
+ "vite": "^5.4.0"
18
+ }
19
+ }
@@ -0,0 +1,55 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import * as api from "./api.js";
3
+ import SearchView from "./components/SearchView.jsx";
4
+ import ManagerLogin from "./components/ManagerLogin.jsx";
5
+ import Settings from "./components/Settings.jsx";
6
+ import Dashboard from "./components/Dashboard.jsx";
7
+
8
+ export default function App() {
9
+ const [view, setView] = useState("search");
10
+ const [status, setStatus] = useState(null);
11
+ const [loggedIn, setLoggedIn] = useState(api.isLoggedIn());
12
+
13
+ useEffect(() => {
14
+ api.getStatus().then(setStatus).catch(() => setStatus({ mongo: false }));
15
+ }, []);
16
+
17
+ function logout() {
18
+ api.setToken(null);
19
+ setLoggedIn(false);
20
+ setView("search");
21
+ }
22
+
23
+ return (
24
+ <div className="container">
25
+ <header className="site">
26
+ <h1>Document Search</h1>
27
+ <p>Search across your documents — by word, by meaning, and by date or collection</p>
28
+ <nav className="top">
29
+ <a onClick={() => setView("search")}>Search</a>
30
+ {loggedIn ? (
31
+ <>
32
+ <a onClick={() => setView("settings")}>Settings</a>
33
+ <a onClick={() => setView("dashboard")}>Dashboard</a>
34
+ <a onClick={logout}>Sign out</a>
35
+ </>
36
+ ) : (
37
+ <a onClick={() => setView("login")}>Manager sign-in</a>
38
+ )}
39
+ </nav>
40
+ </header>
41
+
42
+ {view === "search" && <SearchView status={status} />}
43
+ {view === "login" && (
44
+ <ManagerLogin
45
+ onLoggedIn={() => {
46
+ setLoggedIn(true);
47
+ setView("settings");
48
+ }}
49
+ />
50
+ )}
51
+ {view === "settings" && loggedIn && <Settings />}
52
+ {view === "dashboard" && loggedIn && <Dashboard />}
53
+ </div>
54
+ );
55
+ }
@@ -0,0 +1,125 @@
1
+ // Backend base URL baked in at build time. The backend is mounted at /backend on
2
+ // the same entity, so same-origin "" works in production. Override with
3
+ // VITE_BACKEND_URL for split-origin local dev.
4
+ const BASE = import.meta.env.VITE_BACKEND_URL || "";
5
+
6
+ function url(path) {
7
+ return `${BASE}${path}`;
8
+ }
9
+
10
+ let token = localStorage.getItem("mgr_token") || null;
11
+ export function setToken(t) {
12
+ token = t;
13
+ if (t) localStorage.setItem("mgr_token", t);
14
+ else localStorage.removeItem("mgr_token");
15
+ }
16
+ export function isLoggedIn() {
17
+ return !!token;
18
+ }
19
+ function authHeaders() {
20
+ return token ? { Authorization: `Bearer ${token}` } : {};
21
+ }
22
+
23
+ export async function getStatus() {
24
+ const r = await fetch(url("/backend/status"));
25
+ return r.json();
26
+ }
27
+
28
+ export async function search(params) {
29
+ const qs = new URLSearchParams(
30
+ Object.entries(params).filter(([, v]) => v !== "" && v != null)
31
+ );
32
+ const r = await fetch(url(`/backend/search?${qs}`));
33
+ return r.json();
34
+ }
35
+
36
+ export async function count(params) {
37
+ const qs = new URLSearchParams(
38
+ Object.entries(params).filter(([, v]) => v !== "" && v != null)
39
+ );
40
+ const r = await fetch(url(`/backend/count?${qs}`));
41
+ return r.json();
42
+ }
43
+
44
+ export async function listCollections() {
45
+ const r = await fetch(url("/backend/collections"));
46
+ return r.json();
47
+ }
48
+
49
+ export async function answer(question) {
50
+ const r = await fetch(url("/backend/answer"), {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json" },
53
+ body: JSON.stringify({ question }),
54
+ });
55
+ return r.json();
56
+ }
57
+
58
+ export function downloadUrl(documentId) {
59
+ return url(`/backend/documents/${documentId}/download`);
60
+ }
61
+
62
+ // ── manager ──
63
+ export async function login(password) {
64
+ const r = await fetch(url("/backend/admin/login"), {
65
+ method: "POST",
66
+ headers: { "Content-Type": "application/json" },
67
+ body: JSON.stringify({ password }),
68
+ });
69
+ if (!r.ok) throw new Error((await r.json()).detail || "Login failed");
70
+ const data = await r.json();
71
+ setToken(data.token);
72
+ return data;
73
+ }
74
+
75
+ export async function getSettings() {
76
+ const r = await fetch(url("/backend/admin/settings"), { headers: authHeaders() });
77
+ if (!r.ok) throw new Error("Not authorized");
78
+ return r.json();
79
+ }
80
+
81
+ export async function updateSettings(body) {
82
+ const r = await fetch(url("/backend/admin/settings"), {
83
+ method: "PUT",
84
+ headers: { "Content-Type": "application/json", ...authHeaders() },
85
+ body: JSON.stringify(body),
86
+ });
87
+ return r.json();
88
+ }
89
+
90
+ export async function updateSynonyms(map) {
91
+ const r = await fetch(url("/backend/admin/synonyms"), {
92
+ method: "PUT",
93
+ headers: { "Content-Type": "application/json", ...authHeaders() },
94
+ body: JSON.stringify({ map }),
95
+ });
96
+ return r.json();
97
+ }
98
+
99
+ export async function changePassword(current, nw) {
100
+ const r = await fetch(url("/backend/admin/password"), {
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json", ...authHeaders() },
103
+ body: JSON.stringify({ current, new: nw }),
104
+ });
105
+ return r.json();
106
+ }
107
+
108
+ export async function indexReport() {
109
+ const r = await fetch(url("/backend/admin/index-report"), { headers: authHeaders() });
110
+ return r.json();
111
+ }
112
+
113
+ export async function refreshNow() {
114
+ const r = await fetch(url("/backend/admin/refresh"), {
115
+ method: "POST",
116
+ headers: authHeaders(),
117
+ });
118
+ return r.json();
119
+ }
120
+
121
+ export async function usage() {
122
+ const r = await fetch(url("/backend/admin/usage"), { headers: authHeaders() });
123
+ if (!r.ok) throw new Error("Not authorized");
124
+ return r.json();
125
+ }
@@ -0,0 +1,61 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import * as api from "../api.js";
3
+
4
+ export default function Dashboard() {
5
+ const [u, setU] = useState(null);
6
+ const [err, setErr] = useState(null);
7
+
8
+ useEffect(() => {
9
+ api.usage().then(setU).catch((e) => setErr(e.message));
10
+ }, []);
11
+
12
+ if (err) return <div className="card note">{err}</div>;
13
+ if (!u) return <div className="card">Loading…</div>;
14
+
15
+ return (
16
+ <div>
17
+ <div className="card">
18
+ <h3>Usage overview</h3>
19
+ <div className="stat-grid">
20
+ <div className="stat"><div className="num">{u.total_searches}</div><div className="lbl">Searches</div></div>
21
+ <div className="stat"><div className="num">{u.unique_users}</div><div className="lbl">Unique users</div></div>
22
+ <div className="stat"><div className="num">{u.indexed_documents}</div><div className="lbl">Indexed documents</div></div>
23
+ </div>
24
+ <p className="note">Last refresh: {u.last_refresh || "never"}</p>
25
+ </div>
26
+
27
+ <div className="card">
28
+ <h3>Searches by mode</h3>
29
+ <table className="usage">
30
+ <tbody>
31
+ {Object.entries(u.by_mode || {}).map(([mode, n]) => (
32
+ <tr key={mode}><td>{mode}</td><td>{n}</td></tr>
33
+ ))}
34
+ </tbody>
35
+ </table>
36
+ </div>
37
+
38
+ <div className="card">
39
+ <h3>Top queries</h3>
40
+ <table className="usage">
41
+ <tbody>
42
+ {(u.top_queries || []).map((q, i) => (
43
+ <tr key={i}><td>{q.query}</td><td>{q.count}</td></tr>
44
+ ))}
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+
49
+ <div className="card">
50
+ <h3>Zero-result queries</h3>
51
+ <table className="usage">
52
+ <tbody>
53
+ {(u.zero_result_queries || []).map((q, i) => (
54
+ <tr key={i}><td>{q.query}</td><td>{q.count}</td></tr>
55
+ ))}
56
+ </tbody>
57
+ </table>
58
+ </div>
59
+ </div>
60
+ );
61
+ }
@@ -0,0 +1,39 @@
1
+ import React, { useState } from "react";
2
+ import * as api from "../api.js";
3
+
4
+ export default function ManagerLogin({ onLoggedIn }) {
5
+ const [password, setPassword] = useState("");
6
+ const [err, setErr] = useState(null);
7
+ const [busy, setBusy] = useState(false);
8
+
9
+ async function submit(e) {
10
+ e.preventDefault();
11
+ setBusy(true);
12
+ setErr(null);
13
+ try {
14
+ await api.login(password);
15
+ onLoggedIn();
16
+ } catch (ex) {
17
+ setErr(ex.message);
18
+ } finally {
19
+ setBusy(false);
20
+ }
21
+ }
22
+
23
+ return (
24
+ <form className="card" onSubmit={submit}>
25
+ <h3>Manager sign-in</h3>
26
+ <label className="field">Password</label>
27
+ <input
28
+ className="text-input"
29
+ type="password"
30
+ value={password}
31
+ onChange={(e) => setPassword(e.target.value)}
32
+ />
33
+ {err && <p className="note" style={{ color: "#b00" }}>{err}</p>}
34
+ <div style={{ marginTop: 12 }}>
35
+ <button disabled={busy}>{busy ? "Signing in…" : "Sign in"}</button>
36
+ </div>
37
+ </form>
38
+ );
39
+ }
@@ -0,0 +1,166 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import * as api from "../api.js";
3
+
4
+ const MODES = [
5
+ { id: "hybrid", label: "Hybrid" },
6
+ { id: "lexical", label: "Exact / keyword" },
7
+ { id: "semantic", label: "Semantic" },
8
+ { id: "metadata", label: "By date / collection" },
9
+ ];
10
+
11
+ // Render «...» highlight markers from the backend as <mark>.
12
+ function Passage({ text }) {
13
+ if (!text) return null;
14
+ const parts = text.split(/(«[^»]*»)/g);
15
+ return (
16
+ <div className="passage">
17
+ {parts.map((p, i) =>
18
+ p.startsWith("«") && p.endsWith("»") ? (
19
+ <mark key={i}>{p.slice(1, -1)}</mark>
20
+ ) : (
21
+ <span key={i}>{p}</span>
22
+ )
23
+ )}
24
+ </div>
25
+ );
26
+ }
27
+
28
+ export default function SearchView({ status }) {
29
+ const [q, setQ] = useState("");
30
+ const [mode, setMode] = useState("hybrid");
31
+ const [collection, setCollection] = useState("");
32
+ const [dateFrom, setDateFrom] = useState("");
33
+ const [dateTo, setDateTo] = useState("");
34
+ const [collectionList, setCollectionList] = useState([]);
35
+ const [res, setRes] = useState(null);
36
+ const [loading, setLoading] = useState(false);
37
+ const [answerMode, setAnswerMode] = useState(false);
38
+ const [answerRes, setAnswerRes] = useState(null);
39
+
40
+ useEffect(() => {
41
+ api.listCollections().then((d) => setCollectionList(d.collections || [])).catch(() => {});
42
+ }, []);
43
+
44
+ async function runSearch(e) {
45
+ e && e.preventDefault();
46
+ setLoading(true);
47
+ setAnswerRes(null);
48
+ try {
49
+ if (answerMode && q.trim()) {
50
+ setAnswerRes(await api.answer(q));
51
+ }
52
+ const params = { q, mode, collection, date_from: dateFrom, date_to: dateTo };
53
+ setRes(await api.search(params));
54
+ } finally {
55
+ setLoading(false);
56
+ }
57
+ }
58
+
59
+ const notIndexed = status && status.indexed_documents === 0;
60
+ const answerEnabled = status && status.answer_mode_enabled;
61
+
62
+ return (
63
+ <div>
64
+ {status && !status.mongo && (
65
+ <div className="banner">The service is not connected to the database right now.</div>
66
+ )}
67
+ {notIndexed && status.mongo && (
68
+ <div className="banner">
69
+ The catalog is not indexed yet
70
+ {!status.source_configured &&
71
+ ` (source "${status.source_type}" is not configured)`}
72
+ {status.source_configured && !status.embeddings_configured &&
73
+ " — semantic search will be available once the embeddings key is set"}
74
+ .
75
+ </div>
76
+ )}
77
+
78
+ <form className="card" onSubmit={runSearch}>
79
+ <div className="searchbar">
80
+ <input
81
+ type="text"
82
+ placeholder="Search a word, phrase, or idea…"
83
+ value={q}
84
+ onChange={(e) => setQ(e.target.value)}
85
+ />
86
+ <button type="submit" disabled={loading}>
87
+ {loading ? "Searching…" : "Search"}
88
+ </button>
89
+ </div>
90
+
91
+ <div className="modes">
92
+ {MODES.map((m) => (
93
+ <span
94
+ key={m.id}
95
+ className={`chip ${mode === m.id ? "active" : ""}`}
96
+ onClick={() => setMode(m.id)}
97
+ >
98
+ {m.label}
99
+ </span>
100
+ ))}
101
+ </div>
102
+
103
+ <div className="filters">
104
+ <select value={collection} onChange={(e) => setCollection(e.target.value)}>
105
+ <option value="">All collections</option>
106
+ {collectionList.map((c) => (
107
+ <option key={c} value={c}>{c}</option>
108
+ ))}
109
+ </select>
110
+ <input type="date" value={dateFrom} onChange={(e) => setDateFrom(e.target.value)} />
111
+ <input type="date" value={dateTo} onChange={(e) => setDateTo(e.target.value)} />
112
+ </div>
113
+
114
+ {answerEnabled && (
115
+ <div className="toggle" style={{ marginTop: 12 }}>
116
+ <input
117
+ id="answerMode"
118
+ type="checkbox"
119
+ checked={answerMode}
120
+ onChange={(e) => setAnswerMode(e.target.checked)}
121
+ />
122
+ <label htmlFor="answerMode">Grounded answer mode</label>
123
+ </div>
124
+ )}
125
+ </form>
126
+
127
+ {answerRes && (
128
+ <div className="card">
129
+ <h3>Grounded answer</h3>
130
+ {answerRes.answer ? (
131
+ <>
132
+ <div className="answer-box">{answerRes.answer}</div>
133
+ <div className="citations">
134
+ Sources: {answerRes.citations.map((c) => c.title).join(" · ")}
135
+ </div>
136
+ </>
137
+ ) : (
138
+ <p className="note">{answerRes.note}</p>
139
+ )}
140
+ </div>
141
+ )}
142
+
143
+ {res && (
144
+ <div className="card">
145
+ <div className="note" style={{ marginBottom: 10 }}>
146
+ {res.total_matching_documents} matching documents
147
+ {res.note ? ` — ${res.note}` : ""}
148
+ </div>
149
+ {res.results.length === 0 && <p className="note">No results found.</p>}
150
+ {res.results.map((r) => (
151
+ <div className="result" key={r.document_id}>
152
+ <h3>{r.title}</h3>
153
+ <div className="meta">
154
+ {r.collection && <span>Collection: {r.collection} · </span>}
155
+ {r.date && <span>{r.date} · </span>}
156
+ {r.has_media && <span>🎧 media · </span>}
157
+ <a href={api.downloadUrl(r.document_id)}>Download text</a>
158
+ </div>
159
+ <Passage text={r.best_passage} />
160
+ </div>
161
+ ))}
162
+ </div>
163
+ )}
164
+ </div>
165
+ );
166
+ }
@@ -0,0 +1,148 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import * as api from "../api.js";
3
+
4
+ export default function Settings() {
5
+ const [settings, setSettings] = useState(null);
6
+ const [synonymsText, setSynonymsText] = useState("");
7
+ const [report, setReport] = useState(null);
8
+ const [msg, setMsg] = useState(null);
9
+ const [refreshing, setRefreshing] = useState(false);
10
+ const [pw, setPw] = useState({ current: "", nw: "" });
11
+ const [pwResult, setPwResult] = useState(null);
12
+
13
+ async function load() {
14
+ const s = await api.getSettings();
15
+ setSettings(s);
16
+ setSynonymsText(
17
+ Object.entries(s.synonyms || {})
18
+ .map(([k, v]) => `${k}: ${v.join(", ")}`)
19
+ .join("\n")
20
+ );
21
+ setReport(await api.indexReport());
22
+ }
23
+ useEffect(() => {
24
+ load().catch((e) => setMsg(e.message));
25
+ }, []);
26
+
27
+ async function saveFeatures() {
28
+ await api.updateSettings({ answer_mode_enabled: settings.answer_mode_enabled });
29
+ setMsg("Settings saved");
30
+ }
31
+
32
+ async function saveSynonyms() {
33
+ const map = {};
34
+ synonymsText.split("\n").forEach((line) => {
35
+ const [k, rest] = line.split(":");
36
+ if (k && rest) map[k.trim()] = rest.split(",").map((x) => x.trim()).filter(Boolean);
37
+ });
38
+ await api.updateSynonyms(map);
39
+ setMsg("Synonyms saved");
40
+ }
41
+
42
+ async function doRefresh() {
43
+ setRefreshing(true);
44
+ try {
45
+ await api.refreshNow();
46
+ setReport(await api.indexReport());
47
+ setMsg("Sync complete");
48
+ } finally {
49
+ setRefreshing(false);
50
+ }
51
+ }
52
+
53
+ async function doChangePassword() {
54
+ const r = await api.changePassword(pw.current, pw.nw);
55
+ setPwResult(r);
56
+ }
57
+
58
+ if (!settings) return <div className="card">{msg || "Loading…"}</div>;
59
+
60
+ return (
61
+ <div>
62
+ {msg && <div className="banner">{msg}</div>}
63
+
64
+ <div className="card">
65
+ <h3>Index</h3>
66
+ <p className="note">
67
+ Re-index new and changed documents from the configured source. This is
68
+ the supported refresh path today. A scheduled (cron) refresh is a
69
+ follow-up, blocked on a platform issue — see AGENTS.md.
70
+ </p>
71
+ <button onClick={doRefresh} disabled={refreshing}>
72
+ {refreshing ? "Syncing…" : "Refresh now"}
73
+ </button>
74
+ <p className="note">Last refresh: {settings.last_refresh || "never"}</p>
75
+ </div>
76
+
77
+ <div className="card">
78
+ <h3>Answer mode</h3>
79
+ <div className="toggle">
80
+ <input
81
+ id="am"
82
+ type="checkbox"
83
+ checked={settings.answer_mode_enabled}
84
+ onChange={(e) => setSettings({ ...settings, answer_mode_enabled: e.target.checked })}
85
+ />
86
+ <label htmlFor="am">Enable grounded answer mode</label>
87
+ </div>
88
+ <button className="ghost" onClick={saveFeatures} style={{ marginTop: 8 }}>Save</button>
89
+ </div>
90
+
91
+ <div className="card">
92
+ <h3>Synonyms</h3>
93
+ <p className="note">One line per term, format: <code>term: synonym1, synonym2</code></p>
94
+ <textarea
95
+ className="text-input"
96
+ rows={5}
97
+ value={synonymsText}
98
+ onChange={(e) => setSynonymsText(e.target.value)}
99
+ />
100
+ <button className="ghost" onClick={saveSynonyms} style={{ marginTop: 8 }}>Save synonyms</button>
101
+ </div>
102
+
103
+ <div className="card">
104
+ <h3>Index report</h3>
105
+ {report && report.reports && report.reports.length > 0 ? (
106
+ report.reports.slice(0, 1).map((rep, i) => (
107
+ <div key={i}>
108
+ <p className="note">
109
+ {rep.status} — {rep.started_at}
110
+ {rep.note ? ` — ${rep.note}` : ""}
111
+ </p>
112
+ <table className="usage">
113
+ <tbody>
114
+ {(rep.files || []).slice(0, 50).map((f, j) => (
115
+ <tr key={j}>
116
+ <td>{f.file}</td>
117
+ <td>{f.result}</td>
118
+ <td>{f.chunks ?? ""}</td>
119
+ </tr>
120
+ ))}
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+ ))
125
+ ) : (
126
+ <p className="note">No reports yet.</p>
127
+ )}
128
+ </div>
129
+
130
+ <div className="card">
131
+ <h3>Change password</h3>
132
+ <label className="field">Current password</label>
133
+ <input className="text-input" type="password"
134
+ value={pw.current} onChange={(e) => setPw({ ...pw, current: e.target.value })} />
135
+ <label className="field">New password</label>
136
+ <input className="text-input" type="password"
137
+ value={pw.nw} onChange={(e) => setPw({ ...pw, nw: e.target.value })} />
138
+ <button className="ghost" onClick={doChangePassword} style={{ marginTop: 8 }}>Change password</button>
139
+ {pwResult && (
140
+ <div className="banner" style={{ marginTop: 10 }}>
141
+ <div>{pwResult.note}</div>
142
+ <code style={{ wordBreak: "break-all" }}>MANAGER_PASSWORD_HASH={pwResult.new_hash}</code>
143
+ </div>
144
+ )}
145
+ </div>
146
+ </div>
147
+ );
148
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import App from "./App.jsx";
4
+ import "./styles.css";
5
+
6
+ createRoot(document.getElementById("root")).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );