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
|
@@ -26,6 +26,9 @@ export declare function readExternalPlugins(): ExternalPluginEntry[];
|
|
|
26
26
|
export declare function installExternalPlugin(url: string, options?: {
|
|
27
27
|
directory?: string;
|
|
28
28
|
}): Promise<ExternalPluginEntry>;
|
|
29
|
+
/** Identifies the installed plugin set, independent of the Node runtime. */
|
|
30
|
+
export declare function hotKernelKey(plugins?: ExternalPluginEntry[]): string;
|
|
31
|
+
/** Identifies a runtime-specific static kernel cache entry. */
|
|
29
32
|
export declare function kernelKey(plugins?: ExternalPluginEntry[]): string;
|
|
30
33
|
export type ActiveKernel = {
|
|
31
34
|
buildIdentity: string;
|
package/dist/plugins/external.js
CHANGED
|
@@ -163,7 +163,7 @@ function internalSourceAliases(root = kernelSourceRoot()) {
|
|
|
163
163
|
const aliases = {};
|
|
164
164
|
for (const [name, path] of Object.entries({
|
|
165
165
|
"@raggle-ai/agents": "packages/agents/src",
|
|
166
|
-
"
|
|
166
|
+
"kennel-plugins": "packages/plugins/src",
|
|
167
167
|
"@raggle-ai/kennel-api": "packages/api/src",
|
|
168
168
|
"@raggle-ai/markdown": "packages/markdown/src",
|
|
169
169
|
"@raggle-ai/notes": "packages/notes/src",
|
|
@@ -373,21 +373,33 @@ export async function installExternalPlugin(url, options = {}) {
|
|
|
373
373
|
function cliRoot() {
|
|
374
374
|
return resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
375
375
|
}
|
|
376
|
+
function kernelPlugins(plugins) {
|
|
377
|
+
return plugins.map((plugin) => ({
|
|
378
|
+
url: plugin.url,
|
|
379
|
+
requestedRef: plugin.requestedRef ?? null,
|
|
380
|
+
packageName: plugin.packageName,
|
|
381
|
+
id: plugin.id,
|
|
382
|
+
directory: plugin.directory ?? null,
|
|
383
|
+
commit: plugin.commit,
|
|
384
|
+
trigger: plugin.trigger,
|
|
385
|
+
entries: plugin.entries,
|
|
386
|
+
}));
|
|
387
|
+
}
|
|
388
|
+
/** Identifies the installed plugin set, independent of the Node runtime. */
|
|
389
|
+
export function hotKernelKey(plugins = readExternalPlugins()) {
|
|
390
|
+
return hash(JSON.stringify({
|
|
391
|
+
buildIdentity: BUILD_IDENTITY,
|
|
392
|
+
schema: KENNEL_KERNEL_SCHEMA,
|
|
393
|
+
plugins: kernelPlugins(plugins),
|
|
394
|
+
}));
|
|
395
|
+
}
|
|
396
|
+
/** Identifies a runtime-specific static kernel cache entry. */
|
|
376
397
|
export function kernelKey(plugins = readExternalPlugins()) {
|
|
377
398
|
return hash(JSON.stringify({
|
|
378
399
|
buildIdentity: BUILD_IDENTITY,
|
|
379
400
|
schema: KENNEL_KERNEL_SCHEMA,
|
|
380
401
|
runtime: BUILD_RUNTIME,
|
|
381
|
-
plugins: plugins
|
|
382
|
-
url: plugin.url,
|
|
383
|
-
requestedRef: plugin.requestedRef ?? null,
|
|
384
|
-
packageName: plugin.packageName,
|
|
385
|
-
id: plugin.id,
|
|
386
|
-
directory: plugin.directory ?? null,
|
|
387
|
-
commit: plugin.commit,
|
|
388
|
-
trigger: plugin.trigger,
|
|
389
|
-
entries: plugin.entries,
|
|
390
|
-
})),
|
|
402
|
+
plugins: kernelPlugins(plugins),
|
|
391
403
|
}));
|
|
392
404
|
}
|
|
393
405
|
function kernelRoot(key) {
|
|
@@ -448,7 +460,7 @@ export async function prepareExternalPluginModules(temp, target = temp, plugins
|
|
|
448
460
|
const cssImports = plugins.map((plugin) => plugin.entries.css ? `import ${JSON.stringify(plugin.entries.css)};` : "").filter(Boolean).join("\n");
|
|
449
461
|
const clientImports = plugins.map((plugin, index) => `import { ${plugin.entries.manifestSymbol} as manifest${index} } from ${JSON.stringify(plugin.entries.manifest)};`).join("\n");
|
|
450
462
|
const clientItems = plugins.map((plugin, index) => ` { ...manifest${index}, component: lazy(async () => ({ default: (await import(${JSON.stringify(plugin.entries.client)}))[${JSON.stringify(plugin.entries.clientSymbol)}].component })) }`).join(",\n");
|
|
451
|
-
await writeFile(clientModule, `import { lazy } from "react";\nimport type { FolderPluginClient } from "
|
|
463
|
+
await writeFile(clientModule, `import { lazy } from "react";\nimport type { FolderPluginClient } from "kennel-plugins/client";\n${cssImports}\n${clientImports}\nexport const externalFolderPlugins: FolderPluginClient[] = [\n${clientItems}\n];\n`);
|
|
452
464
|
const serverEntries = [];
|
|
453
465
|
const apiEntries = [];
|
|
454
466
|
for (const plugin of plugins) {
|
package/dist/site/hot-viewer.js
CHANGED
|
@@ -7,12 +7,15 @@ import { tmpdir } from 'node:os';
|
|
|
7
7
|
import { dirname, relative, resolve } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { createKennelClient } from '../core/api-client.js';
|
|
10
|
+
import { hotKernelKey, readExternalPlugins } from '../plugins/external.js';
|
|
10
11
|
function sourceRoot() {
|
|
11
12
|
return resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
12
13
|
}
|
|
13
14
|
async function viewerStatus(url) {
|
|
14
15
|
return createKennelClient({ baseUrl: url }).health({ signal: AbortSignal.timeout(1_000) })
|
|
15
|
-
.then((body) => body.viewer === 'kennel-vite' || body.viewer === 'kennel-core'
|
|
16
|
+
.then((body) => body.viewer === 'kennel-vite' || body.viewer === 'kennel-core'
|
|
17
|
+
? { viewer: body.viewer, kernelKey: body.kernelKey }
|
|
18
|
+
: 'other')
|
|
16
19
|
.catch((error) => {
|
|
17
20
|
// HTTP rejection means a different service owns the port; connection and
|
|
18
21
|
// timeout failures mean the viewer is unavailable, so startup may retry.
|
|
@@ -20,17 +23,17 @@ async function viewerStatus(url) {
|
|
|
20
23
|
? 'other' : 'unavailable';
|
|
21
24
|
});
|
|
22
25
|
}
|
|
23
|
-
async function
|
|
26
|
+
async function runningViewer(url, attempts = 1, waitOnOther = false) {
|
|
24
27
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
25
28
|
const status = await viewerStatus(url);
|
|
26
|
-
if (status === '
|
|
27
|
-
return
|
|
29
|
+
if (typeof status === 'object')
|
|
30
|
+
return status;
|
|
28
31
|
if (status === 'other' && !waitOnOther)
|
|
29
|
-
return
|
|
32
|
+
return undefined;
|
|
30
33
|
if (attempt + 1 < attempts)
|
|
31
34
|
await new Promise((done) => setTimeout(done, 250));
|
|
32
35
|
}
|
|
33
|
-
return
|
|
36
|
+
return undefined;
|
|
34
37
|
}
|
|
35
38
|
async function portOpen(host, port) {
|
|
36
39
|
return new Promise((done) => {
|
|
@@ -132,8 +135,20 @@ export async function hotViewer(options) {
|
|
|
132
135
|
console.log(`bun ${[...args, ...(options.open ? ['--open', openPath] : [])].join(' ')}`);
|
|
133
136
|
return;
|
|
134
137
|
}
|
|
135
|
-
const
|
|
136
|
-
|
|
138
|
+
const plugins = readExternalPlugins();
|
|
139
|
+
// Must match the key apps/web/scripts/dev.mjs gives Vite as KENNEL_KERNEL_KEY.
|
|
140
|
+
const expectedKey = plugins.length > 0 ? hotKernelKey(plugins) : 'core';
|
|
141
|
+
// Reuse only a Vite viewer that serves the same plugin set. Anything else on
|
|
142
|
+
// the port is stale for this kernel and must be restarted, never reused.
|
|
143
|
+
const reuse = (running) => {
|
|
144
|
+
const restart = 'Stop that viewer (Ctrl+C in its terminal) and run this command again, or select another port.';
|
|
145
|
+
if (running.viewer !== 'kennel-vite') {
|
|
146
|
+
throw new Error(`Port ${options.port} runs the static Kennel viewer, not the hot viewer. ${restart}`);
|
|
147
|
+
}
|
|
148
|
+
if (running.kernelKey !== expectedKey) {
|
|
149
|
+
throw new Error(`The Kennel hot viewer on port ${options.port} uses kernel ${running.kernelKey}, `
|
|
150
|
+
+ `but the installed plugins need kernel ${expectedKey}. ${restart}`);
|
|
151
|
+
}
|
|
137
152
|
if (options.open) {
|
|
138
153
|
// Do not stack another tab: the viewer is already open. Print the URL
|
|
139
154
|
// so the caller can still get to it deliberately.
|
|
@@ -142,21 +157,19 @@ export async function hotViewer(options) {
|
|
|
142
157
|
else {
|
|
143
158
|
console.log('Kennel hot viewer is already running. Reusing it.');
|
|
144
159
|
}
|
|
160
|
+
};
|
|
161
|
+
const status = await viewerStatus(url);
|
|
162
|
+
if (typeof status === 'object') {
|
|
163
|
+
reuse(status);
|
|
145
164
|
return;
|
|
146
165
|
}
|
|
147
166
|
if (status === 'other') {
|
|
148
167
|
throw new Error(`Port ${options.port} is used by another service. Stop it or select another port.`);
|
|
149
168
|
}
|
|
150
169
|
if (await portOpen(options.host, options.port)) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// so the caller can still get to it deliberately.
|
|
155
|
-
console.log(`Kennel hot viewer is already running at ${viewerUrl}`);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
console.log('Kennel hot viewer is already running. Reusing it.');
|
|
159
|
-
}
|
|
170
|
+
const running = await runningViewer(url, 20, true);
|
|
171
|
+
if (running) {
|
|
172
|
+
reuse(running);
|
|
160
173
|
return;
|
|
161
174
|
}
|
|
162
175
|
throw new Error(`Port ${options.port} is used by another service. Stop it or select another port.`);
|
|
@@ -164,15 +177,9 @@ export async function hotViewer(options) {
|
|
|
164
177
|
const lock = startupLock(options.host, options.port);
|
|
165
178
|
let token = await acquireLock(lock);
|
|
166
179
|
if (!token) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// so the caller can still get to it deliberately.
|
|
171
|
-
console.log(`Kennel hot viewer is already running at ${viewerUrl}`);
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
console.log('Kennel hot viewer is already running. Reusing it.');
|
|
175
|
-
}
|
|
180
|
+
const running = await runningViewer(url, 40, true);
|
|
181
|
+
if (running) {
|
|
182
|
+
reuse(running);
|
|
176
183
|
return;
|
|
177
184
|
}
|
|
178
185
|
await rm(lock, { force: true, recursive: true });
|
|
@@ -180,16 +187,10 @@ export async function hotViewer(options) {
|
|
|
180
187
|
}
|
|
181
188
|
if (!token)
|
|
182
189
|
throw new Error(`Could not acquire the hot viewer startup lock for port ${options.port}.`);
|
|
183
|
-
|
|
190
|
+
const running = await runningViewer(url);
|
|
191
|
+
if (running) {
|
|
184
192
|
await releaseLock(lock, token);
|
|
185
|
-
|
|
186
|
-
// Do not stack another tab: the viewer is already open. Print the URL
|
|
187
|
-
// so the caller can still get to it deliberately.
|
|
188
|
-
console.log(`Kennel hot viewer is already running at ${viewerUrl}`);
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
console.log('Kennel hot viewer is already running. Reusing it.');
|
|
192
|
-
}
|
|
193
|
+
reuse(running);
|
|
193
194
|
return;
|
|
194
195
|
}
|
|
195
196
|
console.log(`bun ${args.join(' ')}`);
|
|
@@ -220,9 +221,15 @@ export async function hotViewer(options) {
|
|
|
220
221
|
done();
|
|
221
222
|
return;
|
|
222
223
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
const existing = await runningViewer(url, 20, true);
|
|
225
|
+
if (existing) {
|
|
226
|
+
try {
|
|
227
|
+
reuse(existing);
|
|
228
|
+
done();
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
fail(error);
|
|
232
|
+
}
|
|
226
233
|
return;
|
|
227
234
|
}
|
|
228
235
|
fail(new Error(`Kennel hot viewer stopped with exit code ${code ?? 'unknown'}`));
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* plain-`node` CLI never imports the plugin packages' runtime sources, while
|
|
9
9
|
* staying type-checked against the one source of truth.
|
|
10
10
|
*/
|
|
11
|
-
import type { FolderPluginServer } from "
|
|
12
|
-
export type { FolderPluginContext, FolderPluginData, FolderPluginDetection, FolderPluginServer, } from "
|
|
11
|
+
import type { FolderPluginServer } from "kennel-plugins/server";
|
|
12
|
+
export type { FolderPluginContext, FolderPluginData, FolderPluginDetection, FolderPluginServer, } from "kennel-plugins/server";
|
|
13
13
|
/**
|
|
14
14
|
* Signal a server-side plugin failure (like a mail preview read error) so the
|
|
15
15
|
* host maps it to an HTTP 5xx instead of a not-found. All other thrown errors
|
|
@@ -515,13 +515,13 @@ function createAgentsPlugin(options = {}) {
|
|
|
515
515
|
};
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
// packages/
|
|
519
|
-
|
|
518
|
+
// packages/plugins/dist/chunk-AX4A4GYF.js
|
|
519
|
+
var FolderPluginFailure = class extends Error {
|
|
520
520
|
constructor(message) {
|
|
521
521
|
super(message);
|
|
522
522
|
this.name = "FolderPluginFailure";
|
|
523
523
|
}
|
|
524
|
-
}
|
|
524
|
+
};
|
|
525
525
|
|
|
526
526
|
// packages/notes/src/server.ts
|
|
527
527
|
import { readdir, stat as stat2 } from "node:fs/promises";
|
|
@@ -730,11 +730,11 @@ async function scaffoldFolderPlugins(folder, options = {}) {
|
|
|
730
730
|
return { created, skipped, supported };
|
|
731
731
|
}
|
|
732
732
|
export {
|
|
733
|
-
|
|
734
|
-
folderServerRegistryAsync,
|
|
735
|
-
folderServerRegistry,
|
|
736
|
-
externalApiHandlers,
|
|
737
|
-
createFolderServerPlugins,
|
|
733
|
+
FolderPluginFailure,
|
|
738
734
|
configuredFolderServerRegistry,
|
|
739
|
-
|
|
735
|
+
createFolderServerPlugins,
|
|
736
|
+
externalApiHandlers,
|
|
737
|
+
folderServerRegistry,
|
|
738
|
+
folderServerRegistryAsync,
|
|
739
|
+
scaffoldFolderPlugins
|
|
740
740
|
};
|
package/dist/site/viewer.js
CHANGED
|
@@ -259,17 +259,15 @@ function tailscaleHost() {
|
|
|
259
259
|
export async function viewer(input) {
|
|
260
260
|
const portExplicit = viewerPortWasExplicit(input);
|
|
261
261
|
const options = splitViewerArgs(input);
|
|
262
|
-
|
|
263
|
-
const externalPlugins = readExternalPlugins();
|
|
264
|
-
if (options.hot && externalPlugins.length === 0) {
|
|
262
|
+
if (options.hot) {
|
|
265
263
|
const { hotViewer } = await import("./hot-viewer.js");
|
|
266
264
|
await hotViewer(options);
|
|
267
265
|
return;
|
|
268
266
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
267
|
+
const { ensureKernel, hotKernelKey, readExternalPlugins } = await import("../plugins/external.js");
|
|
268
|
+
const externalPlugins = readExternalPlugins();
|
|
272
269
|
const kernel = await ensureKernel(externalPlugins);
|
|
270
|
+
const viteKernelKey = externalPlugins.length > 0 ? hotKernelKey(externalPlugins) : "core";
|
|
273
271
|
const web = kernel.webRoot;
|
|
274
272
|
if (!existsSync(resolve(web, "index.html"))) {
|
|
275
273
|
throw new Error(`Kennel web app not found. Run the CLI build first.`);
|
|
@@ -298,9 +296,16 @@ export async function viewer(input) {
|
|
|
298
296
|
.join(",");
|
|
299
297
|
const initialViewerUrl = `http://${options.host}:${options.port}`;
|
|
300
298
|
const existing = await runningViewer(initialViewerUrl);
|
|
299
|
+
// A local Vite viewer is not root-restricted, so it can open any local
|
|
300
|
+
// folder. The static kennel-core viewer is root-scoped: reuse it only for
|
|
301
|
+
// its own root or a descendant.
|
|
301
302
|
if (existing &&
|
|
302
|
-
existing.
|
|
303
|
-
|
|
303
|
+
((existing.viewer === "kennel-vite" &&
|
|
304
|
+
!remote &&
|
|
305
|
+
existing.kernelKey === viteKernelKey) ||
|
|
306
|
+
(existing.viewer !== "kennel-vite" &&
|
|
307
|
+
existing.kernelKey === kernel.key &&
|
|
308
|
+
isSameOrDescendant(existing.root, options.root)))) {
|
|
304
309
|
const viewerUrl = popUrl(displayHost, options.port, options);
|
|
305
310
|
console.log(viewerUrl);
|
|
306
311
|
console.log(`Kennel is already running at ${viewerUrl}`);
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@lexical/react": "0.49.0",
|
|
24
24
|
"@lexical/rich-text": "0.49.0",
|
|
25
25
|
"@raggle-ai/agents": "workspace:*",
|
|
26
|
-
"
|
|
26
|
+
"kennel-plugins": "workspace:*",
|
|
27
27
|
"@raggle-ai/kennel-api": "workspace:*",
|
|
28
28
|
"@raggle-ai/kennel-preview": "workspace:*",
|
|
29
29
|
"@raggle-ai/local": "0.14.0",
|
|
@@ -5,6 +5,7 @@ import { dirname, join, resolve } from "node:path"
|
|
|
5
5
|
import { fileURLToPath } from "node:url"
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
hotKernelKey,
|
|
8
9
|
prepareExternalPluginModules,
|
|
9
10
|
readExternalPlugins,
|
|
10
11
|
} from "../../../cli/src/plugins/external.ts"
|
|
@@ -30,6 +31,9 @@ try {
|
|
|
30
31
|
stdio: "inherit",
|
|
31
32
|
env: {
|
|
32
33
|
...process.env,
|
|
34
|
+
// Reported by /api/health so the CLI reuses this viewer only for the
|
|
35
|
+
// same plugin set; "core" matches the CLI kernel without plugins.
|
|
36
|
+
KENNEL_KERNEL_KEY: plugins.length > 0 ? hotKernelKey(plugins) : "core",
|
|
33
37
|
KENNEL_KERNEL_SOURCE_ROOT: workspace,
|
|
34
38
|
KENNEL_HOST_NODE_MODULES: resolve(workspace, "cli/node_modules"),
|
|
35
39
|
KENNEL_EXTERNAL_CLIENT_MODULE: modules.clientModule,
|
|
@@ -4,39 +4,75 @@ export function subscribeFolderEvent(
|
|
|
4
4
|
folder: string | undefined,
|
|
5
5
|
listener: () => void,
|
|
6
6
|
) {
|
|
7
|
-
return subscribeApiEvent(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
data
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
return subscribeApiEvent(
|
|
8
|
+
event,
|
|
9
|
+
(message) => {
|
|
10
|
+
let data: unknown
|
|
11
|
+
try {
|
|
12
|
+
data = JSON.parse((message as MessageEvent<string>).data)
|
|
13
|
+
} catch {
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
if (
|
|
17
|
+
data &&
|
|
18
|
+
typeof data === "object" &&
|
|
19
|
+
"path" in data &&
|
|
20
|
+
data.path === folder
|
|
21
|
+
)
|
|
22
|
+
listener()
|
|
23
|
+
},
|
|
24
|
+
listener,
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Subscription = {
|
|
29
|
+
event: string
|
|
30
|
+
listener: (event: Event) => void
|
|
31
|
+
resume: () => void
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
let source: EventSource | undefined
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
const subscriptions = new Set<Subscription>()
|
|
36
|
+
|
|
37
|
+
function connect() {
|
|
38
|
+
if (source || document.visibilityState !== "visible") return
|
|
39
|
+
source = new EventSource("/api/events")
|
|
40
|
+
for (const { event, listener } of subscriptions) {
|
|
41
|
+
source.addEventListener(event, listener)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function visibilityChanged() {
|
|
46
|
+
if (document.visibilityState !== "visible") {
|
|
47
|
+
source?.close()
|
|
48
|
+
source = undefined
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
connect()
|
|
52
|
+
// Hidden tabs missed notifications. Refresh each subscriber on return.
|
|
53
|
+
for (const subscription of subscriptions) subscription.resume()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Hidden tabs must not consume the browser's per-origin HTTP/1 connection limit. */
|
|
27
57
|
export function subscribeApiEvent(
|
|
28
58
|
event: string,
|
|
29
59
|
listener: (event: Event) => void,
|
|
60
|
+
resume = () => listener(new Event(event)),
|
|
30
61
|
) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
const subscription = { event, listener, resume }
|
|
63
|
+
subscriptions.add(subscription)
|
|
64
|
+
if (subscriptions.size === 1) {
|
|
65
|
+
document.addEventListener("visibilitychange", visibilityChanged)
|
|
66
|
+
}
|
|
67
|
+
if (source) source.addEventListener(event, listener)
|
|
68
|
+
else connect()
|
|
35
69
|
return () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
70
|
+
if (!subscriptions.delete(subscription)) return
|
|
71
|
+
source?.removeEventListener(event, listener)
|
|
72
|
+
if (subscriptions.size === 0) {
|
|
73
|
+
source?.close()
|
|
39
74
|
source = undefined
|
|
75
|
+
document.removeEventListener("visibilitychange", visibilityChanged)
|
|
40
76
|
}
|
|
41
77
|
}
|
|
42
78
|
}
|
|
@@ -2,7 +2,7 @@ import type { ReactNode } from "react"
|
|
|
2
2
|
import { useQuery } from "@tanstack/react-query"
|
|
3
3
|
import { api } from "~/api-client"
|
|
4
4
|
|
|
5
|
-
import { folderPathId } from "
|
|
5
|
+
import { folderPathId } from "kennel-plugins/client"
|
|
6
6
|
import { FolderFilterIconProvider } from "@raggle-ai/ui/components/folder-filter-bar"
|
|
7
7
|
import { FolderImage } from "@raggle-ai/ui/components/folder-image"
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useParams } from "@tanstack/react-router"
|
|
2
2
|
import { api } from "~/api-client"
|
|
3
3
|
|
|
4
|
-
import type { FolderPluginViewProps } from "
|
|
4
|
+
import type { FolderPluginViewProps } from "kennel-plugins/client"
|
|
5
5
|
|
|
6
6
|
import { FolderFilterMetadataProvider } from "./folder-filter-icons"
|
|
7
7
|
import { getFolderPlugin } from "./plugins"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { lazy } from "react"
|
|
2
2
|
import { externalFolderPlugins } from "@/external-plugins"
|
|
3
3
|
|
|
4
|
-
import type { FolderPluginClient } from "
|
|
4
|
+
import type { FolderPluginClient } from "kennel-plugins/client"
|
|
5
5
|
import { agentsManifest } from "@raggle-ai/agents/manifest"
|
|
6
6
|
|
|
7
7
|
// Keep navigation metadata cheap. Import only the selected plugin's UI;
|
|
@@ -74,7 +74,7 @@ const resolveBarkdown = (): string | undefined => {
|
|
|
74
74
|
const barkdown = resolveBarkdown()
|
|
75
75
|
const internalPackages: Array<[RegExp, string]> = [
|
|
76
76
|
[/^@raggle-ai\/agents(\/.*)?$/, "packages/agents/src"],
|
|
77
|
-
[
|
|
77
|
+
[/^kennel-plugins(\/.*)?$/, "packages/plugins/src"],
|
|
78
78
|
[/^@raggle-ai\/kennel-api(\/.*)?$/, "packages/api/src"],
|
|
79
79
|
[/^@raggle-ai\/markdown(\/.*)?$/, "packages/markdown/src"],
|
|
80
80
|
[/^@raggle-ai\/notes(\/.*)?$/, "packages/notes/src"],
|
|
@@ -215,6 +215,8 @@ export default defineConfig({
|
|
|
215
215
|
corePlugin({
|
|
216
216
|
remoteAccess,
|
|
217
217
|
restrictToRoot: remoteAccess,
|
|
218
|
+
// /api/health reports this name so the CLI reuses only a hot viewer.
|
|
219
|
+
viewerName: "kennel-vite",
|
|
218
220
|
root: process.env.KENNEL_VIEWER_ROOT || root,
|
|
219
221
|
// `kennel pop <file>` (hot) locks document reads to exactly this file;
|
|
220
222
|
// the static viewer applies the same lock in-process.
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"publish:public:dry-run": "npm --@raggle-ai:registry=https://registry.npmjs.org publish --dry-run --access public --registry=https://registry.npmjs.org"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"
|
|
44
|
+
"kennel-plugins": "workspace:*",
|
|
45
45
|
"@raggle-ai/markdown": "workspace:*",
|
|
46
46
|
"@raggle-ai/ui": "workspace:*",
|
|
47
47
|
"@tanstack/react-query": "catalog:tanstack",
|
|
@@ -2,7 +2,7 @@ import type { ReactNode } from "react"
|
|
|
2
2
|
import { useMemo, useState } from "react"
|
|
3
3
|
import { FilePlus2, LoaderCircle, Pencil } from "lucide-react"
|
|
4
4
|
|
|
5
|
-
import type { FolderPluginHostActions } from "
|
|
5
|
+
import type { FolderPluginHostActions } from "kennel-plugins/client"
|
|
6
6
|
import { BarkdownMarkdown, markdownMetadata } from "@raggle-ai/markdown"
|
|
7
7
|
import { FolderContextIcon } from "@raggle-ai/ui/components/folder-filter-bar"
|
|
8
8
|
import {
|
|
@@ -2,7 +2,7 @@ import type {
|
|
|
2
2
|
FolderPluginContext,
|
|
3
3
|
FolderPluginData,
|
|
4
4
|
FolderPluginDetection,
|
|
5
|
-
} from "
|
|
5
|
+
} from "kennel-plugins/server"
|
|
6
6
|
|
|
7
7
|
import type { AgentsResolution, ClientFilter } from "./types.ts"
|
|
8
8
|
import { agentsManifest } from "./manifest.ts"
|
|
@@ -2,7 +2,7 @@ import { useMemo, useRef, useState } from "react"
|
|
|
2
2
|
import { useQuery } from "@tanstack/react-query"
|
|
3
3
|
import { ChevronDown, Info, TriangleAlert } from "lucide-react"
|
|
4
4
|
|
|
5
|
-
import type { FolderPluginViewProps } from "
|
|
5
|
+
import type { FolderPluginViewProps } from "kennel-plugins/client"
|
|
6
6
|
import {
|
|
7
7
|
Collapsible,
|
|
8
8
|
CollapsibleContent,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
21
21
|
"@raggle-ai/agents": "workspace:*",
|
|
22
|
-
"
|
|
22
|
+
"kennel-plugins": "workspace:*",
|
|
23
23
|
"@raggle-ai/kennel-kinds": "workspace:*",
|
|
24
24
|
"@raggle-ai/local": "0.14.0",
|
|
25
25
|
"@raggle-ai/markdown": "workspace:*",
|
|
@@ -10,7 +10,7 @@ import { Readable, Writable } from "node:stream";
|
|
|
10
10
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
11
11
|
import type { ApiHost } from "./host";
|
|
12
12
|
|
|
13
|
-
import { sameOrigin } from "
|
|
13
|
+
import { sameOrigin } from "kennel-plugins/endpoint";
|
|
14
14
|
import localSessions from "@raggle-ai/local/sessions";
|
|
15
15
|
|
|
16
16
|
import type { AcpTransport } from "./acp/transport";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
|
|
4
|
-
import type { ApiRouteSpec } from "
|
|
5
|
-
import { apiError, jsonResponse } from "
|
|
4
|
+
import type { ApiRouteSpec } from "kennel-plugins/endpoint";
|
|
5
|
+
import { apiError, jsonResponse } from "kennel-plugins/endpoint";
|
|
6
6
|
|
|
7
7
|
export type CreateAgentFileContext = {
|
|
8
8
|
/**
|
|
@@ -17,13 +17,13 @@ import {
|
|
|
17
17
|
sep,
|
|
18
18
|
} from "node:path";
|
|
19
19
|
|
|
20
|
-
import type { ApiRouteSpec } from "
|
|
20
|
+
import type { ApiRouteSpec } from "kennel-plugins/endpoint";
|
|
21
21
|
import { replaceSelection } from "../../shared/selection";
|
|
22
22
|
import {
|
|
23
23
|
apiError,
|
|
24
24
|
jsonResponse,
|
|
25
25
|
parseJsonBody,
|
|
26
|
-
} from "
|
|
26
|
+
} from "kennel-plugins/endpoint";
|
|
27
27
|
|
|
28
28
|
const pending = new Map<string, Promise<unknown>>();
|
|
29
29
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
|
|
3
|
-
import type { ApiRouteSpec } from "
|
|
4
|
-
import { apiError } from "
|
|
3
|
+
import type { ApiRouteSpec } from "kennel-plugins/endpoint";
|
|
4
|
+
import { apiError } from "kennel-plugins/endpoint";
|
|
5
5
|
|
|
6
6
|
export type OpenPathContext = {
|
|
7
7
|
/**
|
|
@@ -17,14 +17,14 @@ import type { ApiHost } from "./host";
|
|
|
17
17
|
import { markdownMetadata } from "@raggle-ai/markdown";
|
|
18
18
|
import { readFolder } from "@raggle-ai/markdown/node";
|
|
19
19
|
import { execFile } from "node:child_process";
|
|
20
|
-
import { sameOrigin } from "
|
|
20
|
+
import { sameOrigin } from "kennel-plugins/endpoint";
|
|
21
21
|
import { parse as parseYaml } from "yaml";
|
|
22
22
|
|
|
23
|
-
import type { FolderPluginServer } from "
|
|
23
|
+
import type { FolderPluginServer } from "kennel-plugins/server";
|
|
24
24
|
import type { LocalMarkdownFileSummary, LocalProject } from "@raggle-ai/local";
|
|
25
25
|
import type { FolderSkill } from "@raggle-ai/ui/lib/folder-activity";
|
|
26
|
-
import { runApiRoute } from "
|
|
27
|
-
import { FolderPluginFailure } from "
|
|
26
|
+
import { runApiRoute } from "kennel-plugins/endpoint";
|
|
27
|
+
import { FolderPluginFailure } from "kennel-plugins/server";
|
|
28
28
|
import { folderWorkspace } from "@raggle-ai/schemas/workspace";
|
|
29
29
|
import { createSchemaCollectionServer } from "@raggle-ai/schemas/server";
|
|
30
30
|
import local from "@raggle-ai/local";
|