kennel 0.2.5 → 0.2.7
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 +9 -6
- package/dist/cli/src/plugins/external.d.ts +3 -0
- package/dist/cli/src/plugins/external.js +24 -12
- package/dist/cli/src/site/hot-viewer.js +45 -38
- package/dist/cli/src/site/server-plugins.d.ts +2 -2
- package/dist/cli/src/site/viewer.js +13 -8
- package/dist/core/api-client.js +576 -10317
- package/dist/core/core-folders.js +2313 -12088
- package/dist/core/runtime.js +7899 -17525
- package/dist/package/preview.js +9838 -19692
- package/dist/plugins/external.d.ts +3 -0
- package/dist/plugins/external.js +24 -12
- package/dist/site/hot-viewer.js +45 -38
- package/dist/site/server-plugins.d.ts +2 -2
- package/dist/site/server-plugins.js +9 -9
- package/dist/site/viewer.js +13 -8
- package/kernel/apps/web/package.json +1 -1
- package/kernel/apps/web/scripts/dev.mjs +4 -0
- package/kernel/apps/web/src/api/events.ts +60 -24
- 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/plugins.ts +1 -1
- package/kernel/apps/web/vite.config.ts +3 -1
- 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 -1
- 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 +4 -4
- package/kernel/packages/api/src/server/plugins.ts +3 -3
- package/kernel/packages/api/src/shared/viewer-route.ts +1 -1
- package/kernel/packages/api/test/core.test.ts +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/pages/notes-page.tsx +34 -1
- package/kernel/packages/notes/src/server.ts +1 -1
- package/kernel/packages/notes/src/ui/folder-notes-list.tsx +10 -74
- package/kernel/packages/plugins/SKILL.md +39 -0
- package/kernel/packages/{folder-plugin → plugins}/package.json +65 -11
- package/kernel/packages/plugins/src/index.ts +52 -0
- package/kernel/packages/plugins/src/page.ts +17 -0
- package/kernel/packages/{folder-plugin → 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-xd_g1uK3.js → abnfDiagram-VRR7QNED-CDr-U31F.js} +1 -1
- package/web/assets/app-DHGorUqZ.js +2 -0
- package/web/assets/app-options-CtkiC8GR.js +25 -0
- package/web/assets/{app-view-header-CNk5KnA-.js → app-view-header-DbQuD6_F.js} +1 -1
- package/web/assets/{arc-B0u5yBJA.js → arc-Cwz5OeLQ.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-DfxOAo8P.js → architectureDiagram-ZJ3FMSHR-igGC0b-J.js} +1 -1
- package/web/assets/{ask-tray-SscJecDY.js → ask-tray-y8nkSKNG.js} +1 -1
- package/web/assets/{blockDiagram-677ZJIJ3-Ci3Usxh6.js → blockDiagram-677ZJIJ3-D4SDltQ_.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-BqgwIVgh.js → c4Diagram-LMCZKHZV-Br15uN-s.js} +1 -1
- package/web/assets/channel-DRnAhH31.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-CfX69l2U.js → chunk-2Q5K7J3B-B0RqrvJA.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-CuFlzZkl.js → chunk-32BRIVSS-De9VBEyE.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-DidCMlJa.js → chunk-5VM5RSS4-YIMlZtW3.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-B5CDm1dS.js → chunk-EX3LRPZG-y9kGcrYi.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-D5fGV_sH.js → chunk-JWPE2WC7-D0A13HAu.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-ayhH5Q-H.js → chunk-MOJQB5TN-8v4jL8iu.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-C4BfOOZn.js → chunk-RYQCIY6F-Ri_iNmIp.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-DpUEIM9V.js → chunk-V7JOEXUC-b0mIbG_X.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-DoQuFFRh.js → chunk-VR4S4FIN-BkTZWt1n.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-CI9eiLwn.js → chunk-XXDRQBXY-D7muOXcd.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-BPkIpFlc.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-BPkIpFlc.js +1 -0
- package/web/assets/{client-Dk-NBvJR.js → client-BMso7lHb.js} +2 -2
- package/web/assets/client-Bkl3gwZ5.js +17 -0
- package/web/assets/client-soK_bLWT.js +5 -0
- package/web/assets/{command-zkzH4hVz.js → command-CsN8TfJg.js} +1 -1
- package/web/assets/{copy-context-D5oiWrYC.js → copy-context-DmBNpffM.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-BHRk1mO3.js → cose-bilkent-JH36ORCC-7hnQZylB.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-C1B09TRE.js → cynefin-VYW2F7L2-CTbqXuvk.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-B27qXQbv.js → cynefinDiagram-TSTJHNR4-CmIJtocX.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-B1qEi32g.js → dagre-VKFMJZFB-BLPHNs2Y.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-BMkkgADD.js → diagram-FQU43EPY-L6FVWAuj.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-Cb8_g1A5.js → diagram-G47NLZAW-Bb26dbIM.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-B51wuc5m.js → diagram-NH7WQ7WH-BBauwdU-.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-xnsecbbI.js → diagram-OA4YK3LP-Dj_9FE7R.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-DSZdyaAV.js → diagram-WEI45ONY-Co1MS5BO.js} +1 -1
- package/web/assets/{document-Dc2dftTW.js → document-_ETc5epn.js} +3 -3
- package/web/assets/{ebnfDiagram-CCIWWBDH-aTHmcUGy.js → ebnfDiagram-CCIWWBDH-COGAgW5z.js} +1 -1
- package/web/assets/{entities-CCUtpskY.js → entities-ByGFSWnQ.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-CUUPBcvo.js → erDiagram-Q63AITRT-CRMKCr0m.js} +1 -1
- package/web/assets/{file-viewer-DJ3rsmef.js → file-viewer-Dqx7DbTw.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-aTQXx2Mh.js → flowDiagram-23GEKE2U-Drv72N5g.js} +1 -1
- package/web/assets/folder-filter-bar-Bs_uyU0g.js +4 -0
- package/web/assets/folder-image-BBNRcu1j.js +1 -0
- package/web/assets/{folder-landing-DCnzYXXY.js → folder-landing-0EXAzEpD.js} +3 -3
- package/web/assets/{folder-list-DvVkVjiR.js → folder-list-Do8Kl8uk.js} +1 -1
- package/web/assets/{folder-metadata-C9hMMzIH.js → folder-metadata-DncP3Vx2.js} +1 -1
- package/web/assets/folder-mobile-bar-D-XXKrip.js +1 -0
- package/web/assets/folder-plugin-view-DoRQa8Dz.js +3 -0
- package/web/assets/{ganttDiagram-NO4QXBWP-DiwdUp7u.js → ganttDiagram-NO4QXBWP-DHEt2_9K.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-BL2gG_IS.js → gitGraphDiagram-IHSO6WYX-Bt6XsYTq.js} +1 -1
- package/web/assets/{index-CUTtMSyJ.js → index-7JCizcu7.js} +2 -2
- package/web/assets/index-DY0VGBht.js +1 -0
- package/web/assets/{infoDiagram-FWYZ7A6U-B3n0zZpt.js → infoDiagram-FWYZ7A6U-961DCJAH.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-D7YytbEv.js → ishikawaDiagram-FXEZZL3T-ibSYK50l.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BYwqEl3C.js → journeyDiagram-5HDEW3XC-Cd0ZPqw2.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-BQHNJgXZ.js → kanban-definition-HUTT4EX6-Bu5skY8G.js} +1 -1
- package/web/assets/{linear-BPiQCLNk.js → linear-Cf8Xflqn.js} +1 -1
- package/web/assets/{mermaid.core-CD-KvBjV.js → mermaid.core-C9iHkrxr.js} +4 -4
- package/web/assets/{metadata-COJ7fZul.js → metadata-CLq-ZGmh.js} +1 -1
- package/web/assets/{mindmap-definition-LN4V7U3C-C1L_gyoj.js → mindmap-definition-LN4V7U3C-C5bK3O7k.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-BDAfItqS.js → pegDiagram-2B236MQR-5rN2nkjz.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-CkZYH3Vz.js → pieDiagram-ENE6RG2P-DnSBFuIb.js} +1 -1
- package/web/assets/popover-D7MTK-sz.js +9 -0
- package/web/assets/{project-search-dialog-B2oqMT6h.js → project-search-dialog-Bo1JWdqR.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-Dy8Al3YZ.js → quadrantDiagram-ABIIQ3AL-xinqVpVM.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-Dd9_yo7B.js → railroadDiagram-RFXS5EU6-GsASFEVa.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-DPhIUsbs.js → requirementDiagram-TGXJPOKE-DS5CqNNo.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-B2QkYtub.js → sankeyDiagram-HTMAVEWB-DsnvjCXC.js} +1 -1
- package/web/assets/{search-C1J0-xiB.js → search-BA4r_Yoa.js} +1 -1
- package/web/assets/select-D4TpCgnU.js +30 -0
- package/web/assets/{selection-popup-qhlUFzGq.js → selection-popup-DIME-60e.js} +3 -3
- package/web/assets/{sequenceDiagram-DBY2YBRQ-Bx7fcZDx.js → sequenceDiagram-DBY2YBRQ-PI0WgJrf.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-CIXIhl_A.js → sizeCapture-X5ZJPWSS-Bpul3MSt.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-DCrdAflB.js → stateDiagram-2N3HPSRC-DZEEP9Z2.js} +1 -1
- package/web/assets/stateDiagram-v2-6OUMAXLB-WAp7-BWX.js +1 -0
- package/web/assets/{swimlanes-5IMT3BWC-DA2vc7iZ.js → swimlanes-5IMT3BWC-_qVjNiCh.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-Dy4wBDSi.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-lKfJiV9V.js → timeline-definition-FHXFAJF6-CJev7rIB.js} +1 -1
- package/web/assets/use-folder-filter-hA6fa7nm.js +1 -0
- package/web/assets/{vennDiagram-L72KCM5P-DO1q2KzG.js → vennDiagram-L72KCM5P-BrTVvREy.js} +1 -1
- package/web/assets/{view-context-DXKM3-l1.js → view-context-Co01ON81.js} +35 -35
- package/web/assets/{viewer-capabilities-Cig_xM9u.js → viewer-capabilities-C_kjcYcl.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-Dal9LkuZ.js → wardleyDiagram-EHGQE667-XwMSgrT5.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-B3dPLPII.js → xychartDiagram-FW5EYKEG-Be1kFxeC.js} +1 -1
- package/web/index.html +1 -1
- package/kernel/packages/folder-plugin/src/index.ts +0 -15
- package/web/assets/app-CX20nNIa.js +0 -2
- package/web/assets/app-options-CkPJE5ep.js +0 -25
- package/web/assets/channel-X7WHyxxT.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-BjsLQ3dz.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-BjsLQ3dz.js +0 -1
- package/web/assets/client-7OWw5kW2.js +0 -6
- package/web/assets/client-DYj_td4Q.js +0 -17
- package/web/assets/folder-image-Bnv43tzP.js +0 -1
- package/web/assets/folder-mobile-bar-VoTL1GS0.js +0 -1
- package/web/assets/folder-plugin-view-Cvd804ZU.js +0 -6
- package/web/assets/popover-0oA2lLUV.js +0 -9
- package/web/assets/select-CtXC_PLC.js +0 -30
- package/web/assets/stateDiagram-v2-6OUMAXLB-0KCFLYeQ.js +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-CAw3AV84.js +0 -8
- /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,11 +1,11 @@
|
|
|
1
|
-
import type { FolderPluginContext } from "
|
|
2
|
-
import type { FolderPluginServer } from "
|
|
1
|
+
import type { FolderPluginContext } from "kennel-plugins/server";
|
|
2
|
+
import type { FolderPluginServer } from "kennel-plugins/server";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
6
6
|
import { dirname, relative, resolve, sep } from "node:path";
|
|
7
7
|
import { createAgentsPlugin } from "@raggle-ai/agents/server";
|
|
8
|
-
import { FolderPluginFailure } from "
|
|
8
|
+
import { FolderPluginFailure } from "kennel-plugins/server";
|
|
9
9
|
import { createNotesPlugin } from "@raggle-ai/notes/server";
|
|
10
10
|
|
|
11
11
|
export { FolderPluginFailure };
|
|
@@ -33,7 +33,7 @@ const sectionTabs: Record<ViewerSection, FolderTab> = {
|
|
|
33
33
|
skills: "skills",
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
import { folderPathId as encodeBase64Url } from "
|
|
36
|
+
import { folderPathId as encodeBase64Url } from "kennel-plugins/client";
|
|
37
37
|
|
|
38
38
|
function decodeBase64Url(value: string) {
|
|
39
39
|
const padded = `${value}${"=".repeat((4 - (value.length % 4)) % 4)}`;
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
configuredFolderServerRegistry,
|
|
10
10
|
scaffoldFolderPlugins,
|
|
11
11
|
} from "../src/server/plugins";
|
|
12
|
-
import type { FolderPluginServer } from "
|
|
12
|
+
import type { FolderPluginServer } from "kennel-plugins/server";
|
|
13
13
|
import { createCoreFolderIndex } from "@raggle-ai/schemas/node";
|
|
14
14
|
|
|
15
15
|
const cleanup: (() => Promise<unknown>)[] = [];
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"publish:public:dry-run": "npm --@raggle-ai:registry=https://registry.npmjs.org publish --dry-run --access public --registry=https://registry.npmjs.org"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"
|
|
42
|
+
"kennel-plugins": "workspace:*",
|
|
43
43
|
"@raggle-ai/ui": "workspace:*",
|
|
44
44
|
"@tanstack/react-query": "catalog:tanstack",
|
|
45
45
|
"lucide-react": "^0.562.0"
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { ReactElement } from "react"
|
|
2
2
|
import { useState } from "react"
|
|
3
3
|
|
|
4
|
+
import type { FolderFile } from "@raggle-ai/ui/lib/folder-activity"
|
|
5
|
+
import { FolderFilterBar } from "@raggle-ai/ui/components/folder-filter-bar"
|
|
6
|
+
import { useFolderFilter } from "@raggle-ai/ui/hooks/use-folder-filter"
|
|
7
|
+
|
|
4
8
|
import { useAiInput } from "../data/ai-input.ts"
|
|
5
9
|
import {
|
|
6
10
|
folderDocumentHref,
|
|
@@ -15,6 +19,19 @@ import {
|
|
|
15
19
|
} from "../ui/ai-composer-controls.tsx"
|
|
16
20
|
import { FolderNotesList } from "../ui/folder-notes-list.tsx"
|
|
17
21
|
|
|
22
|
+
/** Folder that directly contains a note, including a note below the view root. */
|
|
23
|
+
function noteFolder(file: FolderFile, viewedFolder?: string): string | null {
|
|
24
|
+
const root = file.folder ?? viewedFolder
|
|
25
|
+
if (!root) return null
|
|
26
|
+
const parent = file.relativePath
|
|
27
|
+
.replaceAll("\\", "/")
|
|
28
|
+
.split("/")
|
|
29
|
+
.slice(0, -1)
|
|
30
|
+
.filter(Boolean)
|
|
31
|
+
.join("/")
|
|
32
|
+
return parent ? `${root.replace(/[\\/]+$/, "")}/${parent}` : root
|
|
33
|
+
}
|
|
34
|
+
|
|
18
35
|
/** Folder Notes page: local and linked Markdown notes plus the AI composer. */
|
|
19
36
|
export function NotesPage(): ReactElement {
|
|
20
37
|
const [composerOpen, setComposerOpen] = useState(false)
|
|
@@ -24,6 +41,11 @@ export function NotesPage(): ReactElement {
|
|
|
24
41
|
const folderId = folder ? folderPathId(folder) : "none"
|
|
25
42
|
// Metadata events are handled once by the shared shell.
|
|
26
43
|
const { local: query, linked, files, retryLinked } = useFolderNotes(href)
|
|
44
|
+
const filter = useFolderFilter(files ?? [], {
|
|
45
|
+
allowOutside: true,
|
|
46
|
+
getFolder: (file) => noteFolder(file, folder),
|
|
47
|
+
rootFolder: folder ?? "",
|
|
48
|
+
})
|
|
27
49
|
|
|
28
50
|
return (
|
|
29
51
|
<>
|
|
@@ -44,7 +66,18 @@ export function NotesPage(): ReactElement {
|
|
|
44
66
|
: file.relativePath
|
|
45
67
|
}}
|
|
46
68
|
error={query.error ? String(query.error) : ""}
|
|
47
|
-
files={
|
|
69
|
+
files={filter.visibleItems}
|
|
70
|
+
filter={
|
|
71
|
+
filter.choices.length > 1 ? (
|
|
72
|
+
<FolderFilterBar
|
|
73
|
+
ariaLabel="Filter notes by folder"
|
|
74
|
+
choices={filter.choices}
|
|
75
|
+
onSelect={filter.setSelected}
|
|
76
|
+
selected={filter.effectiveSelected}
|
|
77
|
+
total={filter.total}
|
|
78
|
+
/>
|
|
79
|
+
) : undefined
|
|
80
|
+
}
|
|
48
81
|
folder={folder}
|
|
49
82
|
folderHref={(source) => folderSectionHref(source, "notes")}
|
|
50
83
|
loading={query.isLoading}
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from "react"
|
|
2
|
-
import { useState } from "react"
|
|
3
|
-
import { Link2 } from "lucide-react"
|
|
4
2
|
|
|
5
3
|
import type { FolderFile } from "@raggle-ai/ui/lib/folder-activity"
|
|
6
|
-
import { Button } from "@raggle-ai/ui/components/button"
|
|
7
4
|
import { NoteCard } from "@raggle-ai/ui/components/note-card"
|
|
8
5
|
|
|
9
|
-
function folderName(folder: string) {
|
|
10
|
-
return (
|
|
11
|
-
folder
|
|
12
|
-
.replace(/[\\/]+$/, "")
|
|
13
|
-
.split(/[\\/]/)
|
|
14
|
-
.at(-1) ?? folder
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
6
|
/**
|
|
19
7
|
* Note rows for the main Notes tab, backed by the shared NoteCard so linked
|
|
20
8
|
* notes render the same way everywhere.
|
|
@@ -24,6 +12,7 @@ export function FolderNotesList({
|
|
|
24
12
|
documentHref,
|
|
25
13
|
error,
|
|
26
14
|
files = [],
|
|
15
|
+
filter,
|
|
27
16
|
folder,
|
|
28
17
|
folderHref,
|
|
29
18
|
loading,
|
|
@@ -32,41 +21,18 @@ export function FolderNotesList({
|
|
|
32
21
|
documentHref: (file: FolderFile) => string
|
|
33
22
|
error: string
|
|
34
23
|
files?: FolderFile[]
|
|
24
|
+
filter?: ReactNode
|
|
35
25
|
folder?: string
|
|
36
26
|
folderHref: (folder: string) => string
|
|
37
27
|
loading: boolean
|
|
38
28
|
}) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
id: "local",
|
|
47
|
-
label: "This folder",
|
|
48
|
-
count: files.filter((file) => !file.folder).length,
|
|
49
|
-
},
|
|
50
|
-
...sources.map((source) => ({
|
|
51
|
-
id: source,
|
|
52
|
-
label: folderName(source),
|
|
53
|
-
count: files.filter((file) => file.folder === source).length,
|
|
54
|
-
})),
|
|
55
|
-
]
|
|
56
|
-
const selected = filters.some((item) => item.id === filter) ? filter : "all"
|
|
57
|
-
const visible = files
|
|
58
|
-
.filter(
|
|
59
|
-
(file) =>
|
|
60
|
-
selected === "all" ||
|
|
61
|
-
(selected === "local" ? !file.folder : file.folder === selected),
|
|
62
|
-
)
|
|
63
|
-
.sort(
|
|
64
|
-
(left, right) =>
|
|
65
|
-
right.activityAt - left.activityAt ||
|
|
66
|
-
`${left.folder ?? ""}/${left.relativePath}`.localeCompare(
|
|
67
|
-
`${right.folder ?? ""}/${right.relativePath}`,
|
|
68
|
-
),
|
|
69
|
-
)
|
|
29
|
+
const visible = files.toSorted(
|
|
30
|
+
(left, right) =>
|
|
31
|
+
right.activityAt - left.activityAt ||
|
|
32
|
+
`${left.folder ?? ""}/${left.relativePath}`.localeCompare(
|
|
33
|
+
`${right.folder ?? ""}/${right.relativePath}`,
|
|
34
|
+
),
|
|
35
|
+
)
|
|
70
36
|
|
|
71
37
|
return (
|
|
72
38
|
<div className="mx-auto grid w-full max-w-3xl gap-4 px-4 py-5">
|
|
@@ -74,37 +40,7 @@ export function FolderNotesList({
|
|
|
74
40
|
<h1 className="m-0 text-2xl font-semibold text-[#233025]">Notes</h1>
|
|
75
41
|
{action}
|
|
76
42
|
</div>
|
|
77
|
-
{
|
|
78
|
-
<div
|
|
79
|
-
role="group"
|
|
80
|
-
aria-label="Filter notes by source"
|
|
81
|
-
className="flex flex-wrap gap-2"
|
|
82
|
-
>
|
|
83
|
-
{filters.map((item) => (
|
|
84
|
-
<Button
|
|
85
|
-
key={item.id}
|
|
86
|
-
type="button"
|
|
87
|
-
size="sm"
|
|
88
|
-
variant={selected === item.id ? "secondary" : "outline"}
|
|
89
|
-
className="h-auto min-h-8 max-w-full rounded-full
|
|
90
|
-
whitespace-normal"
|
|
91
|
-
aria-pressed={selected === item.id}
|
|
92
|
-
onClick={() => setFilter(item.id)}
|
|
93
|
-
title={
|
|
94
|
-
item.id === "local"
|
|
95
|
-
? folder
|
|
96
|
-
: sources.includes(item.id)
|
|
97
|
-
? item.id
|
|
98
|
-
: undefined
|
|
99
|
-
}
|
|
100
|
-
>
|
|
101
|
-
{sources.includes(item.id) ? <Link2 aria-hidden="true" /> : null}
|
|
102
|
-
<span className="break-all">{item.label}</span>
|
|
103
|
-
<span className="text-muted-foreground">{item.count}</span>
|
|
104
|
-
</Button>
|
|
105
|
-
))}
|
|
106
|
-
</div>
|
|
107
|
-
) : null}
|
|
43
|
+
{filter}
|
|
108
44
|
{loading ? <p className="m-0 text-sm text-[#6c7a6d]">Loading…</p> : null}
|
|
109
45
|
{error ? <p className="m-0 text-sm text-[#9c3a3a]">{error}</p> : null}
|
|
110
46
|
{!loading && !error && !visible.length ? (
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kennel-plugins
|
|
3
|
+
description: Install, register, or build a trusted Kennel folder plugin. Use for `knl plugin add`, external plugin kernels, plugin tabs, or deciding where plugin code belongs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kennel Plugin Management
|
|
7
|
+
|
|
8
|
+
## Ownership
|
|
9
|
+
|
|
10
|
+
Keep each concern in its owner:
|
|
11
|
+
|
|
12
|
+
| Concern | Location |
|
|
13
|
+
| ----------------------------------------------------------- | -------------------------------------- |
|
|
14
|
+
| Plugin contract and public client/server types | `packages/plugins` (`kennel-plugins`) |
|
|
15
|
+
| Generic reusable viewer UI | `packages/ui` |
|
|
16
|
+
| Folder metadata API and server registry | `packages/api` |
|
|
17
|
+
| Browser route and static external-plugin registry | `apps/web` |
|
|
18
|
+
| Install, pin, cache, validate, and compose external plugins | `cli/src/plugins/external.ts` |
|
|
19
|
+
| Built-in Agents and Notes feature code | `packages/agents` and `packages/notes` |
|
|
20
|
+
| External plugin feature code | Its own repository |
|
|
21
|
+
|
|
22
|
+
Keep new plugin feature code in its own repository. Add to `packages/plugins` only when every plugin needs a contract change. Add to `packages/ui` only when every viewer can use the UI component.
|
|
23
|
+
|
|
24
|
+
## External plugin install
|
|
25
|
+
|
|
26
|
+
1. Inspect the plugin `package.json`, `src/manifest.ts`, `src/client.tsx`, and `src/server.ts`.
|
|
27
|
+
2. Require `package.json > kennel.plugin` with a unique non-core `id`. The conventional `./manifest`, `./client`, `./server`, and optional `./api` entries must default-export their values. Add `trigger` only when a file can make an otherwise unavailable plugin visible.
|
|
28
|
+
3. Keep the manifest id and package id equal. The client and server must spread or otherwise return that manifest id.
|
|
29
|
+
4. Ensure the repository TypeScript config works outside the Kennel workspace. Do not require unpublished workspace config files during kernel bundling.
|
|
30
|
+
5. Install with `knl plugin add <git-url>`. It pins the resolved commit, validates exports, stores source in `~/.cache/kennel/plugins/sources/`, records the plugin in `~/.config/kennel/config.json`, and composes a static kernel in `~/.cache/kennel/kernels/`.
|
|
31
|
+
6. Use `knl view <folder>` after installation. External plugins require the composed static viewer; a plain Vite hot viewer cannot show their tabs.
|
|
32
|
+
|
|
33
|
+
## Change workflow
|
|
34
|
+
|
|
35
|
+
- Start with the smallest plugin repository change. Do not copy plugin feature code into Kennel.
|
|
36
|
+
- Change `packages/plugins`, `packages/api`, `apps/web`, and `cli` only when the plugin contract or trusted-kernel behavior needs it.
|
|
37
|
+
- Keep plugin ids stable. Do not use core ids: `agents`, `calendar`, `mail`, `notes`, `projects`, or `tasks`.
|
|
38
|
+
- Verify a real install in an isolated `XDG_CONFIG_HOME` and `XDG_CACHE_HOME` first. Then verify the tab and its selected route in the composed viewer.
|
|
39
|
+
- A CLI behavior change requires a new `cli/package.json` version. The publish workflow releases it after merge to `main`.
|
|
@@ -1,21 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"name": "
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"name": "kennel-plugins",
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"description": "Small shared contract for trusted folder view plugins in the Kennel web viewer.",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/raggle-ai/kennel.git",
|
|
11
|
+
"directory": "packages/plugins"
|
|
12
|
+
},
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"registry": "https://registry.npmjs.org",
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
8
21
|
"prettier": "@raggle-ai/prettier-config",
|
|
9
22
|
"exports": {
|
|
10
|
-
".":
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"./
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./client": {
|
|
28
|
+
"types": "./dist/client.d.ts",
|
|
29
|
+
"import": "./dist/client.js"
|
|
30
|
+
},
|
|
31
|
+
"./endpoint": {
|
|
32
|
+
"types": "./dist/endpoint.d.ts",
|
|
33
|
+
"import": "./dist/endpoint.js"
|
|
34
|
+
},
|
|
35
|
+
"./page": {
|
|
36
|
+
"types": "./dist/page.d.ts",
|
|
37
|
+
"import": "./dist/page.js"
|
|
38
|
+
},
|
|
39
|
+
"./server": {
|
|
40
|
+
"types": "./dist/server.d.ts",
|
|
41
|
+
"import": "./dist/server.js"
|
|
42
|
+
},
|
|
43
|
+
"./subpath": {
|
|
44
|
+
"types": "./dist/subpath.d.ts",
|
|
45
|
+
"import": "./dist/subpath.js"
|
|
46
|
+
},
|
|
47
|
+
"./types": {
|
|
48
|
+
"types": "./dist/types.d.ts",
|
|
49
|
+
"import": "./dist/types.js"
|
|
50
|
+
},
|
|
51
|
+
"./validation": {
|
|
52
|
+
"types": "./dist/validation.d.ts",
|
|
53
|
+
"import": "./dist/validation.js"
|
|
54
|
+
}
|
|
17
55
|
},
|
|
18
56
|
"scripts": {
|
|
57
|
+
"build": "tsup",
|
|
58
|
+
"prepack": "bun run build",
|
|
19
59
|
"test": "bun test test/*.test.mjs",
|
|
20
60
|
"typecheck": "tsc --noEmit",
|
|
21
61
|
"format": "prettier . --check --cache --cache-location .cache/.prettiercache --ignore-path ../../.prettierignore",
|
|
@@ -24,8 +64,19 @@
|
|
|
24
64
|
"lint:fix": "eslint . --fix --cache --cache-location .cache/.eslintcache",
|
|
25
65
|
"clean": "git clean -xdf dist node_modules .cache .turbo/cache"
|
|
26
66
|
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"class-variance-authority": "^0.7.1",
|
|
69
|
+
"clsx": "^2.1.1",
|
|
70
|
+
"cmdk": "^1.1.1",
|
|
71
|
+
"lucide-react": "^0.562.0",
|
|
72
|
+
"next-themes": "^0.4.6",
|
|
73
|
+
"radix-ui": "^1.6.7",
|
|
74
|
+
"sonner": "^2.0.7",
|
|
75
|
+
"tailwind-merge": "^3.4.0"
|
|
76
|
+
},
|
|
27
77
|
"peerDependencies": {
|
|
28
|
-
"react": ">=18.3.0"
|
|
78
|
+
"react": ">=18.3.0",
|
|
79
|
+
"react-dom": ">=18.3.0"
|
|
29
80
|
},
|
|
30
81
|
"devDependencies": {
|
|
31
82
|
"@eslint/compat": "catalog:eslint",
|
|
@@ -35,6 +86,8 @@
|
|
|
35
86
|
"@raggle-ai/eslint-config": "workspace:*",
|
|
36
87
|
"@raggle-ai/prettier-config": "workspace:*",
|
|
37
88
|
"@raggle-ai/tsconfig": "workspace:*",
|
|
89
|
+
"@raggle-ai/ui": "workspace:*",
|
|
90
|
+
"kennel-client": "workspace:*",
|
|
38
91
|
"@types/node": "catalog:",
|
|
39
92
|
"@types/react": "catalog:react19",
|
|
40
93
|
"eslint": "catalog:eslint",
|
|
@@ -44,6 +97,7 @@
|
|
|
44
97
|
"prettier-plugin-merge": "catalog:prettier",
|
|
45
98
|
"prettier-plugin-tailwindcss": "catalog:prettier",
|
|
46
99
|
"react": "catalog:react19",
|
|
100
|
+
"tsup": "8.5.1",
|
|
47
101
|
"typescript": "catalog:",
|
|
48
102
|
"typescript-eslint": "catalog:eslint"
|
|
49
103
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// The complete public surface for external folder plugins. Plugins should
|
|
2
|
+
// import this module only; it deliberately exposes selected shared UI, not
|
|
3
|
+
// the underlying @raggle-ai/ui package.
|
|
4
|
+
export {
|
|
5
|
+
CopyContextButton,
|
|
6
|
+
FilePreview,
|
|
7
|
+
FilePreviewList,
|
|
8
|
+
FolderFilterBar,
|
|
9
|
+
PluginPage,
|
|
10
|
+
PluginPageError,
|
|
11
|
+
PluginPageStatus,
|
|
12
|
+
useFolderFilter,
|
|
13
|
+
} from "./page.ts"
|
|
14
|
+
export { folderPathId } from "./client.ts"
|
|
15
|
+
export {
|
|
16
|
+
apiError,
|
|
17
|
+
ApiError,
|
|
18
|
+
jsonError,
|
|
19
|
+
jsonResponse,
|
|
20
|
+
parseJsonBody,
|
|
21
|
+
readBoundedBody,
|
|
22
|
+
runApiRoute,
|
|
23
|
+
sameOrigin,
|
|
24
|
+
} from "./endpoint.ts"
|
|
25
|
+
export { FolderPluginFailure } from "./server.ts"
|
|
26
|
+
export { isPluginPayloadError } from "./types.ts"
|
|
27
|
+
export type {
|
|
28
|
+
FolderPluginDataset,
|
|
29
|
+
FolderPluginDetection,
|
|
30
|
+
FolderPluginId,
|
|
31
|
+
FolderPluginManifest,
|
|
32
|
+
FolderPluginPayload,
|
|
33
|
+
FolderPluginPayloadError,
|
|
34
|
+
} from "./types.ts"
|
|
35
|
+
export type {
|
|
36
|
+
FolderPluginClient,
|
|
37
|
+
FolderPluginHostActions,
|
|
38
|
+
FolderPluginViewProps,
|
|
39
|
+
} from "./client.ts"
|
|
40
|
+
export type { ApiErrorCode, ApiRouteHandle, ApiRouteSpec } from "./endpoint.ts"
|
|
41
|
+
export type {
|
|
42
|
+
FolderPluginContext,
|
|
43
|
+
FolderPluginData,
|
|
44
|
+
FolderPluginInitFile,
|
|
45
|
+
FolderPluginInitResult,
|
|
46
|
+
FolderPluginServer,
|
|
47
|
+
} from "./server.ts"
|
|
48
|
+
export type {
|
|
49
|
+
FolderFilterChoice,
|
|
50
|
+
FolderFilterMode,
|
|
51
|
+
FolderSelection,
|
|
52
|
+
} from "./page.ts"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export {
|
|
2
|
+
EntityError as PluginPageError,
|
|
3
|
+
EntityPage as PluginPage,
|
|
4
|
+
EntityStatus as PluginPageStatus,
|
|
5
|
+
} from "@raggle-ai/ui/pages/entity-page"
|
|
6
|
+
export { CopyContextButton } from "@raggle-ai/ui/components/copy-context"
|
|
7
|
+
export {
|
|
8
|
+
FilePreview,
|
|
9
|
+
FilePreviewList,
|
|
10
|
+
} from "@raggle-ai/ui/components/file-preview"
|
|
11
|
+
export { FolderFilterBar } from "@raggle-ai/ui/components/folder-filter-bar"
|
|
12
|
+
export { useFolderFilter } from "@raggle-ai/ui/hooks/use-folder-filter"
|
|
13
|
+
export type {
|
|
14
|
+
FolderFilterChoice,
|
|
15
|
+
FolderFilterMode,
|
|
16
|
+
FolderSelection,
|
|
17
|
+
} from "@raggle-ai/ui/lib/folder-filter"
|
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
"allowImportingTsExtensions": true,
|
|
10
10
|
// local copy: bun doesn't read paths inherited via `extends`
|
|
11
11
|
"paths": {
|
|
12
|
-
"~/*": ["${configDir}/../../packages/*/src"]
|
|
12
|
+
"~/*": ["${configDir}/../../packages/*/src"],
|
|
13
|
+
"kennel-plugins": ["./src/index.ts"],
|
|
14
|
+
"kennel-plugins/*": ["./src/*"],
|
|
15
|
+
"@raggle-ai/ui/*": ["../ui/src/*"],
|
|
16
|
+
"kennel-client": ["../api-client/src/index.ts"]
|
|
13
17
|
}
|
|
14
18
|
},
|
|
15
19
|
"include": ["src"],
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineConfig } from "tsup"
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
entry: [
|
|
5
|
+
"src/index.ts",
|
|
6
|
+
"src/client.ts",
|
|
7
|
+
"src/endpoint.ts",
|
|
8
|
+
"src/page.ts",
|
|
9
|
+
"src/server.ts",
|
|
10
|
+
"src/subpath.ts",
|
|
11
|
+
"src/types.ts",
|
|
12
|
+
"src/validation.ts",
|
|
13
|
+
],
|
|
14
|
+
format: ["esm"],
|
|
15
|
+
target: "es2022",
|
|
16
|
+
platform: "neutral",
|
|
17
|
+
clean: true,
|
|
18
|
+
esbuildOptions(options) {
|
|
19
|
+
options.jsx = "automatic"
|
|
20
|
+
},
|
|
21
|
+
splitting: true,
|
|
22
|
+
dts: { resolve: [/^@raggle-ai\/ui(?:\/|$)/, /^kennel-client(?:\/|$)/] },
|
|
23
|
+
noExternal: [/^@raggle-ai\/ui(?:\/|$)/, /^kennel-client(?:\/|$)/],
|
|
24
|
+
external: ["react", "react-dom", "react/jsx-runtime"],
|
|
25
|
+
})
|
|
@@ -2,7 +2,7 @@ import type { ReactNode } from "react"
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* One precise content problem, structurally identical to
|
|
5
|
-
* `ContentIssue` from
|
|
5
|
+
* `ContentIssue` from `kennel-plugins` (kept local so the ui
|
|
6
6
|
* package does not depend on the plugin contract's runtime).
|
|
7
7
|
*/
|
|
8
8
|
export type ContentIssue = {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"lib": ["dom", "dom.iterable", "esnext"],
|
|
7
7
|
"jsx": "preserve",
|
|
8
8
|
"baseUrl": ".",
|
|
9
|
-
// Packages whose sources ui compile reach
|
|
9
|
+
// Packages whose sources ui compile reach kennel-plugins entries that
|
|
10
10
|
// import sibling files with .ts extensions (Bundler resolution, noEmit).
|
|
11
11
|
"allowImportingTsExtensions": true
|
|
12
12
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kennel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Open-source pop-up previews for AI output: markdown, HTML artifacts, email, images, code, tables, notes, and calendars, from the terminal or your agent session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,7 +67,6 @@
|
|
|
67
67
|
"@lexical/rich-text": "0.49.0",
|
|
68
68
|
"@libsql/client": "^0.17.3",
|
|
69
69
|
"@raggle-ai/barkdown": "0.6.1",
|
|
70
|
-
"@raggle-ai/folder-plugin": "^0.1.0",
|
|
71
70
|
"@raggle-ai/kennel-knowledge": "^0.1.0",
|
|
72
71
|
"@raggle-ai/kennel-mcp": "^0.1.8",
|
|
73
72
|
"@raggle-ai/kennel-preview": "^0.1.0",
|
|
@@ -116,7 +115,7 @@
|
|
|
116
115
|
"zod": "^4.3.6"
|
|
117
116
|
},
|
|
118
117
|
"devDependencies": {
|
|
119
|
-
"
|
|
118
|
+
"kennel-plugins": "0.1.1",
|
|
120
119
|
"@types/node": "^22.13.4",
|
|
121
120
|
"typescript": "^5.9.3"
|
|
122
121
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-8v4jL8iu.js";import{p as f}from"./chunk-JWPE2WC7-D0A13HAu.js";import{_ as n,l as o}from"./mermaid.core-C9iHkrxr.js";import{b as c,M as d}from"./cynefin-VYW2F7L2-CTbqXuvk.js";import"./index-7JCizcu7.js";import"./react-B9jn2M18.js";import"./markdown-Bw9RgUGR.js";var v=c().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new d(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},I={parser:R,db:a,renderer:u,styles:p};export{I as diagram};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ask-tray-y8nkSKNG.js","assets/react-B9jn2M18.js","assets/markdown-Bw9RgUGR.js","assets/view-context-Co01ON81.js","assets/index-7JCizcu7.js","assets/index-Dwhf8F_U.css","assets/tanstack-YzX_Mi37.js","assets/button-C6arH7zt.js","assets/utils-DCaHk0Gm.js","assets/folder-plugin-view-DoRQa8Dz.js","assets/folder-filter-bar-Bs_uyU0g.js","assets/command-CsN8TfJg.js","assets/index-CCXE8zc9.js","assets/index-CegvVQ1C.js","assets/popover-D7MTK-sz.js","assets/index-DY0VGBht.js","assets/folder-image-BBNRcu1j.js","assets/viewer-capabilities-C_kjcYcl.js","assets/entities-ByGFSWnQ.js","assets/search-BA4r_Yoa.js","assets/search-BOHZTLC-.css","assets/folder-landing-0EXAzEpD.js","assets/folder-metadata-DncP3Vx2.js","assets/copy-context-DmBNpffM.js","assets/index-Bp9DidgD.js","assets/app-options-CtkiC8GR.js","assets/index-CXhBn-ar.js","assets/folder-list-Do8Kl8uk.js","assets/folder-activity-Cv1X2ezj.js","assets/folder-mobile-bar-D-XXKrip.js","assets/app-view-header-DbQuD6_F.js","assets/file-viewer-Dqx7DbTw.js","assets/metadata-CLq-ZGmh.js","assets/project-search-dialog-Bo1JWdqR.js","assets/client-BMso7lHb.js","assets/select-D4TpCgnU.js","assets/client-soK_bLWT.js","assets/use-folder-filter-hA6fa7nm.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as g,i as ne,f as T,c as re,e as ae,p as S,l as je,g as Re,r as _e,b as be}from"./index-7JCizcu7.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-Co01ON81.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-y8nkSKNG.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-DoRQa8Dz.js").then(t=>t.f);return{FolderPluginPage:e}},__vite__mapDeps([9,1,2,6,3,4,5,10,7,8,11,12,13,14,15,16,17]))).FolderPluginPage})),Be=s.lazy(async()=>({default:(await g(async()=>{const{EntitySearchPage:e}=await import("./entities-ByGFSWnQ.js");return{EntitySearchPage:e}},__vite__mapDeps([18,1,2,6,3,4,5]))).EntitySearchPage})),Ue=s.lazy(async()=>({default:(await g(async()=>{const{ProjectSearchPage:e}=await import("./search-BA4r_Yoa.js");return{ProjectSearchPage:e}},__vite__mapDeps([19,1,2,6,3,4,5,20]))).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-0EXAzEpD.js"),__vite__mapDeps([21,1,2,3,4,5,6,7,8,22,23,12,13,15,24,25,26,27,28,16]))).FolderLanding})),Ye=s.lazy(async()=>({default:(await g(()=>import("./folder-mobile-bar-D-XXKrip.js"),__vite__mapDeps([29,1,2,25,3,4,5,6,23,7,8,12,26,15,30,16,14]))).FolderMobileBar})),Je=s.lazy(async()=>({default:(await g(()=>import("./file-viewer-Dqx7DbTw.js"),__vite__mapDeps([31,1,2,3,4,5,6,32]))).FileViewer})),We=s.lazy(async()=>({default:(await g(()=>import("./project-search-dialog-Bo1JWdqR.js"),__vite__mapDeps([33,1,2,6,3,4,5,11,12,8,13]))).ProjectSearchDialog})),Ge=s.lazy(async()=>{const e=await g(()=>import("./client-BMso7lHb.js"),__vite__mapDeps([34,1,2,6,25,3,4,5,23,7,8,12,26,15,30,16,14,35,24,27]));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-soK_bLWT.js"),__vite__mapDeps([36,1,2,10,3,4,5,6,7,8,11,12,13,14,15,37,23,28]))).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};
|