kennel 0.2.2 → 0.2.5

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 (237) 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 +29 -3
  8. package/dist/cli/src/plugins/external.js +78 -24
  9. package/dist/cli/src/site/server-plugins.d.ts +2 -7
  10. package/dist/cli/src/site/viewer.js +1 -0
  11. package/dist/cli/usage.js +1 -1
  12. package/dist/core/command.js +1 -0
  13. package/dist/core/init.js +5 -5
  14. package/dist/core/runtime.js +357 -3207
  15. package/dist/package/preview.js +1232 -5113
  16. package/dist/plugins/external.d.ts +29 -3
  17. package/dist/plugins/external.js +78 -24
  18. package/dist/site/server-plugins.d.ts +2 -7
  19. package/dist/site/server-plugins.js +552 -10447
  20. package/dist/site/viewer.js +1 -0
  21. package/kernel/apps/web/package.json +1 -5
  22. package/kernel/apps/web/scripts/dev.mjs +53 -0
  23. package/kernel/apps/web/src/app.css +0 -3
  24. package/kernel/apps/web/src/main.tsx +0 -1
  25. package/kernel/apps/web/src/plugins.ts +0 -30
  26. package/kernel/apps/web/tsconfig.json +1 -2
  27. package/kernel/apps/web/vite.config.ts +31 -13
  28. package/kernel/packages/api/package.json +0 -4
  29. package/kernel/packages/api/src/server/folder-metadata-plugin.ts +13 -38
  30. package/kernel/packages/api/src/server/index.ts +0 -1
  31. package/kernel/packages/api/src/server/plugins.ts +49 -16
  32. package/kernel/packages/api/test/core.test.ts +13 -25
  33. package/kernel/packages/markdown/README.md +1 -1
  34. package/package.json +1 -1
  35. package/web/assets/{abnfDiagram-VRR7QNED-Bgfb1nEB.js → abnfDiagram-VRR7QNED-xd_g1uK3.js} +1 -1
  36. package/web/assets/app-CX20nNIa.js +2 -0
  37. package/web/assets/{app-options-D-RJiQ-X.js → app-options-CkPJE5ep.js} +1 -1
  38. package/web/assets/{app-view-header-BLvLq02T.js → app-view-header-CNk5KnA-.js} +1 -1
  39. package/web/assets/{arc-Dk_KI36B.js → arc-B0u5yBJA.js} +1 -1
  40. package/web/assets/{architectureDiagram-ZJ3FMSHR-NR_KhRCf.js → architectureDiagram-ZJ3FMSHR-DfxOAo8P.js} +1 -1
  41. package/web/assets/{ask-tray-TzeTcO6-.js → ask-tray-SscJecDY.js} +1 -1
  42. package/web/assets/{blockDiagram-677ZJIJ3-CkLkwx9C.js → blockDiagram-677ZJIJ3-Ci3Usxh6.js} +1 -1
  43. package/web/assets/{c4Diagram-LMCZKHZV-CFCUH8e_.js → c4Diagram-LMCZKHZV-BqgwIVgh.js} +1 -1
  44. package/web/assets/channel-X7WHyxxT.js +1 -0
  45. package/web/assets/{chunk-2Q5K7J3B-B_BPLWsW.js → chunk-2Q5K7J3B-CfX69l2U.js} +1 -1
  46. package/web/assets/{chunk-32BRIVSS-B1VB1hOy.js → chunk-32BRIVSS-CuFlzZkl.js} +1 -1
  47. package/web/assets/{chunk-5VM5RSS4-KFcYr8Co.js → chunk-5VM5RSS4-DidCMlJa.js} +1 -1
  48. package/web/assets/{chunk-EX3LRPZG-CpBX3kuK.js → chunk-EX3LRPZG-B5CDm1dS.js} +1 -1
  49. package/web/assets/{chunk-JWPE2WC7-BPSl40wG.js → chunk-JWPE2WC7-D5fGV_sH.js} +1 -1
  50. package/web/assets/{chunk-MOJQB5TN-D2RcYmoU.js → chunk-MOJQB5TN-ayhH5Q-H.js} +1 -1
  51. package/web/assets/{chunk-RYQCIY6F-m7Gyn-t3.js → chunk-RYQCIY6F-C4BfOOZn.js} +1 -1
  52. package/web/assets/{chunk-V7JOEXUC-TDvdopxS.js → chunk-V7JOEXUC-DpUEIM9V.js} +1 -1
  53. package/web/assets/{chunk-VR4S4FIN-DZTsG51a.js → chunk-VR4S4FIN-DoQuFFRh.js} +1 -1
  54. package/web/assets/{chunk-XXDRQBXY-Dp0--RE2.js → chunk-XXDRQBXY-CI9eiLwn.js} +1 -1
  55. package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +1 -0
  56. package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +1 -0
  57. package/web/assets/client-7OWw5kW2.js +6 -0
  58. package/web/assets/client-DYj_td4Q.js +17 -0
  59. package/web/assets/{client-j2kQmxsO.js → client-Dk-NBvJR.js} +4 -4
  60. package/web/assets/command-zkzH4hVz.js +38 -0
  61. package/web/assets/{copy-context-C0Uqsp-3.js → copy-context-D5oiWrYC.js} +1 -1
  62. package/web/assets/{cose-bilkent-JH36ORCC-CPu3PI8h.js → cose-bilkent-JH36ORCC-BHRk1mO3.js} +1 -1
  63. package/web/assets/{cynefin-VYW2F7L2-DWxftYAm.js → cynefin-VYW2F7L2-C1B09TRE.js} +1 -1
  64. package/web/assets/{cynefinDiagram-TSTJHNR4-DsmN2V-p.js → cynefinDiagram-TSTJHNR4-B27qXQbv.js} +1 -1
  65. package/web/assets/{dagre-VKFMJZFB-COEbApyY.js → dagre-VKFMJZFB-B1qEi32g.js} +1 -1
  66. package/web/assets/{diagram-FQU43EPY-0O9WGWKB.js → diagram-FQU43EPY-BMkkgADD.js} +1 -1
  67. package/web/assets/{diagram-G47NLZAW-CutEdMVh.js → diagram-G47NLZAW-Cb8_g1A5.js} +1 -1
  68. package/web/assets/{diagram-NH7WQ7WH-C9KZc3B2.js → diagram-NH7WQ7WH-B51wuc5m.js} +1 -1
  69. package/web/assets/{diagram-OA4YK3LP-D8kkPXbY.js → diagram-OA4YK3LP-xnsecbbI.js} +1 -1
  70. package/web/assets/{diagram-WEI45ONY-_YqiTaGP.js → diagram-WEI45ONY-DSZdyaAV.js} +1 -1
  71. package/web/assets/{document-Dgt5eZFj.js → document-Dc2dftTW.js} +3 -3
  72. package/web/assets/{ebnfDiagram-CCIWWBDH-JO-zQh6g.js → ebnfDiagram-CCIWWBDH-aTHmcUGy.js} +1 -1
  73. package/web/assets/{entities-C3wz7FCx.js → entities-CCUtpskY.js} +1 -1
  74. package/web/assets/{erDiagram-Q63AITRT-9UjQwJ4P.js → erDiagram-Q63AITRT-CUUPBcvo.js} +1 -1
  75. package/web/assets/{file-viewer-DZJ8nYnl.js → file-viewer-DJ3rsmef.js} +1 -1
  76. package/web/assets/{flowDiagram-23GEKE2U-Ca08tnYM.js → flowDiagram-23GEKE2U-aTQXx2Mh.js} +1 -1
  77. package/web/assets/{folder-image-BfGgxo7i.js → folder-image-Bnv43tzP.js} +1 -1
  78. package/web/assets/{folder-landing-qUKBCnG-.js → folder-landing-DCnzYXXY.js} +1 -1
  79. package/web/assets/{folder-list-BfFjv7rR.js → folder-list-DvVkVjiR.js} +1 -1
  80. package/web/assets/{folder-metadata-DCw8xzHk.js → folder-metadata-C9hMMzIH.js} +1 -1
  81. package/web/assets/{folder-mobile-bar-Ubz4babf.js → folder-mobile-bar-VoTL1GS0.js} +1 -1
  82. package/web/assets/folder-plugin-view-Cvd804ZU.js +6 -0
  83. package/web/assets/{ganttDiagram-NO4QXBWP-KnHzX5W3.js → ganttDiagram-NO4QXBWP-DiwdUp7u.js} +1 -1
  84. package/web/assets/{gitGraphDiagram-IHSO6WYX-Cm8woNtK.js → gitGraphDiagram-IHSO6WYX-BL2gG_IS.js} +1 -1
  85. package/web/assets/{index-CNyy98F8.js → index-CUTtMSyJ.js} +2 -2
  86. package/web/assets/index-CegvVQ1C.js +1 -0
  87. package/web/assets/index-Dwhf8F_U.css +1 -0
  88. package/web/assets/{infoDiagram-FWYZ7A6U-yyqmUtIb.js → infoDiagram-FWYZ7A6U-B3n0zZpt.js} +1 -1
  89. package/web/assets/{ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js → ishikawaDiagram-FXEZZL3T-D7YytbEv.js} +1 -1
  90. package/web/assets/{journeyDiagram-5HDEW3XC-BKuw06HM.js → journeyDiagram-5HDEW3XC-BYwqEl3C.js} +1 -1
  91. package/web/assets/{kanban-definition-HUTT4EX6-n0010rmQ.js → kanban-definition-HUTT4EX6-BQHNJgXZ.js} +1 -1
  92. package/web/assets/{linear-C0d0lT8O.js → linear-BPiQCLNk.js} +1 -1
  93. package/web/assets/{mermaid.core-BDVbShyO.js → mermaid.core-CD-KvBjV.js} +4 -4
  94. package/web/assets/{metadata-KV0dpp4G.js → metadata-COJ7fZul.js} +1 -1
  95. package/web/assets/{mindmap-definition-LN4V7U3C--_0ks3GF.js → mindmap-definition-LN4V7U3C-C1L_gyoj.js} +1 -1
  96. package/web/assets/{pegDiagram-2B236MQR-CBoNIpKR.js → pegDiagram-2B236MQR-BDAfItqS.js} +1 -1
  97. package/web/assets/{pieDiagram-ENE6RG2P-MA5tkYh5.js → pieDiagram-ENE6RG2P-CkZYH3Vz.js} +1 -1
  98. package/web/assets/{popover-DBD7FF-W.js → popover-0oA2lLUV.js} +2 -2
  99. package/web/assets/{project-search-dialog-DM1IkSZu.js → project-search-dialog-B2oqMT6h.js} +1 -1
  100. package/web/assets/{quadrantDiagram-ABIIQ3AL-CWT1ryqF.js → quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js} +1 -1
  101. package/web/assets/{railroadDiagram-RFXS5EU6-ZiLB5FGi.js → railroadDiagram-RFXS5EU6-Dd9_yo7B.js} +1 -1
  102. package/web/assets/{requirementDiagram-TGXJPOKE-CQq9uneq.js → requirementDiagram-TGXJPOKE-DPhIUsbs.js} +1 -1
  103. package/web/assets/{sankeyDiagram-HTMAVEWB-qDG-0JqI.js → sankeyDiagram-HTMAVEWB-B2QkYtub.js} +1 -1
  104. package/web/assets/{search-DNrQA5fF.js → search-C1J0-xiB.js} +1 -1
  105. package/web/assets/select-CtXC_PLC.js +30 -0
  106. package/web/assets/{selection-popup-DmtTeRs2.js → selection-popup-qhlUFzGq.js} +1 -1
  107. package/web/assets/{sequenceDiagram-DBY2YBRQ-CiApurLO.js → sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js} +1 -1
  108. package/web/assets/{sizeCapture-X5ZJPWSS-DZSR5QXm.js → sizeCapture-X5ZJPWSS-CIXIhl_A.js} +1 -1
  109. package/web/assets/{stateDiagram-2N3HPSRC-CjJJR9_z.js → stateDiagram-2N3HPSRC-DCrdAflB.js} +1 -1
  110. package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +1 -0
  111. package/web/assets/{swimlanes-5IMT3BWC-CKmo1sg6.js → swimlanes-5IMT3BWC-DA2vc7iZ.js} +2 -2
  112. package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +8 -0
  113. package/web/assets/{timeline-definition-FHXFAJF6-D-NMwS3y.js → timeline-definition-FHXFAJF6-lKfJiV9V.js} +1 -1
  114. package/web/assets/{vennDiagram-L72KCM5P-CfL6LBWw.js → vennDiagram-L72KCM5P-DO1q2KzG.js} +1 -1
  115. package/web/assets/{view-context-gyDl_p2V.js → view-context-DXKM3-l1.js} +4 -4
  116. package/web/assets/{viewer-capabilities-Bpp8Uvcg.js → viewer-capabilities-Cig_xM9u.js} +1 -1
  117. package/web/assets/{wardleyDiagram-EHGQE667-DgldMxaj.js → wardleyDiagram-EHGQE667-Dal9LkuZ.js} +1 -1
  118. package/web/assets/{xychartDiagram-FW5EYKEG-CIoAIFX8.js → xychartDiagram-FW5EYKEG-B3dPLPII.js} +1 -1
  119. package/web/index.html +2 -2
  120. package/kernel/packages/api/test/partial-loading.test.ts +0 -43
  121. package/kernel/plugins/calendar/SKILL.md +0 -173
  122. package/kernel/plugins/calendar/eslint.config.js +0 -10
  123. package/kernel/plugins/calendar/package.json +0 -73
  124. package/kernel/plugins/calendar/schema.json +0 -137
  125. package/kernel/plugins/calendar/src/calendar.tsx +0 -328
  126. package/kernel/plugins/calendar/src/client.tsx +0 -139
  127. package/kernel/plugins/calendar/src/context.ts +0 -48
  128. package/kernel/plugins/calendar/src/copy-button.tsx +0 -66
  129. package/kernel/plugins/calendar/src/event-dialog.tsx +0 -270
  130. package/kernel/plugins/calendar/src/index.ts +0 -4
  131. package/kernel/plugins/calendar/src/manifest.ts +0 -7
  132. package/kernel/plugins/calendar/src/parse.ts +0 -610
  133. package/kernel/plugins/calendar/src/server.ts +0 -160
  134. package/kernel/plugins/calendar/src/utils.ts +0 -80
  135. package/kernel/plugins/calendar/src/views.tsx +0 -418
  136. package/kernel/plugins/calendar/test/context.test.mjs +0 -60
  137. package/kernel/plugins/calendar/test/package.test.mjs +0 -43
  138. package/kernel/plugins/calendar/test/parse.test.mjs +0 -392
  139. package/kernel/plugins/calendar/test/server.test.mjs +0 -126
  140. package/kernel/plugins/calendar/tsconfig.json +0 -17
  141. package/kernel/plugins/mail/SKILL.md +0 -97
  142. package/kernel/plugins/mail/eslint.config.js +0 -10
  143. package/kernel/plugins/mail/package.json +0 -79
  144. package/kernel/plugins/mail/src/api.ts +0 -359
  145. package/kernel/plugins/mail/src/bun-ffi.d.ts +0 -14
  146. package/kernel/plugins/mail/src/client.tsx +0 -14
  147. package/kernel/plugins/mail/src/flock.ts +0 -137
  148. package/kernel/plugins/mail/src/folders.ts +0 -37
  149. package/kernel/plugins/mail/src/history.ts +0 -485
  150. package/kernel/plugins/mail/src/index.ts +0 -3
  151. package/kernel/plugins/mail/src/mail-card.tsx +0 -123
  152. package/kernel/plugins/mail/src/mail-conversation.tsx +0 -153
  153. package/kernel/plugins/mail/src/mail-detail-page.tsx +0 -467
  154. package/kernel/plugins/mail/src/mail-hooks.ts +0 -252
  155. package/kernel/plugins/mail/src/mail-page.tsx +0 -109
  156. package/kernel/plugins/mail/src/mail-request.ts +0 -78
  157. package/kernel/plugins/mail/src/mail-send-box.tsx +0 -175
  158. package/kernel/plugins/mail/src/mailos.ts +0 -723
  159. package/kernel/plugins/mail/src/manifest.ts +0 -7
  160. package/kernel/plugins/mail/src/node.ts +0 -171
  161. package/kernel/plugins/mail/src/parse.ts +0 -139
  162. package/kernel/plugins/mail/src/server.ts +0 -125
  163. package/kernel/plugins/mail/src/types.ts +0 -10
  164. package/kernel/plugins/mail/src/viewer.tsx +0 -147
  165. package/kernel/plugins/mail/test/flock.test.mjs +0 -156
  166. package/kernel/plugins/mail/test/folders.test.mjs +0 -138
  167. package/kernel/plugins/mail/test/history.test.mjs +0 -460
  168. package/kernel/plugins/mail/test/mailos.test.mjs +0 -752
  169. package/kernel/plugins/mail/test/node.test.mjs +0 -207
  170. package/kernel/plugins/mail/test/package.test.mjs +0 -54
  171. package/kernel/plugins/mail/test/parse.test.mjs +0 -32
  172. package/kernel/plugins/mail/test/server.test.mjs +0 -116
  173. package/kernel/plugins/mail/test/viewer.test.mjs +0 -192
  174. package/kernel/plugins/mail/tsconfig.json +0 -17
  175. package/kernel/plugins/projects/SKILL.md +0 -73
  176. package/kernel/plugins/projects/eslint.config.js +0 -10
  177. package/kernel/plugins/projects/package.json +0 -70
  178. package/kernel/plugins/projects/src/client.tsx +0 -17
  179. package/kernel/plugins/projects/src/data/model.ts +0 -129
  180. package/kernel/plugins/projects/src/index.ts +0 -17
  181. package/kernel/plugins/projects/src/manifest.ts +0 -7
  182. package/kernel/plugins/projects/src/project-context.ts +0 -41
  183. package/kernel/plugins/projects/src/server.ts +0 -276
  184. package/kernel/plugins/projects/src/ui/project-card.tsx +0 -61
  185. package/kernel/plugins/projects/src/ui/projects-page.tsx +0 -102
  186. package/kernel/plugins/projects/test/package.test.mjs +0 -51
  187. package/kernel/plugins/projects/tsconfig.json +0 -17
  188. package/kernel/plugins/tasks/SKILL.md +0 -341
  189. package/kernel/plugins/tasks/eslint.config.js +0 -10
  190. package/kernel/plugins/tasks/package.json +0 -74
  191. package/kernel/plugins/tasks/schema.json +0 -939
  192. package/kernel/plugins/tasks/src/api.ts +0 -212
  193. package/kernel/plugins/tasks/src/client.tsx +0 -23
  194. package/kernel/plugins/tasks/src/data/parse.ts +0 -544
  195. package/kernel/plugins/tasks/src/data/task-id.ts +0 -56
  196. package/kernel/plugins/tasks/src/data/todo-model.ts +0 -795
  197. package/kernel/plugins/tasks/src/index.ts +0 -34
  198. package/kernel/plugins/tasks/src/manifest.ts +0 -7
  199. package/kernel/plugins/tasks/src/pages/task-detail.tsx +0 -48
  200. package/kernel/plugins/tasks/src/pages/task-list.tsx +0 -88
  201. package/kernel/plugins/tasks/src/server.ts +0 -447
  202. package/kernel/plugins/tasks/src/styles.css +0 -9
  203. package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +0 -372
  204. package/kernel/plugins/tasks/src/ui/error-details.tsx +0 -78
  205. package/kernel/plugins/tasks/src/ui/task-page.tsx +0 -392
  206. package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +0 -36
  207. package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +0 -66
  208. package/kernel/plugins/tasks/src/ui/todo-item.tsx +0 -494
  209. package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +0 -60
  210. package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +0 -48
  211. package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +0 -106
  212. package/kernel/plugins/tasks/test/api.test.mjs +0 -99
  213. package/kernel/plugins/tasks/test/folder-sources.test.mjs +0 -46
  214. package/kernel/plugins/tasks/test/package.test.mjs +0 -54
  215. package/kernel/plugins/tasks/test/parse.test.mjs +0 -225
  216. package/kernel/plugins/tasks/test/server.test.mjs +0 -386
  217. package/kernel/plugins/tasks/tsconfig.json +0 -17
  218. package/web/assets/app-DoGr2Zi7.js +0 -2
  219. package/web/assets/channel-uMEjV8qc.js +0 -1
  220. package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +0 -1
  221. package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +0 -1
  222. package/web/assets/client-C6Nxdfif.js +0 -2
  223. package/web/assets/client-CXYfBko5.js +0 -17
  224. package/web/assets/client-CoKtOq-X.js +0 -7
  225. package/web/assets/client-DyRQz5RU.js +0 -53
  226. package/web/assets/client-OY6HUzuD.js +0 -98
  227. package/web/assets/client-YOYWZIFi.js +0 -34
  228. package/web/assets/command-BugZBGXE.js +0 -38
  229. package/web/assets/folder-plugin-view-DsWR1zmQ.js +0 -6
  230. package/web/assets/index-BaRnbYRw.js +0 -1
  231. package/web/assets/index-BexmLxIP.css +0 -1
  232. package/web/assets/index-DDirZMgx.js +0 -1
  233. package/web/assets/note-card-DBfX6gW1.js +0 -6
  234. package/web/assets/select-D8cqNgcp.js +0 -30
  235. package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +0 -1
  236. package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +0 -8
  237. package/web/assets/use-folder-filter-LQyXns5Q.js +0 -1
@@ -1,386 +0,0 @@
1
- import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"
2
- import { tmpdir } from "node:os"
3
- import { basename, join } from "node:path"
4
- import { afterAll, beforeAll, expect, test } from "bun:test"
5
-
6
- import { createTasksPlugin } from "../src/server.ts"
7
-
8
- let base
9
- let empty
10
- let withTasks
11
- let withZeroTasks
12
- let withInvalidStatus
13
- let withBrokenJson
14
-
15
- beforeAll(async () => {
16
- base = await mkdtemp(join(tmpdir(), "kennel-tasks-plugin-"))
17
- empty = join(base, "empty")
18
- withTasks = join(base, "with-tasks")
19
- withZeroTasks = join(base, "with-zero-tasks")
20
- withInvalidStatus = join(base, "with-invalid-status")
21
- withBrokenJson = join(base, "with-broken-json")
22
- for (const folder of [
23
- empty,
24
- withTasks,
25
- withZeroTasks,
26
- withInvalidStatus,
27
- withBrokenJson,
28
- ]) {
29
- await mkdir(folder, { recursive: true })
30
- }
31
- await writeFile(
32
- join(withTasks, "todo.json"),
33
- JSON.stringify({
34
- id: "todo",
35
- tasks: [{ id: "t1", key: "TODO-1", name: "One", done: false }],
36
- title: "Project",
37
- }),
38
- )
39
- await writeFile(
40
- join(withZeroTasks, "todo.json"),
41
- JSON.stringify({
42
- id: "todo",
43
- tasks: [],
44
- title: "Empty",
45
- }),
46
- )
47
- await writeFile(
48
- join(withInvalidStatus, "todo.json"),
49
- JSON.stringify({
50
- id: "todo",
51
- tasks: [{ id: "t1", name: "One", status: "in-progress" }],
52
- title: "Broken",
53
- }),
54
- )
55
- await writeFile(join(withBrokenJson, "todo.json"), '{"tasks": [')
56
- })
57
-
58
- afterAll(async () => {
59
- await rm(base, { recursive: true, force: true })
60
- })
61
-
62
- test("detect is unavailable without a todo.json file", async () => {
63
- const plugin = createTasksPlugin()
64
- const detection = await plugin.detect({ folder: empty })
65
- expect(detection.status).toBe("unavailable")
66
- })
67
-
68
- test("a valid todo document activates even with zero tasks", async () => {
69
- const plugin = createTasksPlugin()
70
- const zero = await plugin.detect({ folder: withZeroTasks })
71
- expect(zero.status).toBe("available")
72
- expect(zero.count).toBe(0)
73
-
74
- const withCount = await plugin.detect({ folder: withTasks })
75
- expect(withCount.status).toBe("available")
76
- expect(withCount.count).toBe(1)
77
- })
78
-
79
- test("handle list returns a schema-valid task dataset", async () => {
80
- const plugin = createTasksPlugin()
81
- const result = await plugin.handle({ folder: withTasks }, "")
82
- expect(result.kind).toBe("available")
83
- if (result.kind !== "available") return
84
- expect(result.data.status).toBe("available")
85
- expect(result.data.dataset.tasks).toHaveLength(1)
86
- expect(result.data.dataset.summary.open).toBe(1)
87
- })
88
-
89
- test("handle returns an empty dataset when the folder has no task document", async () => {
90
- const plugin = createTasksPlugin()
91
- const result = await plugin.handle({ folder: empty }, "")
92
- expect(result.kind).toBe("available")
93
- expect(result.data.dataset.tasks).toEqual([])
94
- expect(result.data.dataset.summary).toEqual({
95
- completed: 0,
96
- open: 0,
97
- sources: 1,
98
- })
99
- expect(result.data.dataset.version).toBe(1)
100
- expect(result.data.dataset.$schema).toBe(
101
- "https://raggle.co/schemas/tasks.json",
102
- )
103
- })
104
-
105
- test("detect reports an error, not availability, for an invalid document", async () => {
106
- const plugin = createTasksPlugin()
107
- const invalid = await plugin.detect({ folder: withInvalidStatus })
108
- expect(invalid.status).toBe("error")
109
- if (invalid.status !== "error") return
110
- expect(invalid.error).toContain("tasks[0].status")
111
-
112
- const broken = await plugin.detect({ folder: withBrokenJson })
113
- expect(broken.status).toBe("error")
114
- if (broken.status !== "error") return
115
- expect(broken.error).toContain("not valid JSON")
116
- })
117
-
118
- test("handle returns in-band issues for an invalid document", async () => {
119
- const plugin = createTasksPlugin()
120
- const result = await plugin.handle({ folder: withInvalidStatus }, "")
121
- expect(result.kind).toBe("available")
122
- if (result.kind !== "available") return
123
- expect(result.data.status).toBe("error")
124
- expect(result.data.issues).toContainEqual({
125
- path: "tasks[0].status",
126
- message:
127
- 'must be one of todo, in_progress, blocked, review, done, canceled; got "in-progress"',
128
- })
129
- })
130
-
131
- test("handle reports broken JSON as an issue, not a throw", async () => {
132
- const plugin = createTasksPlugin()
133
- const result = await plugin.handle({ folder: withBrokenJson }, "")
134
- expect(result.kind).toBe("available")
135
- if (result.kind !== "available") return
136
- expect(result.data.status).toBe("error")
137
- expect(result.data.issues).toHaveLength(1)
138
- expect(result.data.issues[0].path).toBe("#")
139
- expect(result.data.issues[0].message).toContain("not valid JSON")
140
- })
141
-
142
- test("handle with a task id subpath returns a single-task dataset", async () => {
143
- const plugin = createTasksPlugin()
144
- const result = await plugin.handle({ folder: withTasks }, "t1")
145
- expect(result.kind).toBe("available")
146
- if (result.kind !== "available") return
147
- expect(result.data.status).toBe("available")
148
- expect(result.data.dataset.tasks).toHaveLength(1)
149
- expect(result.data.dataset.tasks[0].id).toBe("t1")
150
- expect(result.data.dataset.summary.open).toBe(1)
151
- })
152
-
153
- test("handle with a task key subpath returns the matching task", async () => {
154
- const plugin = createTasksPlugin()
155
- const result = await plugin.handle({ folder: withTasks }, "TODO-1")
156
- expect(result.kind).toBe("available")
157
- if (result.kind !== "available") return
158
- expect(result.data.status).toBe("available")
159
- expect(result.data.dataset.tasks).toHaveLength(1)
160
- expect(result.data.dataset.tasks[0].id).toBe("t1")
161
- })
162
-
163
- test("handle with an unknown task subpath returns an error message", async () => {
164
- const plugin = createTasksPlugin()
165
- const result = await plugin.handle({ folder: withTasks }, "nope")
166
- expect(result.kind).toBe("available")
167
- if (result.kind !== "available") return
168
- expect(result.data.status).toBe("error")
169
- expect(result.data.message).toContain("nope")
170
- expect(result.data.dataset).toBeUndefined()
171
- })
172
-
173
- test("handle with a task subpath surfaces issues for an invalid document", async () => {
174
- const plugin = createTasksPlugin()
175
- const result = await plugin.handle({ folder: withInvalidStatus }, "t1")
176
- expect(result.kind).toBe("available")
177
- if (result.kind !== "available") return
178
- expect(result.data.status).toBe("error")
179
- expect(result.data.issues).toHaveLength(1)
180
- expect(result.data.issues[0].path).toBe("tasks[0].status")
181
- })
182
-
183
- test("handle with a task subpath on a missing document returns an empty dataset", async () => {
184
- const plugin = createTasksPlugin()
185
- const result = await plugin.handle({ folder: empty }, "t1")
186
- expect(result.kind).toBe("available")
187
- if (result.kind !== "available") return
188
- expect(result.data.status).toBe("available")
189
- expect(result.data.dataset.tasks).toEqual([])
190
- })
191
-
192
- test("a nested workspace merges task files into folder-tagged sources", async () => {
193
- const folder = await mkdtemp(join(tmpdir(), "kennel-tasks-plugin-"))
194
- try {
195
- const nested = join(folder, "clients", "client-one")
196
- await mkdir(nested, { recursive: true })
197
- await writeFile(
198
- join(folder, "todo.json"),
199
- JSON.stringify({
200
- id: "todo",
201
- tasks: [{ id: "root1", key: "ROOT-1", name: "Root", done: false }],
202
- title: "Example Workspace",
203
- }),
204
- )
205
- await writeFile(
206
- join(nested, "todo.json"),
207
- JSON.stringify({
208
- id: "todo",
209
- tasks: [{ id: "n1", key: "N-1", name: "Nested", done: true }],
210
- title: "Client One",
211
- }),
212
- )
213
-
214
- const plugin = createTasksPlugin()
215
- const detection = await plugin.detect({ folder })
216
- expect(detection.status).toBe("available")
217
- if (detection.status !== "available") return
218
- expect(detection.count).toBe(2)
219
-
220
- const result = await plugin.handle({ folder }, "")
221
- expect(result.kind).toBe("available")
222
- if (result.kind !== "available") return
223
- const dataset = result.data.dataset
224
- expect(dataset.tasks).toHaveLength(2)
225
- expect(dataset.summary).toEqual({ completed: 1, open: 1, sources: 2 })
226
- // Each task is tagged with its owning folder for the shared chips.
227
- expect(dataset.tasks.map((task) => task.source.id).sort()).toEqual(
228
- [folder, nested].sort(),
229
- )
230
- expect(dataset.sources.map((source) => source.id).sort()).toEqual(
231
- [folder, nested].sort(),
232
- )
233
- } finally {
234
- await rm(folder, { recursive: true, force: true })
235
- }
236
- })
237
-
238
- test("detail subpaths match tasks inside nested files", async () => {
239
- const folder = await mkdtemp(join(tmpdir(), "kennel-tasks-plugin-"))
240
- try {
241
- const nested = join(folder, "clients", "client-one")
242
- await mkdir(nested, { recursive: true })
243
- await writeFile(
244
- join(folder, "todo.json"),
245
- JSON.stringify({ tasks: [{ id: "root1", name: "Root" }] }),
246
- )
247
- await writeFile(
248
- join(nested, "todo.json"),
249
- JSON.stringify({ tasks: [{ id: "n1", name: "Nested" }] }),
250
- )
251
-
252
- const plugin = createTasksPlugin()
253
- const result = await plugin.handle({ folder }, "n1")
254
- expect(result.kind).toBe("available")
255
- if (result.kind !== "available") return
256
- expect(result.data.status).toBe("available")
257
- expect(result.data.dataset.tasks).toHaveLength(1)
258
- expect(result.data.dataset.tasks[0].id).toBe("n1")
259
- expect(result.data.dataset.tasks[0].source.id).toBe(nested)
260
- } finally {
261
- await rm(folder, { recursive: true, force: true })
262
- }
263
- })
264
-
265
- test("linked folder tasks merge into the dataset under their own source", async () => {
266
- const folder = await mkdtemp(join(tmpdir(), "kennel-tasks-plugin-"))
267
- const linked = await mkdtemp(join(tmpdir(), "kennel-tasks-linked-"))
268
- try {
269
- await writeFile(
270
- join(folder, "todo.json"),
271
- JSON.stringify({
272
- id: "todo",
273
- tasks: [{ id: "root1", name: "Root" }],
274
- title: "Local project",
275
- }),
276
- )
277
- await writeFile(
278
- join(linked, "todo.json"),
279
- JSON.stringify({
280
- id: "todo",
281
- tasks: [
282
- { id: "l1", key: "LINK-1", name: "Linked one", done: false },
283
- { id: "l2", key: "LINK-2", name: "Linked two", done: true },
284
- ],
285
- title: "Linked project",
286
- }),
287
- )
288
-
289
- const plugin = createTasksPlugin()
290
-
291
- // Without the host-provided link the folder stays a single local source.
292
- const local = await plugin.detect({ folder })
293
- expect(local.status).toBe("available")
294
- if (local.status !== "available") return
295
- expect(local.count).toBe(1)
296
-
297
- const detection = await plugin.detect({
298
- folder,
299
- linkedFolders: [linked],
300
- })
301
- expect(detection.status).toBe("available")
302
- if (detection.status !== "available") return
303
- expect(detection.count).toBe(3)
304
-
305
- const result = await plugin.handle({ folder, linkedFolders: [linked] }, "")
306
- expect(result.kind).toBe("available")
307
- if (result.kind !== "available") return
308
- expect(result.data.status).toBe("available")
309
- const dataset = result.data.dataset
310
- expect(dataset.title).toBe("Local project")
311
- expect(dataset.summary).toEqual({ completed: 1, open: 2, sources: 2 })
312
- expect(dataset.sources).toContainEqual({
313
- id: linked,
314
- open: 1,
315
- title: `${basename(linked)} tasks`,
316
- total: 2,
317
- })
318
- const linkedTask = dataset.tasks.find((task) => task.id === "l1")
319
- expect(linkedTask?.source).toEqual({
320
- id: linked,
321
- title: `${basename(linked)} tasks`,
322
- })
323
- // Detail subpaths resolve across linked sources too.
324
- const detail = await plugin.handle(
325
- { folder, linkedFolders: [linked] },
326
- "LINK-2",
327
- )
328
- expect(detail.kind).toBe("available")
329
- if (detail.kind !== "available") return
330
- expect(detail.data.dataset.tasks).toHaveLength(1)
331
- expect(detail.data.dataset.tasks[0].id).toBe("l2")
332
- expect(detail.data.dataset.summary.completed).toBe(1)
333
- } finally {
334
- await rm(folder, { recursive: true, force: true })
335
- await rm(linked, { recursive: true, force: true })
336
- }
337
- })
338
-
339
- test("linked files never shadow the root todo.json semantics", async () => {
340
- const folder = await mkdtemp(join(tmpdir(), "kennel-tasks-plugin-"))
341
- const linked = await mkdtemp(join(tmpdir(), "kennel-tasks-linked-"))
342
- try {
343
- await writeFile(
344
- join(folder, "todo.json"),
345
- JSON.stringify({ tasks: [{ id: "root1", name: "Root" }] }),
346
- )
347
- await writeFile(
348
- join(linked, "todo.json"),
349
- JSON.stringify({ tasks: [{ id: "l1", name: "Linked" }] }),
350
- )
351
-
352
- const plugin = createTasksPlugin()
353
- // A linked folder alone activates the item, with the viewed root title.
354
- const alone = await plugin.handle(
355
- { folder: empty, linkedFolders: [linked] },
356
- "",
357
- )
358
- expect(alone.kind).toBe("available")
359
- if (alone.kind !== "available") return
360
- expect(alone.data.status).toBe("available")
361
- expect(alone.data.dataset.tasks).toHaveLength(1)
362
- expect(alone.data.dataset.tasks[0].source.id).toBe(linked)
363
- // The viewed root always owns an (empty) source row, so linked-only
364
- // content shows root + linked sources.
365
- expect(alone.data.dataset.summary).toEqual({
366
- completed: 0,
367
- open: 1,
368
- sources: 2,
369
- })
370
- // Invalid linked json is skipped from content and never breaks the root
371
- // error panel, but still flags detection like any nested file would.
372
- await writeFile(join(linked, "todo.json"), '{"tasks": [')
373
- const broken = await plugin.detect({ folder, linkedFolders: [linked] })
374
- expect(broken.status).toBe("error")
375
- if (broken.status !== "error") return
376
- expect(broken.error).toContain("not valid JSON")
377
- const panel = await plugin.handle({ folder, linkedFolders: [linked] }, "")
378
- expect(panel.kind).toBe("available")
379
- if (panel.kind !== "available") return
380
- expect(panel.data.status).toBe("available")
381
- expect(panel.data.dataset.tasks).toHaveLength(1)
382
- } finally {
383
- await rm(folder, { recursive: true, force: true })
384
- await rm(linked, { recursive: true, force: true })
385
- }
386
- })
@@ -1,17 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "@raggle-ai/tsconfig/base.json",
4
- "compilerOptions": {
5
- "target": "ES2022",
6
- "lib": ["dom", "dom.iterable", "esnext"],
7
- "jsx": "preserve",
8
- "baseUrl": ".",
9
- "allowImportingTsExtensions": true,
10
- // local copy: bun doesn't read paths inherited via `extends`
11
- "paths": {
12
- "~/*": ["${configDir}/../../packages/*/src"]
13
- }
14
- },
15
- "include": ["src"],
16
- "exclude": ["node_modules", "dist", "eslint.config.mjs"]
17
- }
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ask-tray-TzeTcO6-.js","assets/react-B9jn2M18.js","assets/markdown-Bw9RgUGR.js","assets/view-context-gyDl_p2V.js","assets/index-CNyy98F8.js","assets/index-BexmLxIP.css","assets/tanstack-YzX_Mi37.js","assets/button-C6arH7zt.js","assets/utils-DCaHk0Gm.js","assets/folder-plugin-view-DsWR1zmQ.js","assets/command-BugZBGXE.js","assets/index-CCXE8zc9.js","assets/index-DDirZMgx.js","assets/popover-DBD7FF-W.js","assets/folder-image-BfGgxo7i.js","assets/viewer-capabilities-Bpp8Uvcg.js","assets/entities-C3wz7FCx.js","assets/search-DNrQA5fF.js","assets/search-BOHZTLC-.css","assets/folder-landing-qUKBCnG-.js","assets/folder-metadata-DCw8xzHk.js","assets/copy-context-C0Uqsp-3.js","assets/index-Bp9DidgD.js","assets/app-options-D-RJiQ-X.js","assets/index-CXhBn-ar.js","assets/folder-list-BfFjv7rR.js","assets/folder-activity-Cv1X2ezj.js","assets/folder-mobile-bar-Ubz4babf.js","assets/app-view-header-BLvLq02T.js","assets/file-viewer-DZJ8nYnl.js","assets/metadata-KV0dpp4G.js","assets/project-search-dialog-DM1IkSZu.js","assets/client-j2kQmxsO.js","assets/select-D8cqNgcp.js","assets/index-BaRnbYRw.js","assets/client-C6Nxdfif.js","assets/note-card-DBfX6gW1.js"])))=>i.map(i=>d[i]);
2
- import{_ as g,i as ne,f as T,b as re,c as ae,p as S,l as je,d as Re,r as _e,e as be}from"./index-CNyy98F8.js";import{c as s,j as r}from"./react-B9jn2M18.js";import{m as x,c as f}from"./tanstack-YzX_Mi37.js";import{b as ke,c as Ee,q as Ie,L as Te,T as Se,v as Q,V as De,i as se,s as ie,a as M,t as ce,g as Ae,h as Oe,j as E,k as F,m as Fe}from"./view-context-gyDl_p2V.js";function N(e){const t=new TextEncoder().encode(e);let o="";for(const c of t)o+=String.fromCharCode(c);return btoa(o).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")}function Le(e){const t=new URL(e,window.location.origin),o=t.pathname.split("/").filter(Boolean),c=o.indexOf("folder"),d=c>=0?o[c+1]:void 0;let i=t.searchParams.get("folder")??void 0;if(!i&&d){const l=d.replaceAll("-","+").replaceAll("_","/"),a=l.padEnd(Math.ceil(l.length/4)*4,"="),u=atob(a),m=Uint8Array.from(u,j=>j.charCodeAt(0));i=new TextDecoder().decode(m)}return{folder:i}}function xt(e,t){return`/folder/${N(e)}/${t}`}function jt(e,t){return`/folder/${N(e)}/document/${N(t)}`}async function Ne(e,t,o={}){const c=new URL(e,window.location.origin),d=new URL("/api/metadata",window.location.origin),i=c.pathname.split("/").filter(Boolean),l=i[0]==="folder"?i[1]:void 0,a=c.searchParams.get("folder");if(a)d.searchParams.set("path",a);else if(l){const m=l.replaceAll("-","+").replaceAll("_","/"),j=m.padEnd(Math.ceil(m.length/4)*4,"="),y=atob(j),C=Uint8Array.from(y,V=>V.charCodeAt(0));d.searchParams.set("path",new TextDecoder().decode(C))}d.searchParams.set("part",t),o.notesScope&&d.searchParams.set("notesScope",o.notesScope);const u=await fetch(d,{headers:o.headers,signal:o.signal});if(!u.ok)throw new Error(await u.text());return await u.json()}function Ce(e,t=!0){const o=s.useRef(!1),c=Le(e).folder,d=c?N(c):"none",i=m=>({enabled:t&&!!c,gcTime:5*6e4,queryFn:({signal:j})=>{const y=m==="linked"&&o.current;return y&&(o.current=!1),Ne(e,"notes",{headers:y?{"x-kennel-retry-linked":"1"}:void 0,notesScope:m,signal:j})},queryKey:["folder",d,"notes",m],staleTime:15e3}),l=x.useQuery(i("local")),a=x.useQuery(i("linked")),u=s.useMemo(()=>l.data||a.data?[...l.data?.files.items??[],...a.data?.files.items??[]]:void 0,[l.data,a.data]);return{local:l,linked:a,files:u,retryLinked:()=>{o.current=!0,a.refetch()}}}const Ve=s.lazy(async()=>({default:(await g(async()=>{const{AskTray:e}=await import("./ask-tray-TzeTcO6-.js");return{AskTray:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8]))).AskTray}));function $e({folder:e}){const{enabled:t}=ke(),{draft:o}=Ee(e);return!t&&!o.comments.length&&!o.attachments.length?null:r.jsx(s.Suspense,{fallback:null,children:r.jsx(Ve,{folder:e})})}function Ke(e){const t=e.slice(e.lastIndexOf(".")).toLowerCase();if(t===".htm"||t===".html")return"html";if(t===".md"||t===".markdown")return"markdown";if(t===".text"||t===".txt")return"text"}async function le(e,t=""){const o=[];for await(const c of e.values()){const d=t?`${t}/${c.name}`:c.name;if(c.kind==="directory"){o.push(...await le(c,d));continue}const i=Ke(c.name);if(!i)continue;const l=await c.getFile();o.push({path:d,content:await l.text(),kind:i})}return o}async function qe(e){const t=await le(e);return t.sort((o,c)=>o.path.localeCompare(c.path)),{root:e.name,documents:t}}async function He(e){for(const t of e){if(t.kind!=="file")continue;const o=t.getAsFileSystemHandle;if(!o)throw new Error("This browser cannot read dropped folders.");const c=await o.call(t);if(c?.kind==="directory")return c}throw new Error("Drop one folder to open it.")}const Qe="kennel-folder-query-cache",z="queries",U=1,Me=10080*60*1e3;function ze(){return new Promise((e,t)=>{const o=indexedDB.open(Qe,U);o.onupgradeneeded=()=>{o.result.createObjectStore(z)},o.onerror=()=>t(o.error),o.onsuccess=()=>e(o.result)})}async function de(e,t){const o=await ze();return new Promise((c,d)=>{const i=o.transaction(z,e),l=t(i.objectStore(z));l.onerror=()=>d(l.error),l.onsuccess=()=>c(l.result),i.oncomplete=()=>o.close(),i.onerror=()=>{o.close(),d(i.error)}})}async function ee(e){const t=await de("readonly",o=>o.get(JSON.stringify(e))).catch(()=>{});if(t?.version===U&&!(Date.now()-t.savedAt>Me))return t.data}async function te(e,t){t&&await de("readwrite",o=>o.put({data:t,savedAt:Date.now(),version:U},JSON.stringify(e))).catch(()=>{})}const ue=s.lazy(async()=>({default:(await g(async()=>{const{FolderPluginPage:e}=await import("./folder-plugin-view-DsWR1zmQ.js").then(t=>t.f);return{FolderPluginPage:e}},__vite__mapDeps([9,1,2,6,3,4,5,7,8,10,11,12,13,14,15]))).FolderPluginPage})),Be=s.lazy(async()=>({default:(await g(async()=>{const{EntitySearchPage:e}=await import("./entities-C3wz7FCx.js");return{EntitySearchPage:e}},__vite__mapDeps([16,1,2,6,3,4,5]))).EntitySearchPage})),Ue=s.lazy(async()=>({default:(await g(async()=>{const{ProjectSearchPage:e}=await import("./search-DNrQA5fF.js");return{ProjectSearchPage:e}},__vite__mapDeps([17,1,2,6,3,4,5,18]))).ProjectSearchPage}));function I(){return r.jsx("p",{role:"status",className:"text-muted-foreground p-4 text-sm",children:"Loading page…"})}const D=f.createRootRoute({component:f.Outlet}),oe=s.lazy(async()=>({default:(await g(()=>import("./folder-landing-qUKBCnG-.js"),__vite__mapDeps([19,1,2,3,4,5,6,7,8,20,21,11,12,14,22,23,24,25,26]))).FolderLanding})),Ye=s.lazy(async()=>({default:(await g(()=>import("./folder-mobile-bar-Ubz4babf.js"),__vite__mapDeps([27,1,2,23,3,4,5,6,21,7,8,11,24,14,28,13]))).FolderMobileBar})),Je=s.lazy(async()=>({default:(await g(()=>import("./file-viewer-DZJ8nYnl.js"),__vite__mapDeps([29,1,2,3,4,5,6,30]))).FileViewer})),We=s.lazy(async()=>({default:(await g(()=>import("./project-search-dialog-DM1IkSZu.js"),__vite__mapDeps([31,1,2,6,3,4,5,10,11,8,12]))).ProjectSearchDialog})),Ge=s.lazy(async()=>{const e=await g(()=>import("./client-j2kQmxsO.js"),__vite__mapDeps([32,1,2,6,23,3,4,5,21,7,8,11,24,14,28,13,33,34,22,25]));return{default:function(){const o=f.useLocation(),c=`${window.location.origin}${o.href}`;return r.jsx(e.CollectionPage,{href:c,request:(d,i,l)=>M.metadata(d,i,l),subscribeApiEvent:ie,parseRoute:S,collectionHref:ae,documentHref:re,folderHref:B,homeHref:d=>T(d,"notes"),openFolder:d=>{M.openPath(d).catch(i=>ce.error(i instanceof Error?i.message:"Could not open the default app."))}})}}}),Xe=s.lazy(async()=>({default:(await g(()=>import("./client-C6Nxdfif.js"),__vite__mapDeps([35,1,2,3,4,5,6,7,8,36,21,26]))).NotesPage})),Ze=f.createRoute({getParentRoute:()=>D,path:"/",component:fe}),b=f.createRoute({getParentRoute:()=>D,path:"folder/$folderId",component:fe}),et=f.createRoute({getParentRoute:()=>b,path:"skills"}),tt=f.createRoute({getParentRoute:()=>b,path:"views/$pluginId",component:ue}),ot=f.createRoute({getParentRoute:()=>b,path:"views/$pluginId/$subpath",component:ue}),nt=f.createRoute({getParentRoute:()=>b,path:"collections/$collectionId",component:()=>r.jsx(s.Suspense,{fallback:r.jsx("p",{role:"status",children:"Loading collection…"}),children:r.jsx(Ge,{})})}),rt=f.createRoute({getParentRoute:()=>b,path:"notes",component:Xe}),at=f.createRoute({getParentRoute:()=>b,path:"projects"}),st=f.createRoute({getParentRoute:()=>D,path:"entities",component:Be}),it=f.createRoute({getParentRoute:()=>D,path:"search",component:Ue}),ct=D.addChildren([Ze,st,it,b.addChildren([rt,nt,et,tt,ot,at])]),lt=f.createRouter({routeTree:ct});function dt(){const e=S(window.location.href).folder;return e?T(e,"notes"):"/"}function B(e){return T(e,"notes")}function ut(e){const t=S(window.location.href).folder;return t?re(t,e):e}function ft(e){const t=S(window.location.href).folder;return t?e==="files"?T(t,"notes"):T(t,e):"/"}function pt(e){const t=S(window.location.href).folder;return t?be(t,e):"/"}function mt({href:e,...t}){return!e?.startsWith("/")||ne(e)?r.jsx("a",{href:e,...t}):r.jsx(f.Link,{to:e,...t})}function ht(){return r.jsx(x.QueryClientProvider,{client:Ie,children:r.jsxs(Te,{component:mt,children:[r.jsx(s.Suspense,{fallback:r.jsx(I,{}),children:r.jsx(f.RouterProvider,{router:lt})}),r.jsx(Se,{})]})})}const L={discovery:Number.POSITIVE_INFINITY,identity:Number.POSITIVE_INFINITY,plugins:Number.POSITIVE_INFINITY,skills:15e3};function P(e,t){return["folder",e,t]}function fe(){const e=f.useLocation(),t=`${window.location.origin}${e.href}`,o=Q(t);return r.jsx(De,{kind:"folder",folder:se(t)?void 0:o.folder,children:r.jsx(yt,{})})}function yt(){const e=Ae(),t=je(window.location.href);t&&window.history.replaceState(null,"",t);const o=x.useQueryClient(),c=f.useNavigate(),d=f.useLocation(),i=`${window.location.origin}${d.href}`,l=se(i),a=Q(i),u=a.folder?Re(a.folder):"none",[m,j]=s.useState(()=>window.matchMedia("(max-width: 767px)").matches),[y,C]=s.useState(),[V,$]=s.useState(!1),[Y,J]=s.useState(!1),[pe,me]=s.useState(!1),W=pe&&!a.document,A=s.useRef(0),k=!l&&!y,R=k&&!!a.folder,he=P(u,"identity"),ye=P(u,"discovery");Oe(i,k);const ge=s.useMemo(()=>y?{read:async()=>y}:l?{read:E.read}:{...E},[y,l]),v=x.useQuery({enabled:!!R,gcTime:Number.POSITIVE_INFINITY,queryFn:({signal:n})=>F(i,"identity",{signal:n}),queryKey:he,staleTime:L.identity}),h=x.useQuery({enabled:!!(R&&a.section==="projects"),gcTime:Number.POSITIVE_INFINITY,queryFn:({signal:n})=>F(i,"discovery",{signal:n}),queryKey:ye,staleTime:L.discovery}),G=x.useQuery({enabled:!!R,gcTime:Number.POSITIVE_INFINITY,queryFn:({signal:n})=>F(i,"plugins",{signal:n}),queryKey:P(u,"plugins"),staleTime:L.plugins}),X=Ce(i,R&&a.section==="notes"),Z=x.useQuery({enabled:!!(R&&a.section==="skills"),gcTime:5*6e4,queryFn:({signal:n})=>F(i,"skills",{signal:n}),queryKey:P(u,"skills"),staleTime:L.skills}),_=s.useMemo(()=>{if(v.data)return{assets:{...h.data?.assets,...v.data.assets},files:{items:X.files??[]},folder:v.data.folder,iconAssetKey:v.data.iconAssetKey,plugins:G.data?.plugins??{items:[]},projects:h.data?.projects??{items:[]},workspace:e.workspace??h.data?.workspace,sessions:{items:[]},skills:Z.data?.skills??{items:[]}}},[h.data,v.data,X.files,G.data,Z.data,e.workspace]),K=v.error??(a.section==="projects"?h.error:void 0)??void 0,we=K?K instanceof Error?K.message:"Could not load folder activity.":"",ve=(_?.folder??y?.root??a.folder??"Kennel").replace(/\/+$/,"").split("/").pop()??"Kennel",Pe=_?.iconAssetKey?_.assets[_.iconAssetKey]:void 0;s.useEffect(()=>{const n=window.matchMedia("(max-width: 767px)"),p=()=>j(n.matches);return n.addEventListener("change",p),()=>n.removeEventListener("change",p)},[]),s.useEffect(()=>ie("kennel:metadata-changed",()=>{o.invalidateQueries({queryKey:["folder",u]})}),[u,o]),s.useEffect(()=>Fe("kennel:linked-folders-changed",a.folder,()=>{for(const n of[["notes","linked"],["plugins"]])o.invalidateQueries({queryKey:["folder",u,...n]},{cancelRefetch:!1})}),[u,a.folder,o]),s.useEffect(()=>{if(!R)return;const n=P(u,"identity"),p=P(u,"discovery");ee(n).then(w=>{w&&!o.getQueryData(n)&&o.setQueryData(n,w)}),ee(p).then(w=>{w&&!o.getQueryData(p)&&o.setQueryData(p,w)})},[u,R,o]),s.useEffect(()=>{te(P(u,"identity"),v.data)},[u,v.data]),s.useEffect(()=>{te(P(u,"discovery"),h.data)},[h.data,u]);const xe=n=>{const p=new URL(n,window.location.origin);Q(p.href),c({to:`${p.pathname}${p.search}`})},q=a.view||a.collectionId||a.section==="notes"?r.jsx(s.Suspense,{fallback:r.jsx(I,{}),children:r.jsx(f.Outlet,{})}):a.section==="projects"&&!h.data&&(h.isPending||h.error)?r.jsx("div",{className:"p-4",role:h.error?"alert":"status",children:h.error?r.jsxs(r.Fragment,{children:["Projects could not load."," ",r.jsx("button",{onClick:()=>{h.refetch()},children:"Retry projects"})]}):"Loading projects…"}):null,O=!!a.collectionId,H={data:_,collectionId:a.collectionId,collectionHref:n=>a.folder?ae(a.folder,n):"/",documentHref:ut,error:we,folder:a.folder,folderHref:B,onFindProject:()=>J(!0),onOpenFolder:()=>{E.openRoot?.()},onOpenPath:n=>{M.openPath(n).catch(p=>ce.error(p instanceof Error?p.message:"Could not open the default app."))},pluginHref:pt,tab:_e(a),tabHref:ft,view:a.view};return r.jsxs("div",{className:"folder-drop-zone","data-mobile-landing":k&&m?"true":void 0,onClickCapture:n=>{if(n.defaultPrevented||n.button!==0||n.metaKey||n.ctrlKey||n.shiftKey||n.altKey||!(n.target instanceof Element))return;const w=n.target.closest("a[href]")?.getAttribute("href");if(w?.startsWith("/folder/")&&!ne(w)){n.preventDefault(),xe(w);return}},onDragEnter:n=>{l||[...n.dataTransfer.items].some(p=>p.kind==="file")&&(n.preventDefault(),A.current+=1,$(!0))},onDragLeave:()=>{A.current-=1,A.current<=0&&$(!1)},onDragOver:n=>{l||(n.preventDefault(),n.dataTransfer.dropEffect="copy")},onDrop:n=>{l||(n.preventDefault(),A.current=0,$(!1),He(n.dataTransfer.items).then(qe).then(p=>{window.history.replaceState(null,"",window.location.pathname),C(p)}))},children:[O?null:r.jsx(s.Suspense,{fallback:null,children:r.jsx(Ye,{canOpen:!l&&!y,homeHref:dt(),icon:Pe,name:ve,folder:_?.folder??a.folder,folderHref:B,collectionHref:H.collectionHref,workspace:e.workspace??_?.workspace,onOpen:()=>{if(m){me(!0);return}E.openRoot?.()},onOpenFolder:()=>{E.openRoot?.()}})}),k&&O?r.jsx(s.Suspense,{fallback:r.jsx(I,{}),children:q}):null,k&&!O&&!m?r.jsx(s.Suspense,{fallback:r.jsx(I,{}),children:r.jsx(oe,{...H,children:q})}):null,k&&!O&&m?r.jsx("div",{className:"mobile-landing-content",children:r.jsx(s.Suspense,{fallback:r.jsx(I,{}),children:r.jsx(oe,{...H,children:q})})}):null,W?r.jsx(s.Suspense,{fallback:null,children:r.jsx(Je,{source:ge})}):null,a.folder&&!W?r.jsx($e,{folder:a.folder},a.folder):null,V?r.jsx("div",{className:"folder-drop-overlay",children:"Drop folder to open"}):null,Y?r.jsx(s.Suspense,{fallback:null,children:r.jsx(We,{open:Y,onOpenChange:J})}):null]})}const Rt=Object.freeze(Object.defineProperty({__proto__:null,App:ht},Symbol.toStringTag,{value:"Module"}));export{xt as a,jt as b,Rt as c,N as f,Le as p,Ce as u};
@@ -1 +0,0 @@
1
- import{U as a,T as n}from"./mermaid.core-BDVbShyO.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-TDvdopxS.js";import{_ as i}from"./mermaid.core-BDVbShyO.js";import"./chunk-5VM5RSS4-KFcYr8Co.js";import"./chunk-XXDRQBXY-Dp0--RE2.js";import"./chunk-VR4S4FIN-DZTsG51a.js";import"./chunk-32BRIVSS-B1VB1hOy.js";import"./index-CNyy98F8.js";import"./react-B9jn2M18.js";import"./markdown-Bw9RgUGR.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-TDvdopxS.js";import{_ as i}from"./mermaid.core-BDVbShyO.js";import"./chunk-5VM5RSS4-KFcYr8Co.js";import"./chunk-XXDRQBXY-Dp0--RE2.js";import"./chunk-VR4S4FIN-DZTsG51a.js";import"./chunk-32BRIVSS-B1VB1hOy.js";import"./index-CNyy98F8.js";import"./react-B9jn2M18.js";import"./markdown-Bw9RgUGR.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
@@ -1,2 +0,0 @@
1
- import{c as x,j as t}from"./react-B9jn2M18.js";import{p as v,f as k,u as w,a as y,b as C}from"./app-DoGr2Zi7.js";import{l as g}from"./view-context-gyDl_p2V.js";import{B as j}from"./button-C6arH7zt.js";import{N as P}from"./note-card-DBfX6gW1.js";import"./markdown-Bw9RgUGR.js";import"./index-CNyy98F8.js";import"./tanstack-YzX_Mi37.js";import"./utils-DCaHk0Gm.js";import"./copy-context-C0Uqsp-3.js";import"./folder-activity-Cv1X2ezj.js";const A={id:"notes",label:"Notes"},b=new Map;async function $(a){const r=new URL("/api/config",window.location.origin);a&&r.searchParams.set("path",a);const l=await fetch(r);if(!l.ok)return null;const n=(await l.json()).aiInputModule;if(typeof n!="string"||!n)return null;const u=b.get(n);if(u)return u;const s=import(n).then(d=>{const p=d.default;if(!p?.Composer)throw new Error("The AI input module must default-export an adapter with a Composer component.");return p});return b.set(n,s),s}function L(a){const[r,l]=x.useState();return x.useEffect(()=>{let o=!0;return $(a).then(async n=>{o&&(await n?.install?.(),o&&l({folder:a,adapter:n}))}).catch(n=>{console.error("Could not load the configured AI input adapter.",n)}),()=>{o=!1}},[a]),r?.folder===a?r?.adapter??null:null}function N(a,r){return()=>r(!a)}function I({open:a,onOpenChange:r}){const l=a?"Hide bark input":"Open bark input";return t.jsx(j,{"aria-controls":"bark-composer","aria-expanded":a,"aria-label":l,onClick:N(a,r),title:l,type:"button",variant:"outline",children:t.jsx(g.Plus,{"aria-hidden":"true",className:"size-4"})})}function F({adapter:a,open:r,onOpenChange:l}){const o=r?"Hide bark input":"Open bark input";return t.jsxs(t.Fragment,{children:[t.jsx(j,{"aria-controls":"bark-composer","aria-expanded":r,"aria-label":o,className:"mobile-bark-toggle",onClick:N(r,l),title:o,type:"button",variant:"outline",children:t.jsx(g.Plus,{"aria-hidden":"true"})}),r?t.jsx("section",{"aria-label":"AI composer",className:"ai-input-host",id:"bark-composer",children:t.jsx(a.Composer,{})}):null]})}function H(a){return a.replace(/[\\/]+$/,"").split(/[\\/]/).at(-1)??a}function O({action:a,documentHref:r,error:l,files:o=[],folder:n,folderHref:u,loading:s}){const[d,p]=x.useState("all"),m=[...new Set(o.flatMap(e=>e.folder?[e.folder]:[]))],i=[{id:"all",label:"All",count:o.length},{id:"local",label:"This folder",count:o.filter(e=>!e.folder).length},...m.map(e=>({id:e,label:H(e),count:o.filter(h=>h.folder===e).length}))],c=i.some(e=>e.id===d)?d:"all",f=o.filter(e=>c==="all"||(c==="local"?!e.folder:e.folder===c)).sort((e,h)=>h.activityAt-e.activityAt||`${e.folder??""}/${e.relativePath}`.localeCompare(`${h.folder??""}/${h.relativePath}`));return t.jsxs("div",{className:"mx-auto grid w-full max-w-3xl gap-4 px-4 py-5",children:[t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("h1",{className:"m-0 text-2xl font-semibold text-[#233025]",children:"Notes"}),a]}),m.length?t.jsx("div",{role:"group","aria-label":"Filter notes by source",className:"flex flex-wrap gap-2",children:i.map(e=>t.jsxs(j,{type:"button",size:"sm",variant:c===e.id?"secondary":"outline",className:`h-auto min-h-8 max-w-full rounded-full
2
- whitespace-normal`,"aria-pressed":c===e.id,onClick:()=>p(e.id),title:e.id==="local"?n:m.includes(e.id)?e.id:void 0,children:[m.includes(e.id)?t.jsx(g.Link2,{"aria-hidden":"true"}):null,t.jsx("span",{className:"break-all",children:e.label}),t.jsx("span",{className:"text-muted-foreground",children:e.count})]},e.id))}):null,s?t.jsx("p",{className:"m-0 text-sm text-[#6c7a6d]",children:"Loading…"}):null,l?t.jsx("p",{className:"m-0 text-sm text-[#9c3a3a]",children:l}):null,!s&&!l&&!f.length?t.jsx("p",{className:"m-0 text-sm text-[#6c7a6d]",children:o.length?"No notes match this filter.":"No notes found."}):null,f.length?t.jsx("ol",{className:"m-0 grid list-none gap-2 p-0",children:f.map(e=>t.jsx("li",{children:t.jsx(P,{activityAt:e.activityAt,context:e.folder?`${e.folder.replace(/[\\/]+$/,"")}/${e.relativePath}`:n?`${n.replace(/[\\/]+$/,"")}/${e.relativePath}`:e.relativePath,folderHref:e.folder?u(e.folder):void 0,href:r(e),linkedFolder:e.folder,path:e.relativePath,title:e.name})},`${e.folder??""}:${e.relativePath}`))}):null]})}function R(){const[a,r]=x.useState(!1),l=window.location.href,o=v(l).folder,n=L(o),u=o?k(o):"none",{local:s,linked:d,files:p,retryLinked:m}=w(l);return t.jsxs(t.Fragment,{children:[t.jsx(O,{action:n?t.jsx(I,{onOpenChange:r,open:a}):void 0,documentHref:i=>{const c=i.folder??o;return c?C(c,i.relativePath):i.relativePath},error:s.error?String(s.error):"",files:p,folder:o,folderHref:i=>y(i,"notes"),loading:s.isLoading},u),s.error?t.jsx("button",{className:"px-4",onClick:()=>{s.refetch()},children:"Retry local notes"}):null,d.isLoading?t.jsx("p",{role:"status",className:"text-muted-foreground px-4 text-sm",children:"Loading linked notes…"}):null,d.error?t.jsxs("p",{role:"alert",className:"px-4 text-sm",children:["Linked notes could not load."," ",t.jsx("button",{type:"button",onClick:m,children:"Retry"})]}):null,n?t.jsx(F,{adapter:n,onOpenChange:r,open:a}):null]})}const J={...A,component:R};export{R as NotesPage,J as notesClient,w as useFolderNotes};
@@ -1,17 +0,0 @@
1
- import{j as e,c as d}from"./react-B9jn2M18.js";import{F as A,a as B,b as W}from"./folder-plugin-view-DsWR1zmQ.js";import{m as H}from"./tanstack-YzX_Mi37.js";import{l as f,t as b,e as q}from"./view-context-gyDl_p2V.js";import{C as M,a as L,b as I,S as K,c as J,d as Q,e as X,f as Y}from"./select-D8cqNgcp.js";import{u as Z}from"./use-folder-filter-LQyXns5Q.js";import{a as v}from"./utils-DCaHk0Gm.js";import{m as ee}from"./metadata-KV0dpp4G.js";import{F as E,f as O}from"./folder-metadata-DCw8xzHk.js";import"./markdown-Bw9RgUGR.js";import"./index-CNyy98F8.js";import"./button-C6arH7zt.js";import"./command-BugZBGXE.js";import"./index-CCXE8zc9.js";import"./index-DDirZMgx.js";import"./popover-DBD7FF-W.js";import"./folder-image-BfGgxo7i.js";import"./viewer-capabilities-Bpp8Uvcg.js";import"./index-BaRnbYRw.js";import"./index-CXhBn-ar.js";import"./index-Bp9DidgD.js";import"./copy-context-C0Uqsp-3.js";const w="min-w-0 overflow-hidden rounded-lg border border-[#e7ebe7] bg-white",te="inline-flex min-h-11 shrink-0 items-center justify-center gap-2 rounded-md border border-[#d5dcd5] bg-white px-3 py-2 text-sm font-medium text-[#4a554b] transition-colors hover:bg-[#f3f5f2] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#56725e] disabled:cursor-wait disabled:opacity-60",se="inline-flex h-9 shrink-0 items-center justify-center gap-1.5 rounded-md border border-[#d5dcd5] bg-white px-2.5 text-xs font-medium text-[#4a554b] transition-colors hover:bg-[#f3f5f2] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#56725e] disabled:cursor-wait disabled:opacity-60";function S({children:s,actions:i}){return e.jsxs("div",{className:"flex min-w-0 items-start justify-between gap-3 p-4",children:[e.jsx("div",{className:"min-w-0 flex-1 space-y-2",children:s}),i?e.jsx("div",{className:"ml-auto flex shrink-0 items-center gap-2",children:i}):null]})}function y({hostActions:s,source:i,embedded:l=!1}){const[o,u]=d.useState(!1),p=s?.openPath,a=d.useMemo(()=>i.status==="loaded"?ee(i.text):null,[i]);return e.jsxs("article",{className:l?"min-w-0":w,children:[e.jsxs(S,{actions:p?e.jsxs("button",{"aria-label":`Edit ${i.filename} in the default Markdown app`,className:te,disabled:o,title:`Edit ${i.filename} in the default Markdown app`,type:"button",onClick:()=>{u(!0),p(i.path).then(()=>{u(!1),b.success(`Opened ${i.filename}`)},n=>{u(!1),b.error(n instanceof Error?n.message:`Could not open ${i.filename}`)})},children:[o?e.jsx(f.LoaderCircle,{"aria-hidden":"true",className:"size-3.5 animate-spin"}):e.jsx(f.Pencil,{"aria-hidden":"true",className:"size-3.5"}),"Edit"]}):null,children:[e.jsx(E,{className:"max-w-full",path:i.directory,icon:e.jsx(A,{folder:i.directory})}),e.jsxs("div",{className:"flex min-w-0 flex-wrap items-center gap-2",children:[e.jsx("h4",{className:"m-0 text-sm font-semibold break-words text-[#2f382f]",children:i.filename}),i.override?e.jsx("span",{className:"rounded bg-[#f3f5f2] px-2 py-1 text-xs text-[#4a554b]",children:"override"}):null]})]}),e.jsx("div",{className:"min-w-0 overflow-x-auto px-4 pb-4 break-words",children:i.status==="loaded"?i.text.trim()&&a?e.jsxs(e.Fragment,{children:[a.entries.length?e.jsxs("details",{className:`mb-4 rounded-lg border border-[#e7ebe7]
2
- bg-[#fafbfa] px-3 py-2`,children:[e.jsxs("summary",{className:`cursor-pointer text-sm font-semibold
3
- text-[#435447]`,children:["Document details (",a.entries.length,")"]}),e.jsx("dl",{className:"mt-3 grid gap-2 text-sm",children:a.entries.map(([n,r])=>e.jsxs("div",{className:`grid grid-cols-[120px_1fr] gap-3
4
- max-[767px]:grid-cols-1`,children:[e.jsx("dt",{className:"font-semibold text-[#5a6b5c] capitalize",children:n.replaceAll(/[-_]/g," ")}),e.jsx("dd",{className:"m-0 text-[#2f382f]",children:Array.isArray(r)?r.map(String).join(", "):typeof r=="object"&&r?JSON.stringify(r):String(r??"")})]},n))})]}):null,a.body.trim()?e.jsx("div",{className:`prose prose-neutral max-w-none
5
- [&>:first-child]:mt-0 [&>:last-child]:mb-0`,children:e.jsx(q,{value:a.body})}):null]}):e.jsx("p",{className:"m-0 mt-2 text-[0.8rem] text-[#6c7a6d]",children:"(empty file)"}):e.jsx("p",{className:"m-0 mt-2 text-[0.8rem] text-[#9c3a3a]",children:i.reason??"Could not read this file"})})]})}function U({folder:s,createAction:i,onCreated:l}){const[o,u]=d.useState(!1);if(!i)return null;const p=async()=>{u(!0);try{const a=await i(s),n=a&&typeof a=="object"&&"path"in a&&typeof a.path=="string"?a.path:null;b.success(n?`Created ${O(n)} — edit it to add instructions`:"AGENTS.md created"),l()}catch(a){b.error(a instanceof Error?a.message:"Could not create AGENTS.md")}finally{u(!1)}};return e.jsxs("button",{className:se,title:`Create an empty AGENTS.md in ${s}`,disabled:o,type:"button",onClick:()=>{p()},children:[o?e.jsx(f.LoaderCircle,{"aria-hidden":"true",className:"size-3.5 animate-spin"}):e.jsx(f.FilePlus2,{"aria-hidden":"true",className:"size-3.5"}),"Create"]})}function ie({folder:s,hasOwn:i,createAction:l,onCreated:o}){return e.jsx(S,{actions:i?void 0:e.jsx(U,{createAction:l,folder:s,onCreated:o}),children:e.jsx("div",{className:"flex min-w-0 flex-wrap items-center gap-2",children:e.jsx(E,{className:"max-w-full",path:s,icon:e.jsx(A,{folder:s})})})})}function le({entry:s,createAction:i,onCreated:l}){const o=s.filenames.length>0;return e.jsx(S,{actions:o?void 0:e.jsx(U,{createAction:i,folder:s.directory,onCreated:l}),children:e.jsx("div",{className:"flex min-w-0 flex-wrap items-center gap-2",children:e.jsx(E,{className:"max-w-full",icon:e.jsx(A,{folder:s.directory}),name:O(s.directory)||"Filesystem root",path:s.directory})})})}const $={generic:{id:"generic",label:"Generic",scope:"root",files:["AGENTS.md"],filesMode:"first",globalDir:".agents",globalFiles:["AGENTS.md"],globalMode:"first",verified:!1,note:"Reference view of the ancestor AGENTS.md chain. No client execution behavior is claimed.",limits:"Walks to the filesystem root like Stepladder; only AGENTS.md files are read."},codex:{id:"codex",label:"Codex",scope:"git",files:["AGENTS.override.md","AGENTS.md"],filesMode:"first",globalDir:".codex",globalEnv:"CODEX_HOME",globalFiles:["AGENTS.override.md","AGENTS.md"],globalMode:"first",verified:!0,note:"Verified from the Codex 0.154.0 binary: reads the repository root plus every directory from the CWD up to the root, and prefers AGENTS.override.md over AGENTS.md per directory.",limits:"A configured model_instructions_file fallback is not applied here; a warning appears when it is configured."},claude:{id:"claude",label:"Claude Code",scope:"root",files:["CLAUDE.md",".claude/CLAUDE.md","CLAUDE.local.md"],filesMode:"all",globalDir:".claude",globalFiles:["CLAUDE.md"],globalMode:"first",verified:!0,note:"Verified from the Claude Code 2.1.274 binary: loads ~/.claude/CLAUDE.md and, walking to the filesystem root, each ancestor's CLAUDE.md, .claude/CLAUDE.md, and CLAUDE.local.md.",limits:"Conditional .claude/rules/*.md files and @path imports are not expanded here."},pi:{id:"pi",label:"Pi",scope:"root",files:["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"],filesMode:"first",globalDir:".pi/agent",globalEnv:"PI_CODING_AGENT_DIR",globalFiles:["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"],globalMode:"first",verified:!0,note:"Verified from the Pi 0.85.1 source (resource-loader.js): first match wins from AGENTS.override.md, AGENTS.md, AGENTS.MD, CLAUDE.md, CLAUDE.MD, in each ancestor directory and in the global directory.",limits:"Uses the same candidate list for the global directory."}},ae=[{id:"generic",label:"Generic"},{id:"codex",label:"Codex"},{id:"claude",label:"Claude Code"},{id:"pi",label:"Pi"}];function re(s){return $[s].label}function ne(s){return s==="generic"||s==="codex"||s==="claude"||s==="pi"?s:"pi"}function oe({client:s,href:i}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{className:`text-[0.78rem] font-medium tracking-wide text-[#6c7a6d]
6
- uppercase`,children:"AI client"}),e.jsxs(K,{onValueChange:l=>{window.location.href=i(l)},value:s,children:[e.jsx(J,{"aria-label":"AI client",size:"sm",className:"w-44",children:e.jsx(Q,{placeholder:"Select client"})}),e.jsx(X,{children:ae.map(l=>e.jsx(Y,{value:l.id,children:l.label},l.id))})]})]})}function de({folder:s,folderId:i,hostActions:l,href:o,request:u,subpath:p}){const a=ne(p||null),n=d.useRef(!1),r=H.useQuery({enabled:!!s,gcTime:5*6e4,queryFn:({signal:t})=>{const x=n.current?{"x-kennel-retry-linked":"1"}:void 0;return n.current=!1,u(p,{signal:t,headers:x})},queryKey:["folder",i,"agents",p??""],staleTime:15e3,refetchInterval:t=>t.state.data?.linkedStatus==="pending"?1e3:!1}),c=r.data,k=d.useMemo(()=>c?.sources??[],[c]),j=d.useMemo(()=>c?.warnings??[],[c]),m=Z(k,{allowOutside:!0,getFolder:t=>t.directory,rootFolder:s}),D=$[a],[h,P]=d.useState(!1),[g,z]=d.useState(!1),R=c?.folder??s,_=k.some(t=>t.level==="project"),T=d.useMemo(()=>(c?.chain??[]).slice(1),[c]),N=d.useMemo(()=>m.visibleItems.filter(t=>t.level==="project"),[m.visibleItems]),G=d.useMemo(()=>m.visibleItems.filter(t=>t.level==="global"),[m.visibleItems]),V=t=>m.visibleItems.filter(x=>x.directory===t),C=t=>`${t.id}:${t.clientIds.join(",")}`;return e.jsxs("div",{className:`mx-auto grid w-full max-w-5xl min-w-0 grid-cols-1 gap-4 px-4
7
- py-5`,children:[e.jsxs(M,{onOpenChange:P,open:h,children:[e.jsxs("header",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("h1",{className:"m-0 text-2xl font-semibold text-[#233025]",children:"Agents"}),e.jsx(L,{asChild:!0,children:e.jsxs("button",{"aria-expanded":h,"aria-label":h?"Hide client details":"Show client details",className:`inline-flex items-center gap-1.5 rounded-md border
8
- border-[#e7ebe7] bg-white px-2.5 py-1 text-[0.78rem] font-medium
9
- text-[#4a554b] hover:bg-[#f3f5f2] focus-visible:outline-2
10
- focus-visible:outline-[#56725e]`,type:"button",children:[e.jsx(f.Info,{className:"size-4 text-[#6c7a6d]"}),"Details",e.jsx(f.ChevronDown,{className:v("size-3.5 text-[#6c7a6d] transition-transform",h&&"rotate-180")})]})})]}),e.jsx(I,{className:`data-[state=closed]:animate-out
11
- data-[state=open]:animate-in`,children:e.jsxs("p",{className:`m-0 mt-3 flex items-start gap-2 text-[0.72rem]
12
- text-[#6c7a6d]`,children:[e.jsx(f.TriangleAlert,{className:"mt-0.5 size-3.5 shrink-0"}),e.jsxs("span",{children:[D.note," ",D.limits]})]})})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[e.jsx(oe,{client:a,href:o}),m.choices.length>1?e.jsx(B,{ariaLabel:"Filter by instruction folder",choices:m.choices,onSelect:m.setSelected,selected:m.effectiveSelected,total:m.total}):null]}),c?e.jsxs("section",{className:w,"aria-label":"Current folder instructions",children:[N.length?null:e.jsx(ie,{createAction:l?.createAgentFile,folder:R,hasOwn:_,onCreated:()=>{r.refetch()}}),N.length?e.jsx("div",{className:"grid grid-cols-1",children:N.map(t=>e.jsx(y,{hostActions:l,source:t,embedded:!0},C(t)))}):null]}):null,c?.linkedStatus==="pending"?e.jsx("p",{role:"status",className:"m-0 text-sm text-[#6c7a6d]",children:"Local instructions loaded. Looking for linked project instructions…"}):null,c?.linkedStatus==="error"?e.jsxs("p",{role:"status",className:"m-0 text-sm text-[#9c3a3a]",children:["Linked project discovery is unavailable. Local instructions are shown.",e.jsx("button",{onClick:()=>{n.current=!0,r.refetch()},children:"Retry linked instructions"})]}):null,r.isPending?e.jsx("p",{className:"m-0 text-sm text-[#6c7a6d]",children:"Loading…"}):null,r.error?e.jsxs("p",{role:"alert",className:"m-0 text-sm text-[#9c3a3a]",children:[String(r.error)," ",e.jsx("button",{onClick:()=>{r.refetch()},children:"Retry instructions"})]}):null,j.length?e.jsxs(M,{onOpenChange:z,open:g,children:[e.jsx(L,{asChild:!0,children:e.jsxs("button",{"aria-expanded":g,"aria-label":g?"Hide warnings":"Show warnings",className:`inline-flex items-center gap-1.5 rounded-md border
13
- border-[#e7ebe7] bg-white px-2.5 py-1 text-[0.78rem] font-medium
14
- text-[#4a554b] hover:bg-[#f3f5f2] focus-visible:outline-2
15
- focus-visible:outline-[#56725e]`,type:"button",children:[e.jsx(f.TriangleAlert,{className:"size-4 text-[#6c7a6d]"}),"Warnings",e.jsx("span",{className:`rounded-full bg-[#f3f5f2] px-1.5 py-0.5
16
- text-[0.68rem] text-[#6c7a6d]`,children:j.length}),e.jsx(f.ChevronDown,{className:v("size-3.5 text-[#6c7a6d] transition-transform",g&&"rotate-180")})]})}),e.jsx(I,{className:`data-[state=closed]:animate-out
17
- data-[state=open]:animate-in`,children:e.jsx("ul",{className:"m-0 mt-3 list-none space-y-1 p-0",children:j.map(t=>e.jsxs("li",{className:"text-[0.72rem] text-[#6c7a6d]",children:["path"in t?`${t.path} — `:"",t.reason," (",t.clientIds.map(x=>re(x)).join(", "),")"]},`${t.kind}:${"path"in t?t.path:""}:${t.clientIds.join(",")}`))})})]}):null,T.length?e.jsx("div",{className:"grid grid-cols-1 gap-4",children:T.map(t=>{const x=V(t.directory);return e.jsxs("section",{className:v(w,"scroll-mt-6"),"aria-label":`Instructions for ${t.directory}`,id:`agents-folder-${t.directory}`,children:[x.length?null:e.jsx(le,{createAction:l?.createAgentFile,entry:t,onCreated:()=>{r.refetch()}}),x.length?e.jsx("div",{className:"grid grid-cols-1",children:x.map(F=>e.jsx(y,{hostActions:l,source:F,embedded:!0},C(F)))}):null]},t.directory)})}):null,G.length?e.jsxs("section",{className:"scroll-mt-6",children:[e.jsxs("div",{className:"flex items-baseline gap-2",children:[e.jsx("h3",{className:"m-0 text-[0.82rem] font-semibold",style:{color:"#315c3b"},children:"Global instructions"}),e.jsx("span",{className:"text-[0.7rem] text-[#6c7a6d]",children:"Global"})]}),e.jsx("div",{className:"mt-1 grid grid-cols-1 gap-3",children:G.map(t=>e.jsx(y,{hostActions:l,source:t},C(t)))})]}):null]})}function ce(s){return e.jsx(de,{...s})}const Me={...W,component:ce};export{ce as AgentsPlugin,Me as agentsClient};
@@ -1,7 +0,0 @@
1
- import{j as t}from"./react-B9jn2M18.js";import{F as f,p as h}from"./folder-plugin-view-DsWR1zmQ.js";import{m as j}from"./tanstack-YzX_Mi37.js";import{C as m}from"./copy-context-C0Uqsp-3.js";import{l as g}from"./view-context-gyDl_p2V.js";import{a as x}from"./index-CNyy98F8.js";import{B as y}from"./button-C6arH7zt.js";import{a}from"./utils-DCaHk0Gm.js";import{F as w}from"./folder-metadata-DCw8xzHk.js";import"./markdown-Bw9RgUGR.js";import"./command-BugZBGXE.js";import"./index-CCXE8zc9.js";import"./index-DDirZMgx.js";import"./popover-DBD7FF-W.js";import"./folder-image-BfGgxo7i.js";import"./viewer-capabilities-Bpp8Uvcg.js";const l=["dependency","implementation","notes","related"];function b(r){if(typeof r!="object"||r===null)throw new Error("connected project entry must be an object");const e=r;if(typeof e.worktree!="string"||!e.worktree.trim())throw new Error("connected project entry needs a worktree path");if(!l.includes(e.type))throw new Error(`connected project type must be one of ${l.join(", ")}; got ${String(e.type)||"nothing"}`);if(e.direction!=="incoming"&&e.direction!=="outgoing")throw new Error(`connected project direction must be "incoming" or "outgoing"; got ${String(e.direction)||"nothing"}`);if(typeof e.depth!="number"||e.depth<1)throw new Error("connected project depth must be a positive number");return{repository:typeof e.repository=="string"&&e.repository.trim()?e.repository:void 0,type:e.type,direction:e.direction,depth:e.depth,worktree:e.worktree}}function N(r){if(typeof r!="object"||r===null)throw new Error("Project data is not valid.");const e=r;if(typeof e.folder!="string"||!e.folder.trim())throw new Error("Project data needs a folder path");if(e.status!=="available"&&e.status!=="error")throw new Error("Project data status must be available or error");if(!Array.isArray(e.projects))throw new Error("Project data needs a projects array");return{folder:e.folder,projects:e.projects.map(b),status:e.status,message:typeof e.message=="string"&&e.message.trim()?e.message:void 0}}function P(r,e){return["The Kennel Projects view for this folder failed. Use the context below to","diagnose the cause, then re-check the Projects tab.","","Instructions for the LLM:","- The Projects view runs Raggle Scout connected-project discovery"," (`@raggle-ai/local` listConnectedProjects) in a child process and"," renders one card per relation.",`- Folder: ${r}`,"","Failure:",e].join(`
2
- `)}function v({className:r,...e}){return t.jsx("div",{"data-slot":"card",className:a(`bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6
3
- shadow-sm`,r),...e})}function C({className:r,...e}){return t.jsx("div",{"data-slot":"card-header",className:a(`@container/card-header grid auto-rows-min grid-rows-[auto_auto]
4
- items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto]
5
- [.border-b]:pb-6`,r),...e})}function E({className:r,...e}){return t.jsx("div",{"data-slot":"card-title",className:a("leading-none font-semibold",r),...e})}function k({className:r,...e}){return t.jsx("div",{"data-slot":"card-action",className:a("col-start-2 row-span-2 row-start-1 self-start justify-self-end",r),...e})}function F({project:r}){const i=`/folder/${x(r.worktree)}/notes`;return t.jsx("article",{className:"min-w-0",children:t.jsx(v,{className:"h-full min-h-48 py-5",children:t.jsxs(C,{className:"min-w-0 gap-1.5",children:[t.jsx(E,{className:"min-w-0 break-words",children:t.jsx(w,{href:i,icon:t.jsx(f,{folder:r.worktree}),path:r.worktree,size:"large"})}),t.jsxs(k,{className:"flex items-center gap-1",children:[r.repository?t.jsx(y,{asChild:!0,size:"icon-sm",variant:"ghost",children:t.jsx("a",{"aria-label":"Open Git repository",href:r.repository,rel:"noreferrer",target:"_blank",title:"Open Git repository",children:t.jsx(g.Link,{className:"size-4"})})}):null,t.jsx(m,{context:r.worktree,label:"Copy folder path",size:"icon-sm"})]})]})})})}function I(r){const{folder:e,folderId:i,request:p,subpath:d}=r,o=j.useQuery({queryKey:["folder",i,"projects",d],queryFn:({signal:s})=>p(d,{signal:s}),staleTime:3e4}),n=o.data?(()=>{try{return N(o.data)}catch(s){return{folder:e,message:s instanceof Error&&s.message?s.message:"Could not parse the projects payload.",projects:[],status:"error"}}})():void 0,c=(o.error instanceof Error&&o.error.message?o.error.message:void 0)??(n?.status==="error"?n.message:void 0)??void 0,u=!o.error&&!n&&o.isPending;return t.jsx("main",{className:"min-h-full bg-transparent text-slate-950",children:t.jsxs("section",{className:`mx-auto grid w-full max-w-5xl min-w-0 grid-cols-1 gap-4 px-4
6
- py-5`,children:[t.jsx("h2",{className:"m-0 text-lg font-semibold",children:"Connected projects"}),u?t.jsx("p",{className:"text-muted-foreground m-0 text-sm",children:"Loading connected projects…"}):null,c?t.jsxs("div",{className:`rounded-lg border border-red-200 bg-red-50 px-3 py-2
7
- text-sm text-red-700`,children:[t.jsx("p",{className:"m-0",role:"alert",children:c}),t.jsx("button",{className:"mt-2 underline underline-offset-2",onClick:()=>{o.refetch()},type:"button",children:"Retry"}),t.jsx(m,{className:"mt-2",context:()=>P(e,c),label:"Copy full context for the Projects failure"})]}):null,n?.status==="available"?n.projects.length?t.jsx("div",{className:"grid min-w-0 grid-cols-1 gap-4",children:n.projects.map(s=>t.jsx(F,{project:s},s.worktree))}):t.jsx("p",{className:"text-muted-foreground m-0 text-sm",children:"No connected projects found."}):null]})})}function L(r){return t.jsx(I,{...r})}const D={...h,component:L};export{L as ProjectsPlugin,D as projectsClient};