kennel 0.2.3 → 0.2.6

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 (274) hide show
  1. package/README.md +23 -13
  2. package/dist/cli/dispatch.js +16 -3
  3. package/dist/cli/src/cli/dispatch.js +16 -3
  4. package/dist/cli/src/cli/usage.js +1 -1
  5. package/dist/cli/src/core/command.js +1 -0
  6. package/dist/cli/src/core/init.js +5 -5
  7. package/dist/cli/src/plugins/external.d.ts +28 -2
  8. package/dist/cli/src/plugins/external.js +77 -23
  9. package/dist/cli/src/site/server-plugins.d.ts +4 -9
  10. package/dist/cli/src/site/viewer.js +1 -0
  11. package/dist/cli/usage.js +1 -1
  12. package/dist/core/api-client.js +576 -10317
  13. package/dist/core/command.js +1 -0
  14. package/dist/core/core-folders.js +2313 -12088
  15. package/dist/core/init.js +5 -5
  16. package/dist/core/runtime.js +8237 -20713
  17. package/dist/package/preview.js +19617 -33352
  18. package/dist/plugins/external.d.ts +28 -2
  19. package/dist/plugins/external.js +77 -23
  20. package/dist/site/server-plugins.d.ts +4 -9
  21. package/dist/site/server-plugins.js +557 -10452
  22. package/dist/site/viewer.js +1 -0
  23. package/kernel/apps/web/package.json +2 -6
  24. package/kernel/apps/web/scripts/dev.mjs +53 -0
  25. package/kernel/apps/web/src/app.css +0 -3
  26. package/kernel/apps/web/src/external-plugins.ts +1 -1
  27. package/kernel/apps/web/src/folder-filter-icons.tsx +1 -1
  28. package/kernel/apps/web/src/folder-plugin-view.tsx +1 -1
  29. package/kernel/apps/web/src/main.tsx +0 -1
  30. package/kernel/apps/web/src/plugins.ts +1 -31
  31. package/kernel/apps/web/tsconfig.json +1 -2
  32. package/kernel/apps/web/vite.config.ts +32 -14
  33. package/kernel/packages/agents/package.json +1 -1
  34. package/kernel/packages/agents/src/agent-card.tsx +1 -1
  35. package/kernel/packages/agents/src/client.tsx +1 -1
  36. package/kernel/packages/agents/src/manifest.ts +1 -1
  37. package/kernel/packages/agents/src/server.ts +1 -1
  38. package/kernel/packages/agents/src/viewer.tsx +1 -1
  39. package/kernel/packages/api/package.json +1 -5
  40. package/kernel/packages/api/src/server/acp-live-plugin.ts +1 -1
  41. package/kernel/packages/api/src/server/api/create-agent-file.ts +2 -2
  42. package/kernel/packages/api/src/server/api/document-edit.ts +2 -2
  43. package/kernel/packages/api/src/server/api/open-path.ts +2 -2
  44. package/kernel/packages/api/src/server/folder-metadata-plugin.ts +17 -42
  45. package/kernel/packages/api/src/server/index.ts +0 -1
  46. package/kernel/packages/api/src/server/plugins.ts +52 -19
  47. package/kernel/packages/api/src/shared/viewer-route.ts +1 -1
  48. package/kernel/packages/api/test/core.test.ts +14 -26
  49. package/kernel/packages/markdown/README.md +1 -1
  50. package/kernel/packages/notes/package.json +1 -1
  51. package/kernel/packages/notes/src/client.tsx +1 -1
  52. package/kernel/packages/notes/src/manifest.ts +1 -1
  53. package/kernel/packages/notes/src/server.ts +1 -1
  54. package/kernel/packages/plugins/SKILL.md +39 -0
  55. package/kernel/{plugins/mail → packages/plugins}/package.json +53 -28
  56. package/kernel/packages/plugins/src/index.ts +52 -0
  57. package/kernel/packages/plugins/src/page.ts +17 -0
  58. package/kernel/{plugins/projects → packages/plugins}/tsconfig.json +5 -1
  59. package/kernel/packages/plugins/tsup.config.ts +25 -0
  60. package/kernel/packages/ui/src/components/content-issues.tsx +1 -1
  61. package/kernel/packages/ui/tsconfig.json +1 -1
  62. package/package.json +2 -3
  63. package/web/assets/{abnfDiagram-VRR7QNED-Bgfb1nEB.js → abnfDiagram-VRR7QNED-xd_g1uK3.js} +1 -1
  64. package/web/assets/app-CX20nNIa.js +2 -0
  65. package/web/assets/{app-options-D-RJiQ-X.js → app-options-CkPJE5ep.js} +1 -1
  66. package/web/assets/{app-view-header-BLvLq02T.js → app-view-header-CNk5KnA-.js} +1 -1
  67. package/web/assets/{arc-Dk_KI36B.js → arc-B0u5yBJA.js} +1 -1
  68. package/web/assets/{architectureDiagram-ZJ3FMSHR-NR_KhRCf.js → architectureDiagram-ZJ3FMSHR-DfxOAo8P.js} +1 -1
  69. package/web/assets/{ask-tray-TzeTcO6-.js → ask-tray-SscJecDY.js} +1 -1
  70. package/web/assets/{blockDiagram-677ZJIJ3-CkLkwx9C.js → blockDiagram-677ZJIJ3-Ci3Usxh6.js} +1 -1
  71. package/web/assets/{c4Diagram-LMCZKHZV-CFCUH8e_.js → c4Diagram-LMCZKHZV-BqgwIVgh.js} +1 -1
  72. package/web/assets/channel-X7WHyxxT.js +1 -0
  73. package/web/assets/{chunk-2Q5K7J3B-B_BPLWsW.js → chunk-2Q5K7J3B-CfX69l2U.js} +1 -1
  74. package/web/assets/{chunk-32BRIVSS-B1VB1hOy.js → chunk-32BRIVSS-CuFlzZkl.js} +1 -1
  75. package/web/assets/{chunk-5VM5RSS4-KFcYr8Co.js → chunk-5VM5RSS4-DidCMlJa.js} +1 -1
  76. package/web/assets/{chunk-EX3LRPZG-CpBX3kuK.js → chunk-EX3LRPZG-B5CDm1dS.js} +1 -1
  77. package/web/assets/{chunk-JWPE2WC7-BPSl40wG.js → chunk-JWPE2WC7-D5fGV_sH.js} +1 -1
  78. package/web/assets/{chunk-MOJQB5TN-D2RcYmoU.js → chunk-MOJQB5TN-ayhH5Q-H.js} +1 -1
  79. package/web/assets/{chunk-RYQCIY6F-m7Gyn-t3.js → chunk-RYQCIY6F-C4BfOOZn.js} +1 -1
  80. package/web/assets/{chunk-V7JOEXUC-TDvdopxS.js → chunk-V7JOEXUC-DpUEIM9V.js} +1 -1
  81. package/web/assets/{chunk-VR4S4FIN-DZTsG51a.js → chunk-VR4S4FIN-DoQuFFRh.js} +1 -1
  82. package/web/assets/{chunk-XXDRQBXY-Dp0--RE2.js → chunk-XXDRQBXY-CI9eiLwn.js} +1 -1
  83. package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +1 -0
  84. package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +1 -0
  85. package/web/assets/client-7OWw5kW2.js +6 -0
  86. package/web/assets/client-DYj_td4Q.js +17 -0
  87. package/web/assets/{client-j2kQmxsO.js → client-Dk-NBvJR.js} +4 -4
  88. package/web/assets/command-zkzH4hVz.js +38 -0
  89. package/web/assets/{copy-context-C0Uqsp-3.js → copy-context-D5oiWrYC.js} +1 -1
  90. package/web/assets/{cose-bilkent-JH36ORCC-CPu3PI8h.js → cose-bilkent-JH36ORCC-BHRk1mO3.js} +1 -1
  91. package/web/assets/{cynefin-VYW2F7L2-DWxftYAm.js → cynefin-VYW2F7L2-C1B09TRE.js} +1 -1
  92. package/web/assets/{cynefinDiagram-TSTJHNR4-DsmN2V-p.js → cynefinDiagram-TSTJHNR4-B27qXQbv.js} +1 -1
  93. package/web/assets/{dagre-VKFMJZFB-COEbApyY.js → dagre-VKFMJZFB-B1qEi32g.js} +1 -1
  94. package/web/assets/{diagram-FQU43EPY-0O9WGWKB.js → diagram-FQU43EPY-BMkkgADD.js} +1 -1
  95. package/web/assets/{diagram-G47NLZAW-CutEdMVh.js → diagram-G47NLZAW-Cb8_g1A5.js} +1 -1
  96. package/web/assets/{diagram-NH7WQ7WH-C9KZc3B2.js → diagram-NH7WQ7WH-B51wuc5m.js} +1 -1
  97. package/web/assets/{diagram-OA4YK3LP-D8kkPXbY.js → diagram-OA4YK3LP-xnsecbbI.js} +1 -1
  98. package/web/assets/{diagram-WEI45ONY-_YqiTaGP.js → diagram-WEI45ONY-DSZdyaAV.js} +1 -1
  99. package/web/assets/{document-Dgt5eZFj.js → document-Dc2dftTW.js} +3 -3
  100. package/web/assets/{ebnfDiagram-CCIWWBDH-JO-zQh6g.js → ebnfDiagram-CCIWWBDH-aTHmcUGy.js} +1 -1
  101. package/web/assets/{entities-C3wz7FCx.js → entities-CCUtpskY.js} +1 -1
  102. package/web/assets/{erDiagram-Q63AITRT-9UjQwJ4P.js → erDiagram-Q63AITRT-CUUPBcvo.js} +1 -1
  103. package/web/assets/{file-viewer-DZJ8nYnl.js → file-viewer-DJ3rsmef.js} +1 -1
  104. package/web/assets/{flowDiagram-23GEKE2U-Ca08tnYM.js → flowDiagram-23GEKE2U-aTQXx2Mh.js} +1 -1
  105. package/web/assets/{folder-image-BfGgxo7i.js → folder-image-Bnv43tzP.js} +1 -1
  106. package/web/assets/{folder-landing-qUKBCnG-.js → folder-landing-DCnzYXXY.js} +1 -1
  107. package/web/assets/{folder-list-BfFjv7rR.js → folder-list-DvVkVjiR.js} +1 -1
  108. package/web/assets/{folder-metadata-DCw8xzHk.js → folder-metadata-C9hMMzIH.js} +1 -1
  109. package/web/assets/{folder-mobile-bar-Ubz4babf.js → folder-mobile-bar-VoTL1GS0.js} +1 -1
  110. package/web/assets/folder-plugin-view-Cvd804ZU.js +6 -0
  111. package/web/assets/{ganttDiagram-NO4QXBWP-KnHzX5W3.js → ganttDiagram-NO4QXBWP-DiwdUp7u.js} +1 -1
  112. package/web/assets/{gitGraphDiagram-IHSO6WYX-Cm8woNtK.js → gitGraphDiagram-IHSO6WYX-BL2gG_IS.js} +1 -1
  113. package/web/assets/{index-CNyy98F8.js → index-CUTtMSyJ.js} +2 -2
  114. package/web/assets/index-CegvVQ1C.js +1 -0
  115. package/web/assets/index-Dwhf8F_U.css +1 -0
  116. package/web/assets/{infoDiagram-FWYZ7A6U-yyqmUtIb.js → infoDiagram-FWYZ7A6U-B3n0zZpt.js} +1 -1
  117. package/web/assets/{ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js → ishikawaDiagram-FXEZZL3T-D7YytbEv.js} +1 -1
  118. package/web/assets/{journeyDiagram-5HDEW3XC-BKuw06HM.js → journeyDiagram-5HDEW3XC-BYwqEl3C.js} +1 -1
  119. package/web/assets/{kanban-definition-HUTT4EX6-n0010rmQ.js → kanban-definition-HUTT4EX6-BQHNJgXZ.js} +1 -1
  120. package/web/assets/{linear-C0d0lT8O.js → linear-BPiQCLNk.js} +1 -1
  121. package/web/assets/{mermaid.core-BDVbShyO.js → mermaid.core-CD-KvBjV.js} +4 -4
  122. package/web/assets/{metadata-KV0dpp4G.js → metadata-COJ7fZul.js} +1 -1
  123. package/web/assets/{mindmap-definition-LN4V7U3C--_0ks3GF.js → mindmap-definition-LN4V7U3C-C1L_gyoj.js} +1 -1
  124. package/web/assets/{pegDiagram-2B236MQR-CBoNIpKR.js → pegDiagram-2B236MQR-BDAfItqS.js} +1 -1
  125. package/web/assets/{pieDiagram-ENE6RG2P-MA5tkYh5.js → pieDiagram-ENE6RG2P-CkZYH3Vz.js} +1 -1
  126. package/web/assets/{popover-DBD7FF-W.js → popover-0oA2lLUV.js} +2 -2
  127. package/web/assets/{project-search-dialog-DM1IkSZu.js → project-search-dialog-B2oqMT6h.js} +1 -1
  128. package/web/assets/{quadrantDiagram-ABIIQ3AL-CWT1ryqF.js → quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js} +1 -1
  129. package/web/assets/{railroadDiagram-RFXS5EU6-ZiLB5FGi.js → railroadDiagram-RFXS5EU6-Dd9_yo7B.js} +1 -1
  130. package/web/assets/{requirementDiagram-TGXJPOKE-CQq9uneq.js → requirementDiagram-TGXJPOKE-DPhIUsbs.js} +1 -1
  131. package/web/assets/{sankeyDiagram-HTMAVEWB-qDG-0JqI.js → sankeyDiagram-HTMAVEWB-B2QkYtub.js} +1 -1
  132. package/web/assets/{search-DNrQA5fF.js → search-C1J0-xiB.js} +1 -1
  133. package/web/assets/select-CtXC_PLC.js +30 -0
  134. package/web/assets/{selection-popup-DmtTeRs2.js → selection-popup-qhlUFzGq.js} +1 -1
  135. package/web/assets/{sequenceDiagram-DBY2YBRQ-CiApurLO.js → sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js} +1 -1
  136. package/web/assets/{sizeCapture-X5ZJPWSS-DZSR5QXm.js → sizeCapture-X5ZJPWSS-CIXIhl_A.js} +1 -1
  137. package/web/assets/{stateDiagram-2N3HPSRC-CjJJR9_z.js → stateDiagram-2N3HPSRC-DCrdAflB.js} +1 -1
  138. package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +1 -0
  139. package/web/assets/{swimlanes-5IMT3BWC-CKmo1sg6.js → swimlanes-5IMT3BWC-DA2vc7iZ.js} +2 -2
  140. package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +8 -0
  141. package/web/assets/{timeline-definition-FHXFAJF6-D-NMwS3y.js → timeline-definition-FHXFAJF6-lKfJiV9V.js} +1 -1
  142. package/web/assets/{vennDiagram-L72KCM5P-CfL6LBWw.js → vennDiagram-L72KCM5P-DO1q2KzG.js} +1 -1
  143. package/web/assets/{view-context-gyDl_p2V.js → view-context-DXKM3-l1.js} +4 -4
  144. package/web/assets/{viewer-capabilities-Bpp8Uvcg.js → viewer-capabilities-Cig_xM9u.js} +1 -1
  145. package/web/assets/{wardleyDiagram-EHGQE667-DgldMxaj.js → wardleyDiagram-EHGQE667-Dal9LkuZ.js} +1 -1
  146. package/web/assets/{xychartDiagram-FW5EYKEG-CIoAIFX8.js → xychartDiagram-FW5EYKEG-B3dPLPII.js} +1 -1
  147. package/web/index.html +2 -2
  148. package/kernel/packages/api/test/partial-loading.test.ts +0 -43
  149. package/kernel/packages/folder-plugin/package.json +0 -50
  150. package/kernel/packages/folder-plugin/src/index.ts +0 -15
  151. package/kernel/packages/folder-plugin/tsconfig.json +0 -17
  152. package/kernel/plugins/calendar/SKILL.md +0 -173
  153. package/kernel/plugins/calendar/eslint.config.js +0 -10
  154. package/kernel/plugins/calendar/package.json +0 -73
  155. package/kernel/plugins/calendar/schema.json +0 -137
  156. package/kernel/plugins/calendar/src/calendar.tsx +0 -328
  157. package/kernel/plugins/calendar/src/client.tsx +0 -139
  158. package/kernel/plugins/calendar/src/context.ts +0 -48
  159. package/kernel/plugins/calendar/src/copy-button.tsx +0 -66
  160. package/kernel/plugins/calendar/src/event-dialog.tsx +0 -270
  161. package/kernel/plugins/calendar/src/index.ts +0 -4
  162. package/kernel/plugins/calendar/src/manifest.ts +0 -7
  163. package/kernel/plugins/calendar/src/parse.ts +0 -610
  164. package/kernel/plugins/calendar/src/server.ts +0 -160
  165. package/kernel/plugins/calendar/src/utils.ts +0 -80
  166. package/kernel/plugins/calendar/src/views.tsx +0 -418
  167. package/kernel/plugins/calendar/test/context.test.mjs +0 -60
  168. package/kernel/plugins/calendar/test/package.test.mjs +0 -43
  169. package/kernel/plugins/calendar/test/parse.test.mjs +0 -392
  170. package/kernel/plugins/calendar/test/server.test.mjs +0 -126
  171. package/kernel/plugins/calendar/tsconfig.json +0 -17
  172. package/kernel/plugins/mail/SKILL.md +0 -97
  173. package/kernel/plugins/mail/eslint.config.js +0 -10
  174. package/kernel/plugins/mail/src/api.ts +0 -359
  175. package/kernel/plugins/mail/src/bun-ffi.d.ts +0 -14
  176. package/kernel/plugins/mail/src/client.tsx +0 -14
  177. package/kernel/plugins/mail/src/flock.ts +0 -137
  178. package/kernel/plugins/mail/src/folders.ts +0 -37
  179. package/kernel/plugins/mail/src/history.ts +0 -485
  180. package/kernel/plugins/mail/src/index.ts +0 -3
  181. package/kernel/plugins/mail/src/mail-card.tsx +0 -123
  182. package/kernel/plugins/mail/src/mail-conversation.tsx +0 -153
  183. package/kernel/plugins/mail/src/mail-detail-page.tsx +0 -467
  184. package/kernel/plugins/mail/src/mail-hooks.ts +0 -252
  185. package/kernel/plugins/mail/src/mail-page.tsx +0 -109
  186. package/kernel/plugins/mail/src/mail-request.ts +0 -78
  187. package/kernel/plugins/mail/src/mail-send-box.tsx +0 -175
  188. package/kernel/plugins/mail/src/mailos.ts +0 -723
  189. package/kernel/plugins/mail/src/manifest.ts +0 -7
  190. package/kernel/plugins/mail/src/node.ts +0 -171
  191. package/kernel/plugins/mail/src/parse.ts +0 -139
  192. package/kernel/plugins/mail/src/server.ts +0 -125
  193. package/kernel/plugins/mail/src/types.ts +0 -10
  194. package/kernel/plugins/mail/src/viewer.tsx +0 -147
  195. package/kernel/plugins/mail/test/flock.test.mjs +0 -156
  196. package/kernel/plugins/mail/test/folders.test.mjs +0 -138
  197. package/kernel/plugins/mail/test/history.test.mjs +0 -460
  198. package/kernel/plugins/mail/test/mailos.test.mjs +0 -752
  199. package/kernel/plugins/mail/test/node.test.mjs +0 -207
  200. package/kernel/plugins/mail/test/package.test.mjs +0 -54
  201. package/kernel/plugins/mail/test/parse.test.mjs +0 -32
  202. package/kernel/plugins/mail/test/server.test.mjs +0 -116
  203. package/kernel/plugins/mail/test/viewer.test.mjs +0 -192
  204. package/kernel/plugins/mail/tsconfig.json +0 -17
  205. package/kernel/plugins/projects/SKILL.md +0 -73
  206. package/kernel/plugins/projects/eslint.config.js +0 -10
  207. package/kernel/plugins/projects/package.json +0 -70
  208. package/kernel/plugins/projects/src/client.tsx +0 -17
  209. package/kernel/plugins/projects/src/data/model.ts +0 -129
  210. package/kernel/plugins/projects/src/index.ts +0 -17
  211. package/kernel/plugins/projects/src/manifest.ts +0 -7
  212. package/kernel/plugins/projects/src/project-context.ts +0 -41
  213. package/kernel/plugins/projects/src/server.ts +0 -276
  214. package/kernel/plugins/projects/src/ui/project-card.tsx +0 -61
  215. package/kernel/plugins/projects/src/ui/projects-page.tsx +0 -102
  216. package/kernel/plugins/projects/test/package.test.mjs +0 -51
  217. package/kernel/plugins/tasks/SKILL.md +0 -341
  218. package/kernel/plugins/tasks/eslint.config.js +0 -10
  219. package/kernel/plugins/tasks/package.json +0 -74
  220. package/kernel/plugins/tasks/schema.json +0 -939
  221. package/kernel/plugins/tasks/src/api.ts +0 -212
  222. package/kernel/plugins/tasks/src/client.tsx +0 -23
  223. package/kernel/plugins/tasks/src/data/parse.ts +0 -544
  224. package/kernel/plugins/tasks/src/data/task-id.ts +0 -56
  225. package/kernel/plugins/tasks/src/data/todo-model.ts +0 -795
  226. package/kernel/plugins/tasks/src/index.ts +0 -34
  227. package/kernel/plugins/tasks/src/manifest.ts +0 -7
  228. package/kernel/plugins/tasks/src/pages/task-detail.tsx +0 -48
  229. package/kernel/plugins/tasks/src/pages/task-list.tsx +0 -88
  230. package/kernel/plugins/tasks/src/server.ts +0 -447
  231. package/kernel/plugins/tasks/src/styles.css +0 -9
  232. package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +0 -372
  233. package/kernel/plugins/tasks/src/ui/error-details.tsx +0 -78
  234. package/kernel/plugins/tasks/src/ui/task-page.tsx +0 -392
  235. package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +0 -36
  236. package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +0 -66
  237. package/kernel/plugins/tasks/src/ui/todo-item.tsx +0 -494
  238. package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +0 -60
  239. package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +0 -48
  240. package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +0 -106
  241. package/kernel/plugins/tasks/test/api.test.mjs +0 -99
  242. package/kernel/plugins/tasks/test/folder-sources.test.mjs +0 -46
  243. package/kernel/plugins/tasks/test/package.test.mjs +0 -54
  244. package/kernel/plugins/tasks/test/parse.test.mjs +0 -225
  245. package/kernel/plugins/tasks/test/server.test.mjs +0 -386
  246. package/kernel/plugins/tasks/tsconfig.json +0 -17
  247. package/web/assets/app-DoGr2Zi7.js +0 -2
  248. package/web/assets/channel-uMEjV8qc.js +0 -1
  249. package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +0 -1
  250. package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +0 -1
  251. package/web/assets/client-C6Nxdfif.js +0 -2
  252. package/web/assets/client-CXYfBko5.js +0 -17
  253. package/web/assets/client-CoKtOq-X.js +0 -7
  254. package/web/assets/client-DyRQz5RU.js +0 -53
  255. package/web/assets/client-OY6HUzuD.js +0 -98
  256. package/web/assets/client-YOYWZIFi.js +0 -34
  257. package/web/assets/command-BugZBGXE.js +0 -38
  258. package/web/assets/folder-plugin-view-DsWR1zmQ.js +0 -6
  259. package/web/assets/index-BaRnbYRw.js +0 -1
  260. package/web/assets/index-BexmLxIP.css +0 -1
  261. package/web/assets/index-DDirZMgx.js +0 -1
  262. package/web/assets/note-card-DBfX6gW1.js +0 -6
  263. package/web/assets/select-D8cqNgcp.js +0 -30
  264. package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +0 -1
  265. package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +0 -8
  266. package/web/assets/use-folder-filter-LQyXns5Q.js +0 -1
  267. /package/kernel/packages/{folder-plugin → plugins}/eslint.config.js +0 -0
  268. /package/kernel/packages/{folder-plugin → plugins}/src/client.ts +0 -0
  269. /package/kernel/packages/{folder-plugin → plugins}/src/endpoint.ts +0 -0
  270. /package/kernel/packages/{folder-plugin → plugins}/src/server.ts +0 -0
  271. /package/kernel/packages/{folder-plugin → plugins}/src/subpath.ts +0 -0
  272. /package/kernel/packages/{folder-plugin → plugins}/src/types.ts +0 -0
  273. /package/kernel/packages/{folder-plugin → plugins}/src/validation.ts +0 -0
  274. /package/kernel/packages/{folder-plugin → plugins}/test/contract.test.mjs +0 -0
@@ -1,252 +0,0 @@
1
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
2
-
3
- import { folderPathId } from "@raggle-ai/folder-plugin/client"
4
-
5
- import { mailRequest } from "./mail-request.js"
6
-
7
- export type MailListResponse = {
8
- folder: string
9
- items: MailListItemPayload[]
10
- }
11
-
12
- export type MailListItemPayload = {
13
- attachments: string[]
14
- bcc: string[]
15
- cc: string[]
16
- createdAt: string | null
17
- excerpt: string
18
- filePath: string
19
- folder: string | null
20
- from: string | null
21
- id: string
22
- inReplyTo: string | null
23
- references: string[]
24
- revision: string
25
- status: string | null
26
- subject: string | null
27
- tags: string[]
28
- to: string[]
29
- updatedAt: string | null
30
- noSignature: boolean
31
- }
32
-
33
- export type MailDetailPayload = Omit<MailListItemPayload, "excerpt"> & {
34
- body: string
35
- }
36
-
37
- export type MailSenderPayload = {
38
- from: string | null
39
- name: string | null
40
- ok: boolean
41
- }
42
-
43
- export type ConversationMessagePayload = {
44
- body: string
45
- date: string | null
46
- from: string | null
47
- id: string
48
- subject: string | null
49
- to: string | null
50
- }
51
-
52
- export type ConversationOutcome =
53
- "empty" | "ok" | "partial" | "not-found" | "timeout"
54
-
55
- export type ConversationPayload = {
56
- items: ConversationMessagePayload[]
57
- missing: string[]
58
- outcome: ConversationOutcome
59
- }
60
-
61
- export type MailSendPreviewPayload = {
62
- dryRun: true
63
- output: string
64
- revision: string
65
- }
66
-
67
- export type MailSendResultPayload = {
68
- dryRun: false
69
- output: string
70
- }
71
-
72
- function mailPath(folder: string | null | undefined) {
73
- return { path: folder ?? "" }
74
- }
75
-
76
- function folderCacheKey(folder: string | null | undefined) {
77
- return ["folder", folder ? folderPathId(folder) : "none", "mail"] as const
78
- }
79
-
80
- export function useMailList(folder: string | null | undefined) {
81
- return useQuery({
82
- enabled: Boolean(folder),
83
- gcTime: 5 * 60_000,
84
- queryFn: ({ signal }) =>
85
- mailRequest<MailListResponse>("/api/mail", {
86
- search: mailPath(folder),
87
- signal,
88
- }),
89
- queryKey: [...folderCacheKey(folder)],
90
- staleTime: 15_000,
91
- })
92
- }
93
-
94
- export type MailPreviewPayload = {
95
- body: string
96
- signature: string | null
97
- }
98
-
99
- export type MailDetailResponsePayload = {
100
- mail: MailDetailPayload
101
- preview?: MailPreviewPayload
102
- }
103
-
104
- export function useMailDetail(
105
- folder: string | null | undefined,
106
- mailId: string | null | undefined,
107
- ) {
108
- return useQuery<MailDetailResponsePayload>({
109
- enabled: Boolean(folder && mailId),
110
- gcTime: 5 * 60_000,
111
- queryFn: ({ signal }) =>
112
- mailRequest<MailDetailResponsePayload>("/api/mail/item", {
113
- search: { ...mailPath(folder), id: mailId ?? "" },
114
- signal,
115
- }),
116
- queryKey: [...folderCacheKey(folder), mailId ?? ""],
117
- retry: false,
118
- staleTime: 15_000,
119
- })
120
- }
121
-
122
- /** Lazy sender resolution: runs only when the draft has no recorded From. */
123
- export function useMailSender(
124
- folder: string | null | undefined,
125
- mailId: string | null | undefined,
126
- enabled: boolean,
127
- ) {
128
- return useQuery({
129
- enabled: Boolean(enabled && mailId),
130
- gcTime: 5 * 60_000,
131
- queryFn: ({ signal }) =>
132
- mailRequest<MailSenderPayload>("/api/mail/from", {
133
- search: { ...mailPath(folder), id: mailId ?? "" },
134
- signal,
135
- }),
136
- queryKey: [...folderCacheKey(folder), mailId ?? "", "from"],
137
- retry: false,
138
- staleTime: 15_000,
139
- })
140
- }
141
-
142
- export function useMailConversation(
143
- folder: string | null | undefined,
144
- mailId: string | null | undefined,
145
- enabled: boolean,
146
- ) {
147
- return useQuery<ConversationPayload>({
148
- enabled: Boolean(enabled && mailId),
149
- gcTime: 5 * 60_000,
150
- queryFn: ({ signal }) =>
151
- mailRequest<ConversationPayload>("/api/mail/conversation", {
152
- search: { ...mailPath(folder), id: mailId ?? "" },
153
- signal,
154
- }),
155
- queryKey: [...folderCacheKey(folder), mailId ?? "", "conversation"],
156
- retry: false,
157
- staleTime: 5 * 60_000,
158
- })
159
- }
160
-
161
- export type MailActionInput = {
162
- action: "archive" | "delete" | "remove-attachment"
163
- id: string
164
- path: string
165
- revision: string
166
- /** Absolute attachment path; used only with the remove-attachment action. */
167
- attachment?: string
168
- }
169
-
170
- export function useMailAction(folder: string | null | undefined) {
171
- const queryClient = useQueryClient()
172
- return useMutation({
173
- mutationFn: (input: MailActionInput) =>
174
- mailRequest<{ action: string; id: string; ok: true }>(
175
- "/api/mail/action",
176
- {
177
- body: input,
178
- method: "POST",
179
- },
180
- ),
181
- onSuccess: () => {
182
- void queryClient.invalidateQueries({
183
- queryKey: [...folderCacheKey(folder)],
184
- })
185
- },
186
- })
187
- }
188
-
189
- export function useMailSend(folder: string | null | undefined) {
190
- const queryClient = useQueryClient()
191
- return useMutation({
192
- mutationFn: (input: { dryRun: boolean; id: string; revision?: string }) =>
193
- mailRequest<MailSendPreviewPayload | MailSendResultPayload>(
194
- "/api/mail/send",
195
- {
196
- body: { path: folder ?? "", ...input },
197
- method: "POST",
198
- },
199
- ),
200
- onSuccess: () => {
201
- void queryClient.invalidateQueries({
202
- queryKey: [...folderCacheKey(folder)],
203
- })
204
- },
205
- })
206
- }
207
-
208
- export type ConversationPanelState =
209
- | { variant: "hidden" }
210
- | { variant: "loading" }
211
- | { variant: "error"; message: string }
212
- | { variant: "empty" }
213
- | { variant: "ok" }
214
- | { variant: "partial"; missing: number }
215
- | { variant: "not-found" }
216
- | { variant: "timeout" }
217
-
218
- /**
219
- * Pure mapping from the conversation query to a UI state. A disabled query
220
- * (no references, or the detail still loading) is "hidden" — never an
221
- * endless loading spinner.
222
- */
223
- export function conversationPanelState(input: {
224
- data?: ConversationPayload
225
- enabled: boolean
226
- error: unknown
227
- isPending: boolean
228
- }): ConversationPanelState {
229
- if (!input.enabled) return { variant: "hidden" }
230
- if (input.isPending && !input.data) return { variant: "loading" }
231
- if (input.error && !input.data) {
232
- const message =
233
- input.error instanceof Error
234
- ? input.error.message
235
- : "Could not load the conversation."
236
- return { variant: "error", message }
237
- }
238
- switch (input.data?.outcome) {
239
- case "empty":
240
- return { variant: "empty" }
241
- case "ok":
242
- return input.data.items.length ? { variant: "ok" } : { variant: "empty" }
243
- case "partial":
244
- return { variant: "partial", missing: input.data.missing.length }
245
- case "not-found":
246
- return { variant: "not-found" }
247
- case "timeout":
248
- return { variant: "timeout" }
249
- default:
250
- return { variant: "hidden" }
251
- }
252
- }
@@ -1,109 +0,0 @@
1
- import { RefreshCw } from "lucide-react"
2
-
3
- import type { FolderPluginViewProps } from "@raggle-ai/folder-plugin/client"
4
- import { folderLabel } from "@raggle-ai/mail/folders"
5
- import {
6
- MailFolderFilter,
7
- mailItemContext,
8
- MailList,
9
- } from "@raggle-ai/mail/viewer"
10
- import { CopyContextButton } from "@raggle-ai/ui/components/copy-context"
11
- import { useFolderFilter } from "@raggle-ai/ui/hooks/use-folder-filter"
12
-
13
- import { useMailList } from "./mail-hooks.js"
14
- import { mailErrorText } from "./mail-request.js"
15
-
16
- export function MailPage({
17
- folder,
18
- href,
19
- }: Pick<FolderPluginViewProps, "folder" | "href">) {
20
- const query = useMailList(folder)
21
-
22
- const items = query.data?.items ?? []
23
- const hasItems = Boolean(query.data?.items.length)
24
- // Shared folder-filter state: derives the chips from the drafts' owning
25
- // folders and filters the list. A selection whose folder no longer has
26
- // drafts falls back to All folders rather than showing a dead-end list.
27
- const { choices, effectiveSelected, setSelected, total, visibleItems } =
28
- useFolderFilter(items, {
29
- getFolder: (item) => item.folder,
30
- rootFolder: folder ?? "",
31
- })
32
-
33
- if (!folder) {
34
- return (
35
- <div
36
- className="mx-auto grid w-full max-w-3xl min-w-0 grid-cols-1 gap-4 px-4
37
- py-5"
38
- >
39
- <p className="m-0 text-sm text-[#6c7a6d]">Open mail from a folder.</p>
40
- </div>
41
- )
42
- }
43
-
44
- return (
45
- <div
46
- className="mx-auto grid w-full max-w-3xl min-w-0 grid-cols-1 gap-4 px-4
47
- py-5"
48
- >
49
- <div className="flex flex-wrap items-center justify-between gap-3">
50
- <h1 className="m-0 text-2xl font-semibold text-[#233025]">Mail</h1>
51
- <button
52
- type="button"
53
- className="inline-flex items-center gap-2 rounded-md border px-3
54
- py-1.5 text-sm disabled:pointer-events-none disabled:opacity-50"
55
- onClick={() => void query.refetch()}
56
- disabled={query.isFetching}
57
- >
58
- <RefreshCw
59
- className={query.isFetching ? "size-4 animate-spin" : "size-4"}
60
- />
61
- Refresh
62
- </button>
63
- </div>
64
-
65
- {hasItems ? (
66
- <MailFolderFilter
67
- choices={choices}
68
- onSelect={setSelected}
69
- selected={effectiveSelected}
70
- total={total}
71
- />
72
- ) : null}
73
-
74
- {query.isPending ? (
75
- <p className="m-0 text-sm text-[#6c7a6d]">Loading…</p>
76
- ) : null}
77
- {query.error ? (
78
- <p className="m-0 text-sm text-[#9c3a3a]">
79
- {mailErrorText(query.error)}
80
- </p>
81
- ) : null}
82
-
83
- {!query.isPending && !query.error && !query.data?.items.length ? (
84
- <p className="m-0 text-sm text-[#6c7a6d]">No mail found.</p>
85
- ) : null}
86
-
87
- {hasItems ? (
88
- visibleItems.length ? (
89
- <MailList
90
- actions={(item) => (
91
- <CopyContextButton
92
- className="text-[#6c7a6d] hover:text-[#2f382f]"
93
- context={() => mailItemContext(item)}
94
- label={`Copy context for ${item.subject ?? "this draft"}`}
95
- />
96
- )}
97
- folderLabel={(mailFolder) => folderLabel(mailFolder, folder)}
98
- items={visibleItems}
99
- mailHref={href}
100
- />
101
- ) : (
102
- <p className="m-0 text-sm text-[#6c7a6d]">
103
- No drafts in this folder.
104
- </p>
105
- )
106
- ) : null}
107
- </div>
108
- )
109
- }
@@ -1,78 +0,0 @@
1
- export type MailRequestOptions = {
2
- body?: unknown
3
- method?: "GET" | "POST" | "DELETE"
4
- search?: Record<string, string | undefined>
5
- signal?: AbortSignal
6
- }
7
-
8
- export class MailRequestFailure extends Error {
9
- readonly status: number
10
-
11
- constructor(status: number, message: string) {
12
- super(message)
13
- this.name = "MailRequestFailure"
14
- this.status = status
15
- }
16
- }
17
-
18
- function structuredMessage(text: string) {
19
- try {
20
- const parsed = JSON.parse(text) as {
21
- error?: { code?: string; message?: string }
22
- }
23
- if (parsed.error?.message) return parsed.error.message
24
- } catch {
25
- // Non-JSON error bodies fall back to the raw text.
26
- }
27
- return text.trim() || "Mail request failed."
28
- }
29
-
30
- /**
31
- * Shared typed request helper for the mail API. GET requests never carry a
32
- * body (the server forbids mutations over GET); mutations send JSON which the
33
- * server's same-origin guard accepts only for same-site pages. JSON responses
34
- * are enforced and structured server errors become readable messages.
35
- */
36
- export async function mailRequest<T>(
37
- path: string,
38
- options: MailRequestOptions = {},
39
- ): Promise<T> {
40
- const search = new URLSearchParams()
41
- for (const [key, value] of Object.entries(options.search ?? {})) {
42
- if (value !== undefined) search.set(key, value)
43
- }
44
- const query = search.toString()
45
- const url = `${path}${query ? `?${query}` : ""}`
46
-
47
- const headers: Record<string, string> = {}
48
- let body: string | undefined
49
- if (options.body !== undefined) {
50
- headers["content-type"] = "application/json"
51
- body = JSON.stringify(options.body)
52
- }
53
-
54
- const response = await fetch(url, {
55
- body,
56
- headers,
57
- method: options.method ?? "GET",
58
- signal: options.signal,
59
- })
60
-
61
- const text = await response.text()
62
- if (!response.ok) {
63
- throw new MailRequestFailure(response.status, structuredMessage(text))
64
- }
65
- if (!response.headers.get("content-type")?.includes("application/json")) {
66
- throw new MailRequestFailure(
67
- response.status,
68
- "The server returned a non-JSON response.",
69
- )
70
- }
71
- return JSON.parse(text) as T
72
- }
73
-
74
- export function mailErrorText(error: unknown) {
75
- if (error instanceof MailRequestFailure) return error.message
76
- if (error instanceof Error) return error.message
77
- return "Mail request failed."
78
- }
@@ -1,175 +0,0 @@
1
- import { useEffect, useState } from "react"
2
- import { CheckCircle2, Loader2, Send, XCircle } from "lucide-react"
3
-
4
- import type { MailSendPreviewPayload } from "./mail-hooks.js"
5
- import { useMailSend } from "./mail-hooks.js"
6
- import { mailErrorText } from "./mail-request.js"
7
-
8
- type SendPhase =
9
- "idle" | "previewing" | "confirm" | "sending" | "sent" | "failed"
10
-
11
- /**
12
- * The preview-then-confirm send flow for one draft. State resets when the
13
- * active draft changes so navigation never carries a stale preview, and every
14
- * action disables the buttons while a request is in flight (double
15
- * submissions cannot start a send twice).
16
- */
17
- export function MailSendBox({
18
- folder,
19
- mailId,
20
- status,
21
- }: {
22
- folder: string | null | undefined
23
- mailId: string | null | undefined
24
- status: string | null | undefined
25
- }) {
26
- const [phase, setPhase] = useState<SendPhase>("idle")
27
- const [preview, setPreview] = useState<MailSendPreviewPayload | null>(null)
28
- const [error, setError] = useState<string | null>(null)
29
- const send = useMailSend(folder)
30
-
31
- useEffect(() => {
32
- setPhase("idle")
33
- setPreview(null)
34
- setError(null)
35
- }, [mailId])
36
-
37
- const pending =
38
- send.isPending || phase === "previewing" || phase === "sending"
39
-
40
- async function runPreview() {
41
- if (!mailId || pending) return
42
- setError(null)
43
- setPhase("previewing")
44
- try {
45
- const result = await send.mutateAsync({ dryRun: true, id: mailId })
46
- if (!("revision" in result)) {
47
- throw new Error("MailOS did not return a revision.")
48
- }
49
- setPreview(result)
50
- setPhase("confirm")
51
- } catch (cause) {
52
- setError(mailErrorText(cause))
53
- setPhase("failed")
54
- }
55
- }
56
-
57
- async function runSend() {
58
- if (!mailId || !preview || pending) return
59
- setError(null)
60
- setPhase("sending")
61
- try {
62
- await send.mutateAsync({
63
- dryRun: false,
64
- id: mailId,
65
- revision: preview.revision,
66
- })
67
- setPhase("sent")
68
- } catch (cause) {
69
- setError(mailErrorText(cause))
70
- setPhase("failed")
71
- }
72
- }
73
-
74
- return (
75
- <div
76
- className="rounded-xl border border-[#e7ebe7] bg-white px-4 py-3
77
- shadow-[0_1px_2px_rgb(31_41_55/0.05)]"
78
- >
79
- {phase === "idle" ? (
80
- <div className="flex flex-wrap items-center gap-3">
81
- <button
82
- type="button"
83
- className="inline-flex w-fit items-center gap-2 rounded-md
84
- bg-[#395641] px-3 py-1.5 text-sm text-white hover:bg-[#2f4b38]
85
- disabled:pointer-events-none disabled:opacity-50"
86
- onClick={() => void runPreview()}
87
- disabled={status === "sent" || pending}
88
- >
89
- <Send className="size-4" />
90
- {status === "sent" ? "Already sent" : "Send"}
91
- </button>
92
- <span className="text-[0.82rem] text-[#6c7a6d]">
93
- Will preview for confirmation before delivering.
94
- </span>
95
- </div>
96
- ) : null}
97
-
98
- {phase === "previewing" || phase === "sending" ? (
99
- <p className="m-0 flex items-center gap-2 text-sm text-[#4a554b]">
100
- <Loader2 className="size-4 animate-spin" />
101
- {phase === "previewing" ? "Previewing…" : "Sending…"}
102
- </p>
103
- ) : null}
104
-
105
- {phase === "confirm" && preview ? (
106
- <div className="grid gap-3">
107
- <p className="m-0 text-sm text-[#4a554b]">
108
- Ready to send this draft to its recipients.
109
- </p>
110
- <div className="flex flex-wrap items-center gap-2">
111
- <button
112
- type="button"
113
- className="inline-flex w-fit items-center gap-2 rounded-md
114
- bg-[#395641] px-3 py-1.5 text-sm text-white hover:bg-[#2f4b38]
115
- disabled:pointer-events-none disabled:opacity-50"
116
- onClick={() => void runSend()}
117
- disabled={pending}
118
- >
119
- <Send className="size-4" />
120
- Send now
121
- </button>
122
- <button
123
- type="button"
124
- className="w-fit rounded-md border border-[#dde1dc] bg-white px-3
125
- py-1.5 text-sm text-[#4a554b] hover:bg-[#f3f5f2]
126
- disabled:pointer-events-none disabled:opacity-50"
127
- onClick={() => {
128
- setPhase("idle")
129
- setPreview(null)
130
- }}
131
- disabled={pending}
132
- >
133
- Cancel
134
- </button>
135
- </div>
136
- <details className="text-[0.82rem] text-[#6c7a6d]">
137
- <summary className="cursor-pointer">Preview output</summary>
138
- <pre
139
- className="mt-2 max-h-48 overflow-auto rounded-md bg-[#f3f5f2] p-2
140
- text-[0.75rem] whitespace-pre-wrap text-[#4a554b]"
141
- >
142
- {preview.output}
143
- </pre>
144
- </details>
145
- </div>
146
- ) : null}
147
-
148
- {phase === "sent" ? (
149
- <p className="m-0 flex items-center gap-2 text-sm text-[#2f5b3a]">
150
- <CheckCircle2 className="size-4" />
151
- Sent.
152
- </p>
153
- ) : null}
154
-
155
- {phase === "failed" ? (
156
- <div className="grid gap-3">
157
- <p className="m-0 flex items-center gap-2 text-sm text-[#9c3a3a]">
158
- <XCircle className="size-4 shrink-0" />
159
- <span className="break-words">{error}</span>
160
- </p>
161
- <button
162
- type="button"
163
- className="inline-flex w-fit items-center gap-2 rounded-md border
164
- border-[#dde1dc] bg-white px-3 py-1.5 text-sm text-[#4a554b]
165
- hover:bg-[#f3f5f2]"
166
- onClick={() => void runPreview()}
167
- >
168
- <Send className="size-4" />
169
- Try again
170
- </button>
171
- </div>
172
- ) : null}
173
- </div>
174
- )
175
- }