kennel 0.2.45 → 0.2.46
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/dist/core/api-client.js +34 -1
- package/dist/core/runtime.js +189 -129
- package/dist/package/preview.js +217 -141
- package/package.json +2 -2
- package/web/assets/{abnfDiagram-VRR7QNED-D8mHNUwf.js → abnfDiagram-VRR7QNED-BOm3iBSE.js} +1 -1
- package/web/assets/{arc-DORR-Lbn.js → arc-D_zfnjJW.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-CnmL2DAX.js → architectureDiagram-ZJ3FMSHR-CTXAbDtC.js} +1 -1
- package/web/assets/{ask-tray-KUTWZ4MV-VQJJAsDn.js → ask-tray-CT6DQRTC-DfTc3bnC.js} +1 -1
- package/web/assets/{blockDiagram-677ZJIJ3-_SWUT5nP.js → blockDiagram-677ZJIJ3-CcPWOAKO.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-r7ghc180.js → c4Diagram-LMCZKHZV-B_eNO2-f.js} +1 -1
- package/web/assets/channel-Dlb_u_Yk.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-D_LeMwFJ.js → chunk-2Q5K7J3B-BtQX_f5i.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-AeVZw1It.js → chunk-32BRIVSS-BBtfsm8_.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-Bp_epQ8r.js → chunk-5VM5RSS4-CG0bf9ML.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-Dz4n-DeM.js → chunk-EX3LRPZG-DS2H7ilP.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-B0MQp8TQ.js → chunk-JWPE2WC7-CGLMMKkr.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-Bkomqk1x.js → chunk-MOJQB5TN-C76lqDkU.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-B0F7WMyE.js → chunk-RYQCIY6F-ZY-EzC5l.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-BDifU9oY.js → chunk-V7JOEXUC-sBv90hIh.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-Bgd4HCG_.js → chunk-VR4S4FIN-jW9aFTp3.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-BK8FhRs4.js → chunk-XXDRQBXY-FPtE6zce.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-CinFzRGQ.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-CinFzRGQ.js +1 -0
- package/web/assets/{client-5Q4VI7ZT-BkTtFalV.js → client-5Q4VI7ZT-DYH5SwVp.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-Dm3k2U47.js → cose-bilkent-JH36ORCC-NdJGLzeJ.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-DCnilF1f.js → cynefin-VYW2F7L2-D-o_obcW.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-BrulEEQ9.js → cynefinDiagram-TSTJHNR4-RA4QYrtB.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-Dda61i4h.js → dagre-VKFMJZFB-Bq4DfO16.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-sTmDEDMM.js → diagram-FQU43EPY-bPnACaba.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-d-KQnPrm.js → diagram-G47NLZAW-cPca5hvp.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-DcRxa_ps.js → diagram-NH7WQ7WH-DHyP34H8.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-CYzWtWvV.js → diagram-OA4YK3LP-hVk7mHu1.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-FI3V_N07.js → diagram-WEI45ONY-Cd3AEJO3.js} +1 -1
- package/web/assets/{document-view-TGFRNHKS-VSJS3BGw.js → document-view-VX2ZTQM5-CDdtofzz.js} +8 -8
- package/web/assets/{ebnfDiagram-CCIWWBDH-DcvVmQhu.js → ebnfDiagram-CCIWWBDH-BxtDx2MR.js} +1 -1
- package/web/assets/{entity-search-page-RIYQYIJJ-Bed3y-5Q.js → entity-search-page-RIYQYIJJ-IvZzjXvt.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-DI5DBlBp.js → erDiagram-Q63AITRT-CtdOkrpo.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-Bz1AbRxB.js → flowDiagram-23GEKE2U-BDHfaJo6.js} +1 -1
- package/web/assets/{ganttDiagram-NO4QXBWP-ChKlhxeo.js → ganttDiagram-NO4QXBWP-BhV7JFJA.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-BtTqLSyY.js → gitGraphDiagram-IHSO6WYX-BVRBRDVk.js} +1 -1
- package/web/assets/index-BxCXNDe6.css +1 -0
- package/web/assets/{index-CDAH4UPU.js → index-Cl-kcrk3.js} +191 -182
- package/web/assets/{infoDiagram-FWYZ7A6U-COpIz9uZ.js → infoDiagram-FWYZ7A6U-BKuFQe6t.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-CB7Bdsfr.js → ishikawaDiagram-FXEZZL3T-lNbhlHEo.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BMytnJBE.js → journeyDiagram-5HDEW3XC-CoGf_pSm.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-BFS4G0g-.js → kanban-definition-HUTT4EX6-Cgp0WGrq.js} +1 -1
- package/web/assets/{linear-DMUO2qBp.js → linear-B3UMk7TK.js} +1 -1
- package/web/assets/{linked-session-header-7BUTWROP-DzEcA4Fq.js → linked-session-header-7BUTWROP-Coqn-Dz0.js} +1 -1
- package/web/assets/{mermaid.core-BAj-Ltr-.js → mermaid.core-6bZ5bkAq.js} +4 -4
- package/web/assets/{mindmap-definition-LN4V7U3C-CjymOEvH.js → mindmap-definition-LN4V7U3C-BowQNgIG.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-D64jiUPu.js → pegDiagram-2B236MQR-DrhWFvfI.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-CCbI5U6o.js → pieDiagram-ENE6RG2P-DNOg53mu.js} +1 -1
- package/web/assets/{plugin-host-modules-D7pHtNJn.js → plugin-host-modules-NvyHieUX.js} +26 -26
- package/web/assets/{project-search-page-O6YRLDGU-1bPrifgb.js → project-search-page-O6YRLDGU-CFA4lf0c.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-B7dN_Kn5.js → quadrantDiagram-ABIIQ3AL-BOJ4UGbk.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-BPjAzqcL.js → railroadDiagram-RFXS5EU6-_UJ9_AEC.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-BFhnnUWa.js → requirementDiagram-TGXJPOKE-BFa61FSa.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-W2UguUjW.js → sankeyDiagram-HTMAVEWB-V1J9w6jl.js} +1 -1
- package/web/assets/{selection-popup-ABYH3A27-DsiLbG7S.js → selection-popup-ZX4VUZ3A-Duh9LSP2.js} +1 -1
- package/web/assets/{sequenceDiagram-DBY2YBRQ-DcOakOD4.js → sequenceDiagram-DBY2YBRQ-xdS7JpTx.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-D3N248Z6.js → sizeCapture-X5ZJPWSS-DBULLaws.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-Cir3yiDe.js → stateDiagram-2N3HPSRC-DfBpQAQb.js} +1 -1
- package/web/assets/{stateDiagram-v2-6OUMAXLB-BwL0KYLn.js → stateDiagram-v2-6OUMAXLB-C-dC_PIX.js} +1 -1
- package/web/assets/{swimlanes-5IMT3BWC-Dhq7FmZr.js → swimlanes-5IMT3BWC-L-RTYuhP.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-BErklojq.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-CMa1wjsI.js → timeline-definition-FHXFAJF6-CAEbvdzk.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-DvglazwQ.js → vennDiagram-L72KCM5P-J10bFP8c.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-DcogrL32.js → wardleyDiagram-EHGQE667-Bm0goK-9.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-BlsDcr_U.js → xychartDiagram-FW5EYKEG-BAH4TTVb.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/channel-r9-1szjb.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-L_jmDmNd.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-L_jmDmNd.js +0 -1
- package/web/assets/index-Di6pguZz.css +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-D4q-nPpB.js +0 -8
package/dist/core/runtime.js
CHANGED
|
@@ -17027,8 +17027,8 @@ var require__2020 = __commonJS(function(exports, module) {
|
|
|
17027
17027
|
import {
|
|
17028
17028
|
createServer
|
|
17029
17029
|
} from "node:http";
|
|
17030
|
-
import { readFile as readFile12, realpath as
|
|
17031
|
-
import { extname as
|
|
17030
|
+
import { readFile as readFile12, realpath as realpath10, stat as stat13 } from "node:fs/promises";
|
|
17031
|
+
import { extname as extname8, isAbsolute as isAbsolute9, relative as relative14, resolve as resolve17 } from "node:path";
|
|
17032
17032
|
|
|
17033
17033
|
// packages/api/src/server/watcher.ts
|
|
17034
17034
|
import { existsSync, statSync, watch } from "node:fs";
|
|
@@ -21796,6 +21796,10 @@ var metadataQuerySchema = object({
|
|
|
21796
21796
|
sort: _enum(["alpha", "recent"]).optional(),
|
|
21797
21797
|
schema: string2().optional()
|
|
21798
21798
|
});
|
|
21799
|
+
var deleteNoteSchema = object({
|
|
21800
|
+
folder: string2(),
|
|
21801
|
+
path: string2()
|
|
21802
|
+
});
|
|
21799
21803
|
var documentEditSchema = object({
|
|
21800
21804
|
folder: string2(),
|
|
21801
21805
|
path: string2(),
|
|
@@ -21855,7 +21859,11 @@ var routes = {
|
|
|
21855
21859
|
path: "/api/health",
|
|
21856
21860
|
method: "get",
|
|
21857
21861
|
query: emptyQuery,
|
|
21858
|
-
response: object({
|
|
21862
|
+
response: object({
|
|
21863
|
+
viewer: string2(),
|
|
21864
|
+
root: string2(),
|
|
21865
|
+
kernelKey: string2()
|
|
21866
|
+
})
|
|
21859
21867
|
},
|
|
21860
21868
|
capabilities: {
|
|
21861
21869
|
path: "/api/capabilities",
|
|
@@ -21943,6 +21951,13 @@ var routes = {
|
|
|
21943
21951
|
path: "/api/open-path",
|
|
21944
21952
|
method: "get",
|
|
21945
21953
|
query: object({ path: string2() })
|
|
21954
|
+
},
|
|
21955
|
+
deleteNote: {
|
|
21956
|
+
path: "/api/delete-note",
|
|
21957
|
+
method: "post",
|
|
21958
|
+
query: emptyQuery,
|
|
21959
|
+
body: deleteNoteSchema,
|
|
21960
|
+
response: object({ deleted: literal(true) })
|
|
21946
21961
|
}
|
|
21947
21962
|
};
|
|
21948
21963
|
|
|
@@ -21995,16 +22010,16 @@ function sendContract(response, url, body, headers = {}) {
|
|
|
21995
22010
|
|
|
21996
22011
|
// packages/api/src/server/folder-metadata-plugin.ts
|
|
21997
22012
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
21998
|
-
import { readdir as readdir7, readFile as readFile11, realpath as
|
|
22013
|
+
import { readdir as readdir7, readFile as readFile11, realpath as realpath9, stat as stat12 } from "node:fs/promises";
|
|
21999
22014
|
import { homedir as homedir4 } from "node:os";
|
|
22000
22015
|
import {
|
|
22001
22016
|
basename as basename8,
|
|
22002
22017
|
dirname as dirname13,
|
|
22003
|
-
extname as
|
|
22004
|
-
isAbsolute as
|
|
22005
|
-
relative as
|
|
22006
|
-
resolve as
|
|
22007
|
-
sep as
|
|
22018
|
+
extname as extname7,
|
|
22019
|
+
isAbsolute as isAbsolute8,
|
|
22020
|
+
relative as relative13,
|
|
22021
|
+
resolve as resolve16,
|
|
22022
|
+
sep as sep11
|
|
22008
22023
|
} from "node:path";
|
|
22009
22024
|
|
|
22010
22025
|
// node_modules/.bun/@raggle-ai+barkdown@0.7.1+22117d1132b05fb8/node_modules/@raggle-ai/barkdown/dist/react.js
|
|
@@ -37129,23 +37144,55 @@ async function loadEntityWorkspace(root, query, selectedPath, currentWorkspaceRo
|
|
|
37129
37144
|
return { entities, query, rootPath, selected };
|
|
37130
37145
|
}
|
|
37131
37146
|
|
|
37147
|
+
// packages/api/src/server/api/delete-note.ts
|
|
37148
|
+
import { realpath as realpath5, stat as stat5, unlink as unlink2 } from "node:fs/promises";
|
|
37149
|
+
import { extname as extname3, isAbsolute as isAbsolute5, relative as relative8, resolve as resolve8, sep as sep5 } from "node:path";
|
|
37150
|
+
var markdownExtensions2 = new Set([".md", ".markdown"]);
|
|
37151
|
+
var deleteNoteRoute = {
|
|
37152
|
+
method: "POST",
|
|
37153
|
+
maxBodyBytes: 4 * 1024,
|
|
37154
|
+
async handle({ body, context, response }) {
|
|
37155
|
+
const parsed = deleteNoteSchema.safeParse(parseJsonBody(body));
|
|
37156
|
+
if (!parsed.success)
|
|
37157
|
+
throw apiError("bad-request", "Invalid delete request.");
|
|
37158
|
+
const folder = context.authorize(parsed.data.folder);
|
|
37159
|
+
if (!markdownExtensions2.has(extname3(parsed.data.path).toLowerCase()))
|
|
37160
|
+
throw apiError("bad-request", "Only Markdown notes can be deleted.");
|
|
37161
|
+
const target = await containedTarget(parsed.data.path, folder);
|
|
37162
|
+
const details = await stat5(target).catch(() => {
|
|
37163
|
+
return;
|
|
37164
|
+
});
|
|
37165
|
+
if (!details?.isFile() || details.nlink !== 1)
|
|
37166
|
+
throw apiError("forbidden", "Only regular, unlinked files can be deleted.");
|
|
37167
|
+
await unlink2(target);
|
|
37168
|
+
jsonResponse(response, 200, routes.deleteNote.response.parse({ deleted: true }));
|
|
37169
|
+
}
|
|
37170
|
+
};
|
|
37171
|
+
async function containedTarget(path, folder) {
|
|
37172
|
+
const target = await realpath5(resolve8(folder, path));
|
|
37173
|
+
const local = relative8(folder, target);
|
|
37174
|
+
if (!local || local === ".." || local.startsWith(`..${sep5}`) || isAbsolute5(local))
|
|
37175
|
+
throw apiError("forbidden", "The note must be inside its folder.");
|
|
37176
|
+
return target;
|
|
37177
|
+
}
|
|
37178
|
+
|
|
37132
37179
|
// packages/api/src/server/api/document-edit.ts
|
|
37133
37180
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
37134
37181
|
import {
|
|
37135
37182
|
readFile as readFile6,
|
|
37136
|
-
realpath as
|
|
37183
|
+
realpath as realpath6,
|
|
37137
37184
|
rename as rename3,
|
|
37138
|
-
stat as
|
|
37139
|
-
unlink as
|
|
37185
|
+
stat as stat6,
|
|
37186
|
+
unlink as unlink3,
|
|
37140
37187
|
writeFile as writeFile3
|
|
37141
37188
|
} from "node:fs/promises";
|
|
37142
37189
|
import {
|
|
37143
37190
|
dirname as dirname7,
|
|
37144
|
-
extname as
|
|
37145
|
-
isAbsolute as
|
|
37146
|
-
relative as
|
|
37147
|
-
resolve as
|
|
37148
|
-
sep as
|
|
37191
|
+
extname as extname4,
|
|
37192
|
+
isAbsolute as isAbsolute6,
|
|
37193
|
+
relative as relative9,
|
|
37194
|
+
resolve as resolve9,
|
|
37195
|
+
sep as sep6
|
|
37149
37196
|
} from "node:path";
|
|
37150
37197
|
|
|
37151
37198
|
// packages/api/src/shared/selection.ts
|
|
@@ -37161,12 +37208,12 @@ async function editDocument(folder, input) {
|
|
|
37161
37208
|
const { path, original, start, end, replacement } = input;
|
|
37162
37209
|
if (typeof path !== "string" || typeof original !== "string" || typeof replacement !== "string" || typeof start !== "number" || typeof end !== "number")
|
|
37163
37210
|
throw apiError("bad-request", "Invalid document edit.");
|
|
37164
|
-
if (![".md", ".markdown"].includes(
|
|
37211
|
+
if (![".md", ".markdown"].includes(extname4(path).toLowerCase()))
|
|
37165
37212
|
throw apiError("bad-request", "Only Markdown notes can be edited.");
|
|
37166
|
-
const root = await
|
|
37167
|
-
const target = await
|
|
37168
|
-
const local =
|
|
37169
|
-
if (!local || local === ".." || local.startsWith(`..${
|
|
37213
|
+
const root = await realpath6(folder);
|
|
37214
|
+
const target = await realpath6(resolve9(root, path));
|
|
37215
|
+
const local = relative9(root, target);
|
|
37216
|
+
if (!local || local === ".." || local.startsWith(`..${sep6}`) || isAbsolute6(local))
|
|
37170
37217
|
throw apiError("forbidden", "The document must be inside its folder.");
|
|
37171
37218
|
let content;
|
|
37172
37219
|
try {
|
|
@@ -37176,12 +37223,12 @@ async function editDocument(folder, input) {
|
|
|
37176
37223
|
}
|
|
37177
37224
|
const previous = pending.get(target) ?? Promise.resolve();
|
|
37178
37225
|
const operation = previous.catch(() => {}).then(async () => {
|
|
37179
|
-
const details = await
|
|
37226
|
+
const details = await stat6(target);
|
|
37180
37227
|
if (!details.isFile() || details.nlink !== 1)
|
|
37181
37228
|
throw apiError("forbidden", "Only regular, unlinked files can be edited.");
|
|
37182
37229
|
if (await readFile6(target, "utf8") !== original)
|
|
37183
37230
|
throw apiError("conflict", "This note changed on disk. Close this preview, reload the note, and try again.");
|
|
37184
|
-
const temporary =
|
|
37231
|
+
const temporary = resolve9(dirname7(target), `.kennel-edit-${randomUUID2()}.tmp`);
|
|
37185
37232
|
try {
|
|
37186
37233
|
await writeFile3(temporary, content, {
|
|
37187
37234
|
flag: "wx",
|
|
@@ -37191,7 +37238,7 @@ async function editDocument(folder, input) {
|
|
|
37191
37238
|
throw apiError("conflict", "This note changed on disk. Reload before applying an edit.");
|
|
37192
37239
|
await rename3(temporary, target);
|
|
37193
37240
|
} finally {
|
|
37194
|
-
await
|
|
37241
|
+
await unlink3(temporary).catch(() => {});
|
|
37195
37242
|
}
|
|
37196
37243
|
return content;
|
|
37197
37244
|
});
|
|
@@ -37212,7 +37259,7 @@ var documentEditRoute = {
|
|
|
37212
37259
|
throw apiError("bad-request", "Invalid document edit.");
|
|
37213
37260
|
const input = parsed.data;
|
|
37214
37261
|
const folder = context.authorize(input.folder);
|
|
37215
|
-
if (context.lockedFile && (typeof input.path !== "string" || await
|
|
37262
|
+
if (context.lockedFile && (typeof input.path !== "string" || await realpath6(resolve9(folder, input.path)) !== context.lockedFile))
|
|
37216
37263
|
throw apiError("forbidden", "Only the selected document can be edited.");
|
|
37217
37264
|
await editDocument(folder, input);
|
|
37218
37265
|
jsonResponse(response, 200, routes.documentEdit.response.parse({ saved: true }));
|
|
@@ -37221,7 +37268,7 @@ var documentEditRoute = {
|
|
|
37221
37268
|
|
|
37222
37269
|
// packages/api/src/server/api/create-agent-file.ts
|
|
37223
37270
|
import { writeFile as writeFile4 } from "node:fs/promises";
|
|
37224
|
-
import { resolve as
|
|
37271
|
+
import { resolve as resolve10 } from "node:path";
|
|
37225
37272
|
var createAgentFileRoute = {
|
|
37226
37273
|
method: "POST",
|
|
37227
37274
|
maxBodyBytes: 0,
|
|
@@ -37232,7 +37279,7 @@ var createAgentFileRoute = {
|
|
|
37232
37279
|
} catch (error) {
|
|
37233
37280
|
throw apiError("not-found", error instanceof Error ? error.message : "Folder not found");
|
|
37234
37281
|
}
|
|
37235
|
-
const target =
|
|
37282
|
+
const target = resolve10(folder, "AGENTS.md");
|
|
37236
37283
|
try {
|
|
37237
37284
|
await writeFile4(target, "", { flag: "wx" });
|
|
37238
37285
|
} catch (error) {
|
|
@@ -37284,8 +37331,8 @@ async function folderWebsite(folder) {
|
|
|
37284
37331
|
|
|
37285
37332
|
// packages/api/src/server/folder-icons.ts
|
|
37286
37333
|
import { createHash as createHash4 } from "node:crypto";
|
|
37287
|
-
import { readFile as readFile8, stat as
|
|
37288
|
-
import { extname as
|
|
37334
|
+
import { readFile as readFile8, stat as stat7 } from "node:fs/promises";
|
|
37335
|
+
import { extname as extname5 } from "node:path";
|
|
37289
37336
|
import { discoverFolderIcon } from "@raggle-ai/local";
|
|
37290
37337
|
var maxIconBytes2 = 4 * 1024 * 1024;
|
|
37291
37338
|
var iconTypes = new Map([
|
|
@@ -37322,8 +37369,8 @@ function iconUrl(folder, hash, mediaType) {
|
|
|
37322
37369
|
}
|
|
37323
37370
|
async function folderIcon(folder, assets, assetFiles, fallback) {
|
|
37324
37371
|
const icon = discoverFolderIcon(folder);
|
|
37325
|
-
const mediaType = icon ? iconTypes.get(
|
|
37326
|
-
const details = icon && mediaType ? await
|
|
37372
|
+
const mediaType = icon ? iconTypes.get(extname5(icon).toLowerCase()) : null;
|
|
37373
|
+
const details = icon && mediaType ? await stat7(icon).catch(() => {
|
|
37327
37374
|
return;
|
|
37328
37375
|
}) : undefined;
|
|
37329
37376
|
if (!icon || !mediaType || !details?.size || details.size > maxIconBytes2) {
|
|
@@ -37345,10 +37392,10 @@ async function searchIconDataUrl(icon) {
|
|
|
37345
37392
|
return;
|
|
37346
37393
|
if (icon.startsWith("data:"))
|
|
37347
37394
|
return icon;
|
|
37348
|
-
const mediaType = searchIconTypes.get(
|
|
37395
|
+
const mediaType = searchIconTypes.get(extname5(icon).toLowerCase());
|
|
37349
37396
|
if (!mediaType)
|
|
37350
37397
|
return;
|
|
37351
|
-
const details = await
|
|
37398
|
+
const details = await stat7(icon).catch(() => {
|
|
37352
37399
|
return;
|
|
37353
37400
|
});
|
|
37354
37401
|
if (!details?.size || details.size > maxSearchIconBytes)
|
|
@@ -37399,29 +37446,29 @@ async function workspaceBreadcrumbIcons(breadcrumbs, assetFiles, assets = {}) {
|
|
|
37399
37446
|
// packages/api/src/server/plugins.ts
|
|
37400
37447
|
import { pathToFileURL } from "node:url";
|
|
37401
37448
|
import { existsSync as existsSync4 } from "node:fs";
|
|
37402
|
-
import { mkdir as mkdir3, readFile as readFile10, stat as
|
|
37403
|
-
import { dirname as dirname11, resolve as
|
|
37449
|
+
import { mkdir as mkdir3, readFile as readFile10, stat as stat11, writeFile as writeFile5 } from "node:fs/promises";
|
|
37450
|
+
import { dirname as dirname11, resolve as resolve15, sep as sep10 } from "node:path";
|
|
37404
37451
|
|
|
37405
37452
|
// packages/knl/src/server.ts
|
|
37406
|
-
import { stat as
|
|
37453
|
+
import { stat as stat9 } from "node:fs/promises";
|
|
37407
37454
|
import { join as join5 } from "node:path";
|
|
37408
37455
|
|
|
37409
37456
|
// packages/knl/src/knl.ts
|
|
37410
|
-
import { readdir as readdir5, stat as
|
|
37411
|
-
import { basename as basename6, dirname as dirname10, relative as
|
|
37457
|
+
import { readdir as readdir5, stat as stat8 } from "node:fs/promises";
|
|
37458
|
+
import { basename as basename6, dirname as dirname10, relative as relative10, resolve as resolve13, sep as sep8 } from "node:path";
|
|
37412
37459
|
import * as esbuild from "esbuild";
|
|
37413
37460
|
|
|
37414
37461
|
// packages/knl/src/folder-guard.ts
|
|
37415
37462
|
import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
37416
|
-
import { realpath as
|
|
37417
|
-
import { dirname as dirname8, resolve as
|
|
37463
|
+
import { realpath as realpath7 } from "node:fs/promises";
|
|
37464
|
+
import { dirname as dirname8, resolve as resolve11, sep as sep7 } from "node:path";
|
|
37418
37465
|
import { fileURLToPath } from "node:url";
|
|
37419
37466
|
var knlHostResolveDir = dirname8(fileURLToPath(import.meta.url));
|
|
37420
37467
|
var knlHostPackageFolders = (() => {
|
|
37421
37468
|
const folders = [];
|
|
37422
37469
|
let current = knlHostResolveDir;
|
|
37423
37470
|
while (true) {
|
|
37424
|
-
const nodeModules =
|
|
37471
|
+
const nodeModules = resolve11(current, "node_modules");
|
|
37425
37472
|
if (existsSync3(nodeModules))
|
|
37426
37473
|
folders.push(nodeModules);
|
|
37427
37474
|
const parent = dirname8(current);
|
|
@@ -37431,14 +37478,14 @@ var knlHostPackageFolders = (() => {
|
|
|
37431
37478
|
}
|
|
37432
37479
|
})();
|
|
37433
37480
|
async function knlRealRoot(owner) {
|
|
37434
|
-
const expected =
|
|
37435
|
-
const real = await
|
|
37481
|
+
const expected = resolve11(await realpath7(owner), "knl");
|
|
37482
|
+
const real = await realpath7(resolve11(owner, "knl"));
|
|
37436
37483
|
if (real !== expected)
|
|
37437
37484
|
throw new Error("knl/ must be a folder, not a link to another place.");
|
|
37438
37485
|
return real;
|
|
37439
37486
|
}
|
|
37440
37487
|
async function knlReadRoots(owner) {
|
|
37441
|
-
const packages = await Promise.all(knlHostPackageFolders.map((folder) =>
|
|
37488
|
+
const packages = await Promise.all(knlHostPackageFolders.map((folder) => realpath7(folder).catch(() => {
|
|
37442
37489
|
return;
|
|
37443
37490
|
})));
|
|
37444
37491
|
return [
|
|
@@ -37451,9 +37498,9 @@ function isKnlReadable(file, roots) {
|
|
|
37451
37498
|
try {
|
|
37452
37499
|
real = realpathSync2(file);
|
|
37453
37500
|
} catch {
|
|
37454
|
-
real =
|
|
37501
|
+
real = resolve11(file);
|
|
37455
37502
|
}
|
|
37456
|
-
return roots.some((root) => real === root || real.startsWith(`${root}${
|
|
37503
|
+
return roots.some((root) => real === root || real.startsWith(`${root}${sep7}`));
|
|
37457
37504
|
}
|
|
37458
37505
|
function knlReadError(file) {
|
|
37459
37506
|
return `KNL pages can only use files in knl/ and installed packages: ${file}`;
|
|
@@ -37466,7 +37513,7 @@ function assertKnlReadable(file, roots) {
|
|
|
37466
37513
|
// packages/knl/src/tailwind.ts
|
|
37467
37514
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
37468
37515
|
import { createRequire as createRequire2 } from "node:module";
|
|
37469
|
-
import { dirname as dirname9, resolve as
|
|
37516
|
+
import { dirname as dirname9, resolve as resolve12 } from "node:path";
|
|
37470
37517
|
import { compile } from "@tailwindcss/node";
|
|
37471
37518
|
import { Scanner } from "@tailwindcss/oxide";
|
|
37472
37519
|
var require2 = createRequire2(import.meta.url);
|
|
@@ -37509,7 +37556,7 @@ async function compileKnlCss(js, stylesheet, roots) {
|
|
|
37509
37556
|
continue;
|
|
37510
37557
|
const fixed = source.pattern.split("/");
|
|
37511
37558
|
const glob = fixed.findIndex((part) => /[*?[{]/.test(part));
|
|
37512
|
-
assertKnlReadable(
|
|
37559
|
+
assertKnlReadable(resolve12(source.base, fixed.slice(0, glob < 0 ? undefined : glob).join("/")), roots);
|
|
37513
37560
|
}
|
|
37514
37561
|
const scanner = new Scanner({ sources });
|
|
37515
37562
|
const candidates = [
|
|
@@ -37529,23 +37576,23 @@ function sourceFor(file, knlRoot, scanRoot, owner) {
|
|
|
37529
37576
|
return {
|
|
37530
37577
|
id,
|
|
37531
37578
|
file,
|
|
37532
|
-
relative:
|
|
37579
|
+
relative: relative10(scanRoot, file).split(sep8).join("/"),
|
|
37533
37580
|
folder: dirname10(file),
|
|
37534
37581
|
owner
|
|
37535
37582
|
};
|
|
37536
37583
|
}
|
|
37537
37584
|
function toModuleId(file, knlRoot) {
|
|
37538
|
-
const relativeKnl =
|
|
37585
|
+
const relativeKnl = relative10(knlRoot, file).split(sep8).join("/");
|
|
37539
37586
|
return relativeKnl.replace(/\/?index\.(tsx|ts)$/, "") || "index";
|
|
37540
37587
|
}
|
|
37541
37588
|
async function collectKnlSources(scanRoot, owner) {
|
|
37542
|
-
const knlRoot =
|
|
37589
|
+
const knlRoot = resolve13(scanRoot, KNK_FOLDER);
|
|
37543
37590
|
const knlEntries = await readdir5(knlRoot, { withFileTypes: true }).catch(() => []);
|
|
37544
37591
|
const sources = [];
|
|
37545
37592
|
const addModule = async (folder) => {
|
|
37546
37593
|
for (const candidate of MODULE_FILES) {
|
|
37547
|
-
const file =
|
|
37548
|
-
if (await
|
|
37594
|
+
const file = resolve13(folder, candidate);
|
|
37595
|
+
if (await stat8(file).then((d) => d.isFile()).catch(() => false)) {
|
|
37549
37596
|
sources.push(sourceFor(file, knlRoot, scanRoot, owner));
|
|
37550
37597
|
return;
|
|
37551
37598
|
}
|
|
@@ -37557,7 +37604,7 @@ async function collectKnlSources(scanRoot, owner) {
|
|
|
37557
37604
|
continue;
|
|
37558
37605
|
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
37559
37606
|
continue;
|
|
37560
|
-
await addModule(
|
|
37607
|
+
await addModule(resolve13(knlRoot, entry.name));
|
|
37561
37608
|
}
|
|
37562
37609
|
return sources.sort((left, right) => {
|
|
37563
37610
|
const rank = (left.id === "index" ? 0 : 1) - (right.id === "index" ? 0 : 1);
|
|
@@ -37578,10 +37625,10 @@ async function loadKnlSources(viewRoot, linkedFolders = []) {
|
|
|
37578
37625
|
var MAX_CACHED_MODULES = 200;
|
|
37579
37626
|
var compileCache = new Map;
|
|
37580
37627
|
function knlNodePaths(knlRoot) {
|
|
37581
|
-
return [
|
|
37628
|
+
return [resolve13(knlRoot, "node_modules"), ...knlHostPackageFolders];
|
|
37582
37629
|
}
|
|
37583
37630
|
async function compileKnlSource(source) {
|
|
37584
|
-
const sourceBytes = (await
|
|
37631
|
+
const sourceBytes = (await stat8(source.file)).size;
|
|
37585
37632
|
const tooLarge = (bytes, what) => ({
|
|
37586
37633
|
id: source.id,
|
|
37587
37634
|
relative: source.relative,
|
|
@@ -37597,10 +37644,10 @@ async function compileKnlSource(source) {
|
|
|
37597
37644
|
if (sourceBytes > MAX_SOURCE_BYTES)
|
|
37598
37645
|
return tooLarge(sourceBytes, "source");
|
|
37599
37646
|
const cached = compileCache.get(source.file);
|
|
37600
|
-
const unchanged = cached && (await Promise.all(cached.dependencies.map(async ({ file, mtimeMs }) => (await
|
|
37647
|
+
const unchanged = cached && (await Promise.all(cached.dependencies.map(async ({ file, mtimeMs }) => (await stat8(file).catch(() => {
|
|
37601
37648
|
return;
|
|
37602
37649
|
}))?.mtimeMs === mtimeMs))).every(Boolean);
|
|
37603
|
-
const knlRoot =
|
|
37650
|
+
const knlRoot = resolve13(source.owner, KNK_FOLDER);
|
|
37604
37651
|
let issuePath = source.relative;
|
|
37605
37652
|
try {
|
|
37606
37653
|
const nodePaths = knlNodePaths(knlRoot);
|
|
@@ -37641,12 +37688,12 @@ globalThis.__knlMount = (container, context, onError) => {
|
|
|
37641
37688
|
});
|
|
37642
37689
|
js = result.outputFiles?.[0]?.text ?? "";
|
|
37643
37690
|
const files = new Set([
|
|
37644
|
-
|
|
37645
|
-
...Object.keys(result.metafile.inputs).map((file) =>
|
|
37691
|
+
resolve13(knlRoot, "package.json"),
|
|
37692
|
+
...Object.keys(result.metafile.inputs).map((file) => resolve13(source.folder, file)).filter((file) => file !== `${source.file}.mount.ts`)
|
|
37646
37693
|
]);
|
|
37647
37694
|
const dependencies = await Promise.all([...files].map(async (file) => ({
|
|
37648
37695
|
file,
|
|
37649
|
-
mtimeMs: (await
|
|
37696
|
+
mtimeMs: (await stat8(file).catch(() => {
|
|
37650
37697
|
return;
|
|
37651
37698
|
}))?.mtimeMs
|
|
37652
37699
|
})));
|
|
@@ -37655,8 +37702,8 @@ globalThis.__knlMount = (container, context, onError) => {
|
|
|
37655
37702
|
if (compileCache.size > MAX_CACHED_MODULES)
|
|
37656
37703
|
compileCache.delete(compileCache.keys().next().value);
|
|
37657
37704
|
}
|
|
37658
|
-
const stylesheet =
|
|
37659
|
-
issuePath =
|
|
37705
|
+
const stylesheet = resolve13(knlRoot, "style.css");
|
|
37706
|
+
issuePath = relative10(source.owner, stylesheet).split(sep8).join("/");
|
|
37660
37707
|
const css = await compileKnlCss(js, stylesheet, roots);
|
|
37661
37708
|
issuePath = source.relative;
|
|
37662
37709
|
if (js.length + css.length > MAX_JS_BYTES) {
|
|
@@ -37716,7 +37763,7 @@ function knlBuildIssues(error, relativePath, source) {
|
|
|
37716
37763
|
const failures = error?.errors;
|
|
37717
37764
|
if (Array.isArray(failures) && failures.length > 0) {
|
|
37718
37765
|
const first = failures[0];
|
|
37719
|
-
const file = first?.location?.file ?
|
|
37766
|
+
const file = first?.location?.file ? relative10(source.owner, resolve13(source.folder, first.location.file)).split(sep8).join("/") : relativePath;
|
|
37720
37767
|
const location = first?.location ? `${file}:${first.location.line ?? "?"}` : relativePath;
|
|
37721
37768
|
return [
|
|
37722
37769
|
{ path: location, message: first?.text ?? "Module failed to compile." }
|
|
@@ -37756,7 +37803,7 @@ function createKnlPlugin() {
|
|
|
37756
37803
|
return {
|
|
37757
37804
|
...knlManifest,
|
|
37758
37805
|
async detect(context) {
|
|
37759
|
-
const hasKnlFolder = await
|
|
37806
|
+
const hasKnlFolder = await stat9(join5(context.folder, KNK_FOLDER)).then((entry) => entry.isDirectory()).catch(() => false);
|
|
37760
37807
|
if (!hasKnlFolder)
|
|
37761
37808
|
return { status: "unavailable" };
|
|
37762
37809
|
const { sources } = await loadKnlSources(context.folder, context.linkedFolders ?? []);
|
|
@@ -37841,14 +37888,14 @@ function createKnlPlugin() {
|
|
|
37841
37888
|
}
|
|
37842
37889
|
|
|
37843
37890
|
// packages/notes/src/server.ts
|
|
37844
|
-
import { readdir as readdir6, realpath as
|
|
37891
|
+
import { readdir as readdir6, realpath as realpath8, stat as stat10 } from "node:fs/promises";
|
|
37845
37892
|
import {
|
|
37846
37893
|
basename as basename7,
|
|
37847
|
-
extname as
|
|
37848
|
-
isAbsolute as
|
|
37849
|
-
relative as
|
|
37850
|
-
resolve as
|
|
37851
|
-
sep as
|
|
37894
|
+
extname as extname6,
|
|
37895
|
+
isAbsolute as isAbsolute7,
|
|
37896
|
+
relative as relative11,
|
|
37897
|
+
resolve as resolve14,
|
|
37898
|
+
sep as sep9
|
|
37852
37899
|
} from "node:path";
|
|
37853
37900
|
|
|
37854
37901
|
// packages/notes/src/manifest.ts
|
|
@@ -37865,7 +37912,7 @@ var notesManifest = {
|
|
|
37865
37912
|
};
|
|
37866
37913
|
|
|
37867
37914
|
// packages/notes/src/server.ts
|
|
37868
|
-
var
|
|
37915
|
+
var markdownExtensions3 = new Set([".md", ".markdown"]);
|
|
37869
37916
|
var llmNoteLimit = 20;
|
|
37870
37917
|
async function listMarkdownFiles(folder) {
|
|
37871
37918
|
const files = [];
|
|
@@ -37874,31 +37921,31 @@ async function listMarkdownFiles(folder) {
|
|
|
37874
37921
|
for (const entry of entries) {
|
|
37875
37922
|
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
37876
37923
|
continue;
|
|
37877
|
-
const path =
|
|
37924
|
+
const path = resolve14(current, entry.name);
|
|
37878
37925
|
if (entry.isDirectory()) {
|
|
37879
37926
|
await visit(path);
|
|
37880
37927
|
continue;
|
|
37881
37928
|
}
|
|
37882
|
-
if (!entry.isFile() || !
|
|
37929
|
+
if (!entry.isFile() || !markdownExtensions3.has(extname6(entry.name))) {
|
|
37883
37930
|
continue;
|
|
37884
37931
|
}
|
|
37885
|
-
const details = await
|
|
37932
|
+
const details = await stat10(path).catch(() => {
|
|
37886
37933
|
return;
|
|
37887
37934
|
});
|
|
37888
37935
|
files.push({
|
|
37889
37936
|
activityAt: details?.mtimeMs ?? 0,
|
|
37890
|
-
name: basename7(entry.name,
|
|
37891
|
-
relativePath:
|
|
37937
|
+
name: basename7(entry.name, extname6(entry.name)),
|
|
37938
|
+
relativePath: relative11(folder, path).split(sep9).join("/")
|
|
37892
37939
|
});
|
|
37893
37940
|
}
|
|
37894
37941
|
};
|
|
37895
37942
|
await visit(folder);
|
|
37896
37943
|
return files.sort((left, right) => right.activityAt - left.activityAt);
|
|
37897
37944
|
}
|
|
37898
|
-
var canonical = (path) =>
|
|
37945
|
+
var canonical = (path) => realpath8(path).catch(() => path);
|
|
37899
37946
|
function inside5(path, root) {
|
|
37900
|
-
const local =
|
|
37901
|
-
return local === "" || !local.startsWith("..") && !
|
|
37947
|
+
const local = relative11(root, path);
|
|
37948
|
+
return local === "" || !local.startsWith("..") && !isAbsolute7(local);
|
|
37902
37949
|
}
|
|
37903
37950
|
async function withoutManaged(groups, managedRoots) {
|
|
37904
37951
|
if (!managedRoots.length)
|
|
@@ -37909,7 +37956,7 @@ async function withoutManaged(groups, managedRoots) {
|
|
|
37909
37956
|
return { ...group, files: [] };
|
|
37910
37957
|
}
|
|
37911
37958
|
const files = await Promise.all(group.files.map(async (file) => {
|
|
37912
|
-
const real = await canonical(
|
|
37959
|
+
const real = await canonical(resolve14(group.folder, file.relativePath));
|
|
37913
37960
|
return roots.some((root) => inside5(real, root)) ? undefined : file;
|
|
37914
37961
|
}));
|
|
37915
37962
|
return { ...group, files: files.filter((file) => file !== undefined) };
|
|
@@ -37959,7 +38006,7 @@ async function notesLlmSections({
|
|
|
37959
38006
|
continue;
|
|
37960
38007
|
seen.add(identity);
|
|
37961
38008
|
const files = await listMarkdownFiles(source);
|
|
37962
|
-
const paths = files.map((file) =>
|
|
38009
|
+
const paths = files.map((file) => resolve14(source, file.relativePath));
|
|
37963
38010
|
groups.push({ folder: source, paths });
|
|
37964
38011
|
files.forEach((file, index) => notes.push({ activityAt: file.activityAt, path: paths[index] }));
|
|
37965
38012
|
}
|
|
@@ -38032,8 +38079,8 @@ function parsePluginRegistryConfig(content) {
|
|
|
38032
38079
|
}
|
|
38033
38080
|
async function nearestKennelConfig(folder) {
|
|
38034
38081
|
for (let current = folder;; current = dirname11(current)) {
|
|
38035
|
-
const candidate =
|
|
38036
|
-
const details = await
|
|
38082
|
+
const candidate = resolve15(current, "kennel.json");
|
|
38083
|
+
const details = await stat11(candidate).catch(() => {
|
|
38037
38084
|
return;
|
|
38038
38085
|
});
|
|
38039
38086
|
if (details?.isFile())
|
|
@@ -38095,7 +38142,7 @@ async function folderServerRegistryAsync() {
|
|
|
38095
38142
|
...server,
|
|
38096
38143
|
async detect(context) {
|
|
38097
38144
|
const detection = await server.detect(context);
|
|
38098
|
-
if (detection.status === "unavailable" && existsSync4(
|
|
38145
|
+
if (detection.status === "unavailable" && existsSync4(resolve15(context.folder, entry.trigger))) {
|
|
38099
38146
|
return { status: "available" };
|
|
38100
38147
|
}
|
|
38101
38148
|
return detection;
|
|
@@ -38536,13 +38583,13 @@ var metadataExtensions = new Set([
|
|
|
38536
38583
|
".txt"
|
|
38537
38584
|
]);
|
|
38538
38585
|
function metadataFile(path, root) {
|
|
38539
|
-
const candidate =
|
|
38540
|
-
if (!candidate || candidate.startsWith("..") ||
|
|
38586
|
+
const candidate = relative13(root, path);
|
|
38587
|
+
if (!candidate || candidate.startsWith("..") || isAbsolute8(candidate))
|
|
38541
38588
|
return false;
|
|
38542
|
-
const parts = candidate.split(
|
|
38589
|
+
const parts = candidate.split(sep11);
|
|
38543
38590
|
if (parts.some((part) => part === "node_modules"))
|
|
38544
38591
|
return false;
|
|
38545
|
-
return metadataExtensions.has(
|
|
38592
|
+
return metadataExtensions.has(extname7(candidate).toLowerCase());
|
|
38546
38593
|
}
|
|
38547
38594
|
async function configuredAiInputModule(folder) {
|
|
38548
38595
|
const config = folderWorkspace(folder).config;
|
|
@@ -38550,11 +38597,11 @@ async function configuredAiInputModule(folder) {
|
|
|
38550
38597
|
return typeof module === "string" && module.trim() ? module.trim() : null;
|
|
38551
38598
|
}
|
|
38552
38599
|
function folderPath(value, root, lockedRoot) {
|
|
38553
|
-
const folder = realpathSync3(
|
|
38600
|
+
const folder = realpathSync3(resolve16(value ?? root));
|
|
38554
38601
|
if (!lockedRoot)
|
|
38555
38602
|
return folder;
|
|
38556
|
-
const path =
|
|
38557
|
-
if (!path || !path.startsWith("..") && !
|
|
38603
|
+
const path = relative13(lockedRoot, folder);
|
|
38604
|
+
if (!path || !path.startsWith("..") && !isAbsolute8(path))
|
|
38558
38605
|
return folder;
|
|
38559
38606
|
throw new Error(`Folder is outside the viewer root: ${folder}`);
|
|
38560
38607
|
}
|
|
@@ -38630,9 +38677,9 @@ function isMachineRoot(folder) {
|
|
|
38630
38677
|
async function shallowMetadata(folder) {
|
|
38631
38678
|
const entries = await readdir7(folder, { withFileTypes: true });
|
|
38632
38679
|
const visible = entries.filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules");
|
|
38633
|
-
const files = await Promise.all(visible.filter((entry) => entry.isFile() && [".markdown", ".md"].includes(
|
|
38634
|
-
const path =
|
|
38635
|
-
const details = await
|
|
38680
|
+
const files = await Promise.all(visible.filter((entry) => entry.isFile() && [".markdown", ".md"].includes(extname7(entry.name).toLowerCase())).map(async (entry) => {
|
|
38681
|
+
const path = resolve16(folder, entry.name);
|
|
38682
|
+
const details = await stat12(path);
|
|
38636
38683
|
const content = await readFile11(path, "utf8").catch(() => "");
|
|
38637
38684
|
const title = markdownMetadata(content).title;
|
|
38638
38685
|
return {
|
|
@@ -38646,10 +38693,10 @@ async function shallowMetadata(folder) {
|
|
|
38646
38693
|
};
|
|
38647
38694
|
}));
|
|
38648
38695
|
const projects = visible.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
38649
|
-
id: createHash5("sha1").update(
|
|
38696
|
+
id: createHash5("sha1").update(resolve16(folder, entry.name)).digest("hex"),
|
|
38650
38697
|
name: entry.name,
|
|
38651
38698
|
relativePath: entry.name,
|
|
38652
|
-
worktree:
|
|
38699
|
+
worktree: resolve16(folder, entry.name)
|
|
38653
38700
|
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
38654
38701
|
return {
|
|
38655
38702
|
changes: { items: [] },
|
|
@@ -38676,7 +38723,7 @@ async function loadFolderData(folder) {
|
|
|
38676
38723
|
id: project.id,
|
|
38677
38724
|
worktree: project.worktree,
|
|
38678
38725
|
name: project.name ?? basename8(project.worktree),
|
|
38679
|
-
relativePath:
|
|
38726
|
+
relativePath: relative13(folder, project.worktree)
|
|
38680
38727
|
}))
|
|
38681
38728
|
}
|
|
38682
38729
|
};
|
|
@@ -38684,10 +38731,10 @@ async function loadFolderData(folder) {
|
|
|
38684
38731
|
async function notesFiles(folder, files, origin) {
|
|
38685
38732
|
return {
|
|
38686
38733
|
items: await Promise.all(files.map(async (file) => {
|
|
38687
|
-
const path = file.path ?? (file.relativePath ?
|
|
38734
|
+
const path = file.path ?? (file.relativePath ? resolve16(folder, file.relativePath) : undefined);
|
|
38688
38735
|
if (!path)
|
|
38689
38736
|
return origin ? { ...file, folder: origin } : file;
|
|
38690
|
-
const content = [".markdown", ".md"].includes(
|
|
38737
|
+
const content = [".markdown", ".md"].includes(extname7(path).toLowerCase()) ? await readFile11(path, "utf8").catch(() => "") : "";
|
|
38691
38738
|
const title = content ? markdownMetadata(content).title : undefined;
|
|
38692
38739
|
return {
|
|
38693
38740
|
...file,
|
|
@@ -38711,10 +38758,10 @@ async function managedNotesFiles(directory) {
|
|
|
38711
38758
|
};
|
|
38712
38759
|
}));
|
|
38713
38760
|
}
|
|
38714
|
-
var canonicalPath = (path) =>
|
|
38761
|
+
var canonicalPath = (path) => realpath9(path).catch(() => path);
|
|
38715
38762
|
function insideFolder(path, root) {
|
|
38716
|
-
const local =
|
|
38717
|
-
return local === "" || !local.startsWith("..") && !
|
|
38763
|
+
const local = relative13(root, path);
|
|
38764
|
+
return local === "" || !local.startsWith("..") && !isAbsolute8(local);
|
|
38718
38765
|
}
|
|
38719
38766
|
async function withoutManagedFiles(items, managedRoot) {
|
|
38720
38767
|
if (!managedRoot)
|
|
@@ -38745,16 +38792,16 @@ async function localProjectSearchCache(cache) {
|
|
|
38745
38792
|
function mediaTarget(folder, file, lockedTarget) {
|
|
38746
38793
|
if (!file)
|
|
38747
38794
|
return;
|
|
38748
|
-
const rootReal = realpathSync3(
|
|
38749
|
-
const path =
|
|
38795
|
+
const rootReal = realpathSync3(resolve16(folder));
|
|
38796
|
+
const path = resolve16(folder, file);
|
|
38750
38797
|
let pathReal;
|
|
38751
38798
|
try {
|
|
38752
38799
|
pathReal = realpathSync3(path);
|
|
38753
38800
|
} catch {
|
|
38754
38801
|
return;
|
|
38755
38802
|
}
|
|
38756
|
-
const rel =
|
|
38757
|
-
if (rel.startsWith("..") ||
|
|
38803
|
+
const rel = relative13(rootReal, pathReal);
|
|
38804
|
+
if (rel.startsWith("..") || isAbsolute8(rel))
|
|
38758
38805
|
return;
|
|
38759
38806
|
if (lockedTarget && pathReal !== lockedTarget)
|
|
38760
38807
|
return;
|
|
@@ -38793,16 +38840,16 @@ function documentError(response) {
|
|
|
38793
38840
|
function documentTarget(folder, file, lockedTarget) {
|
|
38794
38841
|
if (!file)
|
|
38795
38842
|
return;
|
|
38796
|
-
const rootReal = realpathSync3(
|
|
38797
|
-
const path =
|
|
38843
|
+
const rootReal = realpathSync3(resolve16(folder));
|
|
38844
|
+
const path = resolve16(folder, file);
|
|
38798
38845
|
let pathReal;
|
|
38799
38846
|
try {
|
|
38800
38847
|
pathReal = realpathSync3(path);
|
|
38801
38848
|
} catch {
|
|
38802
38849
|
return;
|
|
38803
38850
|
}
|
|
38804
|
-
const rel =
|
|
38805
|
-
if (rel.startsWith("..") ||
|
|
38851
|
+
const rel = relative13(rootReal, pathReal);
|
|
38852
|
+
if (rel.startsWith("..") || isAbsolute8(rel))
|
|
38806
38853
|
return;
|
|
38807
38854
|
if (lockedTarget && pathReal !== lockedTarget)
|
|
38808
38855
|
return;
|
|
@@ -38940,7 +38987,7 @@ function createFolderApi({
|
|
|
38940
38987
|
if (!folder)
|
|
38941
38988
|
return;
|
|
38942
38989
|
server.emit({
|
|
38943
|
-
data: { path:
|
|
38990
|
+
data: { path: relative13(folder, path) },
|
|
38944
38991
|
event: "kennel:metadata-changed",
|
|
38945
38992
|
type: "custom"
|
|
38946
38993
|
});
|
|
@@ -39095,12 +39142,12 @@ function createFolderApi({
|
|
|
39095
39142
|
}
|
|
39096
39143
|
if (url.pathname === "/api/documents") {
|
|
39097
39144
|
const folder = folderPath(url.searchParams.get("path"), root, lockedRoot);
|
|
39098
|
-
const target = lockedTarget ? documentTarget(folder,
|
|
39145
|
+
const target = lockedTarget ? documentTarget(folder, relative13(folder, lockedTarget), lockedTarget) : undefined;
|
|
39099
39146
|
const dataset = lockedTarget ? {
|
|
39100
39147
|
root: folder,
|
|
39101
39148
|
documents: target ? [
|
|
39102
39149
|
{
|
|
39103
|
-
path:
|
|
39150
|
+
path: relative13(folder, target.path),
|
|
39104
39151
|
kind: target.kind,
|
|
39105
39152
|
content: previewTextKind(target.kind) ? await readFile11(target.path, "utf8") : ""
|
|
39106
39153
|
}
|
|
@@ -39118,7 +39165,7 @@ function createFolderApi({
|
|
|
39118
39165
|
documentError(response);
|
|
39119
39166
|
return;
|
|
39120
39167
|
}
|
|
39121
|
-
const details = await
|
|
39168
|
+
const details = await stat12(target.path);
|
|
39122
39169
|
if (!details.isFile()) {
|
|
39123
39170
|
documentError(response);
|
|
39124
39171
|
return;
|
|
@@ -39134,12 +39181,12 @@ function createFolderApi({
|
|
|
39134
39181
|
sendContract(response, url, {
|
|
39135
39182
|
content,
|
|
39136
39183
|
kind: target.kind,
|
|
39137
|
-
path:
|
|
39184
|
+
path: relative13(target.root, target.path),
|
|
39138
39185
|
root: folder,
|
|
39139
39186
|
...previewTextKind(target.kind) ? {} : {
|
|
39140
39187
|
rawUrl: `/api/raw?${new URLSearchParams({
|
|
39141
39188
|
path: folder,
|
|
39142
|
-
file:
|
|
39189
|
+
file: relative13(target.root, target.path)
|
|
39143
39190
|
})}`
|
|
39144
39191
|
}
|
|
39145
39192
|
}, {
|
|
@@ -39159,7 +39206,7 @@ function createFolderApi({
|
|
|
39159
39206
|
documentError(response);
|
|
39160
39207
|
return;
|
|
39161
39208
|
}
|
|
39162
|
-
const details = await
|
|
39209
|
+
const details = await stat12(target.path);
|
|
39163
39210
|
if (!details.isFile()) {
|
|
39164
39211
|
documentError(response);
|
|
39165
39212
|
return;
|
|
@@ -39197,7 +39244,7 @@ function createFolderApi({
|
|
|
39197
39244
|
documentError(response);
|
|
39198
39245
|
return;
|
|
39199
39246
|
}
|
|
39200
|
-
const details = await
|
|
39247
|
+
const details = await stat12(target.path);
|
|
39201
39248
|
if (!details.isFile()) {
|
|
39202
39249
|
documentError(response);
|
|
39203
39250
|
return;
|
|
@@ -39318,6 +39365,19 @@ function createFolderApi({
|
|
|
39318
39365
|
}))
|
|
39319
39366
|
return;
|
|
39320
39367
|
}
|
|
39368
|
+
if (url.pathname === "/api/delete-note") {
|
|
39369
|
+
if (remote) {
|
|
39370
|
+
response.writeHead(403, {
|
|
39371
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
39372
|
+
});
|
|
39373
|
+
response.end("Host actions are disabled for remote access");
|
|
39374
|
+
return;
|
|
39375
|
+
}
|
|
39376
|
+
await runApiRoute(request, response, url, deleteNoteRoute, {
|
|
39377
|
+
authorize: (folder) => folderPath(folder, root, lockedRoot)
|
|
39378
|
+
});
|
|
39379
|
+
return;
|
|
39380
|
+
}
|
|
39321
39381
|
if (url.pathname === "/api/create-agent-file") {
|
|
39322
39382
|
if (remote) {
|
|
39323
39383
|
response.writeHead(403, {
|
|
@@ -39372,7 +39432,7 @@ function createFolderApi({
|
|
|
39372
39432
|
workspace.breadcrumbs = await workspaceBreadcrumbIcons(workspace.breadcrumbs ?? [], assetFiles);
|
|
39373
39433
|
const files = [
|
|
39374
39434
|
workspace.configPath,
|
|
39375
|
-
|
|
39435
|
+
resolve16(workspace.root, "raggle.json")
|
|
39376
39436
|
].filter((path) => Boolean(path));
|
|
39377
39437
|
for (const path of files)
|
|
39378
39438
|
contexts.add(path);
|
|
@@ -39531,33 +39591,33 @@ var contentTypes = {
|
|
|
39531
39591
|
".ttf": "font/ttf"
|
|
39532
39592
|
};
|
|
39533
39593
|
async function sendFile(request, response, directory, pathname, fallback) {
|
|
39534
|
-
const root = await
|
|
39594
|
+
const root = await realpath10(directory);
|
|
39535
39595
|
const inside = (path) => {
|
|
39536
|
-
const local =
|
|
39537
|
-
return local !== ".." && !local.startsWith("../") && !
|
|
39596
|
+
const local = relative14(root, path);
|
|
39597
|
+
return local !== ".." && !local.startsWith("../") && !isAbsolute9(local);
|
|
39538
39598
|
};
|
|
39539
|
-
let target =
|
|
39599
|
+
let target = resolve17(root, `.${decodeURIComponent(pathname)}`);
|
|
39540
39600
|
if (!inside(target)) {
|
|
39541
39601
|
response.writeHead(403);
|
|
39542
39602
|
response.end();
|
|
39543
39603
|
return;
|
|
39544
39604
|
}
|
|
39545
|
-
if (!(await
|
|
39605
|
+
if (!(await stat13(target).catch(() => null))?.isFile()) {
|
|
39546
39606
|
if (!fallback) {
|
|
39547
39607
|
response.writeHead(404);
|
|
39548
39608
|
response.end();
|
|
39549
39609
|
return;
|
|
39550
39610
|
}
|
|
39551
|
-
target =
|
|
39611
|
+
target = resolve17(root, fallback);
|
|
39552
39612
|
}
|
|
39553
|
-
target = await
|
|
39613
|
+
target = await realpath10(target);
|
|
39554
39614
|
if (!inside(target)) {
|
|
39555
39615
|
response.writeHead(403);
|
|
39556
39616
|
response.end();
|
|
39557
39617
|
return;
|
|
39558
39618
|
}
|
|
39559
39619
|
response.writeHead(200, {
|
|
39560
|
-
"Content-Type": contentTypes[
|
|
39620
|
+
"Content-Type": contentTypes[extname8(target)] ?? "application/octet-stream",
|
|
39561
39621
|
"X-Content-Type-Options": "nosniff"
|
|
39562
39622
|
});
|
|
39563
39623
|
response.end(request.method === "HEAD" ? undefined : await readFile12(target));
|