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,34 +0,0 @@
1
- export { tasksManifest } from "./manifest.ts"
2
- export type { TodoItemProps } from "./ui/todo-item.js"
3
- export type {
4
- TodoItemData,
5
- TodoItemLink,
6
- TodoItemRelation,
7
- TodoItemStatus,
8
- TodoItemStep,
9
- } from "./data/todo-model.js"
10
- export type {
11
- TodoDataset,
12
- TodoDatasetOptions,
13
- TodoFilter,
14
- TodoFilterSelection,
15
- TodoState,
16
- UiTodoItem,
17
- } from "./data/todo-model.js"
18
- export {
19
- decodeTodoDataset,
20
- TodoDatasetSchema,
21
- todoItems,
22
- } from "./data/todo-model.js"
23
- export type { CompactTodoListProps } from "./ui/compact-todo-list.js"
24
- export { CompactTodoList } from "./ui/compact-todo-list.js"
25
- export type { TodoFilterBarProps } from "./ui/todo-filter-bar.js"
26
- export { TodoFilterBar } from "./ui/todo-filter-bar.js"
27
- export type { TodoStatusFilterProps } from "./ui/todo-status-filter.js"
28
- export { TodoStatusFilter } from "./ui/todo-status-filter.js"
29
- export type { TodoAgentFilterProps } from "./ui/todo-agent-filter.js"
30
- export { TodoAgentFilter } from "./ui/todo-agent-filter.js"
31
- export type { TodoTagFilterProps } from "./ui/todo-tag-filter.js"
32
- export { TodoTagFilter } from "./ui/todo-tag-filter.js"
33
- export { TodoItem } from "./ui/todo-item.js"
34
- export { TodoWarningsTrigger } from "./ui/todo-warnings.tsx"
@@ -1,7 +0,0 @@
1
- import type { FolderPluginManifest } from "@raggle-ai/folder-plugin"
2
-
3
- /** Stable Tasks plugin identity and navigation label. No side effects. */
4
- export const tasksManifest: FolderPluginManifest = {
5
- id: "tasks",
6
- label: "Tasks",
7
- }
@@ -1,48 +0,0 @@
1
- import type { FolderPluginViewProps } from "@raggle-ai/folder-plugin/client"
2
-
3
- import { TaskPage, useTaskPage } from "../ui/task-page"
4
- import { TodoItem } from "../ui/todo-item"
5
- import { TodoWarningsTrigger } from "../ui/todo-warnings"
6
-
7
- /** Individual task page: the full single task behind a list row link. */
8
- export function TaskDetailPage({
9
- documentHref,
10
- folder,
11
- folderId,
12
- listHref,
13
- request,
14
- subpath,
15
- }: FolderPluginViewProps) {
16
- const page = useTaskPage({
17
- folder,
18
- folderId,
19
- noun: "task",
20
- request,
21
- subpath,
22
- })
23
-
24
- return (
25
- <TaskPage
26
- body={
27
- page.item ? (
28
- <TodoItem
29
- item={page.item}
30
- documentHref={documentHref}
31
- canToggle={!page.busy}
32
- onToggle={() => {
33
- if (subpath) page.toggle(subpath)
34
- }}
35
- />
36
- ) : undefined
37
- }
38
- extra={
39
- <div className="flex justify-end">
40
- <TodoWarningsTrigger warnings={page.data?.warnings} folder={folder} />
41
- </div>
42
- }
43
- list={{ href: listHref, name: "Tasks" }}
44
- missingMessage="Task not found."
45
- page={page}
46
- />
47
- )
48
- }
@@ -1,88 +0,0 @@
1
- import { useMemo } from "react"
2
-
3
- import type { FolderPluginViewProps } from "@raggle-ai/folder-plugin/client"
4
- import { FolderFilterBar } from "@raggle-ai/ui/components/folder-filter-bar"
5
- import { useFolderFilter } from "@raggle-ai/ui/hooks/use-folder-filter"
6
-
7
- import type { UiTodoItem } from "../data/todo-model"
8
- import { qualifiedTaskId } from "../data/task-id"
9
- import { CompactTodoList } from "../ui/compact-todo-list"
10
- import { TaskPage, useTaskPage } from "../ui/task-page"
11
- import { TodoWarningsTrigger } from "../ui/todo-warnings"
12
-
13
- /** Main Tasks page: filters, counts, and one compact row per task. */
14
- export function TaskListPage({
15
- folder,
16
- folderId,
17
- href,
18
- request,
19
- }: FolderPluginViewProps) {
20
- const page = useTaskPage({
21
- folder,
22
- folderId,
23
- noun: "tasks",
24
- request,
25
- subpath: "",
26
- })
27
- // Shared folder filter over every task: a workspace root merges nested
28
- // task files, so folder chips narrow to directories (status filtering of
29
- // the visible set happens inside the todo list).
30
- const filter = useFolderFilter(page.tasks, {
31
- getFolder: (item) => item.jsonTodo.source.id,
32
- rootFolder: folder,
33
- })
34
- const filteredDataset = useMemo(() => {
35
- if (!page.dataset) return undefined
36
- return {
37
- ...page.dataset,
38
- tasks: filter.visibleItems.map((item) => item.jsonTodo),
39
- }
40
- }, [page.dataset, filter.visibleItems])
41
- // Workspace-qualified task address: the owning folder plus the task id,
42
- // so identical file-local ids (`todo:1` in nested files) stay distinct in
43
- // detail links and toggle writes. Falls back to the bare id when the
44
- // source folder is unknown.
45
- const taskAddress = (item: UiTodoItem) =>
46
- qualifiedTaskId(item.jsonTodo.source?.id, item.jsonTodo) ??
47
- [item.id, item.key].find((value) => value)
48
-
49
- return (
50
- <TaskPage
51
- body={
52
- filteredDataset ? (
53
- <CompactTodoList
54
- dataset={filteredDataset}
55
- trailingFilters={
56
- <TodoWarningsTrigger
57
- warnings={page.data?.warnings}
58
- folder={folder}
59
- />
60
- }
61
- filters
62
- leadingFilters={
63
- filter.choices.length > 1 ? (
64
- <FolderFilterBar
65
- ariaLabel="Filter tasks by folder"
66
- choices={filter.choices}
67
- onSelect={filter.setSelected}
68
- selected={filter.effectiveSelected}
69
- total={filter.total}
70
- />
71
- ) : undefined
72
- }
73
- itemHref={(item) => {
74
- const target = taskAddress(item)
75
- return target ? href(target) : undefined
76
- }}
77
- onToggle={(item) => {
78
- const target = taskAddress(item)
79
- if (target) page.toggle(target)
80
- }}
81
- />
82
- ) : undefined
83
- }
84
- page={page}
85
- unavailableMessage="No local task file in this folder."
86
- />
87
- )
88
- }
@@ -1,447 +0,0 @@
1
- import { readdir, readFile, stat } from "node:fs/promises"
2
- import { basename, dirname, relative, resolve, sep } from "node:path"
3
-
4
- import type {
5
- FolderPluginContext,
6
- FolderPluginDetection,
7
- FolderPluginPayload,
8
- } from "@raggle-ai/folder-plugin/server"
9
- import { matchSubpath } from "@raggle-ai/folder-plugin/subpath"
10
-
11
- import type { TodoFile, TodoIssue } from "./data/parse.ts"
12
- import {
13
- parseTodoSource,
14
- starterTodoSource,
15
- todoFileWarnings,
16
- todoIssueSummary,
17
- } from "./data/parse.ts"
18
- import { parseQualifiedTaskId, refMatchesFolder } from "./data/task-id.ts"
19
- import { tasksManifest } from "./manifest.ts"
20
-
21
- type TaskSource = {
22
- document: TodoFile
23
- /** Absolute directory that owns the `todo.json` file. */
24
- folder: string
25
- /** Path relative to the viewed root, e.g. "todo.json" or "clients/client-one/todo.json". */
26
- path: string
27
- }
28
-
29
- type TaskSourceLoad = {
30
- issues: Array<{ file: string; problems: TodoIssue[] }>
31
- /** Advisory warnings per file; they never invalidate a source. */
32
- warnings: Array<{ file: string; problems: TodoIssue[] }>
33
- sources: TaskSource[]
34
- }
35
-
36
- /**
37
- * Recursively discover `todo.json` files under a folder. Hidden directories
38
- * and `node_modules` are skipped and directory symlinks are not followed, so
39
- * discovered files stay contained inside the folder. Invalid files are
40
- * reported, valid files become task sources (mirroring the calendar
41
- * plugin's recursive discovery). `viewRoot` is the folder the viewer opened;
42
- * `scanRoot` defaults to it but may be a linked folder, in which case source
43
- * paths stay relative to the viewed root.
44
- */
45
- async function loadTaskSources(
46
- viewRoot: string,
47
- scanRoot: string = viewRoot,
48
- ): Promise<TaskSourceLoad> {
49
- const visit = async (current: string): Promise<string[]> => {
50
- const entries = await readdir(current, { withFileTypes: true }).catch(
51
- () => [],
52
- )
53
- const paths: string[] = []
54
- for (const entry of entries) {
55
- if (entry.isFile() && entry.name === "todo.json") {
56
- paths.push(resolve(current, entry.name))
57
- continue
58
- }
59
- if (
60
- !entry.isDirectory() ||
61
- entry.name.startsWith(".") ||
62
- entry.name === "node_modules"
63
- )
64
- continue
65
- paths.push(...(await visit(resolve(current, entry.name))))
66
- }
67
- return paths
68
- }
69
-
70
- const paths = (await visit(scanRoot)).sort((left, right) =>
71
- relative(scanRoot, left).localeCompare(relative(scanRoot, right)),
72
- )
73
- const issues: TaskSourceLoad["issues"] = []
74
- const warnings: TaskSourceLoad["warnings"] = []
75
- const sources: TaskSource[] = []
76
- await Promise.all(
77
- paths.map(async (path) => {
78
- const sourceText = await readFile(path, "utf8")
79
- const file = relative(viewRoot, path).split(sep).join("/")
80
- const parsed = parseTodoSource(sourceText)
81
- if (!parsed.ok) {
82
- issues.push({ file, problems: parsed.issues })
83
- return
84
- }
85
- warnings.push({
86
- file,
87
- problems: [
88
- ...todoFileWarnings(parsed.document),
89
- ...(await missingNoteIssues(parsed.document, dirname(path))),
90
- ],
91
- })
92
- sources.push({
93
- document: parsed.document,
94
- folder: dirname(path),
95
- path: file,
96
- })
97
- }),
98
- )
99
- issues.sort((left, right) => left.file.localeCompare(right.file))
100
- return { issues, sources, warnings }
101
- }
102
-
103
- /**
104
- * Load `todo.json` files from the host-resolved linked folders (the same
105
- * relation graph that powers linked notes). Paths stay relative to the
106
- * viewed root so linked sources never collide with the root `todo.json`
107
- * semantics; the multi-source dataset already renders them as their own
108
- * folder chips.
109
- */
110
- async function loadLinkedTaskSources(
111
- viewRoot: string,
112
- linkedFolders: string[],
113
- ): Promise<TaskSourceLoad> {
114
- const loads = await Promise.all(
115
- linkedFolders.map((folder) => loadTaskSources(viewRoot, folder)),
116
- )
117
- return {
118
- issues: loads.flatMap((load) => load.issues),
119
- sources: loads.flatMap((load) => load.sources),
120
- warnings: loads.flatMap((load) => load.warnings),
121
- }
122
- }
123
-
124
- /** Root-file issues keep their short paths; nested files get a file prefix. */
125
- function flattenIssues(load: TaskSourceLoad) {
126
- return load.issues.flatMap(({ file, problems }) =>
127
- problems.map((problem) => ({
128
- path: file === "todo.json" ? problem.path : `${file}: ${problem.path}`,
129
- message: problem.message,
130
- })),
131
- )
132
- }
133
-
134
- /** Root-file warnings keep their short paths; nested files get a file prefix. */
135
- function flattenWarnings(load: TaskSourceLoad) {
136
- return load.warnings.flatMap(({ file, problems }) =>
137
- problems.map((problem) => ({
138
- path: file === "todo.json" ? problem.path : `${file}: ${problem.path}`,
139
- message: problem.message,
140
- severity: problem.severity,
141
- })),
142
- )
143
- }
144
-
145
- /**
146
- * Server-side advisory: a folder-relative `notes` entry should resolve to a
147
- * real file next to its `todo.json`. A dead reference defeats the point of
148
- * note linking, so it warns (never errors); https entries are skipped.
149
- */
150
- async function missingNoteIssues(
151
- document: TodoFile,
152
- folder: string,
153
- ): Promise<TodoIssue[]> {
154
- const missing: TodoIssue[] = []
155
- for (const [index, task] of document.tasks.entries()) {
156
- const notes = task.notes
157
- if (!Array.isArray(notes)) continue
158
- for (const [noteIndex, note] of notes.entries()) {
159
- if (typeof note !== "string" || /^https?:\/\//i.test(note)) continue
160
- const target = (note.split("#", 1)[0] ?? "").trim()
161
- if (!target) continue
162
- const exists = await stat(resolve(folder, target))
163
- .then((entry) => entry.isFile())
164
- .catch(() => false)
165
- if (!exists) {
166
- missing.push({
167
- message: `references a missing note file: ${target}`,
168
- path: `tasks[${index}].notes[${noteIndex}]`,
169
- severity: "warning",
170
- })
171
- }
172
- }
173
- }
174
- return missing
175
- }
176
-
177
- function taskCompleted(task: Record<string, unknown>) {
178
- return task.done === true || task.status === "done"
179
- }
180
-
181
- function tasksOf(source: TaskSource) {
182
- return Array.isArray(source.document.tasks) ? source.document.tasks : []
183
- }
184
-
185
- function sourceTitle(folder: string) {
186
- return `${basename(folder)} tasks`
187
- }
188
-
189
- /**
190
- * Merged dataset for the workspace list: every valid `todo.json` under the
191
- * viewed folder becomes one source, root folder first, and every task is
192
- * tagged with its owning folder so the client can filter by folder chips.
193
- */
194
- function mergedDataset(folder: string, sources: TaskSource[]) {
195
- const root = sources.find((source) => source.path === "todo.json")
196
- const title =
197
- root && typeof root.document.title === "string"
198
- ? root.document.title
199
- : sourceTitle(folder)
200
-
201
- const byFolder = new Map<string, TaskSource[]>()
202
- for (const source of sources) {
203
- byFolder.set(source.folder, [
204
- ...(byFolder.get(source.folder) ?? []),
205
- source,
206
- ])
207
- }
208
- const ordered = new Map<string, TaskSource[]>()
209
- ordered.set(folder, byFolder.get(folder) ?? [])
210
- for (const sourceFolder of [...byFolder.keys()].sort()) {
211
- const docs = byFolder.get(sourceFolder)
212
- if (docs && sourceFolder !== folder) ordered.set(sourceFolder, docs)
213
- }
214
-
215
- const datasetSources: Array<{
216
- id: string
217
- open: number
218
- title: string
219
- total: number
220
- }> = []
221
- const tasks: Array<Record<string, unknown>> = []
222
- for (const [sourceFolder, docs] of ordered) {
223
- const fileTasks = docs.flatMap(tasksOf)
224
- const completed = fileTasks.filter(taskCompleted).length
225
- datasetSources.push({
226
- id: sourceFolder,
227
- open: fileTasks.length - completed,
228
- title: sourceTitle(sourceFolder),
229
- total: fileTasks.length,
230
- })
231
- for (const task of fileTasks) {
232
- tasks.push({
233
- ...task,
234
- source: { id: sourceFolder, title: sourceTitle(sourceFolder) },
235
- })
236
- }
237
- }
238
-
239
- const completed = tasks.filter(taskCompleted).length
240
- return {
241
- ...root?.document,
242
- $schema:
243
- typeof root?.document.$schema === "string"
244
- ? root.document.$schema
245
- : "https://raggle.co/schemas/tasks.json",
246
- id: typeof root?.document.id === "string" ? root.document.id : "todo",
247
- project: { name: title },
248
- sources: datasetSources,
249
- summary: {
250
- completed,
251
- open: tasks.length - completed,
252
- sources: datasetSources.length,
253
- },
254
- tasks,
255
- title,
256
- version:
257
- typeof root?.document.version === "number" ? root.document.version : 1,
258
- }
259
- }
260
-
261
- function singleTaskDataset(
262
- folder: string,
263
- source: TaskSource,
264
- task: Record<string, unknown>,
265
- ) {
266
- const completed = taskCompleted(task)
267
- return {
268
- ...source.document,
269
- $schema:
270
- typeof source.document.$schema === "string"
271
- ? source.document.$schema
272
- : "https://raggle.co/schemas/tasks.json",
273
- version:
274
- typeof source.document.version === "number" ? source.document.version : 1,
275
- project: { name: sourceTitle(folder) },
276
- sources: [
277
- {
278
- id: source.folder,
279
- open: completed ? 0 : 1,
280
- title: sourceTitle(source.folder),
281
- total: 1,
282
- },
283
- ],
284
- summary: {
285
- completed: completed ? 1 : 0,
286
- open: completed ? 0 : 1,
287
- sources: 1,
288
- },
289
- tasks: [
290
- {
291
- ...task,
292
- source: { id: source.folder, title: sourceTitle(source.folder) },
293
- },
294
- ],
295
- }
296
- }
297
-
298
- export function createTasksPlugin() {
299
- return {
300
- ...tasksManifest,
301
- async detect(context: FolderPluginContext): Promise<FolderPluginDetection> {
302
- const [loads, linked] = await Promise.all([
303
- loadTaskSources(context.folder),
304
- loadLinkedTaskSources(context.folder, context.linkedFolders ?? []),
305
- ])
306
- const merged: TaskSourceLoad = {
307
- issues: [...loads.issues, ...linked.issues],
308
- sources: [...loads.sources, ...linked.sources],
309
- // Warnings are advisory: detection stays "available" with its count.
310
- warnings: [],
311
- }
312
- const noContent =
313
- merged.sources.length === 0 && merged.issues.length === 0
314
- if (noContent) return { status: "unavailable" }
315
- if (merged.issues.length > 0) {
316
- // Explicit error state: a todo.json exists but is not valid (locally
317
- // or in a linked folder). The host flags the navigation item.
318
- return {
319
- status: "error",
320
- error: todoIssueSummary(flattenIssues(merged)),
321
- }
322
- }
323
- return {
324
- count: merged.sources.reduce(
325
- (sum, source) => sum + tasksOf(source).length,
326
- 0,
327
- ),
328
- status: "available",
329
- }
330
- },
331
- async handle(
332
- context: FolderPluginContext,
333
- subpath: string,
334
- ): Promise<FolderPluginPayload<unknown>> {
335
- const [load, linked] = await Promise.all([
336
- loadTaskSources(context.folder),
337
- loadLinkedTaskSources(context.folder, context.linkedFolders ?? []),
338
- ])
339
- const sources = [...load.sources, ...linked.sources]
340
- const rootIssue = load.issues.find((issue) => issue.file === "todo.json")
341
- if (rootIssue) {
342
- // In-band error payload: precise, per-field issues the client renders
343
- // directly. Throwing would map to a misleading 4xx/5xx instead.
344
- return {
345
- kind: "available",
346
- data: {
347
- folder: context.folder,
348
- issues: rootIssue.problems,
349
- status: "error",
350
- },
351
- }
352
- }
353
-
354
- const warnings = flattenWarnings({
355
- issues: [],
356
- sources: [],
357
- warnings: [...load.warnings, ...linked.warnings],
358
- })
359
-
360
- if (subpath === "" || sources.length === 0) {
361
- // Workspace list: the root folder always owns a source (even with no
362
- // file) so a missing/empty folder still yields an empty, valid
363
- // dataset — for the list and for any detail subpath alike.
364
- return {
365
- kind: "available",
366
- data: {
367
- dataset: mergedDataset(context.folder, sources),
368
- folder: context.folder,
369
- status: "available",
370
- warnings,
371
- },
372
- }
373
- }
374
-
375
- // Individual task view: match the subpath against the task id or key
376
- // across every discovered source (local and linked) and return a
377
- // single-task dataset.
378
- const id = subpath.trim()
379
- // Qualified addresses (`<folderPathId(folder)>@<id|key>`) name their
380
- // owning folder, so identical file-local ids `todo:1` resolve to the
381
- // right file. A ref that matches no source is an id that contains "@":
382
- // it drops through to the legacy bare-id search below. A ref that
383
- // matches a real source but no task is a broken address and must not
384
- // silently show a different source's task.
385
- const qualified = parseQualifiedTaskId(id)
386
- if (qualified) {
387
- const source = sources.find((item) =>
388
- refMatchesFolder(qualified.ref, item.folder),
389
- )
390
- if (source) {
391
- const task = tasksOf(source).find(
392
- (item) => item.id === qualified.id || item.key === qualified.id,
393
- )
394
- return {
395
- kind: "available",
396
- data: task
397
- ? {
398
- dataset: singleTaskDataset(context.folder, source, task),
399
- folder: context.folder,
400
- status: "available",
401
- warnings,
402
- }
403
- : {
404
- folder: context.folder,
405
- message: `Task not found: ${id}`,
406
- status: "error",
407
- },
408
- }
409
- }
410
- }
411
- // Legacy bare id/key: first source that contains it wins, via the
412
- // shared subpath matcher (also used by the minimal reference plugin).
413
- const bare = matchSubpath(
414
- sources,
415
- id,
416
- tasksOf,
417
- (item, target) => item.id === target || item.key === target,
418
- )
419
- if (bare) {
420
- return {
421
- kind: "available",
422
- data: {
423
- dataset: singleTaskDataset(context.folder, bare.source, bare.item),
424
- folder: context.folder,
425
- status: "available",
426
- warnings,
427
- },
428
- }
429
- }
430
- return {
431
- kind: "available",
432
- data: {
433
- folder: context.folder,
434
- message: `Task not found: ${id}`,
435
- status: "error",
436
- },
437
- }
438
- },
439
- init(context: FolderPluginContext) {
440
- return {
441
- files: [
442
- { path: "todo.json", content: starterTodoSource(context.folder) },
443
- ],
444
- }
445
- },
446
- }
447
- }
@@ -1,9 +0,0 @@
1
- .todo-panel {
2
- overflow: hidden;
3
- border: 1px solid rgb(226 232 240);
4
- border-radius: 0.75rem;
5
- background: rgb(255 255 255);
6
- box-shadow:
7
- 0 1px 2px rgb(15 23 42 / 0.06),
8
- 0 1px 1px rgb(15 23 42 / 0.04);
9
- }