kennel 0.2.3 → 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.
- 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 +75 -21
- package/dist/cli/src/site/server-plugins.d.ts +2 -7
- package/dist/cli/src/site/viewer.js +1 -0
- package/dist/cli/usage.js +1 -1
- package/dist/core/command.js +1 -0
- package/dist/core/init.js +5 -5
- package/dist/core/runtime.js +357 -3207
- package/dist/package/preview.js +1232 -5113
- package/dist/plugins/external.d.ts +28 -2
- package/dist/plugins/external.js +75 -21
- package/dist/site/server-plugins.d.ts +2 -7
- package/dist/site/server-plugins.js +552 -10447
- package/dist/site/viewer.js +1 -0
- package/kernel/apps/web/package.json +1 -5
- package/kernel/apps/web/scripts/dev.mjs +53 -0
- package/kernel/apps/web/src/app.css +0 -3
- package/kernel/apps/web/src/main.tsx +0 -1
- package/kernel/apps/web/src/plugins.ts +0 -30
- package/kernel/apps/web/tsconfig.json +1 -2
- package/kernel/apps/web/vite.config.ts +31 -13
- package/kernel/packages/api/package.json +0 -4
- package/kernel/packages/api/src/server/folder-metadata-plugin.ts +13 -38
- package/kernel/packages/api/src/server/index.ts +0 -1
- package/kernel/packages/api/src/server/plugins.ts +49 -16
- package/kernel/packages/api/test/core.test.ts +13 -25
- package/kernel/packages/markdown/README.md +1 -1
- package/package.json +1 -1
- 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/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/package.json +0 -79
- 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/projects/tsconfig.json +0 -17
- 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
|
@@ -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
|
-
}
|