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.
- package/README.md +23 -13
- package/dist/cli/dispatch.js +16 -3
- package/dist/cli/src/cli/dispatch.js +16 -3
- package/dist/cli/src/cli/usage.js +1 -1
- package/dist/cli/src/core/command.js +1 -0
- package/dist/cli/src/core/init.js +5 -5
- package/dist/cli/src/plugins/external.d.ts +28 -2
- package/dist/cli/src/plugins/external.js +77 -23
- package/dist/cli/src/site/server-plugins.d.ts +4 -9
- package/dist/cli/src/site/viewer.js +1 -0
- package/dist/cli/usage.js +1 -1
- package/dist/core/api-client.js +576 -10317
- package/dist/core/command.js +1 -0
- package/dist/core/core-folders.js +2313 -12088
- package/dist/core/init.js +5 -5
- package/dist/core/runtime.js +8237 -20713
- package/dist/package/preview.js +19617 -33352
- package/dist/plugins/external.d.ts +28 -2
- package/dist/plugins/external.js +77 -23
- package/dist/site/server-plugins.d.ts +4 -9
- package/dist/site/server-plugins.js +557 -10452
- package/dist/site/viewer.js +1 -0
- package/kernel/apps/web/package.json +2 -6
- package/kernel/apps/web/scripts/dev.mjs +53 -0
- package/kernel/apps/web/src/app.css +0 -3
- package/kernel/apps/web/src/external-plugins.ts +1 -1
- package/kernel/apps/web/src/folder-filter-icons.tsx +1 -1
- package/kernel/apps/web/src/folder-plugin-view.tsx +1 -1
- package/kernel/apps/web/src/main.tsx +0 -1
- package/kernel/apps/web/src/plugins.ts +1 -31
- package/kernel/apps/web/tsconfig.json +1 -2
- package/kernel/apps/web/vite.config.ts +32 -14
- package/kernel/packages/agents/package.json +1 -1
- package/kernel/packages/agents/src/agent-card.tsx +1 -1
- package/kernel/packages/agents/src/client.tsx +1 -1
- package/kernel/packages/agents/src/manifest.ts +1 -1
- package/kernel/packages/agents/src/server.ts +1 -1
- package/kernel/packages/agents/src/viewer.tsx +1 -1
- package/kernel/packages/api/package.json +1 -5
- package/kernel/packages/api/src/server/acp-live-plugin.ts +1 -1
- package/kernel/packages/api/src/server/api/create-agent-file.ts +2 -2
- package/kernel/packages/api/src/server/api/document-edit.ts +2 -2
- package/kernel/packages/api/src/server/api/open-path.ts +2 -2
- package/kernel/packages/api/src/server/folder-metadata-plugin.ts +17 -42
- package/kernel/packages/api/src/server/index.ts +0 -1
- package/kernel/packages/api/src/server/plugins.ts +52 -19
- package/kernel/packages/api/src/shared/viewer-route.ts +1 -1
- package/kernel/packages/api/test/core.test.ts +14 -26
- package/kernel/packages/markdown/README.md +1 -1
- package/kernel/packages/notes/package.json +1 -1
- package/kernel/packages/notes/src/client.tsx +1 -1
- package/kernel/packages/notes/src/manifest.ts +1 -1
- package/kernel/packages/notes/src/server.ts +1 -1
- package/kernel/packages/plugins/SKILL.md +39 -0
- package/kernel/{plugins/mail → packages/plugins}/package.json +53 -28
- package/kernel/packages/plugins/src/index.ts +52 -0
- package/kernel/packages/plugins/src/page.ts +17 -0
- package/kernel/{plugins/projects → packages/plugins}/tsconfig.json +5 -1
- package/kernel/packages/plugins/tsup.config.ts +25 -0
- package/kernel/packages/ui/src/components/content-issues.tsx +1 -1
- package/kernel/packages/ui/tsconfig.json +1 -1
- package/package.json +2 -3
- package/web/assets/{abnfDiagram-VRR7QNED-Bgfb1nEB.js → abnfDiagram-VRR7QNED-xd_g1uK3.js} +1 -1
- package/web/assets/app-CX20nNIa.js +2 -0
- package/web/assets/{app-options-D-RJiQ-X.js → app-options-CkPJE5ep.js} +1 -1
- package/web/assets/{app-view-header-BLvLq02T.js → app-view-header-CNk5KnA-.js} +1 -1
- package/web/assets/{arc-Dk_KI36B.js → arc-B0u5yBJA.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-NR_KhRCf.js → architectureDiagram-ZJ3FMSHR-DfxOAo8P.js} +1 -1
- package/web/assets/{ask-tray-TzeTcO6-.js → ask-tray-SscJecDY.js} +1 -1
- package/web/assets/{blockDiagram-677ZJIJ3-CkLkwx9C.js → blockDiagram-677ZJIJ3-Ci3Usxh6.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-CFCUH8e_.js → c4Diagram-LMCZKHZV-BqgwIVgh.js} +1 -1
- package/web/assets/channel-X7WHyxxT.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-B_BPLWsW.js → chunk-2Q5K7J3B-CfX69l2U.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-B1VB1hOy.js → chunk-32BRIVSS-CuFlzZkl.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-KFcYr8Co.js → chunk-5VM5RSS4-DidCMlJa.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-CpBX3kuK.js → chunk-EX3LRPZG-B5CDm1dS.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-BPSl40wG.js → chunk-JWPE2WC7-D5fGV_sH.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-D2RcYmoU.js → chunk-MOJQB5TN-ayhH5Q-H.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-m7Gyn-t3.js → chunk-RYQCIY6F-C4BfOOZn.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-TDvdopxS.js → chunk-V7JOEXUC-DpUEIM9V.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-DZTsG51a.js → chunk-VR4S4FIN-DoQuFFRh.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-Dp0--RE2.js → chunk-XXDRQBXY-CI9eiLwn.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +1 -0
- package/web/assets/client-7OWw5kW2.js +6 -0
- package/web/assets/client-DYj_td4Q.js +17 -0
- package/web/assets/{client-j2kQmxsO.js → client-Dk-NBvJR.js} +4 -4
- package/web/assets/command-zkzH4hVz.js +38 -0
- package/web/assets/{copy-context-C0Uqsp-3.js → copy-context-D5oiWrYC.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-CPu3PI8h.js → cose-bilkent-JH36ORCC-BHRk1mO3.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-DWxftYAm.js → cynefin-VYW2F7L2-C1B09TRE.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-DsmN2V-p.js → cynefinDiagram-TSTJHNR4-B27qXQbv.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-COEbApyY.js → dagre-VKFMJZFB-B1qEi32g.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-0O9WGWKB.js → diagram-FQU43EPY-BMkkgADD.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-CutEdMVh.js → diagram-G47NLZAW-Cb8_g1A5.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-C9KZc3B2.js → diagram-NH7WQ7WH-B51wuc5m.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-D8kkPXbY.js → diagram-OA4YK3LP-xnsecbbI.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-_YqiTaGP.js → diagram-WEI45ONY-DSZdyaAV.js} +1 -1
- package/web/assets/{document-Dgt5eZFj.js → document-Dc2dftTW.js} +3 -3
- package/web/assets/{ebnfDiagram-CCIWWBDH-JO-zQh6g.js → ebnfDiagram-CCIWWBDH-aTHmcUGy.js} +1 -1
- package/web/assets/{entities-C3wz7FCx.js → entities-CCUtpskY.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-9UjQwJ4P.js → erDiagram-Q63AITRT-CUUPBcvo.js} +1 -1
- package/web/assets/{file-viewer-DZJ8nYnl.js → file-viewer-DJ3rsmef.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-Ca08tnYM.js → flowDiagram-23GEKE2U-aTQXx2Mh.js} +1 -1
- package/web/assets/{folder-image-BfGgxo7i.js → folder-image-Bnv43tzP.js} +1 -1
- package/web/assets/{folder-landing-qUKBCnG-.js → folder-landing-DCnzYXXY.js} +1 -1
- package/web/assets/{folder-list-BfFjv7rR.js → folder-list-DvVkVjiR.js} +1 -1
- package/web/assets/{folder-metadata-DCw8xzHk.js → folder-metadata-C9hMMzIH.js} +1 -1
- package/web/assets/{folder-mobile-bar-Ubz4babf.js → folder-mobile-bar-VoTL1GS0.js} +1 -1
- package/web/assets/folder-plugin-view-Cvd804ZU.js +6 -0
- package/web/assets/{ganttDiagram-NO4QXBWP-KnHzX5W3.js → ganttDiagram-NO4QXBWP-DiwdUp7u.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-Cm8woNtK.js → gitGraphDiagram-IHSO6WYX-BL2gG_IS.js} +1 -1
- package/web/assets/{index-CNyy98F8.js → index-CUTtMSyJ.js} +2 -2
- package/web/assets/index-CegvVQ1C.js +1 -0
- package/web/assets/index-Dwhf8F_U.css +1 -0
- package/web/assets/{infoDiagram-FWYZ7A6U-yyqmUtIb.js → infoDiagram-FWYZ7A6U-B3n0zZpt.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-BfvR_Zy4.js → ishikawaDiagram-FXEZZL3T-D7YytbEv.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BKuw06HM.js → journeyDiagram-5HDEW3XC-BYwqEl3C.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-n0010rmQ.js → kanban-definition-HUTT4EX6-BQHNJgXZ.js} +1 -1
- package/web/assets/{linear-C0d0lT8O.js → linear-BPiQCLNk.js} +1 -1
- package/web/assets/{mermaid.core-BDVbShyO.js → mermaid.core-CD-KvBjV.js} +4 -4
- package/web/assets/{metadata-KV0dpp4G.js → metadata-COJ7fZul.js} +1 -1
- package/web/assets/{mindmap-definition-LN4V7U3C--_0ks3GF.js → mindmap-definition-LN4V7U3C-C1L_gyoj.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-CBoNIpKR.js → pegDiagram-2B236MQR-BDAfItqS.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-MA5tkYh5.js → pieDiagram-ENE6RG2P-CkZYH3Vz.js} +1 -1
- package/web/assets/{popover-DBD7FF-W.js → popover-0oA2lLUV.js} +2 -2
- package/web/assets/{project-search-dialog-DM1IkSZu.js → project-search-dialog-B2oqMT6h.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-CWT1ryqF.js → quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-ZiLB5FGi.js → railroadDiagram-RFXS5EU6-Dd9_yo7B.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-CQq9uneq.js → requirementDiagram-TGXJPOKE-DPhIUsbs.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-qDG-0JqI.js → sankeyDiagram-HTMAVEWB-B2QkYtub.js} +1 -1
- package/web/assets/{search-DNrQA5fF.js → search-C1J0-xiB.js} +1 -1
- package/web/assets/select-CtXC_PLC.js +30 -0
- package/web/assets/{selection-popup-DmtTeRs2.js → selection-popup-qhlUFzGq.js} +1 -1
- package/web/assets/{sequenceDiagram-DBY2YBRQ-CiApurLO.js → sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-DZSR5QXm.js → sizeCapture-X5ZJPWSS-CIXIhl_A.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-CjJJR9_z.js → stateDiagram-2N3HPSRC-DCrdAflB.js} +1 -1
- package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +1 -0
- package/web/assets/{swimlanes-5IMT3BWC-CKmo1sg6.js → swimlanes-5IMT3BWC-DA2vc7iZ.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-D-NMwS3y.js → timeline-definition-FHXFAJF6-lKfJiV9V.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-CfL6LBWw.js → vennDiagram-L72KCM5P-DO1q2KzG.js} +1 -1
- package/web/assets/{view-context-gyDl_p2V.js → view-context-DXKM3-l1.js} +4 -4
- package/web/assets/{viewer-capabilities-Bpp8Uvcg.js → viewer-capabilities-Cig_xM9u.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-DgldMxaj.js → wardleyDiagram-EHGQE667-Dal9LkuZ.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-CIoAIFX8.js → xychartDiagram-FW5EYKEG-B3dPLPII.js} +1 -1
- package/web/index.html +2 -2
- package/kernel/packages/api/test/partial-loading.test.ts +0 -43
- package/kernel/packages/folder-plugin/package.json +0 -50
- package/kernel/packages/folder-plugin/src/index.ts +0 -15
- package/kernel/packages/folder-plugin/tsconfig.json +0 -17
- package/kernel/plugins/calendar/SKILL.md +0 -173
- package/kernel/plugins/calendar/eslint.config.js +0 -10
- package/kernel/plugins/calendar/package.json +0 -73
- package/kernel/plugins/calendar/schema.json +0 -137
- package/kernel/plugins/calendar/src/calendar.tsx +0 -328
- package/kernel/plugins/calendar/src/client.tsx +0 -139
- package/kernel/plugins/calendar/src/context.ts +0 -48
- package/kernel/plugins/calendar/src/copy-button.tsx +0 -66
- package/kernel/plugins/calendar/src/event-dialog.tsx +0 -270
- package/kernel/plugins/calendar/src/index.ts +0 -4
- package/kernel/plugins/calendar/src/manifest.ts +0 -7
- package/kernel/plugins/calendar/src/parse.ts +0 -610
- package/kernel/plugins/calendar/src/server.ts +0 -160
- package/kernel/plugins/calendar/src/utils.ts +0 -80
- package/kernel/plugins/calendar/src/views.tsx +0 -418
- package/kernel/plugins/calendar/test/context.test.mjs +0 -60
- package/kernel/plugins/calendar/test/package.test.mjs +0 -43
- package/kernel/plugins/calendar/test/parse.test.mjs +0 -392
- package/kernel/plugins/calendar/test/server.test.mjs +0 -126
- package/kernel/plugins/calendar/tsconfig.json +0 -17
- package/kernel/plugins/mail/SKILL.md +0 -97
- package/kernel/plugins/mail/eslint.config.js +0 -10
- package/kernel/plugins/mail/src/api.ts +0 -359
- package/kernel/plugins/mail/src/bun-ffi.d.ts +0 -14
- package/kernel/plugins/mail/src/client.tsx +0 -14
- package/kernel/plugins/mail/src/flock.ts +0 -137
- package/kernel/plugins/mail/src/folders.ts +0 -37
- package/kernel/plugins/mail/src/history.ts +0 -485
- package/kernel/plugins/mail/src/index.ts +0 -3
- package/kernel/plugins/mail/src/mail-card.tsx +0 -123
- package/kernel/plugins/mail/src/mail-conversation.tsx +0 -153
- package/kernel/plugins/mail/src/mail-detail-page.tsx +0 -467
- package/kernel/plugins/mail/src/mail-hooks.ts +0 -252
- package/kernel/plugins/mail/src/mail-page.tsx +0 -109
- package/kernel/plugins/mail/src/mail-request.ts +0 -78
- package/kernel/plugins/mail/src/mail-send-box.tsx +0 -175
- package/kernel/plugins/mail/src/mailos.ts +0 -723
- package/kernel/plugins/mail/src/manifest.ts +0 -7
- package/kernel/plugins/mail/src/node.ts +0 -171
- package/kernel/plugins/mail/src/parse.ts +0 -139
- package/kernel/plugins/mail/src/server.ts +0 -125
- package/kernel/plugins/mail/src/types.ts +0 -10
- package/kernel/plugins/mail/src/viewer.tsx +0 -147
- package/kernel/plugins/mail/test/flock.test.mjs +0 -156
- package/kernel/plugins/mail/test/folders.test.mjs +0 -138
- package/kernel/plugins/mail/test/history.test.mjs +0 -460
- package/kernel/plugins/mail/test/mailos.test.mjs +0 -752
- package/kernel/plugins/mail/test/node.test.mjs +0 -207
- package/kernel/plugins/mail/test/package.test.mjs +0 -54
- package/kernel/plugins/mail/test/parse.test.mjs +0 -32
- package/kernel/plugins/mail/test/server.test.mjs +0 -116
- package/kernel/plugins/mail/test/viewer.test.mjs +0 -192
- package/kernel/plugins/mail/tsconfig.json +0 -17
- package/kernel/plugins/projects/SKILL.md +0 -73
- package/kernel/plugins/projects/eslint.config.js +0 -10
- package/kernel/plugins/projects/package.json +0 -70
- package/kernel/plugins/projects/src/client.tsx +0 -17
- package/kernel/plugins/projects/src/data/model.ts +0 -129
- package/kernel/plugins/projects/src/index.ts +0 -17
- package/kernel/plugins/projects/src/manifest.ts +0 -7
- package/kernel/plugins/projects/src/project-context.ts +0 -41
- package/kernel/plugins/projects/src/server.ts +0 -276
- package/kernel/plugins/projects/src/ui/project-card.tsx +0 -61
- package/kernel/plugins/projects/src/ui/projects-page.tsx +0 -102
- package/kernel/plugins/projects/test/package.test.mjs +0 -51
- package/kernel/plugins/tasks/SKILL.md +0 -341
- package/kernel/plugins/tasks/eslint.config.js +0 -10
- package/kernel/plugins/tasks/package.json +0 -74
- package/kernel/plugins/tasks/schema.json +0 -939
- package/kernel/plugins/tasks/src/api.ts +0 -212
- package/kernel/plugins/tasks/src/client.tsx +0 -23
- package/kernel/plugins/tasks/src/data/parse.ts +0 -544
- package/kernel/plugins/tasks/src/data/task-id.ts +0 -56
- package/kernel/plugins/tasks/src/data/todo-model.ts +0 -795
- package/kernel/plugins/tasks/src/index.ts +0 -34
- package/kernel/plugins/tasks/src/manifest.ts +0 -7
- package/kernel/plugins/tasks/src/pages/task-detail.tsx +0 -48
- package/kernel/plugins/tasks/src/pages/task-list.tsx +0 -88
- package/kernel/plugins/tasks/src/server.ts +0 -447
- package/kernel/plugins/tasks/src/styles.css +0 -9
- package/kernel/plugins/tasks/src/ui/compact-todo-list.tsx +0 -372
- package/kernel/plugins/tasks/src/ui/error-details.tsx +0 -78
- package/kernel/plugins/tasks/src/ui/task-page.tsx +0 -392
- package/kernel/plugins/tasks/src/ui/todo-agent-filter.tsx +0 -36
- package/kernel/plugins/tasks/src/ui/todo-filter-bar.tsx +0 -66
- package/kernel/plugins/tasks/src/ui/todo-item.tsx +0 -494
- package/kernel/plugins/tasks/src/ui/todo-status-filter.tsx +0 -60
- package/kernel/plugins/tasks/src/ui/todo-tag-filter.tsx +0 -48
- package/kernel/plugins/tasks/src/ui/todo-warnings.tsx +0 -106
- package/kernel/plugins/tasks/test/api.test.mjs +0 -99
- package/kernel/plugins/tasks/test/folder-sources.test.mjs +0 -46
- package/kernel/plugins/tasks/test/package.test.mjs +0 -54
- package/kernel/plugins/tasks/test/parse.test.mjs +0 -225
- package/kernel/plugins/tasks/test/server.test.mjs +0 -386
- package/kernel/plugins/tasks/tsconfig.json +0 -17
- package/web/assets/app-DoGr2Zi7.js +0 -2
- package/web/assets/channel-uMEjV8qc.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-fbZocVor.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-fbZocVor.js +0 -1
- package/web/assets/client-C6Nxdfif.js +0 -2
- package/web/assets/client-CXYfBko5.js +0 -17
- package/web/assets/client-CoKtOq-X.js +0 -7
- package/web/assets/client-DyRQz5RU.js +0 -53
- package/web/assets/client-OY6HUzuD.js +0 -98
- package/web/assets/client-YOYWZIFi.js +0 -34
- package/web/assets/command-BugZBGXE.js +0 -38
- package/web/assets/folder-plugin-view-DsWR1zmQ.js +0 -6
- package/web/assets/index-BaRnbYRw.js +0 -1
- package/web/assets/index-BexmLxIP.css +0 -1
- package/web/assets/index-DDirZMgx.js +0 -1
- package/web/assets/note-card-DBfX6gW1.js +0 -6
- package/web/assets/select-D8cqNgcp.js +0 -30
- package/web/assets/stateDiagram-v2-6OUMAXLB-BpeGSCu9.js +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-D9RjLKb9.js +0 -8
- package/web/assets/use-folder-filter-LQyXns5Q.js +0 -1
- /package/kernel/packages/{folder-plugin → plugins}/eslint.config.js +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/client.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/endpoint.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/server.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/subpath.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/types.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/src/validation.ts +0 -0
- /package/kernel/packages/{folder-plugin → plugins}/test/contract.test.mjs +0 -0
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react"
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react"
|
|
3
|
-
import { Effect } from "effect"
|
|
4
|
-
import { Check, ChevronRight } from "lucide-react"
|
|
5
|
-
|
|
6
|
-
import { CopyContextButton } from "@raggle-ai/ui/components/copy-context"
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
JsonTodo,
|
|
10
|
-
TodoDataset,
|
|
11
|
-
TodoDatasetOptions,
|
|
12
|
-
TodoFilter,
|
|
13
|
-
TodoFilterSelection,
|
|
14
|
-
TodoState,
|
|
15
|
-
UiTodoItem,
|
|
16
|
-
} from "../data/todo-model.js"
|
|
17
|
-
import { qualifiedTaskId } from "../data/task-id.js"
|
|
18
|
-
import {
|
|
19
|
-
fetchTodoDataset,
|
|
20
|
-
initialState,
|
|
21
|
-
visibleTodos,
|
|
22
|
-
} from "../data/todo-model.js"
|
|
23
|
-
import { TodoFilterBar } from "./todo-filter-bar.js"
|
|
24
|
-
import { todoItemContext } from "./todo-item.js"
|
|
25
|
-
|
|
26
|
-
export type CompactTodoListProps = TodoDatasetOptions & {
|
|
27
|
-
readonly dataset?: TodoDataset | null
|
|
28
|
-
readonly className?: string
|
|
29
|
-
/** When set, each task title links to this href (a task detail view). */
|
|
30
|
-
readonly itemHref?: (item: UiTodoItem) => string | undefined
|
|
31
|
-
/** When set, rows get a complete/reopen tick button. */
|
|
32
|
-
readonly onToggle?: (item: UiTodoItem) => void
|
|
33
|
-
/** When set, the status/tag/agent filter line is shown. */
|
|
34
|
-
readonly filters?: boolean
|
|
35
|
-
/** Filter controls rendered in front of the filter line (e.g. folder
|
|
36
|
-
* chips), so all filter areas share one horizontal row. */
|
|
37
|
-
readonly leadingFilters?: ReactNode
|
|
38
|
-
/** Controls rendered at the right end of the filter line (e.g. the
|
|
39
|
-
* warnings modal trigger). */
|
|
40
|
-
readonly trailingFilters?: ReactNode
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function CompactTodoList({
|
|
44
|
-
dataset = null,
|
|
45
|
-
className = "",
|
|
46
|
-
filters = false,
|
|
47
|
-
leadingFilters,
|
|
48
|
-
trailingFilters,
|
|
49
|
-
itemHref,
|
|
50
|
-
onToggle,
|
|
51
|
-
...options
|
|
52
|
-
}: CompactTodoListProps) {
|
|
53
|
-
const [filter, setFilter] = useState<TodoFilter>(initialState.filter)
|
|
54
|
-
const [tag, setTag] = useState<TodoFilterSelection>([])
|
|
55
|
-
const [assignee, setAssignee] = useState<TodoFilterSelection>([])
|
|
56
|
-
// URL-driven usage (no `dataset` prop) fetches the dataset itself.
|
|
57
|
-
const [fetched, setFetched] = useState<TodoDataset | null>(null)
|
|
58
|
-
const [error, setError] = useState<string | null>(null)
|
|
59
|
-
|
|
60
|
-
const activeDataset = dataset ?? fetched
|
|
61
|
-
|
|
62
|
-
// Fetch only when a dataset is not provided by the caller. State updates
|
|
63
|
-
// happen inside the promise callback, never synchronously in the effect.
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
if (dataset) return
|
|
66
|
-
let cancelled = false
|
|
67
|
-
void Effect.runPromise(
|
|
68
|
-
Effect.either(
|
|
69
|
-
fetchTodoDataset({
|
|
70
|
-
dataUrl: options.dataUrl,
|
|
71
|
-
path: options.path,
|
|
72
|
-
schemaUrl: options.schemaUrl,
|
|
73
|
-
}),
|
|
74
|
-
),
|
|
75
|
-
).then((result) => {
|
|
76
|
-
if (cancelled) return
|
|
77
|
-
if (result._tag === "Left") {
|
|
78
|
-
setError(result.left.message)
|
|
79
|
-
} else {
|
|
80
|
-
setError(null)
|
|
81
|
-
setFetched(result.right)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
return () => {
|
|
85
|
-
cancelled = true
|
|
86
|
-
}
|
|
87
|
-
}, [dataset, options.dataUrl, options.path, options.schemaUrl])
|
|
88
|
-
|
|
89
|
-
const todos = useMemo(() => {
|
|
90
|
-
const state: TodoState = {
|
|
91
|
-
...initialState,
|
|
92
|
-
dataset: activeDataset,
|
|
93
|
-
filter,
|
|
94
|
-
tag,
|
|
95
|
-
assignee,
|
|
96
|
-
}
|
|
97
|
-
return Effect.runSync(visibleTodos(state))
|
|
98
|
-
}, [activeDataset, filter, tag, assignee])
|
|
99
|
-
const loading = !activeDataset && !error
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<main
|
|
103
|
-
className={["min-h-full bg-transparent text-slate-950", className]
|
|
104
|
-
.filter(Boolean)
|
|
105
|
-
.join(" ")}
|
|
106
|
-
>
|
|
107
|
-
<section className="mx-auto w-full max-w-3xl px-3 py-4 sm:px-5 sm:py-5">
|
|
108
|
-
{error ? (
|
|
109
|
-
<p
|
|
110
|
-
className="mb-3 rounded-lg border border-red-200 bg-red-50 px-3 py-2
|
|
111
|
-
text-sm text-red-700"
|
|
112
|
-
>
|
|
113
|
-
{error}
|
|
114
|
-
</p>
|
|
115
|
-
) : null}
|
|
116
|
-
|
|
117
|
-
{filters ? (
|
|
118
|
-
<TodoFilterBar
|
|
119
|
-
assignee={assignee}
|
|
120
|
-
className="mb-3"
|
|
121
|
-
dataset={activeDataset}
|
|
122
|
-
filter={filter}
|
|
123
|
-
leading={leadingFilters}
|
|
124
|
-
trailing={trailingFilters}
|
|
125
|
-
onAssigneeChange={setAssignee}
|
|
126
|
-
onFilterChange={setFilter}
|
|
127
|
-
onTagChange={setTag}
|
|
128
|
-
tag={tag}
|
|
129
|
-
/>
|
|
130
|
-
) : null}
|
|
131
|
-
|
|
132
|
-
{loading ? (
|
|
133
|
-
<p className="py-8 text-center text-sm text-slate-500">
|
|
134
|
-
Loading tasks…
|
|
135
|
-
</p>
|
|
136
|
-
) : todos.length === 0 ? (
|
|
137
|
-
<p className="py-8 text-center text-sm text-slate-500">
|
|
138
|
-
{emptyFilterText(filter, tag)}
|
|
139
|
-
</p>
|
|
140
|
-
) : (
|
|
141
|
-
<ol className="space-y-2">
|
|
142
|
-
{todos.map((item) => (
|
|
143
|
-
<CompactTodoRow
|
|
144
|
-
// Row identity uses the workspace-qualified address, not the
|
|
145
|
-
// bare file-local id: merged nested task files repeat ids
|
|
146
|
-
// like "todo:0" across folders.
|
|
147
|
-
key={
|
|
148
|
-
qualifiedTaskId(item.jsonTodo.source?.id, item.jsonTodo) ??
|
|
149
|
-
item.id
|
|
150
|
-
}
|
|
151
|
-
item={item}
|
|
152
|
-
folderPath={options.path}
|
|
153
|
-
itemHref={itemHref}
|
|
154
|
-
onToggle={onToggle}
|
|
155
|
-
/>
|
|
156
|
-
))}
|
|
157
|
-
</ol>
|
|
158
|
-
)}
|
|
159
|
-
</section>
|
|
160
|
-
</main>
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function CompactTodoRow({
|
|
165
|
-
item,
|
|
166
|
-
folderPath,
|
|
167
|
-
itemHref,
|
|
168
|
-
onToggle,
|
|
169
|
-
}: {
|
|
170
|
-
item: UiTodoItem
|
|
171
|
-
folderPath?: string
|
|
172
|
-
itemHref?: (item: UiTodoItem) => string | undefined
|
|
173
|
-
onToggle?: (item: UiTodoItem) => void
|
|
174
|
-
}) {
|
|
175
|
-
const meta = compactMeta(item)
|
|
176
|
-
const href = itemHref?.(item)
|
|
177
|
-
// Build the prompt on click (wait function), not on render.
|
|
178
|
-
const context = useCallback(
|
|
179
|
-
() => compactTodoPrompt(item, folderPath),
|
|
180
|
-
[item, folderPath],
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<li
|
|
185
|
-
// One border/background style per row: Tailwind sorts same-property
|
|
186
|
-
// classes alphabetically, so stacked classes override each other.
|
|
187
|
-
className={[
|
|
188
|
-
"rounded-md border px-3 py-2",
|
|
189
|
-
item.overdue
|
|
190
|
-
? "border-red-400 bg-red-50"
|
|
191
|
-
: item.status === "blocked"
|
|
192
|
-
? "border-rose-300 bg-rose-50/60"
|
|
193
|
-
: "border-slate-200 bg-white",
|
|
194
|
-
]
|
|
195
|
-
.filter(Boolean)
|
|
196
|
-
.join(" ")}
|
|
197
|
-
>
|
|
198
|
-
<div className="flex items-start gap-3">
|
|
199
|
-
{onToggle ? (
|
|
200
|
-
<button
|
|
201
|
-
type="button"
|
|
202
|
-
aria-pressed={item.status === "done"}
|
|
203
|
-
aria-label={
|
|
204
|
-
item.status === "done"
|
|
205
|
-
? `Reopen ${item.title}`
|
|
206
|
-
: `Complete ${item.title}`
|
|
207
|
-
}
|
|
208
|
-
title={item.status === "done" ? "Reopen task" : "Complete task"}
|
|
209
|
-
onClick={() => onToggle(item)}
|
|
210
|
-
className={[
|
|
211
|
-
"mt-0.5 grid h-5 w-5 shrink-0 place-items-center rounded-full",
|
|
212
|
-
"border transition-colors",
|
|
213
|
-
item.status === "done"
|
|
214
|
-
? "border-emerald-500 bg-emerald-500 text-white hover:bg-emerald-600"
|
|
215
|
-
: item.status === "blocked"
|
|
216
|
-
? "border-rose-300 bg-rose-100 text-rose-600"
|
|
217
|
-
: "border-slate-300 bg-white text-transparent hover:border-emerald-500 hover:bg-emerald-50 hover:text-emerald-600",
|
|
218
|
-
].join(" ")}
|
|
219
|
-
>
|
|
220
|
-
<Check className="h-3 w-3" />
|
|
221
|
-
</button>
|
|
222
|
-
) : null}
|
|
223
|
-
<div className="min-w-0 flex-1 space-y-1">
|
|
224
|
-
{href ? (
|
|
225
|
-
<a
|
|
226
|
-
href={href}
|
|
227
|
-
className={[
|
|
228
|
-
"inline-flex items-center gap-1 text-sm leading-5 font-medium",
|
|
229
|
-
"text-slate-900 no-underline hover:text-indigo-700",
|
|
230
|
-
item.status === "done" ? "text-slate-500 line-through" : "",
|
|
231
|
-
]
|
|
232
|
-
.filter(Boolean)
|
|
233
|
-
.join(" ")}
|
|
234
|
-
>
|
|
235
|
-
<span>{item.title}</span>
|
|
236
|
-
<ChevronRight
|
|
237
|
-
aria-hidden="true"
|
|
238
|
-
className="h-3.5 w-3.5 text-slate-400"
|
|
239
|
-
/>
|
|
240
|
-
</a>
|
|
241
|
-
) : (
|
|
242
|
-
<p
|
|
243
|
-
className={[
|
|
244
|
-
"text-sm leading-5 font-medium text-slate-900",
|
|
245
|
-
item.status === "done" ? "text-slate-500 line-through" : "",
|
|
246
|
-
].join(" ")}
|
|
247
|
-
>
|
|
248
|
-
{item.title}
|
|
249
|
-
</p>
|
|
250
|
-
)}
|
|
251
|
-
{meta.status || meta.folder ? (
|
|
252
|
-
<p className="text-xs leading-4 text-slate-500">
|
|
253
|
-
{meta.status ? (
|
|
254
|
-
<span
|
|
255
|
-
className={item.overdue ? "font-medium text-red-600" : ""}
|
|
256
|
-
>
|
|
257
|
-
{meta.status}
|
|
258
|
-
</span>
|
|
259
|
-
) : null}
|
|
260
|
-
{meta.folder ? (
|
|
261
|
-
<span>
|
|
262
|
-
{meta.status ? " • " : ""}
|
|
263
|
-
{meta.folder}
|
|
264
|
-
</span>
|
|
265
|
-
) : null}
|
|
266
|
-
</p>
|
|
267
|
-
) : null}
|
|
268
|
-
</div>
|
|
269
|
-
<CopyContextButton
|
|
270
|
-
className="shrink-0 text-slate-500 hover:text-slate-900"
|
|
271
|
-
context={context}
|
|
272
|
-
label={`Copy prompt for ${item.title}`}
|
|
273
|
-
/>
|
|
274
|
-
</div>
|
|
275
|
-
</li>
|
|
276
|
-
)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const emptyFilterText = (filter: TodoFilter, tag: TodoFilterSelection) => {
|
|
280
|
-
const status =
|
|
281
|
-
filter === "done"
|
|
282
|
-
? "done"
|
|
283
|
-
: filter === "blocked"
|
|
284
|
-
? "blocked"
|
|
285
|
-
: filter === "overdue"
|
|
286
|
-
? "late"
|
|
287
|
-
: filter === "all"
|
|
288
|
-
? ""
|
|
289
|
-
: "open"
|
|
290
|
-
if (tag.length)
|
|
291
|
-
return `No ${status ? `${status} ` : ""}tasks with the selected tags`
|
|
292
|
-
switch (filter) {
|
|
293
|
-
case "done":
|
|
294
|
-
return "No done tasks"
|
|
295
|
-
case "blocked":
|
|
296
|
-
return "No blocked tasks"
|
|
297
|
-
case "overdue":
|
|
298
|
-
return "No late tasks"
|
|
299
|
-
case "all":
|
|
300
|
-
return "No tasks"
|
|
301
|
-
default:
|
|
302
|
-
return "No open tasks"
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/** Row meta: the status label, then the folder the task file lives in. */
|
|
307
|
-
const compactMeta = (item: UiTodoItem) => ({
|
|
308
|
-
status:
|
|
309
|
-
item.status === "blocked"
|
|
310
|
-
? "Blocked"
|
|
311
|
-
: item.overdue
|
|
312
|
-
? "Late"
|
|
313
|
-
: item.status === "done"
|
|
314
|
-
? "Done"
|
|
315
|
-
: "",
|
|
316
|
-
folder: item.jsonTodo.source.title.replace(/ tasks$/, ""),
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
const compactTodoPrompt = (item: UiTodoItem, folderPath?: string) => {
|
|
320
|
-
const todoJsonPath = folderPath ? `${folderPath}/todo.json` : "todo.json"
|
|
321
|
-
const relatedFiles = relatedReadFiles(item.jsonTodo)
|
|
322
|
-
|
|
323
|
-
return [
|
|
324
|
-
`The model is instructed to complete this specific todo: ${item.title}`,
|
|
325
|
-
"",
|
|
326
|
-
todoItemContext(item),
|
|
327
|
-
"",
|
|
328
|
-
`Todo JSON: ${todoJsonPath}`,
|
|
329
|
-
relatedFiles.length ? "Read these relative files before you start:" : null,
|
|
330
|
-
relatedFiles.length
|
|
331
|
-
? relatedFiles.map((path) => `- ${path}`).join("\n")
|
|
332
|
-
: null,
|
|
333
|
-
]
|
|
334
|
-
.filter((line): line is string => Boolean(line))
|
|
335
|
-
.join("\n")
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const relatedReadFiles = (todo: JsonTodo) =>
|
|
339
|
-
unique(relativePathsFromCustomFields(todo.customFields))
|
|
340
|
-
|
|
341
|
-
const relativePathsFromCustomFields = (
|
|
342
|
-
fields: ReadonlyArray<{ id: string; value: unknown }>,
|
|
343
|
-
) =>
|
|
344
|
-
fields.flatMap((field) =>
|
|
345
|
-
fileFieldName(field.id) ? relativePathsFromValue(field.value) : [],
|
|
346
|
-
)
|
|
347
|
-
|
|
348
|
-
const fileFieldName = (value: string) =>
|
|
349
|
-
/(file|path|read|context|source|doc)/i.test(value)
|
|
350
|
-
|
|
351
|
-
const relativePathsFromValue = (value: unknown): string[] => {
|
|
352
|
-
if (typeof value === "string") {
|
|
353
|
-
return isRelativeFilePath(value) ? [value] : []
|
|
354
|
-
}
|
|
355
|
-
if (Array.isArray(value)) {
|
|
356
|
-
return value.flatMap((entry) => relativePathsFromValue(entry))
|
|
357
|
-
}
|
|
358
|
-
if (value && typeof value === "object") {
|
|
359
|
-
return Object.entries(value).flatMap(([key, entry]) =>
|
|
360
|
-
fileFieldName(key) ? relativePathsFromValue(entry) : [],
|
|
361
|
-
)
|
|
362
|
-
}
|
|
363
|
-
return []
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const isRelativeFilePath = (value: string) =>
|
|
367
|
-
Boolean(value) &&
|
|
368
|
-
!value.startsWith("/") &&
|
|
369
|
-
!/^[a-z]+:\/\//i.test(value) &&
|
|
370
|
-
/[./\\]/.test(value)
|
|
371
|
-
|
|
372
|
-
const unique = (values: ReadonlyArray<string>) => [...new Set(values)]
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react"
|
|
2
|
-
import { useState } from "react"
|
|
3
|
-
import { ChevronDown } from "lucide-react"
|
|
4
|
-
|
|
5
|
-
import type { CopyContextSource } from "@raggle-ai/ui/components/copy-context"
|
|
6
|
-
import { Button } from "@raggle-ai/ui/components/button"
|
|
7
|
-
import { CopyContextButton } from "@raggle-ai/ui/components/copy-context"
|
|
8
|
-
|
|
9
|
-
export type ErrorDetailsProps = {
|
|
10
|
-
/** Short heading, e.g. "Task data is not valid." */
|
|
11
|
-
title: string
|
|
12
|
-
/** Full error text. Collapsed to a short preview by default. */
|
|
13
|
-
error: string
|
|
14
|
-
/** What "Copy context" writes; defaults to the error text. */
|
|
15
|
-
context?: CopyContextSource
|
|
16
|
-
/** Accessible name and tooltip for the copy button. */
|
|
17
|
-
copyLabel?: string
|
|
18
|
-
/** Optional extra action next to copy, e.g. a Retry button. */
|
|
19
|
-
action?: ReactNode
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Collapsible red error panel for the tasks viewer. Long schema and
|
|
24
|
-
* validation dumps take one small collapsed row by default; the full text,
|
|
25
|
-
* plus a copy-context button for pasting the failure back to an agent, is
|
|
26
|
-
* one click away.
|
|
27
|
-
*/
|
|
28
|
-
export function ErrorDetails({
|
|
29
|
-
title,
|
|
30
|
-
error,
|
|
31
|
-
context,
|
|
32
|
-
copyLabel = "Copy error context",
|
|
33
|
-
action,
|
|
34
|
-
}: ErrorDetailsProps): ReactNode {
|
|
35
|
-
const [expanded, setExpanded] = useState(false)
|
|
36
|
-
const isLong = error.length > 200 || error.includes("\n")
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="rounded-md border border-[#9c3a3a]/40 p-4">
|
|
40
|
-
<div className="flex items-start justify-between gap-2">
|
|
41
|
-
<p className="m-0 text-sm font-semibold text-[#9c3a3a]">{title}</p>
|
|
42
|
-
<div className="flex shrink-0 items-center gap-1">
|
|
43
|
-
{action}
|
|
44
|
-
<CopyContextButton
|
|
45
|
-
className="text-[#9c3a3a] hover:text-[#6f2020]"
|
|
46
|
-
context={context ?? error}
|
|
47
|
-
label={copyLabel}
|
|
48
|
-
/>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
<p
|
|
52
|
-
className={`m-0 mt-1 text-[13px] text-[#9c3a3a] ${
|
|
53
|
-
expanded || !isLong
|
|
54
|
-
? "break-words whitespace-pre-wrap"
|
|
55
|
-
: "line-clamp-2"
|
|
56
|
-
}`}
|
|
57
|
-
>
|
|
58
|
-
{error}
|
|
59
|
-
</p>
|
|
60
|
-
{isLong ? (
|
|
61
|
-
<Button
|
|
62
|
-
className="mt-1 -ml-2 text-[#9c3a3a] hover:text-[#6f2020]"
|
|
63
|
-
onClick={() => setExpanded((value) => !value)}
|
|
64
|
-
size="sm"
|
|
65
|
-
type="button"
|
|
66
|
-
variant="ghost"
|
|
67
|
-
>
|
|
68
|
-
{expanded ? "Show less" : "Show more"}
|
|
69
|
-
<ChevronDown
|
|
70
|
-
className={`size-3.5 transition-transform ${
|
|
71
|
-
expanded ? "rotate-180" : ""
|
|
72
|
-
}`}
|
|
73
|
-
/>
|
|
74
|
-
</Button>
|
|
75
|
-
) : null}
|
|
76
|
-
</div>
|
|
77
|
-
)
|
|
78
|
-
}
|