cognova 0.1.9 → 0.2.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 (299) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{B4LjQa2N.js → 4MiwzAAt.js} +2 -2
  3. package/.output/public/_nuxt/{BZZeOWzQ.js → 5ZXA0Ckq.js} +1 -1
  4. package/.output/public/_nuxt/{B194okoV.js → 9IQmsEjr.js} +1 -1
  5. package/.output/public/_nuxt/{DQ_ZoW_9.js → 9QnH0xQM.js} +1 -1
  6. package/.output/public/_nuxt/{CF0HGIV6.js → B1X4Bzcy.js} +1 -1
  7. package/.output/public/_nuxt/{D9lowtoI.js → B3y_Qqox.js} +1 -1
  8. package/.output/public/_nuxt/{BB1R_SaV.js → B6S_ob86.js} +1 -1
  9. package/.output/public/_nuxt/{DVf1IpSh.js → BAIz-dEB.js} +1 -1
  10. package/.output/public/_nuxt/{CNFNMRY1.js → BCtfQCzC.js} +1 -1
  11. package/.output/public/_nuxt/BIIJhjQO.js +1 -0
  12. package/.output/public/_nuxt/BIckl6wA.js +1 -0
  13. package/.output/public/_nuxt/{Biy6boRV.js → BJ3o57WW.js} +1 -1
  14. package/.output/public/_nuxt/{B5rIsDOv.js → BNetzZzF.js} +1 -1
  15. package/.output/public/_nuxt/{DFXLcgxL.js → BOj6t-oo.js} +1 -1
  16. package/.output/public/_nuxt/{BDUpLPg_.js → BS0ofHJK.js} +1 -1
  17. package/.output/public/_nuxt/{DIdcflWi.js → BWhMnjID.js} +1 -1
  18. package/.output/public/_nuxt/{CExLOuIW.js → BYjadNrw.js} +1 -1
  19. package/.output/public/_nuxt/{C8ytOrRD.js → BZXMQuYP.js} +1 -1
  20. package/.output/public/_nuxt/{Ddih3UKd.js → B_3_hrpn.js} +1 -1
  21. package/.output/public/_nuxt/{CxSyRXlk.js → BaBZjmMC.js} +1 -1
  22. package/.output/public/_nuxt/BaMqDm5u.js +1 -0
  23. package/.output/public/_nuxt/BasgsT_S.js +1 -0
  24. package/.output/public/_nuxt/{Cehzuz52.js → BffWCM73.js} +1 -1
  25. package/.output/public/_nuxt/{Dh0BcDEI.js → BhzMoffi.js} +1 -1
  26. package/.output/public/_nuxt/{DmV68Eyp.js → BjjCvHLT.js} +1 -1
  27. package/.output/public/_nuxt/{nzAH3Wk0.js → BlAZO7nq.js} +1 -1
  28. package/.output/public/_nuxt/{BRPJdy3u.js → BlhFigLL.js} +1 -1
  29. package/.output/public/_nuxt/{CfTFjEuh.js → Bm9LyG4F.js} +1 -1
  30. package/.output/public/_nuxt/BoIxv-gM.js +1 -0
  31. package/.output/public/_nuxt/{BslL2E8V.js → BqKFIuRj.js} +1 -1
  32. package/.output/public/_nuxt/Br19oYkq.js +1 -0
  33. package/.output/public/_nuxt/{PtGESE-F.js → BrNqhp1a.js} +3 -3
  34. package/.output/public/_nuxt/{FvV9sv7q.js → BsEZoHd1.js} +1 -1
  35. package/.output/public/_nuxt/{BaPPQtFe.js → BxXOsXrM.js} +10 -10
  36. package/.output/public/_nuxt/BzOqrmGa.js +7 -0
  37. package/.output/public/_nuxt/{BNAsyazX.js → C0JKNMDO.js} +1 -1
  38. package/.output/public/_nuxt/C0kh_F7v.js +1 -0
  39. package/.output/public/_nuxt/{4Ew5YctE.js → C3FxIITy.js} +1 -1
  40. package/.output/public/_nuxt/{DnToOWVx.js → C4pxqdgg.js} +1 -1
  41. package/.output/public/_nuxt/{C5Ue4WbD.js → C61KgSco.js} +1 -1
  42. package/.output/public/_nuxt/{DcMvYcFq.js → C69W7k2j.js} +1 -1
  43. package/.output/public/_nuxt/{BnnFvWzv.js → C6RC3lA1.js} +1 -1
  44. package/.output/public/_nuxt/{DBENYi9d.js → C6aqGHu1.js} +1 -1
  45. package/.output/public/_nuxt/{YldWqMAh.js → CJUdYEdO.js} +1 -1
  46. package/.output/public/_nuxt/{BPAM-iC7.js → CKkC3Ptm.js} +1 -1
  47. package/.output/public/_nuxt/{CTXhFIUN.js → CNnJrDvu.js} +1 -1
  48. package/.output/public/_nuxt/{BwH2E0-a.js → CVJQGP1Q.js} +1 -1
  49. package/.output/public/_nuxt/{q0vhMpUB.js → CVgTJeSq.js} +1 -1
  50. package/.output/public/_nuxt/CWMUi89H.js +1 -0
  51. package/.output/public/_nuxt/{BU9VyOEC.js → CYP_MLH8.js} +1 -1
  52. package/.output/public/_nuxt/{76CHU1js.js → C_BdYLzz.js} +1 -1
  53. package/.output/public/_nuxt/{BQbnVFXA.js → Cdt3I3Go.js} +1 -1
  54. package/.output/public/_nuxt/Cdu2qGgq.js +1 -0
  55. package/.output/public/_nuxt/{ChMIRIq6.js → CeIVm4A3.js} +1 -1
  56. package/.output/public/_nuxt/CeIu7z4p.js +1 -0
  57. package/.output/public/_nuxt/{CZZw0T2a.js → Ci7UEZQh.js} +1 -1
  58. package/.output/public/_nuxt/{BP_jQhKs.js → CihWZmJe.js} +2 -2
  59. package/.output/public/_nuxt/{Bluqlt6l.js → CitkKxhw.js} +1 -1
  60. package/.output/public/_nuxt/{DIM73BjE.js → CmzH6R-N.js} +2 -2
  61. package/.output/public/_nuxt/{CD5hHJBM.js → Cp2MA0cm.js} +1 -1
  62. package/.output/public/_nuxt/{DflBkWfa.js → CqU2XbzO.js} +1 -1
  63. package/.output/public/_nuxt/{Ccc8OoR8.js → Cqy_L_ip.js} +1 -1
  64. package/.output/public/_nuxt/Cr8ixbr1.js +1 -0
  65. package/.output/public/_nuxt/{DdLGO0wP.js → CsJ9KhQ4.js} +1 -1
  66. package/.output/public/_nuxt/{mHNfVoS0.js → CtYFj7k1.js} +1 -1
  67. package/.output/public/_nuxt/{DIBimEIe.js → CtchsY6e.js} +1 -1
  68. package/.output/public/_nuxt/{BboG47Wz.js → Cvp7FI3T.js} +1 -1
  69. package/.output/public/_nuxt/CxuZBC8n.js +70 -0
  70. package/.output/public/_nuxt/D2689qk4.js +1 -0
  71. package/.output/public/_nuxt/{CWWmC6Y7.js → D31L7Ks6.js} +1 -1
  72. package/.output/public/_nuxt/{JxSV3wOO.js → D3RiUGdz.js} +1 -1
  73. package/.output/public/_nuxt/{C1tYtAeV.js → D3e44mCL.js} +1 -1
  74. package/.output/public/_nuxt/{BTWyDDBM.js → D6t3dcTl.js} +1 -1
  75. package/.output/public/_nuxt/{DpLjEbYb.js → DAQhmSv4.js} +1 -1
  76. package/.output/public/_nuxt/{BnwR3LQL.js → DB359q8R.js} +1 -1
  77. package/.output/public/_nuxt/{jCKYMNtT.js → DCzfkCGa.js} +1 -1
  78. package/.output/public/_nuxt/{BXWm1qrj.js → DG-T44jj.js} +1 -1
  79. package/.output/public/_nuxt/{BBygTbuF.js → DGX0tzL8.js} +1 -1
  80. package/.output/public/_nuxt/DHG66LPS.js +1 -0
  81. package/.output/public/_nuxt/{jBqB49XU.js → DHKLCQRG.js} +1 -1
  82. package/.output/public/_nuxt/{BDw-JoCx.js → DIoI0uJm.js} +1 -1
  83. package/.output/public/_nuxt/{DOQA5CEF.js → DJ5V-y_x.js} +1 -1
  84. package/.output/public/_nuxt/{BGaNWD0s.js → DJMS2og1.js} +1 -1
  85. package/.output/public/_nuxt/{UmgHYYVi.js → DJjDvbZE.js} +1 -1
  86. package/.output/public/_nuxt/{DdtX5kio.js → DK9jxJ0g.js} +1 -1
  87. package/.output/public/_nuxt/{Cc6GlQCO.js → DKZxeXDQ.js} +1 -1
  88. package/.output/public/_nuxt/{Tp-9mt9j.js → DLETdGFL.js} +1 -1
  89. package/.output/public/_nuxt/DOICd-Ld.js +1 -0
  90. package/.output/public/_nuxt/DPEcH-gi.js +65 -0
  91. package/.output/public/_nuxt/{CVNY6Bll.js → DSRrg8JT.js} +1 -1
  92. package/.output/public/_nuxt/{Sm7TJN7_.js → DTDgHTuh.js} +2 -2
  93. package/.output/public/_nuxt/{DeGKAWfY.js → D_3Rq1BS.js} +1 -1
  94. package/.output/public/_nuxt/{BvnL4Jyv.js → Daz4MeL6.js} +1 -1
  95. package/.output/public/_nuxt/{Dyd3g9po.js → Db2v8O7O.js} +1 -1
  96. package/.output/public/_nuxt/{D0FBwEzN.js → Db8-_gO7.js} +1 -1
  97. package/.output/public/_nuxt/{Cv4Qjbqk.js → DfQu3kEw.js} +1 -1
  98. package/.output/public/_nuxt/{c-RGQpsW.js → DgV-EDJ9.js} +1 -1
  99. package/.output/public/_nuxt/{CSF2cTe9.js → DnjGH3SQ.js} +1 -1
  100. package/.output/public/_nuxt/Dp2X5R2m.js +1 -0
  101. package/.output/public/_nuxt/DqB723Z0.js +1 -0
  102. package/.output/public/_nuxt/{DhRePYUI.js → DyRelyfs.js} +1 -1
  103. package/.output/public/_nuxt/{DZiAD6YN.js → Dy_Cq5LQ.js} +1 -1
  104. package/.output/public/_nuxt/{DWQMV4k2.js → DznawRFW.js} +1 -1
  105. package/.output/public/_nuxt/EuOqK1A6.js +1 -0
  106. package/.output/public/_nuxt/{BVZHIuu-.js → FNC8XZTk.js} +1 -1
  107. package/.output/public/_nuxt/{Dsk8JtTw.js → Fukkqjkf.js} +1 -1
  108. package/.output/public/_nuxt/{DNpdNXnv.js → FvlxxmNk.js} +2 -2
  109. package/.output/public/_nuxt/{zt0Txq93.js → IRSbVPIu.js} +1 -1
  110. package/.output/public/_nuxt/{T_w6A2Zo.js → JJ3634gV.js} +9 -9
  111. package/.output/public/_nuxt/{6Tt_Iaya.js → Jez9DHn7.js} +1 -1
  112. package/.output/public/_nuxt/{Cr7nQmYw.js → KKK6HVeG.js} +1 -1
  113. package/.output/public/_nuxt/{BJPw54Qz.js → Lwdv_RKd.js} +1 -1
  114. package/.output/public/_nuxt/{WqUIRM3G.js → Nb2jBtYT.js} +1 -1
  115. package/.output/public/_nuxt/Q8Ps7oN5.js +1 -0
  116. package/.output/public/_nuxt/SXTDhzp6.js +1 -0
  117. package/.output/public/_nuxt/{rfcePMfo.js → Sg2Lwc46.js} +1 -1
  118. package/.output/public/_nuxt/{gEpwc5gO.js → YuTZB7sD.js} +1 -1
  119. package/.output/public/_nuxt/{B2OKrc4G.js → _CYZi8HN.js} +1 -1
  120. package/.output/public/_nuxt/_J_7XIn-.js +1 -0
  121. package/.output/public/_nuxt/builds/latest.json +1 -1
  122. package/.output/public/_nuxt/builds/meta/a1e9100c-1a4f-4f7e-bb53-9dbe0d07effb.json +1 -0
  123. package/.output/public/_nuxt/{Bwx_Kl-4.js → cABRLVee.js} +1 -1
  124. package/.output/public/_nuxt/{DPuJYSUH.js → eko-0FUm.js} +1 -1
  125. package/.output/public/_nuxt/entry.CGxIBGAf.css +1 -0
  126. package/.output/public/_nuxt/{TQOIXkvr.js → g20UHUCv.js} +1 -1
  127. package/.output/public/_nuxt/{zOs8gUGl.js → gBC9k4Qj.js} +1 -1
  128. package/.output/public/_nuxt/{CJ3DQEW9.js → ghuJ76mD.js} +1 -1
  129. package/.output/public/_nuxt/{S6GTaxiQ.js → iBGCpHdw.js} +1 -1
  130. package/.output/public/_nuxt/{VGlRzjk3.js → inmzPrjz.js} +1 -1
  131. package/.output/public/_nuxt/{CCkumwhk.js → m5kGCDpI.js} +4 -4
  132. package/.output/public/_nuxt/{CXkbkhUa.js → nIU2F7ia.js} +3 -3
  133. package/.output/public/_nuxt/oIX-ZDN6.js +1 -0
  134. package/.output/public/_nuxt/{TsIha0iy.js → pcUI-zuY.js} +1 -1
  135. package/.output/public/_nuxt/{BN_2zhBR.js → sf57orEk.js} +1 -1
  136. package/.output/public/_nuxt/usage.vakN1lvi.css +1 -0
  137. package/.output/public/_nuxt/{DHYn0MnY.js → wCGVE8_e.js} +1 -1
  138. package/.output/public/_nuxt/{DMkXE4gH.js → xuzLdW-o.js} +1 -1
  139. package/.output/public/_nuxt/{DdoFnl6e.js → yNrp2XvX.js} +1 -1
  140. package/.output/public/_nuxt/{4hIPJQLp.js → yuf23kh9.js} +1 -1
  141. package/.output/server/chunks/build/CodeIcon-CWD5HcV7.mjs +1 -1
  142. package/.output/server/chunks/build/DropdownMenu-BBrV9nXz.mjs +1 -1
  143. package/.output/server/chunks/build/EditorToolbar-DIfb5arC.mjs +1 -1
  144. package/.output/server/chunks/build/Img-CWLmvN1t.mjs +1 -1
  145. package/.output/server/chunks/build/MDC-Dx0YPDhe.mjs +1 -1
  146. package/.output/server/chunks/build/Select-BB1oLrCD.mjs +1 -1
  147. package/.output/server/chunks/build/SelectMenu-DPssg6zD.mjs +1 -1
  148. package/.output/server/chunks/build/Table-DCwTlhCj.mjs +1 -1
  149. package/.output/server/chunks/build/Tooltip-TRyl6dje.mjs +1 -1
  150. package/.output/server/chunks/build/{_uuid_-CQEMsF1D.mjs → _uuid_-0UgdUhfY.mjs} +8 -7
  151. package/.output/server/chunks/build/{_uuid_-CQEMsF1D.mjs.map → _uuid_-0UgdUhfY.mjs.map} +1 -1
  152. package/.output/server/chunks/build/chat-CZMiB68R.mjs.map +1 -1
  153. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  154. package/.output/server/chunks/build/cookie-C_iulBi6.mjs +1 -1
  155. package/.output/server/chunks/build/{dashboard-24rCroiO.mjs → dashboard-CpMVYnDV.mjs} +13 -6
  156. package/.output/server/chunks/build/{dashboard-24rCroiO.mjs.map → dashboard-CpMVYnDV.mjs.map} +1 -1
  157. package/.output/server/chunks/build/dashboard-YEscLBQN.mjs +1109 -0
  158. package/.output/server/chunks/build/dashboard-YEscLBQN.mjs.map +1 -0
  159. package/.output/server/chunks/build/{docs-DOGZUctm.mjs → docs-Dk2JnYq3.mjs} +8 -7
  160. package/.output/server/chunks/build/{docs-DOGZUctm.mjs.map → docs-Dk2JnYq3.mjs.map} +1 -1
  161. package/.output/server/chunks/build/fetch-BB7Qzkwe.mjs +1 -1
  162. package/.output/server/chunks/build/{hooks-CuyNIRFI.mjs → hooks-DP8WoUPS.mjs} +2 -2
  163. package/.output/server/chunks/build/{hooks-CuyNIRFI.mjs.map → hooks-DP8WoUPS.mjs.map} +1 -1
  164. package/.output/server/chunks/build/{index-BZI-Mj1-.mjs → index-Ba_bPJgk.mjs} +2 -2
  165. package/.output/server/chunks/build/{index-BZI-Mj1-.mjs.map → index-Ba_bPJgk.mjs.map} +1 -1
  166. package/.output/server/chunks/build/index-CxDxc9fm.mjs +1 -1
  167. package/.output/server/chunks/build/server.mjs +26 -17
  168. package/.output/server/chunks/build/server.mjs.map +1 -1
  169. package/.output/server/chunks/build/settings-DdkKCJ00.mjs +1 -1
  170. package/.output/server/chunks/build/styles.mjs +2 -2
  171. package/.output/server/chunks/build/{tasks-DR55Wjpi.mjs → tasks-DiOi1HG_.mjs} +2 -2
  172. package/.output/server/chunks/build/{tasks-DR55Wjpi.mjs.map → tasks-DiOi1HG_.mjs.map} +1 -1
  173. package/.output/server/chunks/build/usage-H_mcd_fz.mjs +1578 -0
  174. package/.output/server/chunks/build/usage-H_mcd_fz.mjs.map +1 -0
  175. package/.output/server/chunks/build/{CodeEditorFallback-DfYly7f5.mjs → useCopyToClipboard-vi6FYyyZ.mjs} +29 -2
  176. package/.output/server/chunks/build/useCopyToClipboard-vi6FYyyZ.mjs.map +1 -0
  177. package/.output/server/chunks/build/useNotificationBus-BG5JNQf1.mjs +1 -1
  178. package/.output/server/chunks/build/{usePreferences-CUvZsOq5.mjs → usePreferences-CzC8fRzd.mjs} +7 -1
  179. package/.output/server/chunks/build/usePreferences-CzC8fRzd.mjs.map +1 -0
  180. package/.output/server/chunks/build/view-Dc8mvzCB.mjs +1 -1
  181. package/.output/server/chunks/nitro/nitro.mjs +884 -818
  182. package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
  183. package/.output/server/chunks/routes/_ws/chat.mjs +18 -4
  184. package/.output/server/chunks/routes/_ws/chat.mjs.map +1 -1
  185. package/.output/server/chunks/routes/api/dashboard/overview.get.mjs +149 -0
  186. package/.output/server/chunks/routes/api/dashboard/overview.get.mjs.map +1 -0
  187. package/.output/server/chunks/routes/api/documents/_id/public.get.mjs +1 -1
  188. package/.output/server/chunks/routes/api/documents/_id/restore.post.mjs +1 -1
  189. package/.output/server/chunks/routes/api/documents/by-path.post.mjs +1 -1
  190. package/.output/server/chunks/routes/api/documents/index.delete.mjs +1 -1
  191. package/.output/server/chunks/routes/api/documents/index.put.mjs +1 -1
  192. package/.output/server/chunks/routes/api/fs/delete.post.mjs +1 -1
  193. package/.output/server/chunks/routes/api/fs/list.get.mjs +1 -1
  194. package/.output/server/chunks/routes/api/fs/mkdir.post.mjs +1 -1
  195. package/.output/server/chunks/routes/api/fs/move.post.mjs +1 -1
  196. package/.output/server/chunks/routes/api/fs/read.post.mjs +1 -1
  197. package/.output/server/chunks/routes/api/fs/rename.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/fs/write.post.mjs +1 -1
  199. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  200. package/.output/server/chunks/routes/api/home.get.mjs +1 -1
  201. package/.output/server/chunks/routes/api/hooks/index.get.mjs +1 -1
  202. package/.output/server/chunks/routes/api/hooks/index.post.mjs +1 -1
  203. package/.output/server/chunks/routes/api/hooks/stats.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/index.get3.mjs +1 -1
  205. package/.output/server/chunks/routes/api/index.get4.mjs +1 -1
  206. package/.output/server/chunks/routes/api/index.get5.mjs +1 -1
  207. package/.output/server/chunks/routes/api/index.get6.mjs +1 -1
  208. package/.output/server/chunks/routes/api/index.get7.mjs +1 -1
  209. package/.output/server/chunks/routes/api/index.get8.mjs +82 -0
  210. package/.output/server/chunks/routes/api/index.get8.mjs.map +1 -0
  211. package/.output/server/chunks/routes/api/index.post2.mjs +1 -1
  212. package/.output/server/chunks/routes/api/index.post3.mjs +1 -1
  213. package/.output/server/chunks/routes/api/index.post4.mjs +1 -1
  214. package/.output/server/chunks/routes/api/index.put.mjs +1 -1
  215. package/.output/server/chunks/routes/api/memory/_id_.delete.mjs +1 -1
  216. package/.output/server/chunks/routes/api/memory/context.get.mjs +1 -1
  217. package/.output/server/chunks/routes/api/memory/extract.post.mjs +20 -1
  218. package/.output/server/chunks/routes/api/memory/extract.post.mjs.map +1 -1
  219. package/.output/server/chunks/routes/api/memory/search.get.mjs +1 -1
  220. package/.output/server/chunks/routes/api/memory/store.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/projects/index.delete.mjs +1 -1
  222. package/.output/server/chunks/routes/api/projects/index.get.mjs +1 -1
  223. package/.output/server/chunks/routes/api/projects/index.put.mjs +1 -1
  224. package/.output/server/chunks/routes/api/secrets/_key_.delete.mjs +1 -1
  225. package/.output/server/chunks/routes/api/secrets/_key_.get.mjs +1 -1
  226. package/.output/server/chunks/routes/api/secrets/_key_.put.mjs +1 -1
  227. package/.output/server/chunks/routes/api/tasks/_id/restore.post.mjs +1 -1
  228. package/.output/server/chunks/routes/api/tasks/index.delete.mjs +1 -1
  229. package/.output/server/chunks/routes/api/tasks/index.put.mjs +1 -1
  230. package/.output/server/chunks/routes/api/tasks/tags.get.mjs +1 -1
  231. package/.output/server/chunks/routes/api/usage/stats.get.mjs +130 -0
  232. package/.output/server/chunks/routes/api/usage/stats.get.mjs.map +1 -0
  233. package/.output/server/chunks/routes/api/user/email.patch.mjs +1 -1
  234. package/.output/server/chunks/routes/notifications.mjs +1 -1
  235. package/.output/server/chunks/routes/renderer.mjs +1 -1
  236. package/.output/server/chunks/routes/terminal.mjs +1 -1
  237. package/.output/server/index.mjs +1 -1
  238. package/.output/server/package.json +1 -1
  239. package/app/components/dashboard/RecentChats.vue +93 -0
  240. package/app/components/dashboard/RecentDocs.vue +108 -0
  241. package/app/components/dashboard/StatCards.vue +82 -0
  242. package/app/components/dashboard/UpcomingTasks.vue +119 -0
  243. package/app/components/dashboard/UsageSummary.vue +94 -0
  244. package/app/components/editor/DocumentEditor.vue +5 -3
  245. package/app/components/usage/UsageCostChart.client.vue +174 -0
  246. package/app/components/usage/UsageCostChart.server.vue +22 -0
  247. package/app/components/usage/UsageRecordsTable.vue +249 -0
  248. package/app/components/usage/UsageSourceDonut.client.vue +93 -0
  249. package/app/components/usage/UsageSourceDonut.server.vue +21 -0
  250. package/app/components/usage/UsageStatsCards.vue +101 -0
  251. package/app/components/usage/UsageTopConsumers.vue +89 -0
  252. package/app/composables/useCopyToClipboard.ts +37 -0
  253. package/app/composables/usePreferences.ts +10 -0
  254. package/app/layouts/dashboard.vue +8 -1
  255. package/app/pages/chat.vue +11 -1
  256. package/app/pages/dashboard.vue +65 -64
  257. package/app/pages/usage.vue +130 -0
  258. package/app/pages/view/[uuid].vue +4 -3
  259. package/package.json +1 -1
  260. package/server/api/dashboard/overview.get.ts +133 -0
  261. package/server/api/usage/index.get.ts +69 -0
  262. package/server/api/usage/stats.get.ts +127 -0
  263. package/server/db/schema.ts +17 -0
  264. package/server/drizzle/migrations/0011_tearful_johnny_storm.sql +12 -0
  265. package/server/drizzle/migrations/meta/0011_snapshot.json +1634 -0
  266. package/server/drizzle/migrations/meta/_journal.json +7 -0
  267. package/server/routes/_ws/chat.ts +29 -2
  268. package/server/services/agent-executor.ts +13 -0
  269. package/server/services/memory-extractor.ts +25 -0
  270. package/server/utils/log-token-usage.ts +22 -0
  271. package/shared/types/index.ts +81 -0
  272. package/.output/public/_nuxt/B34UfOg4.js +0 -1
  273. package/.output/public/_nuxt/B3DmiwBX.js +0 -1
  274. package/.output/public/_nuxt/BESViHC6.js +0 -1
  275. package/.output/public/_nuxt/BIm_buQF.js +0 -1
  276. package/.output/public/_nuxt/BMh-dHBK.js +0 -1
  277. package/.output/public/_nuxt/Bkv1Ouue.js +0 -1
  278. package/.output/public/_nuxt/C4i10ReQ.js +0 -1
  279. package/.output/public/_nuxt/C5euqjeX.js +0 -1
  280. package/.output/public/_nuxt/C9hy_rtV.js +0 -1
  281. package/.output/public/_nuxt/CWJhKIyp.js +0 -1
  282. package/.output/public/_nuxt/Ck24Z-8o.js +0 -1
  283. package/.output/public/_nuxt/D1JmZKz7.js +0 -1
  284. package/.output/public/_nuxt/D6xvQUYG.js +0 -1
  285. package/.output/public/_nuxt/DGTbw5AQ.js +0 -1
  286. package/.output/public/_nuxt/Da8Xd1w6.js +0 -1
  287. package/.output/public/_nuxt/DamUHI17.js +0 -1
  288. package/.output/public/_nuxt/DoIiMqKa.js +0 -76
  289. package/.output/public/_nuxt/builds/meta/75ff59f2-0860-4bfc-a288-c670397cae5c.json +0 -1
  290. package/.output/public/_nuxt/entry.tLLAvqs1.css +0 -1
  291. package/.output/public/_nuxt/iJ4KRInq.js +0 -1
  292. package/.output/public/_nuxt/mSr5c6cB.js +0 -1
  293. package/.output/public/_nuxt/r8g_V5AH.js +0 -1
  294. package/.output/public/_nuxt/rZmMQHiC.js +0 -1
  295. package/.output/server/chunks/build/CodeEditorFallback-DfYly7f5.mjs.map +0 -1
  296. package/.output/server/chunks/build/dashboard-DtbGchTa.mjs +0 -277
  297. package/.output/server/chunks/build/dashboard-DtbGchTa.mjs.map +0 -1
  298. package/.output/server/chunks/build/usePreferences-CUvZsOq5.mjs.map +0 -1
  299. /package/.output/public/_nuxt/{language-detection.Be_IvFWy.css → useCopyToClipboard.Be_IvFWy.css} +0 -0
@@ -0,0 +1,130 @@
1
+ <script setup lang="ts">
2
+ import type { StatsPeriod, UsageStats } from '~~/shared/types'
3
+
4
+ definePageMeta({
5
+ layout: 'dashboard',
6
+ middleware: 'auth'
7
+ })
8
+
9
+ const { usageStatsPeriod } = usePreferences()
10
+ const period = ref<StatsPeriod>(usageStatsPeriod.value)
11
+ const granularity = ref<'daily' | 'hourly'>('daily')
12
+ const stats = ref<UsageStats | null>(null)
13
+ const loading = ref(false)
14
+
15
+ const periodOptions = [
16
+ { label: '24h', value: '24h' as StatsPeriod },
17
+ { label: '7d', value: '7d' as StatsPeriod },
18
+ { label: '30d', value: '30d' as StatsPeriod }
19
+ ]
20
+
21
+ async function loadStats() {
22
+ loading.value = true
23
+ try {
24
+ const res = await $fetch<{ data: UsageStats }>('/api/usage/stats', {
25
+ query: {
26
+ period: period.value,
27
+ granularity: granularity.value,
28
+ tzOffset: new Date().getTimezoneOffset()
29
+ }
30
+ })
31
+ stats.value = res.data
32
+ } catch {
33
+ // Silently fail
34
+ } finally {
35
+ loading.value = false
36
+ }
37
+ }
38
+
39
+ watch(period, (value) => {
40
+ usageStatsPeriod.value = value
41
+ loadStats()
42
+ })
43
+
44
+ watch(granularity, () => {
45
+ loadStats()
46
+ })
47
+
48
+ onMounted(() => {
49
+ loadStats()
50
+ })
51
+ </script>
52
+
53
+ <template>
54
+ <div class="contents">
55
+ <UDashboardPanel
56
+ id="usage"
57
+ grow
58
+ >
59
+ <template #header>
60
+ <UDashboardNavbar title="Token Usage">
61
+ <template #right>
62
+ <UFieldGroup>
63
+ <UButton
64
+ v-for="opt in periodOptions"
65
+ :key="opt.value"
66
+ :color="period === opt.value ? 'primary' : 'neutral'"
67
+ :variant="period === opt.value ? 'solid' : 'ghost'"
68
+ size="sm"
69
+ @click="period = opt.value"
70
+ >
71
+ {{ opt.label }}
72
+ </UButton>
73
+ </UFieldGroup>
74
+ </template>
75
+ </UDashboardNavbar>
76
+ </template>
77
+
78
+ <template #body>
79
+ <div class="p-4 space-y-6">
80
+ <UsageStatsCards
81
+ :stats="stats"
82
+ :loading="loading"
83
+ />
84
+
85
+ <UsageCostChart
86
+ v-if="stats && stats.dailyUsage.length > 0"
87
+ v-model:granularity="granularity"
88
+ :data="stats.dailyUsage"
89
+ title="Cost Over Time"
90
+ />
91
+
92
+ <div class="grid gap-6 lg:grid-cols-2">
93
+ <UsageSourceDonut
94
+ v-if="stats && stats.bySource.length > 0"
95
+ :data="stats.bySource"
96
+ title="Cost by Source"
97
+ />
98
+
99
+ <UsageTopConsumers
100
+ v-if="stats && stats.topConsumers.length > 0"
101
+ :data="stats.topConsumers"
102
+ title="Top Consumers"
103
+ />
104
+ </div>
105
+
106
+ <UsageRecordsTable
107
+ v-if="stats && stats.totalCalls > 0"
108
+ :period="period"
109
+ />
110
+
111
+ <div
112
+ v-if="!loading && stats && stats.totalCalls === 0"
113
+ class="flex flex-col items-center justify-center h-64 text-muted"
114
+ >
115
+ <UIcon
116
+ name="i-lucide-bar-chart-3"
117
+ class="size-12 mb-4"
118
+ />
119
+ <p class="text-lg font-medium">
120
+ No usage data yet
121
+ </p>
122
+ <p class="text-sm mt-1">
123
+ Token usage will appear here once you start using chat or agents
124
+ </p>
125
+ </div>
126
+ </div>
127
+ </template>
128
+ </UDashboardPanel>
129
+ </div>
130
+ </template>
@@ -60,18 +60,19 @@ watch(viewSource, v => viewSourceMode.value = v)
60
60
 
61
61
  // Copy content to clipboard
62
62
  const toast = useToast()
63
+ const { copy } = useCopyToClipboard()
63
64
  async function copyContent() {
64
65
  const content = data.value?.data?.content
65
66
  if (!content) return
66
67
 
67
- try {
68
- await navigator.clipboard.writeText(content)
68
+ const ok = await copy(content)
69
+ if (ok) {
69
70
  toast.add({
70
71
  title: 'Copied to clipboard',
71
72
  icon: 'i-lucide-check',
72
73
  color: 'success'
73
74
  })
74
- } catch {
75
+ } else {
75
76
  toast.add({
76
77
  title: 'Failed to copy',
77
78
  icon: 'i-lucide-x',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cognova",
3
3
  "type": "module",
4
- "version": "0.1.9",
4
+ "version": "0.2.0",
5
5
  "description": "Personal knowledge management system with Claude Code integration",
6
6
  "repository": {
7
7
  "type": "git",
@@ -0,0 +1,133 @@
1
+ import { eq, isNull, and, inArray, gte, desc, sql, ne } from 'drizzle-orm'
2
+ import { getDb, schema } from '~~/server/db'
3
+ import { requireDb } from '~~/server/utils/db-guard'
4
+ import type { DashboardOverview } from '~~/shared/types'
5
+
6
+ export default defineEventHandler(async (event) => {
7
+ requireDb(event)
8
+
9
+ const db = getDb()
10
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
11
+
12
+ const [taskCounts, upcomingTasks, recentConversations, recentDocuments, usageAgg] = await Promise.all([
13
+ // Task counts: todo + in_progress (not deleted)
14
+ db.select({
15
+ status: schema.tasks.status,
16
+ count: sql<number>`count(*)::int`
17
+ })
18
+ .from(schema.tasks)
19
+ .where(and(
20
+ isNull(schema.tasks.deletedAt),
21
+ inArray(schema.tasks.status, ['todo', 'in_progress'])
22
+ ))
23
+ .groupBy(schema.tasks.status),
24
+
25
+ // Top 5 upcoming tasks (not done, not deleted)
26
+ db.select({
27
+ id: schema.tasks.id,
28
+ title: schema.tasks.title,
29
+ status: schema.tasks.status,
30
+ priority: schema.tasks.priority,
31
+ dueDate: schema.tasks.dueDate,
32
+ projectName: schema.projects.name,
33
+ projectColor: schema.projects.color
34
+ })
35
+ .from(schema.tasks)
36
+ .leftJoin(schema.projects, eq(schema.tasks.projectId, schema.projects.id))
37
+ .where(and(
38
+ isNull(schema.tasks.deletedAt),
39
+ ne(schema.tasks.status, 'done')
40
+ ))
41
+ .orderBy(
42
+ sql`${schema.tasks.dueDate} ASC NULLS LAST`,
43
+ desc(schema.tasks.priority)
44
+ )
45
+ .limit(5),
46
+
47
+ // Last 3 conversations
48
+ db.select({
49
+ id: schema.conversations.id,
50
+ sessionId: schema.conversations.sessionId,
51
+ title: schema.conversations.title,
52
+ messageCount: schema.conversations.messageCount,
53
+ startedAt: schema.conversations.startedAt
54
+ })
55
+ .from(schema.conversations)
56
+ .orderBy(desc(schema.conversations.startedAt))
57
+ .limit(3),
58
+
59
+ // Last 3 documents (not deleted)
60
+ db.select({
61
+ id: schema.documents.id,
62
+ title: schema.documents.title,
63
+ path: schema.documents.path,
64
+ modifiedAt: schema.documents.modifiedAt,
65
+ projectName: schema.projects.name,
66
+ projectColor: schema.projects.color
67
+ })
68
+ .from(schema.documents)
69
+ .leftJoin(schema.projects, eq(schema.documents.projectId, schema.projects.id))
70
+ .where(isNull(schema.documents.deletedAt))
71
+ .orderBy(desc(schema.documents.modifiedAt))
72
+ .limit(3),
73
+
74
+ // 7-day usage summary
75
+ db.select({
76
+ totalCost: sql<number>`coalesce(sum(${schema.tokenUsage.costUsd}), 0)::real`,
77
+ totalCalls: sql<number>`count(*)::int`,
78
+ totalInputTokens: sql<number>`coalesce(sum(${schema.tokenUsage.inputTokens}), 0)::int`,
79
+ totalOutputTokens: sql<number>`coalesce(sum(${schema.tokenUsage.outputTokens}), 0)::int`
80
+ })
81
+ .from(schema.tokenUsage)
82
+ .where(gte(schema.tokenUsage.createdAt, sevenDaysAgo))
83
+ ])
84
+
85
+ // Build task counts
86
+ let todoCount = 0
87
+ let inProgressCount = 0
88
+ for (const row of taskCounts) {
89
+ if (row.status === 'todo') todoCount = row.count
90
+ else if (row.status === 'in_progress') inProgressCount = row.count
91
+ }
92
+
93
+ const usageRow = usageAgg[0]
94
+
95
+ const overview: DashboardOverview = {
96
+ tasks: {
97
+ todoCount,
98
+ inProgressCount,
99
+ upcoming: upcomingTasks.map(t => ({
100
+ id: t.id,
101
+ title: t.title,
102
+ status: t.status as DashboardOverview['tasks']['upcoming'][0]['status'],
103
+ priority: t.priority,
104
+ dueDate: t.dueDate?.toISOString() ?? null,
105
+ projectName: t.projectName ?? null,
106
+ projectColor: t.projectColor ?? null
107
+ }))
108
+ },
109
+ conversations: recentConversations.map(c => ({
110
+ id: c.id,
111
+ sessionId: c.sessionId,
112
+ title: c.title ?? null,
113
+ messageCount: c.messageCount,
114
+ startedAt: c.startedAt.toISOString()
115
+ })),
116
+ documents: recentDocuments.map(d => ({
117
+ id: d.id,
118
+ title: d.title,
119
+ path: d.path,
120
+ modifiedAt: d.modifiedAt?.toISOString() ?? null,
121
+ projectName: d.projectName ?? null,
122
+ projectColor: d.projectColor ?? null
123
+ })),
124
+ usage: {
125
+ totalCost7d: usageRow?.totalCost ?? 0,
126
+ totalCalls7d: usageRow?.totalCalls ?? 0,
127
+ totalInputTokens7d: usageRow?.totalInputTokens ?? 0,
128
+ totalOutputTokens7d: usageRow?.totalOutputTokens ?? 0
129
+ }
130
+ }
131
+
132
+ return { data: overview }
133
+ })
@@ -0,0 +1,69 @@
1
+ import { and, gte, eq, ilike, desc } from 'drizzle-orm'
2
+ import { getDb, schema } from '~~/server/db'
3
+ import { requireDb } from '~~/server/utils/db-guard'
4
+ import type { StatsPeriod, TokenUsageSource } from '~~/shared/types'
5
+
6
+ function getPeriodInterval(period: StatsPeriod): Date {
7
+ const now = new Date()
8
+ switch (period) {
9
+ case '24h':
10
+ return new Date(now.getTime() - 24 * 60 * 60 * 1000)
11
+ case '7d':
12
+ return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
13
+ case '30d':
14
+ return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)
15
+ }
16
+ }
17
+
18
+ const VALID_SOURCES: TokenUsageSource[] = ['chat', 'agent', 'memory_extraction']
19
+
20
+ export default defineEventHandler(async (event) => {
21
+ requireDb(event)
22
+
23
+ const query = getQuery(event)
24
+ const period = (query.period as StatsPeriod) || '7d'
25
+ const source = query.source as TokenUsageSource | undefined
26
+ const search = query.search as string | undefined
27
+ const page = Math.max(1, Number(query.page) || 1)
28
+ const limit = Math.min(100, Math.max(1, Number(query.limit) || 20))
29
+ const offset = (page - 1) * limit
30
+
31
+ const periodStart = getPeriodInterval(period)
32
+ const db = getDb()
33
+
34
+ // Build conditions
35
+ const conditions = [gte(schema.tokenUsage.createdAt, periodStart)]
36
+
37
+ if (source && VALID_SOURCES.includes(source))
38
+ conditions.push(eq(schema.tokenUsage.source, source))
39
+
40
+ if (search && search.trim())
41
+ conditions.push(ilike(schema.tokenUsage.sourceName, `%${search.trim()}%`))
42
+
43
+ const where = and(...conditions)
44
+
45
+ // Get total count
46
+ const allMatching = await db.select({ id: schema.tokenUsage.id })
47
+ .from(schema.tokenUsage)
48
+ .where(where)
49
+
50
+ const total = allMatching.length
51
+
52
+ // Get paginated records
53
+ const records = await db.select()
54
+ .from(schema.tokenUsage)
55
+ .where(where)
56
+ .orderBy(desc(schema.tokenUsage.createdAt))
57
+ .limit(limit)
58
+ .offset(offset)
59
+
60
+ return {
61
+ data: records,
62
+ pagination: {
63
+ page,
64
+ limit,
65
+ total,
66
+ totalPages: Math.ceil(total / limit)
67
+ }
68
+ }
69
+ })
@@ -0,0 +1,127 @@
1
+ import { gte } from 'drizzle-orm'
2
+ import { getDb, schema } from '~~/server/db'
3
+ import { requireDb } from '~~/server/utils/db-guard'
4
+ import type { StatsPeriod, UsageStats, DailyUsageData, TokenUsageSource } from '~~/shared/types'
5
+
6
+ function getPeriodInterval(period: StatsPeriod): Date {
7
+ const now = new Date()
8
+ switch (period) {
9
+ case '24h':
10
+ return new Date(now.getTime() - 24 * 60 * 60 * 1000)
11
+ case '7d':
12
+ return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
13
+ case '30d':
14
+ return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000)
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Get a bucket key for the given timestamp, adjusted to the client's timezone.
20
+ * tzOffset is in minutes (same as Date.getTimezoneOffset(), positive = behind UTC).
21
+ */
22
+ function getBucketKey(date: Date, granularity: string, tzOffsetMs: number): string {
23
+ const local = new Date(date.getTime() - tzOffsetMs)
24
+ const iso = local.toISOString()
25
+ if (granularity === 'hourly')
26
+ return iso.slice(0, 13) // "2026-02-18T05"
27
+ return iso.slice(0, 10) // "2026-02-18"
28
+ }
29
+
30
+ export default defineEventHandler(async (event) => {
31
+ requireDb(event)
32
+
33
+ const query = getQuery(event)
34
+ const period = (query.period as StatsPeriod) || '7d'
35
+ const granularity = (query.granularity as string) === 'hourly' ? 'hourly' : 'daily'
36
+ const tzOffset = Number(query.tzOffset) || 0 // minutes from UTC
37
+ const tzOffsetMs = tzOffset * 60 * 1000
38
+ const periodStart = getPeriodInterval(period)
39
+
40
+ const db = getDb()
41
+
42
+ // Get all usage records in period
43
+ const records = await db.select()
44
+ .from(schema.tokenUsage)
45
+ .where(gte(schema.tokenUsage.createdAt, periodStart))
46
+
47
+ // Aggregate totals
48
+ let totalCostUsd = 0
49
+ let totalInputTokens = 0
50
+ let totalOutputTokens = 0
51
+ const totalCalls = records.length
52
+
53
+ // Time-series breakdown
54
+ const bucketMap = new Map<string, DailyUsageData>()
55
+
56
+ // By source breakdown
57
+ const sourceMap = new Map<TokenUsageSource, { cost: number, calls: number, tokens: number }>()
58
+
59
+ // Top consumers
60
+ const consumerMap = new Map<string, { name: string, source: TokenUsageSource, cost: number, calls: number }>()
61
+
62
+ for (const r of records) {
63
+ totalCostUsd += r.costUsd
64
+ totalInputTokens += r.inputTokens
65
+ totalOutputTokens += r.outputTokens
66
+
67
+ // Time-series bucket (timezone-aware)
68
+ const bucket = getBucketKey(r.createdAt, granularity, tzOffsetMs)
69
+ const existing = bucketMap.get(bucket) || {
70
+ date: bucket,
71
+ chat: 0,
72
+ agent: 0,
73
+ memory: 0,
74
+ totalCost: 0,
75
+ inputTokens: 0,
76
+ outputTokens: 0,
77
+ calls: 0
78
+ }
79
+ existing.totalCost += r.costUsd
80
+ existing.inputTokens += r.inputTokens
81
+ existing.outputTokens += r.outputTokens
82
+ existing.calls++
83
+ if (r.source === 'chat') existing.chat += r.costUsd
84
+ else if (r.source === 'agent') existing.agent += r.costUsd
85
+ else if (r.source === 'memory_extraction') existing.memory += r.costUsd
86
+ bucketMap.set(bucket, existing)
87
+
88
+ // By source
89
+ const source = r.source as TokenUsageSource
90
+ const srcEntry = sourceMap.get(source) || { cost: 0, calls: 0, tokens: 0 }
91
+ srcEntry.cost += r.costUsd
92
+ srcEntry.calls++
93
+ srcEntry.tokens += r.inputTokens + r.outputTokens
94
+ sourceMap.set(source, srcEntry)
95
+
96
+ // Top consumers (group by sourceName)
97
+ const consumerKey = `${r.source}:${r.sourceName || 'Unknown'}`
98
+ const consumer = consumerMap.get(consumerKey) || {
99
+ name: r.sourceName || 'Unknown',
100
+ source,
101
+ cost: 0,
102
+ calls: 0
103
+ }
104
+ consumer.cost += r.costUsd
105
+ consumer.calls++
106
+ consumerMap.set(consumerKey, consumer)
107
+ }
108
+
109
+ const dailyUsage = Array.from(bucketMap.values()).sort((a, b) => a.date.localeCompare(b.date))
110
+ const bySource = Array.from(sourceMap.entries()).map(([source, data]) => ({ source, ...data }))
111
+ const topConsumers = Array.from(consumerMap.values())
112
+ .sort((a, b) => b.cost - a.cost)
113
+ .slice(0, 10)
114
+
115
+ const stats: UsageStats = {
116
+ totalCostUsd,
117
+ totalInputTokens,
118
+ totalOutputTokens,
119
+ totalCalls,
120
+ avgCostPerCall: totalCalls > 0 ? totalCostUsd / totalCalls : 0,
121
+ dailyUsage,
122
+ bySource,
123
+ topConsumers
124
+ }
125
+
126
+ return { data: stats }
127
+ })
@@ -359,3 +359,20 @@ export const userSettings = pgTable('user_settings', {
359
359
  export const userSettingsRelations = relations(userSettings, ({ one }) => ({
360
360
  user: one(user, { fields: [userSettings.userId], references: [user.id] })
361
361
  }))
362
+
363
+ // =============================================================================
364
+ // Token Usage - Unified AI cost & token tracking
365
+ // =============================================================================
366
+
367
+ export const tokenUsage = pgTable('token_usage', {
368
+ id: uuid('id').primaryKey().defaultRandom(),
369
+ source: text('source', { enum: ['chat', 'agent', 'memory_extraction'] }).notNull(),
370
+ sourceId: text('source_id'),
371
+ sourceName: text('source_name'),
372
+ inputTokens: integer('input_tokens').default(0).notNull(),
373
+ outputTokens: integer('output_tokens').default(0).notNull(),
374
+ costUsd: real('cost_usd').default(0).notNull(),
375
+ durationMs: integer('duration_ms'),
376
+ numTurns: integer('num_turns'),
377
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull()
378
+ })
@@ -0,0 +1,12 @@
1
+ CREATE TABLE "token_usage" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "source" text NOT NULL,
4
+ "source_id" text,
5
+ "source_name" text,
6
+ "input_tokens" integer DEFAULT 0 NOT NULL,
7
+ "output_tokens" integer DEFAULT 0 NOT NULL,
8
+ "cost_usd" real DEFAULT 0 NOT NULL,
9
+ "duration_ms" integer,
10
+ "num_turns" integer,
11
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
12
+ );