kennel 0.2.32 → 0.2.34

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.
Files changed (81) hide show
  1. package/dist/cli/dispatch.js +5 -0
  2. package/dist/cli/usage.js +5 -0
  3. package/dist/core/runtime.js +458 -166
  4. package/dist/llm/command.js +10 -3
  5. package/dist/llm/worker.js +297 -32
  6. package/dist/notes/command.d.ts +1 -0
  7. package/dist/notes/command.js +556 -0
  8. package/dist/package/preview.js +481 -188
  9. package/dist/site/server-plugins.js +51 -10
  10. package/package.json +6 -3
  11. package/schemas/config.schema.json +11 -0
  12. package/scripts/verify-config.mjs +59 -0
  13. package/web/assets/{abnfDiagram-VRR7QNED-DPZyna8O.js → abnfDiagram-VRR7QNED-CpP1VHKI.js} +1 -1
  14. package/web/assets/{arc-BAcU9y_V.js → arc-kL4AxfvR.js} +1 -1
  15. package/web/assets/{architectureDiagram-ZJ3FMSHR-D5yd7Cag.js → architectureDiagram-ZJ3FMSHR-BWaRktRJ.js} +1 -1
  16. package/web/assets/{ask-tray-PMT6VVXN-C4dJH21Q.js → ask-tray-PMT6VVXN-FqPDpwtw.js} +3 -3
  17. package/web/assets/{blockDiagram-677ZJIJ3-C7LSGyxV.js → blockDiagram-677ZJIJ3-B07uVoPU.js} +1 -1
  18. package/web/assets/{c4Diagram-LMCZKHZV-BW2KfoQr.js → c4Diagram-LMCZKHZV-uvoaQC09.js} +1 -1
  19. package/web/assets/channel-Djmf1Ik1.js +1 -0
  20. package/web/assets/{chunk-2Q5K7J3B-4Og6VAFG.js → chunk-2Q5K7J3B-BH3SaHqk.js} +1 -1
  21. package/web/assets/{chunk-32BRIVSS-BYOowQl5.js → chunk-32BRIVSS-SPD8Eraw.js} +1 -1
  22. package/web/assets/{chunk-5VM5RSS4-C1m-lq64.js → chunk-5VM5RSS4-DNeOgOuZ.js} +1 -1
  23. package/web/assets/{chunk-EX3LRPZG-B2hriRpJ.js → chunk-EX3LRPZG-SJQ-vKGz.js} +1 -1
  24. package/web/assets/{chunk-JWPE2WC7-C6RsnzVA.js → chunk-JWPE2WC7-Dy_9wZ2Y.js} +1 -1
  25. package/web/assets/{chunk-MOJQB5TN-yKbMmUWf.js → chunk-MOJQB5TN-CuIx80Vn.js} +1 -1
  26. package/web/assets/{chunk-RYQCIY6F-BOokm3Qc.js → chunk-RYQCIY6F-DDG61RKR.js} +1 -1
  27. package/web/assets/{chunk-V7JOEXUC-CKW-H5An.js → chunk-V7JOEXUC-7OMVhaoH.js} +1 -1
  28. package/web/assets/{chunk-VR4S4FIN-BU5pFrup.js → chunk-VR4S4FIN-Y-HNaSmV.js} +1 -1
  29. package/web/assets/{chunk-XXDRQBXY-DYtdSJHU.js → chunk-XXDRQBXY-CtG0MPgC.js} +1 -1
  30. package/web/assets/classDiagram-OUVF2IWQ-hlDS9RWf.js +1 -0
  31. package/web/assets/classDiagram-v2-EOCWNBFH-hlDS9RWf.js +1 -0
  32. package/web/assets/{cose-bilkent-JH36ORCC-BZeXtC6E.js → cose-bilkent-JH36ORCC-BZaPMYcl.js} +1 -1
  33. package/web/assets/{cynefin-VYW2F7L2-BSDVyzMI.js → cynefin-VYW2F7L2-DxAlRHA1.js} +1 -1
  34. package/web/assets/{cynefinDiagram-TSTJHNR4-CReoDBYo.js → cynefinDiagram-TSTJHNR4-gjgzmagS.js} +1 -1
  35. package/web/assets/{dagre-VKFMJZFB-CBLLzMxd.js → dagre-VKFMJZFB-DvLPeYuw.js} +1 -1
  36. package/web/assets/{diagram-FQU43EPY-BcGWiZXZ.js → diagram-FQU43EPY-443LFnzG.js} +1 -1
  37. package/web/assets/{diagram-G47NLZAW-BXUYZA9N.js → diagram-G47NLZAW-CqfUewot.js} +1 -1
  38. package/web/assets/{diagram-NH7WQ7WH-BrvrZs7N.js → diagram-NH7WQ7WH-D-FElUGW.js} +1 -1
  39. package/web/assets/{diagram-OA4YK3LP-7lnVcjXL.js → diagram-OA4YK3LP-DbidUAp5.js} +1 -1
  40. package/web/assets/{diagram-WEI45ONY-s58_bMFf.js → diagram-WEI45ONY-CPLeckCZ.js} +1 -1
  41. package/web/assets/{ebnfDiagram-CCIWWBDH-BemWecoD.js → ebnfDiagram-CCIWWBDH-DR0rqZzN.js} +1 -1
  42. package/web/assets/{entity-search-page-G6QEQNXT--sKP5dP3.js → entity-search-page-G6QEQNXT-CnG8d-at.js} +1 -1
  43. package/web/assets/{erDiagram-Q63AITRT-ClVJddch.js → erDiagram-Q63AITRT-DMXv_8Tj.js} +1 -1
  44. package/web/assets/{flowDiagram-23GEKE2U-xzUJu-i_.js → flowDiagram-23GEKE2U-DnbQjZs0.js} +1 -1
  45. package/web/assets/{ganttDiagram-NO4QXBWP-CXQmtF5g.js → ganttDiagram-NO4QXBWP-DBKIrjj8.js} +1 -1
  46. package/web/assets/{gitGraphDiagram-IHSO6WYX-DCdljcLl.js → gitGraphDiagram-IHSO6WYX-BqqxKWT_.js} +1 -1
  47. package/web/assets/{index-CtTx1o2d.js → index-Bd3ghcW-.js} +5 -5
  48. package/web/assets/{index-vjrhIAJn.css → index-Dt8OzQCe.css} +1 -1
  49. package/web/assets/{infoDiagram-FWYZ7A6U-B11SJYSK.js → infoDiagram-FWYZ7A6U-Ba6Fs17y.js} +1 -1
  50. package/web/assets/{ishikawaDiagram-FXEZZL3T-B2CCGlAm.js → ishikawaDiagram-FXEZZL3T-D3BOtFjy.js} +1 -1
  51. package/web/assets/{journeyDiagram-5HDEW3XC-CBPETzOk.js → journeyDiagram-5HDEW3XC-MbzFPQm8.js} +1 -1
  52. package/web/assets/{kanban-definition-HUTT4EX6-unhQ3RPE.js → kanban-definition-HUTT4EX6-CurBmwu1.js} +1 -1
  53. package/web/assets/{linear-DuP_pG51.js → linear-CQIr4JjI.js} +1 -1
  54. package/web/assets/{linked-session-header-M7WY6IGF-DwlNCJlj.js → linked-session-header-M7WY6IGF-BBgN8zTq.js} +1 -1
  55. package/web/assets/{mermaid.core-BlYNzkpn.js → mermaid.core-bE6Vl3bZ.js} +4 -4
  56. package/web/assets/{mindmap-definition-LN4V7U3C-CtKHN6O1.js → mindmap-definition-LN4V7U3C-C1a46OGU.js} +1 -1
  57. package/web/assets/{pegDiagram-2B236MQR-CRyz6XWY.js → pegDiagram-2B236MQR-DZxMOxek.js} +1 -1
  58. package/web/assets/{pieDiagram-ENE6RG2P-BXfkPm3Q.js → pieDiagram-ENE6RG2P-BN0XOKLi.js} +1 -1
  59. package/web/assets/{plugin-host-modules-5NQgs5Cq.js → plugin-host-modules-CaRD5_5q.js} +1 -1
  60. package/web/assets/{project-search-dialog-HJFGW4DG-DPly4OiB.js → project-search-dialog-HJFGW4DG-h_dHeh7g.js} +1 -1
  61. package/web/assets/{project-search-page-NKQEBGPF-Cc6HV7BN.js → project-search-page-NKQEBGPF-2AzjjLEC.js} +1 -1
  62. package/web/assets/{quadrantDiagram-ABIIQ3AL-Drb_qWex.js → quadrantDiagram-ABIIQ3AL-C6IegTP-.js} +1 -1
  63. package/web/assets/{railroadDiagram-RFXS5EU6-DCKk2Pix.js → railroadDiagram-RFXS5EU6-bsjyAl-q.js} +1 -1
  64. package/web/assets/{requirementDiagram-TGXJPOKE-6WwZwcpD.js → requirementDiagram-TGXJPOKE-Cl8EZWy7.js} +1 -1
  65. package/web/assets/{sankeyDiagram-HTMAVEWB-DGGk3WCE.js → sankeyDiagram-HTMAVEWB-DhK4rRux.js} +1 -1
  66. package/web/assets/{selection-popup-532EHNCZ-yPhTrk7L.js → selection-popup-532EHNCZ-E2iQ2gQQ.js} +1 -1
  67. package/web/assets/{sequenceDiagram-DBY2YBRQ-a4tGi3DH.js → sequenceDiagram-DBY2YBRQ-DQTaPSD6.js} +1 -1
  68. package/web/assets/{sizeCapture-X5ZJPWSS-CHehBmy9.js → sizeCapture-X5ZJPWSS-k77bZ1zg.js} +1 -1
  69. package/web/assets/{stateDiagram-2N3HPSRC-Bn9GSWgV.js → stateDiagram-2N3HPSRC-Cv_5WuZJ.js} +1 -1
  70. package/web/assets/{stateDiagram-v2-6OUMAXLB-DI7fdBd7.js → stateDiagram-v2-6OUMAXLB-DJ1Lrskh.js} +1 -1
  71. package/web/assets/{swimlanes-5IMT3BWC-BX0WRzfR.js → swimlanes-5IMT3BWC-gBtAjG3z.js} +2 -2
  72. package/web/assets/swimlanesDiagram-G3AALYLV-DF1K9voG.js +8 -0
  73. package/web/assets/{timeline-definition-FHXFAJF6-9Ni2kIzq.js → timeline-definition-FHXFAJF6-CFjnM1Qq.js} +1 -1
  74. package/web/assets/{vennDiagram-L72KCM5P-rfBSNh3U.js → vennDiagram-L72KCM5P-CeMWrThY.js} +1 -1
  75. package/web/assets/{wardleyDiagram-EHGQE667-CzziImCC.js → wardleyDiagram-EHGQE667-R-ZaAOAI.js} +1 -1
  76. package/web/assets/{xychartDiagram-FW5EYKEG-DTLI4h5R.js → xychartDiagram-FW5EYKEG-BFXoMXiN.js} +1 -1
  77. package/web/index.html +2 -2
  78. package/web/assets/channel-um92dqpm.js +0 -1
  79. package/web/assets/classDiagram-OUVF2IWQ-h7sFEJBg.js +0 -1
  80. package/web/assets/classDiagram-v2-EOCWNBFH-h7sFEJBg.js +0 -1
  81. package/web/assets/swimlanesDiagram-G3AALYLV-OGHC9nqi.js +0 -8
@@ -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 readFile10, realpath as realpath5, stat as stat9 } from "node:fs/promises";
17031
- import { extname as extname7, isAbsolute as isAbsolute7, relative as relative11, resolve as resolve12 } from "node:path";
17030
+ import { readFile as readFile11, realpath as realpath8, stat as stat10 } from "node:fs/promises";
17031
+ import { extname as extname7, isAbsolute as isAbsolute8, relative as relative12, resolve as resolve13 } from "node:path";
17032
17032
 
17033
17033
  // packages/api/src/server/watcher.ts
17034
17034
  import { existsSync, statSync, watch } from "node:fs";
@@ -21993,16 +21993,16 @@ function sendContract(response, url, body, headers = {}) {
21993
21993
 
21994
21994
  // packages/api/src/server/folder-metadata-plugin.ts
21995
21995
  import { realpathSync as realpathSync2 } from "node:fs";
21996
- import { readdir as readdir5, readFile as readFile9, stat as stat8 } from "node:fs/promises";
21997
- import { homedir as homedir3 } from "node:os";
21996
+ import { readdir as readdir6, readFile as readFile10, realpath as realpath7, stat as stat9 } from "node:fs/promises";
21997
+ import { homedir as homedir4 } from "node:os";
21998
21998
  import {
21999
- basename as basename6,
22000
- dirname as dirname9,
21999
+ basename as basename7,
22000
+ dirname as dirname10,
22001
22001
  extname as extname6,
22002
- isAbsolute as isAbsolute6,
22003
- relative as relative10,
22004
- resolve as resolve11,
22005
- sep as sep7
22002
+ isAbsolute as isAbsolute7,
22003
+ relative as relative11,
22004
+ resolve as resolve12,
22005
+ sep as sep8
22006
22006
  } from "node:path";
22007
22007
 
22008
22008
  // node_modules/.bun/@raggle-ai+barkdown@0.7.1+22117d1132b05fb8/node_modules/@raggle-ai/barkdown/dist/react.js
@@ -35561,7 +35561,7 @@ async function readFolder(root) {
35561
35561
  }
35562
35562
 
35563
35563
  // packages/api/src/server/folder-metadata-plugin.ts
35564
- import { execFile as execFile4 } from "node:child_process";
35564
+ import { execFile as execFile5 } from "node:child_process";
35565
35565
 
35566
35566
  // packages/plugins/src/endpoint.ts
35567
35567
  var statusByCode = {
@@ -36688,19 +36688,215 @@ function createSchemaCollectionServer(host, options = {}) {
36688
36688
  // packages/api/src/server/folder-metadata-plugin.ts
36689
36689
  import local from "@raggle-ai/local";
36690
36690
 
36691
- // packages/api/src/server/entity-folder.ts
36692
- import { readdir as readdir3, readFile as readFile4, realpath as realpath3, stat as stat3 } from "node:fs/promises";
36691
+ // packages/notes/src/store.ts
36692
+ import { execFile } from "node:child_process";
36693
+ import {
36694
+ mkdir as mkdir2,
36695
+ readdir as readdir3,
36696
+ readFile as readFile4,
36697
+ realpath as realpath3,
36698
+ rename as rename2,
36699
+ rm,
36700
+ stat as stat3,
36701
+ writeFile as writeFile2
36702
+ } from "node:fs/promises";
36693
36703
  import { homedir as homedir2 } from "node:os";
36704
+ import { basename as basename4, dirname as dirname5, join as join2, relative as relative6, resolve as resolve6, sep as sep4 } from "node:path";
36705
+ import { promisify } from "node:util";
36706
+ var run = promisify(execFile);
36707
+ var REPOSITORY_ID_KEY = "kennel.repoId";
36708
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u;
36709
+ var markdownExtensions = new Set([".md", ".markdown"]);
36710
+ var caseInsensitiveHosts = new Set(["github.com", "gitlab.com", "bitbucket.org"]);
36711
+ class RepositoryNotesError extends Error {
36712
+ code;
36713
+ constructor(code, message) {
36714
+ super(message);
36715
+ this.name = "RepositoryNotesError";
36716
+ this.code = code;
36717
+ }
36718
+ }
36719
+ function kennelConfigHome() {
36720
+ const xdg = process.env.XDG_CONFIG_HOME?.trim();
36721
+ return xdg ? xdg : join2(homedir2(), ".config");
36722
+ }
36723
+ function kennelConfigFile() {
36724
+ return join2(kennelConfigHome(), "kennel", "config.json");
36725
+ }
36726
+ function repositoryNotesRoot() {
36727
+ return join2(kennelConfigHome(), "kennel", "repos");
36728
+ }
36729
+ function isRepositoryId(value) {
36730
+ return typeof value === "string" && UUID.test(value);
36731
+ }
36732
+ function managedNotesDirectory(id) {
36733
+ if (!isRepositoryId(id)) {
36734
+ throw new RepositoryNotesError("invalid-id", `Invalid repository id: ${id}`);
36735
+ }
36736
+ return join2(repositoryNotesRoot(), id);
36737
+ }
36738
+ async function readRepositoryNotesSettings() {
36739
+ const file = kennelConfigFile();
36740
+ let text;
36741
+ try {
36742
+ text = await readFile4(file, "utf8");
36743
+ } catch (error) {
36744
+ if (error.code === "ENOENT") {
36745
+ return { enabled: false };
36746
+ }
36747
+ throw new RepositoryNotesError("config-invalid", `Cannot read ${file}: ${errorMessage(error)}`);
36748
+ }
36749
+ let value;
36750
+ try {
36751
+ value = JSON.parse(text);
36752
+ } catch (error) {
36753
+ throw new RepositoryNotesError("config-invalid", `Invalid JSON in ${file}: ${errorMessage(error)}`);
36754
+ }
36755
+ if (!isRecord(value)) {
36756
+ throw new RepositoryNotesError("config-invalid", `${file} must hold an object`);
36757
+ }
36758
+ const section = value.repositoryNotes;
36759
+ if (section === undefined)
36760
+ return { enabled: false };
36761
+ if (!isRecord(section) || section.enabled !== undefined && typeof section.enabled !== "boolean") {
36762
+ throw new RepositoryNotesError("config-invalid", `${file}: repositoryNotes must be an object with a boolean "enabled" field`);
36763
+ }
36764
+ return { enabled: section.enabled === true };
36765
+ }
36766
+ async function git(args, cwd) {
36767
+ const { stdout } = await run("git", args, {
36768
+ cwd,
36769
+ env: { ...process.env, GIT_OPTIONAL_LOCKS: "0", GIT_TERMINAL_PROMPT: "0" },
36770
+ maxBuffer: 1024 * 1024
36771
+ });
36772
+ return stdout.replace(/\r?\n$/u, "");
36773
+ }
36774
+ function gitExitCode(error) {
36775
+ const code = error.code;
36776
+ return typeof code === "number" ? code : undefined;
36777
+ }
36778
+ async function resolveCheckout(folder) {
36779
+ let start;
36780
+ try {
36781
+ start = await realpath3(resolve6(folder));
36782
+ if (!(await stat3(start)).isDirectory())
36783
+ start = dirname5(start);
36784
+ } catch {
36785
+ throw new RepositoryNotesError("not-git", `Folder does not exist: ${folder}`);
36786
+ }
36787
+ let output;
36788
+ try {
36789
+ output = await git(["rev-parse", "--path-format=absolute", "--show-toplevel", "--git-common-dir"], start);
36790
+ } catch (error) {
36791
+ if (gitExitCode(error) === 128) {
36792
+ throw new RepositoryNotesError("not-git", `Not a Git repository: ${start}. Repository notes need a Git checkout.`);
36793
+ }
36794
+ throw error;
36795
+ }
36796
+ const [top, common] = output.split(/\r?\n/u);
36797
+ if (!top || !common) {
36798
+ throw new RepositoryNotesError("not-git", `Not a Git work tree: ${start}`);
36799
+ }
36800
+ const root = await realpath3(top);
36801
+ const commonDir = await realpath3(common);
36802
+ return { root, commonDir, configFile: join2(commonDir, "config") };
36803
+ }
36804
+ async function readBinding(checkout) {
36805
+ let value;
36806
+ try {
36807
+ value = await git(["config", "--file", checkout.configFile, "--get", REPOSITORY_ID_KEY], checkout.root);
36808
+ } catch (error) {
36809
+ if (gitExitCode(error) === 1)
36810
+ return;
36811
+ throw error;
36812
+ }
36813
+ const id = value.trim();
36814
+ if (!id)
36815
+ return;
36816
+ if (!isRepositoryId(id)) {
36817
+ throw new RepositoryNotesError("invalid-binding", `${checkout.configFile} has an invalid ${REPOSITORY_ID_KEY} value. Remove it or run "kennel notes new-identity".`);
36818
+ }
36819
+ return id;
36820
+ }
36821
+ function isRecord(value) {
36822
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
36823
+ }
36824
+ function errorMessage(error) {
36825
+ return error instanceof Error ? error.message : String(error);
36826
+ }
36827
+ async function lookupRepositoryNotes(folder) {
36828
+ let checkout;
36829
+ try {
36830
+ checkout = await resolveCheckout(folder);
36831
+ } catch (error) {
36832
+ if (error instanceof RepositoryNotesError && error.code === "not-git") {
36833
+ return { status: "not-git", folder };
36834
+ }
36835
+ throw error;
36836
+ }
36837
+ const id = await readBinding(checkout);
36838
+ if (!id)
36839
+ return { status: "unregistered", checkout, root: checkout.root };
36840
+ return {
36841
+ status: "registered",
36842
+ checkout,
36843
+ id,
36844
+ notesDirectory: managedNotesDirectory(id),
36845
+ root: checkout.root
36846
+ };
36847
+ }
36848
+ async function listManagedNotes(directory) {
36849
+ const notes = [];
36850
+ const visit = async (current) => {
36851
+ let entries;
36852
+ try {
36853
+ entries = await readdir3(current, { withFileTypes: true });
36854
+ } catch (error) {
36855
+ if (error.code === "ENOENT")
36856
+ return;
36857
+ throw error;
36858
+ }
36859
+ for (const entry of entries) {
36860
+ if (entry.name.startsWith(".") || entry.isSymbolicLink())
36861
+ continue;
36862
+ const path = join2(current, entry.name);
36863
+ if (entry.isDirectory()) {
36864
+ await visit(path);
36865
+ continue;
36866
+ }
36867
+ if (!entry.isFile())
36868
+ continue;
36869
+ const dot = entry.name.lastIndexOf(".");
36870
+ const extension = dot === -1 ? "" : entry.name.slice(dot).toLowerCase();
36871
+ if (!markdownExtensions.has(extension))
36872
+ continue;
36873
+ const details = await stat3(path);
36874
+ notes.push({
36875
+ activityAt: details.mtimeMs,
36876
+ name: dot === -1 ? entry.name : entry.name.slice(0, dot),
36877
+ path,
36878
+ relativePath: relative6(directory, path).split(sep4).join("/"),
36879
+ size: details.size
36880
+ });
36881
+ }
36882
+ };
36883
+ await visit(directory);
36884
+ return notes.sort((left, right) => right.activityAt - left.activityAt);
36885
+ }
36886
+
36887
+ // packages/api/src/server/entity-folder.ts
36888
+ import { readdir as readdir4, readFile as readFile5, realpath as realpath4, stat as stat4 } from "node:fs/promises";
36889
+ import { homedir as homedir3 } from "node:os";
36694
36890
  import {
36695
- basename as basename4,
36696
- dirname as dirname5,
36891
+ basename as basename5,
36892
+ dirname as dirname6,
36697
36893
  extname as extname2,
36698
36894
  isAbsolute as isAbsolute4,
36699
- join as join2,
36700
- relative as relative6,
36701
- resolve as resolve6
36895
+ join as join3,
36896
+ relative as relative7,
36897
+ resolve as resolve7
36702
36898
  } from "node:path";
36703
- var CONFIG_FILE = join2("kennel", "config.json");
36899
+ var CONFIG_FILE = join3("kennel", "config.json");
36704
36900
  var IGNORED_DIRECTORIES = new Set([
36705
36901
  ".git",
36706
36902
  ".gtl",
@@ -36741,11 +36937,11 @@ function paragraph(body) {
36741
36937
  }
36742
36938
  function configPath() {
36743
36939
  const xdg = process.env.XDG_CONFIG_HOME?.trim();
36744
- return xdg ? join2(xdg, CONFIG_FILE) : join2(homedir2(), ".config", CONFIG_FILE);
36940
+ return xdg ? join3(xdg, CONFIG_FILE) : join3(homedir3(), ".config", CONFIG_FILE);
36745
36941
  }
36746
36942
  async function readConfig(path) {
36747
36943
  try {
36748
- return parseConfig(await readFile4(path, "utf8"));
36944
+ return parseConfig(await readFile5(path, "utf8"));
36749
36945
  } catch (error) {
36750
36946
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
36751
36947
  return null;
@@ -36762,6 +36958,8 @@ function parseConfig(source) {
36762
36958
  if (!value || typeof value !== "object" || Array.isArray(value))
36763
36959
  throw new Error("Invalid Kennel entity root config");
36764
36960
  const roots = value.allowedRoots;
36961
+ if (roots === undefined)
36962
+ return {};
36765
36963
  if (!Array.isArray(roots))
36766
36964
  throw new Error("Invalid Kennel entity root config");
36767
36965
  const allowedRoots = roots.map((root) => {
@@ -36773,12 +36971,12 @@ function parseConfig(source) {
36773
36971
  }
36774
36972
  async function allowedRoots(currentWorkspaceRoot) {
36775
36973
  const config = await readConfig(configPath());
36776
- if (config)
36974
+ if (config?.allowedRoots)
36777
36975
  return config.allowedRoots;
36778
36976
  return currentWorkspaceRoot?.trim() ? [currentWorkspaceRoot] : [];
36779
36977
  }
36780
36978
  function inside4(root, path) {
36781
- const local = relative6(root, path);
36979
+ const local = relative7(root, path);
36782
36980
  return local === "" || !local.startsWith("..") && !isAbsolute4(local);
36783
36981
  }
36784
36982
  async function normalizeRoot(rootPath, currentWorkspaceRoot) {
@@ -36786,13 +36984,13 @@ async function normalizeRoot(rootPath, currentWorkspaceRoot) {
36786
36984
  const fallback = currentWorkspaceRoot?.trim();
36787
36985
  if (!trimmed && !fallback)
36788
36986
  return null;
36789
- const requested = resolve6(trimmed || fallback);
36790
- const resolved = await realpath3(requested);
36791
- const info = await stat3(resolved);
36987
+ const requested = resolve7(trimmed || fallback);
36988
+ const resolved = await realpath4(requested);
36989
+ const info = await stat4(resolved);
36792
36990
  if (!info.isDirectory())
36793
36991
  throw new Error(`${resolved} is not a folder`);
36794
36992
  const roots = await allowedRoots(currentWorkspaceRoot);
36795
- const realAllowedRoots = await Promise.all(roots.map((root) => realpath3(root)));
36993
+ const realAllowedRoots = await Promise.all(roots.map((root) => realpath4(root)));
36796
36994
  const allowed = realAllowedRoots.some((root) => inside4(root, resolved));
36797
36995
  if (!allowed)
36798
36996
  throw new Error("Entity root is outside the configured roots");
@@ -36801,11 +36999,11 @@ async function normalizeRoot(rootPath, currentWorkspaceRoot) {
36801
36999
  async function markdownFiles(folderPath) {
36802
37000
  const files = [];
36803
37001
  async function walk(currentPath) {
36804
- const entries = await readdir3(currentPath, { withFileTypes: true });
37002
+ const entries = await readdir4(currentPath, { withFileTypes: true });
36805
37003
  for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
36806
37004
  if (entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name))
36807
37005
  continue;
36808
- const entryPath = join2(currentPath, entry.name);
37006
+ const entryPath = join3(currentPath, entry.name);
36809
37007
  if (entry.isDirectory()) {
36810
37008
  if (entryPath !== folderPath && await hasIndex(entryPath))
36811
37009
  continue;
@@ -36820,36 +37018,36 @@ async function markdownFiles(folderPath) {
36820
37018
  return files;
36821
37019
  }
36822
37020
  async function hasIndex(folderPath) {
36823
- return stat3(join2(folderPath, "index.md")).then((value) => value.isFile()).catch(() => false);
37021
+ return stat4(join3(folderPath, "index.md")).then((value) => value.isFile()).catch(() => false);
36824
37022
  }
36825
37023
  async function schemaPath(folderPath, rootPath) {
36826
37024
  let current = folderPath;
36827
37025
  while (current === rootPath || current.startsWith(`${rootPath}/`)) {
36828
37026
  for (const name of ["schema.json", "_schema.json"]) {
36829
- const candidate = join2(current, name);
36830
- if (await stat3(candidate).then((value) => value.isFile()).catch(() => false))
37027
+ const candidate = join3(current, name);
37028
+ if (await stat4(candidate).then((value) => value.isFile()).catch(() => false))
36831
37029
  return candidate;
36832
37030
  }
36833
37031
  if (current === rootPath)
36834
37032
  return null;
36835
- current = dirname5(current);
37033
+ current = dirname6(current);
36836
37034
  }
36837
37035
  return null;
36838
37036
  }
36839
37037
  async function readEntity(folderPath, rootPath) {
36840
- const indexPath = join2(folderPath, "index.md");
36841
- const index = parseMarkdown(await readFile4(indexPath, "utf8"));
37038
+ const indexPath = join3(folderPath, "index.md");
37039
+ const index = parseMarkdown(await readFile5(indexPath, "utf8"));
36842
37040
  const files = await markdownFiles(folderPath);
36843
37041
  const documents = await Promise.all(files.map(async (filePath) => {
36844
- const document2 = parseMarkdown(await readFile4(filePath, "utf8"));
37042
+ const document2 = parseMarkdown(await readFile5(filePath, "utf8"));
36845
37043
  return {
36846
37044
  content: document2.body,
36847
- path: relative6(folderPath, filePath),
36848
- title: stringValue(document2.frontmatter.title) ?? heading(document2.body) ?? basename4(filePath, extname2(filePath))
37045
+ path: relative7(folderPath, filePath),
37046
+ title: stringValue(document2.frontmatter.title) ?? heading(document2.body) ?? basename5(filePath, extname2(filePath))
36849
37047
  };
36850
37048
  }));
36851
- const title = stringValue(index.frontmatter.title) ?? heading(index.body) ?? basename4(folderPath);
36852
- const relativePath = relative6(rootPath, folderPath) || ".";
37049
+ const title = stringValue(index.frontmatter.title) ?? heading(index.body) ?? basename5(folderPath);
37050
+ const relativePath = relative7(rootPath, folderPath) || ".";
36853
37051
  return {
36854
37052
  aliases: stringValues(index.frontmatter.aliases),
36855
37053
  content: [
@@ -36877,11 +37075,11 @@ async function discover(rootPath) {
36877
37075
  async function walk(folderPath) {
36878
37076
  if (await hasIndex(folderPath))
36879
37077
  folders.push(folderPath);
36880
- const entries = await readdir3(folderPath, { withFileTypes: true });
37078
+ const entries = await readdir4(folderPath, { withFileTypes: true });
36881
37079
  for (const entry of entries) {
36882
37080
  if (!entry.isDirectory() || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name))
36883
37081
  continue;
36884
- await walk(join2(folderPath, entry.name));
37082
+ await walk(join3(folderPath, entry.name));
36885
37083
  }
36886
37084
  }
36887
37085
  await walk(rootPath);
@@ -36921,20 +37119,20 @@ async function loadEntityWorkspace(root, query, selectedPath, currentWorkspaceRo
36921
37119
  // packages/api/src/server/api/document-edit.ts
36922
37120
  import { randomUUID as randomUUID2 } from "node:crypto";
36923
37121
  import {
36924
- readFile as readFile5,
36925
- realpath as realpath4,
36926
- rename as rename2,
36927
- stat as stat4,
37122
+ readFile as readFile6,
37123
+ realpath as realpath5,
37124
+ rename as rename3,
37125
+ stat as stat5,
36928
37126
  unlink as unlink2,
36929
- writeFile as writeFile2
37127
+ writeFile as writeFile3
36930
37128
  } from "node:fs/promises";
36931
37129
  import {
36932
- dirname as dirname6,
37130
+ dirname as dirname7,
36933
37131
  extname as extname3,
36934
37132
  isAbsolute as isAbsolute5,
36935
- relative as relative7,
36936
- resolve as resolve7,
36937
- sep as sep4
37133
+ relative as relative8,
37134
+ resolve as resolve8,
37135
+ sep as sep5
36938
37136
  } from "node:path";
36939
37137
 
36940
37138
  // packages/api/src/shared/selection.ts
@@ -36952,10 +37150,10 @@ async function editDocument(folder, input) {
36952
37150
  throw apiError("bad-request", "Invalid document edit.");
36953
37151
  if (![".md", ".markdown"].includes(extname3(path).toLowerCase()))
36954
37152
  throw apiError("bad-request", "Only Markdown notes can be edited.");
36955
- const root = await realpath4(folder);
36956
- const target = await realpath4(resolve7(root, path));
36957
- const local = relative7(root, target);
36958
- if (!local || local === ".." || local.startsWith(`..${sep4}`) || isAbsolute5(local))
37153
+ const root = await realpath5(folder);
37154
+ const target = await realpath5(resolve8(root, path));
37155
+ const local = relative8(root, target);
37156
+ if (!local || local === ".." || local.startsWith(`..${sep5}`) || isAbsolute5(local))
36959
37157
  throw apiError("forbidden", "The document must be inside its folder.");
36960
37158
  let content;
36961
37159
  try {
@@ -36965,20 +37163,20 @@ async function editDocument(folder, input) {
36965
37163
  }
36966
37164
  const previous = pending.get(target) ?? Promise.resolve();
36967
37165
  const operation = previous.catch(() => {}).then(async () => {
36968
- const details = await stat4(target);
37166
+ const details = await stat5(target);
36969
37167
  if (!details.isFile() || details.nlink !== 1)
36970
37168
  throw apiError("forbidden", "Only regular, unlinked files can be edited.");
36971
- if (await readFile5(target, "utf8") !== original)
37169
+ if (await readFile6(target, "utf8") !== original)
36972
37170
  throw apiError("conflict", "This note changed on disk. Close this preview, reload the note, and try again.");
36973
- const temporary = resolve7(dirname6(target), `.kennel-edit-${randomUUID2()}.tmp`);
37171
+ const temporary = resolve8(dirname7(target), `.kennel-edit-${randomUUID2()}.tmp`);
36974
37172
  try {
36975
- await writeFile2(temporary, content, {
37173
+ await writeFile3(temporary, content, {
36976
37174
  flag: "wx",
36977
37175
  mode: details.mode & 511
36978
37176
  });
36979
- if (await readFile5(target, "utf8") !== original)
37177
+ if (await readFile6(target, "utf8") !== original)
36980
37178
  throw apiError("conflict", "This note changed on disk. Reload before applying an edit.");
36981
- await rename2(temporary, target);
37179
+ await rename3(temporary, target);
36982
37180
  } finally {
36983
37181
  await unlink2(temporary).catch(() => {});
36984
37182
  }
@@ -37001,7 +37199,7 @@ var documentEditRoute = {
37001
37199
  throw apiError("bad-request", "Invalid document edit.");
37002
37200
  const input = parsed.data;
37003
37201
  const folder = context.authorize(input.folder);
37004
- if (context.lockedFile && (typeof input.path !== "string" || await realpath4(resolve7(folder, input.path)) !== context.lockedFile))
37202
+ if (context.lockedFile && (typeof input.path !== "string" || await realpath5(resolve8(folder, input.path)) !== context.lockedFile))
37005
37203
  throw apiError("forbidden", "Only the selected document can be edited.");
37006
37204
  await editDocument(folder, input);
37007
37205
  jsonResponse(response, 200, routes.documentEdit.response.parse({ saved: true }));
@@ -37009,8 +37207,8 @@ var documentEditRoute = {
37009
37207
  };
37010
37208
 
37011
37209
  // packages/api/src/server/api/create-agent-file.ts
37012
- import { writeFile as writeFile3 } from "node:fs/promises";
37013
- import { resolve as resolve8 } from "node:path";
37210
+ import { writeFile as writeFile4 } from "node:fs/promises";
37211
+ import { resolve as resolve9 } from "node:path";
37014
37212
  var createAgentFileRoute = {
37015
37213
  method: "POST",
37016
37214
  maxBodyBytes: 0,
@@ -37021,9 +37219,9 @@ var createAgentFileRoute = {
37021
37219
  } catch (error) {
37022
37220
  throw apiError("not-found", error instanceof Error ? error.message : "Folder not found");
37023
37221
  }
37024
- const target = resolve8(folder, "AGENTS.md");
37222
+ const target = resolve9(folder, "AGENTS.md");
37025
37223
  try {
37026
- await writeFile3(target, "", { flag: "wx" });
37224
+ await writeFile4(target, "", { flag: "wx" });
37027
37225
  } catch (error) {
37028
37226
  if (error && typeof error === "object" && "code" in error && error.code === "EEXIST") {
37029
37227
  throw apiError("conflict", "AGENTS.md already exists in this folder");
@@ -37035,7 +37233,7 @@ var createAgentFileRoute = {
37035
37233
  };
37036
37234
 
37037
37235
  // packages/api/src/server/api/open-path.ts
37038
- import { execFile } from "node:child_process";
37236
+ import { execFile as execFile2 } from "node:child_process";
37039
37237
  var openPathRoute = {
37040
37238
  method: "GET",
37041
37239
  async handle({ context, query, response }) {
@@ -37046,7 +37244,7 @@ var openPathRoute = {
37046
37244
  throw apiError("not-found", error instanceof Error ? error.message : "Path not found");
37047
37245
  }
37048
37246
  await new Promise((done, fail) => {
37049
- execFile("/usr/bin/open", [target], (error) => {
37247
+ execFile2("/usr/bin/open", [target], (error) => {
37050
37248
  if (error)
37051
37249
  fail(apiError("failed", "Could not open path"));
37052
37250
  else
@@ -37059,11 +37257,11 @@ var openPathRoute = {
37059
37257
  };
37060
37258
 
37061
37259
  // packages/api/src/server/folder-favicon.ts
37062
- import { readFile as readFile6 } from "node:fs/promises";
37063
- import { join as join3 } from "node:path";
37260
+ import { readFile as readFile7 } from "node:fs/promises";
37261
+ import { join as join4 } from "node:path";
37064
37262
  async function folderWebsite(folder) {
37065
37263
  for (const name of ["AGENTS.md", "README.md"]) {
37066
- const content = await readFile6(join3(folder, name), "utf8").catch(() => "");
37264
+ const content = await readFile7(join4(folder, name), "utf8").catch(() => "");
37067
37265
  const entry = markdownMetadata(content).entries.find(([key]) => key === "website");
37068
37266
  if (entry)
37069
37267
  return websiteHost(entry[1]);
@@ -37073,7 +37271,7 @@ async function folderWebsite(folder) {
37073
37271
 
37074
37272
  // packages/api/src/server/folder-icons.ts
37075
37273
  import { createHash as createHash4 } from "node:crypto";
37076
- import { readFile as readFile7, stat as stat5 } from "node:fs/promises";
37274
+ import { readFile as readFile8, stat as stat6 } from "node:fs/promises";
37077
37275
  import { extname as extname4 } from "node:path";
37078
37276
  import { discoverFolderIcon } from "@raggle-ai/local";
37079
37277
  var maxIconBytes2 = 4 * 1024 * 1024;
@@ -37112,13 +37310,13 @@ function iconUrl(folder, hash, mediaType) {
37112
37310
  async function folderIcon(folder, assets, assetFiles, fallback) {
37113
37311
  const icon = discoverFolderIcon(folder);
37114
37312
  const mediaType = icon ? iconTypes.get(extname4(icon).toLowerCase()) : null;
37115
- const details = icon && mediaType ? await stat5(icon).catch(() => {
37313
+ const details = icon && mediaType ? await stat6(icon).catch(() => {
37116
37314
  return;
37117
37315
  }) : undefined;
37118
37316
  if (!icon || !mediaType || !details?.size || details.size > maxIconBytes2) {
37119
37317
  return fallback ? await fallback(folder, assets) : undefined;
37120
37318
  }
37121
- const data = await readFile7(icon);
37319
+ const data = await readFile8(icon);
37122
37320
  const hash = assetKey(data);
37123
37321
  const key = `local:${hash}`;
37124
37322
  assetFiles.set(hash, { mediaType, path: icon });
@@ -37137,12 +37335,12 @@ async function searchIconDataUrl(icon) {
37137
37335
  const mediaType = searchIconTypes.get(extname4(icon).toLowerCase());
37138
37336
  if (!mediaType)
37139
37337
  return;
37140
- const details = await stat5(icon).catch(() => {
37338
+ const details = await stat6(icon).catch(() => {
37141
37339
  return;
37142
37340
  });
37143
37341
  if (!details?.size || details.size > maxSearchIconBytes)
37144
37342
  return;
37145
- return `data:${mediaType};base64,${(await readFile7(icon)).toString("base64")}`;
37343
+ return `data:${mediaType};base64,${(await readFile8(icon)).toString("base64")}`;
37146
37344
  }
37147
37345
  async function faviconAsset(folderName, assets) {
37148
37346
  if (process.env.KENNEL_EXTERNAL_ICONS !== "1")
@@ -37188,12 +37386,19 @@ async function workspaceBreadcrumbIcons(breadcrumbs, assetFiles, assets = {}) {
37188
37386
  // packages/api/src/server/plugins.ts
37189
37387
  import { pathToFileURL } from "node:url";
37190
37388
  import { existsSync as existsSync3 } from "node:fs";
37191
- import { mkdir as mkdir2, readFile as readFile8, stat as stat7, writeFile as writeFile4 } from "node:fs/promises";
37192
- import { dirname as dirname7, resolve as resolve10, sep as sep6 } from "node:path";
37389
+ import { mkdir as mkdir3, readFile as readFile9, stat as stat8, writeFile as writeFile5 } from "node:fs/promises";
37390
+ import { dirname as dirname8, resolve as resolve11, sep as sep7 } from "node:path";
37193
37391
 
37194
37392
  // packages/notes/src/server.ts
37195
- import { readdir as readdir4, stat as stat6 } from "node:fs/promises";
37196
- import { basename as basename5, extname as extname5, relative as relative8, resolve as resolve9, sep as sep5 } from "node:path";
37393
+ import { readdir as readdir5, realpath as realpath6, stat as stat7 } from "node:fs/promises";
37394
+ import {
37395
+ basename as basename6,
37396
+ extname as extname5,
37397
+ isAbsolute as isAbsolute6,
37398
+ relative as relative9,
37399
+ resolve as resolve10,
37400
+ sep as sep6
37401
+ } from "node:path";
37197
37402
 
37198
37403
  // packages/notes/src/manifest.ts
37199
37404
  var notesManifest = {
@@ -37209,47 +37414,71 @@ var notesManifest = {
37209
37414
  };
37210
37415
 
37211
37416
  // packages/notes/src/server.ts
37212
- var markdownExtensions = new Set([".md", ".markdown"]);
37417
+ var markdownExtensions2 = new Set([".md", ".markdown"]);
37213
37418
  var llmNoteLimit = 20;
37214
37419
  async function listMarkdownFiles(folder) {
37215
37420
  const files = [];
37216
37421
  const visit = async (current) => {
37217
- const entries = await readdir4(current, { withFileTypes: true }).catch(() => []);
37422
+ const entries = await readdir5(current, { withFileTypes: true }).catch(() => []);
37218
37423
  for (const entry of entries) {
37219
37424
  if (entry.name === "node_modules" || entry.name.startsWith("."))
37220
37425
  continue;
37221
- const path = resolve9(current, entry.name);
37426
+ const path = resolve10(current, entry.name);
37222
37427
  if (entry.isDirectory()) {
37223
37428
  await visit(path);
37224
37429
  continue;
37225
37430
  }
37226
- if (!entry.isFile() || !markdownExtensions.has(extname5(entry.name))) {
37431
+ if (!entry.isFile() || !markdownExtensions2.has(extname5(entry.name))) {
37227
37432
  continue;
37228
37433
  }
37229
- const details = await stat6(path).catch(() => {
37434
+ const details = await stat7(path).catch(() => {
37230
37435
  return;
37231
37436
  });
37232
37437
  files.push({
37233
37438
  activityAt: details?.mtimeMs ?? 0,
37234
- name: basename5(entry.name, extname5(entry.name)),
37235
- relativePath: relative8(folder, path).split(sep5).join("/")
37439
+ name: basename6(entry.name, extname5(entry.name)),
37440
+ relativePath: relative9(folder, path).split(sep6).join("/")
37236
37441
  });
37237
37442
  }
37238
37443
  };
37239
37444
  await visit(folder);
37240
37445
  return files.sort((left, right) => right.activityAt - left.activityAt);
37241
37446
  }
37242
- async function loadNotes(folder, linkedFolders = []) {
37447
+ var canonical = (path) => realpath6(path).catch(() => path);
37448
+ function inside5(path, root) {
37449
+ const local = relative9(root, path);
37450
+ return local === "" || !local.startsWith("..") && !isAbsolute6(local);
37451
+ }
37452
+ async function withoutManaged(groups, managedRoots) {
37453
+ if (!managedRoots.length)
37454
+ return groups;
37455
+ const roots = await Promise.all(managedRoots.map(canonical));
37456
+ return Promise.all(groups.map(async (group) => {
37457
+ if (roots.includes(await canonical(group.folder))) {
37458
+ return { ...group, files: [] };
37459
+ }
37460
+ const files = await Promise.all(group.files.map(async (file) => {
37461
+ const real = await canonical(resolve10(group.folder, file.relativePath));
37462
+ return roots.some((root) => inside5(real, root)) ? undefined : file;
37463
+ }));
37464
+ return { ...group, files: files.filter((file) => file !== undefined) };
37465
+ }));
37466
+ }
37467
+ async function loadNotes(folder, linkedFolders = [], managedFolders = []) {
37243
37468
  const localFiles = await listMarkdownFiles(folder);
37244
- const linked = await Promise.all(linkedFolders.map(async (linkedFolder) => ({
37245
- files: await listMarkdownFiles(linkedFolder),
37246
- folder: linkedFolder
37469
+ const listGroups = (folders) => Promise.all(folders.map(async (source) => ({
37470
+ files: await listMarkdownFiles(source),
37471
+ folder: source
37247
37472
  })));
37473
+ const [managed, linked] = await Promise.all([
37474
+ listGroups(managedFolders),
37475
+ listGroups(linkedFolders).then((groups) => withoutManaged(groups, managedFolders))
37476
+ ]);
37248
37477
  return {
37249
37478
  files: {
37250
37479
  items: [
37251
37480
  ...localFiles,
37252
- ...linked.flatMap((group) => group.files.map((file) => ({ ...file, folder: group.folder })))
37481
+ ...[...managed, ...linked].flatMap((group) => group.files.map((file) => ({ ...file, folder: group.folder })))
37253
37482
  ]
37254
37483
  },
37255
37484
  folder,
@@ -37266,14 +37495,20 @@ function codeSpan(text) {
37266
37495
  async function notesLlmSections({
37267
37496
  folder,
37268
37497
  linkedFolders = [],
37498
+ managedFolders = [],
37269
37499
  signal
37270
37500
  }) {
37271
37501
  const groups = [];
37272
37502
  const notes = [];
37273
- for (const source of [folder, ...linkedFolders]) {
37503
+ const seen = new Set;
37504
+ for (const source of [folder, ...managedFolders, ...linkedFolders]) {
37274
37505
  signal.throwIfAborted();
37506
+ const identity = await canonical(source);
37507
+ if (seen.has(identity))
37508
+ continue;
37509
+ seen.add(identity);
37275
37510
  const files = await listMarkdownFiles(source);
37276
- const paths = files.map((file) => resolve9(source, file.relativePath));
37511
+ const paths = files.map((file) => resolve10(source, file.relativePath));
37277
37512
  groups.push({ folder: source, paths });
37278
37513
  files.forEach((file, index) => notes.push({ activityAt: file.activityAt, path: paths[index] }));
37279
37514
  }
@@ -37306,9 +37541,13 @@ function createNotesPlugin() {
37306
37541
  },
37307
37542
  async handle({
37308
37543
  folder,
37309
- linkedFolders
37544
+ linkedFolders,
37545
+ managedFolders
37310
37546
  }) {
37311
- return { data: await loadNotes(folder, linkedFolders), kind: "available" };
37547
+ return {
37548
+ data: await loadNotes(folder, linkedFolders, managedFolders),
37549
+ kind: "available"
37550
+ };
37312
37551
  },
37313
37552
  llm: notesLlmSections
37314
37553
  };
@@ -37341,14 +37580,14 @@ function parsePluginRegistryConfig(content) {
37341
37580
  };
37342
37581
  }
37343
37582
  async function nearestKennelConfig(folder) {
37344
- for (let current = folder;; current = dirname7(current)) {
37345
- const candidate = resolve10(current, "kennel.json");
37346
- const details = await stat7(candidate).catch(() => {
37583
+ for (let current = folder;; current = dirname8(current)) {
37584
+ const candidate = resolve11(current, "kennel.json");
37585
+ const details = await stat8(candidate).catch(() => {
37347
37586
  return;
37348
37587
  });
37349
37588
  if (details?.isFile())
37350
37589
  return candidate;
37351
- if (dirname7(current) === current)
37590
+ if (dirname8(current) === current)
37352
37591
  return;
37353
37592
  }
37354
37593
  }
@@ -37357,7 +37596,7 @@ async function folderPluginRegistryConfig(folder) {
37357
37596
  if (!path)
37358
37597
  return defaultPluginRegistryConfig;
37359
37598
  try {
37360
- return parsePluginRegistryConfig(await readFile8(path, "utf8"));
37599
+ return parsePluginRegistryConfig(await readFile9(path, "utf8"));
37361
37600
  } catch {
37362
37601
  return defaultPluginRegistryConfig;
37363
37602
  }
@@ -37405,7 +37644,7 @@ async function folderServerRegistryAsync() {
37405
37644
  ...server,
37406
37645
  async detect(context) {
37407
37646
  const detection = await server.detect(context);
37408
- if (detection.status === "unavailable" && existsSync3(resolve10(context.folder, entry.trigger))) {
37647
+ if (detection.status === "unavailable" && existsSync3(resolve11(context.folder, entry.trigger))) {
37409
37648
  return { status: "available" };
37410
37649
  }
37411
37650
  return detection;
@@ -37444,13 +37683,13 @@ async function externalApiHandlers() {
37444
37683
  }
37445
37684
 
37446
37685
  // packages/api/src/server/project-discovery.ts
37447
- import { execFile as execFile3 } from "node:child_process";
37686
+ import { execFile as execFile4 } from "node:child_process";
37448
37687
 
37449
37688
  // packages/api/src/server/linked-folder-discovery.ts
37450
- import { execFile as execFile2 } from "node:child_process";
37689
+ import { execFile as execFile3 } from "node:child_process";
37451
37690
  import { existsSync as existsSync4 } from "node:fs";
37452
37691
  import { createRequire as createRequire2 } from "node:module";
37453
- import { dirname as dirname8, join as join4 } from "node:path";
37692
+ import { dirname as dirname9, join as join5 } from "node:path";
37454
37693
  import { fileURLToPath } from "node:url";
37455
37694
  var script = `
37456
37695
  const local = require(process.argv[1]);
@@ -37473,19 +37712,19 @@ function resolveLocalModule(from = import.meta.url) {
37473
37712
  try {
37474
37713
  candidates.push(require2.resolve("@raggle-ai/local"));
37475
37714
  } catch {}
37476
- let directory = dirname8(fileURLToPath(from));
37477
- while (dirname8(directory) !== directory) {
37478
- if (existsSync4(join4(directory, "raggle.json"))) {
37715
+ let directory = dirname9(fileURLToPath(from));
37716
+ while (dirname9(directory) !== directory) {
37717
+ if (existsSync4(join5(directory, "raggle.json"))) {
37479
37718
  for (const candidate of [
37480
- join4(dirname8(directory), "raggle-ai-scout", "packages", "local"),
37481
- join4(directory, "..", "..", "raggle-ai-scout", "packages", "local")
37719
+ join5(dirname9(directory), "raggle-ai-scout", "packages", "local"),
37720
+ join5(directory, "..", "..", "raggle-ai-scout", "packages", "local")
37482
37721
  ]) {
37483
37722
  if (!candidates.includes(candidate))
37484
37723
  candidates.push(candidate);
37485
37724
  }
37486
37725
  break;
37487
37726
  }
37488
- directory = dirname8(directory);
37727
+ directory = dirname9(directory);
37489
37728
  }
37490
37729
  for (const candidate of candidates) {
37491
37730
  try {
@@ -37494,11 +37733,11 @@ function resolveLocalModule(from = import.meta.url) {
37494
37733
  return candidate;
37495
37734
  } catch {}
37496
37735
  }
37497
- return candidates[0] ?? join4(dirname8(fileURLToPath(from)), "..", "..", "..", "raggle-ai-scout", "packages", "local");
37736
+ return candidates[0] ?? join5(dirname9(fileURLToPath(from)), "..", "..", "..", "raggle-ai-scout", "packages", "local");
37498
37737
  }
37499
37738
  function discoverLinkedFolders(folder, signal, modulePath = resolveLocalModule()) {
37500
37739
  return new Promise((resolve, reject) => {
37501
- execFile2(process.execPath, ["-e", script, modulePath, folder], {
37740
+ execFile3(process.execPath, ["-e", script, modulePath, folder], {
37502
37741
  signal,
37503
37742
  timeout: 60000,
37504
37743
  maxBuffer: 8 * 1024 * 1024,
@@ -37589,7 +37828,7 @@ local.discoverProjectsUnderFolder({folder}).then(projects => {
37589
37828
  `;
37590
37829
  function discoverProjects(folder, signal) {
37591
37830
  return new Promise((resolve, reject) => {
37592
- execFile3(process.execPath, ["-e", script2, resolveLocalModule(), folder], {
37831
+ execFile4(process.execPath, ["-e", script2, resolveLocalModule(), folder], {
37593
37832
  signal,
37594
37833
  timeout: 60000,
37595
37834
  maxBuffer: 8 * 1024 * 1024,
@@ -37846,10 +38085,10 @@ var metadataExtensions = new Set([
37846
38085
  ".txt"
37847
38086
  ]);
37848
38087
  function metadataFile(path, root) {
37849
- const candidate = relative10(root, path);
37850
- if (!candidate || candidate.startsWith("..") || isAbsolute6(candidate))
38088
+ const candidate = relative11(root, path);
38089
+ if (!candidate || candidate.startsWith("..") || isAbsolute7(candidate))
37851
38090
  return false;
37852
- const parts = candidate.split(sep7);
38091
+ const parts = candidate.split(sep8);
37853
38092
  if (parts.some((part) => part === "node_modules"))
37854
38093
  return false;
37855
38094
  return metadataExtensions.has(extname6(candidate).toLowerCase());
@@ -37860,11 +38099,11 @@ async function configuredAiInputModule(folder) {
37860
38099
  return typeof module === "string" && module.trim() ? module.trim() : null;
37861
38100
  }
37862
38101
  function folderPath(value, root, lockedRoot) {
37863
- const folder = realpathSync2(resolve11(value ?? root));
38102
+ const folder = realpathSync2(resolve12(value ?? root));
37864
38103
  if (!lockedRoot)
37865
38104
  return folder;
37866
- const path = relative10(lockedRoot, folder);
37867
- if (!path || !path.startsWith("..") && !isAbsolute6(path))
38105
+ const path = relative11(lockedRoot, folder);
38106
+ if (!path || !path.startsWith("..") && !isAbsolute7(path))
37868
38107
  return folder;
37869
38108
  throw new Error(`Folder is outside the viewer root: ${folder}`);
37870
38109
  }
@@ -37935,15 +38174,15 @@ function unique(values) {
37935
38174
  return [...new Set(values)];
37936
38175
  }
37937
38176
  function isMachineRoot(folder) {
37938
- return folder === homedir3() || dirname9(folder) === folder;
38177
+ return folder === homedir4() || dirname10(folder) === folder;
37939
38178
  }
37940
38179
  async function shallowMetadata(folder) {
37941
- const entries = await readdir5(folder, { withFileTypes: true });
38180
+ const entries = await readdir6(folder, { withFileTypes: true });
37942
38181
  const visible = entries.filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules");
37943
38182
  const files = await Promise.all(visible.filter((entry) => entry.isFile() && [".markdown", ".md"].includes(extname6(entry.name).toLowerCase())).map(async (entry) => {
37944
- const path = resolve11(folder, entry.name);
37945
- const details = await stat8(path);
37946
- const content = await readFile9(path, "utf8").catch(() => "");
38183
+ const path = resolve12(folder, entry.name);
38184
+ const details = await stat9(path);
38185
+ const content = await readFile10(path, "utf8").catch(() => "");
37947
38186
  const title = markdownMetadata(content).title;
37948
38187
  return {
37949
38188
  activityAt: details.mtimeMs,
@@ -37956,10 +38195,10 @@ async function shallowMetadata(folder) {
37956
38195
  };
37957
38196
  }));
37958
38197
  const projects = visible.filter((entry) => entry.isDirectory()).map((entry) => ({
37959
- id: createHash5("sha1").update(resolve11(folder, entry.name)).digest("hex"),
38198
+ id: createHash5("sha1").update(resolve12(folder, entry.name)).digest("hex"),
37960
38199
  name: entry.name,
37961
38200
  relativePath: entry.name,
37962
- worktree: resolve11(folder, entry.name)
38201
+ worktree: resolve12(folder, entry.name)
37963
38202
  })).sort((left, right) => left.name.localeCompare(right.name));
37964
38203
  return {
37965
38204
  changes: { items: [] },
@@ -37985,8 +38224,8 @@ async function loadFolderData(folder) {
37985
38224
  items: projects.map((project) => ({
37986
38225
  id: project.id,
37987
38226
  worktree: project.worktree,
37988
- name: project.name ?? basename6(project.worktree),
37989
- relativePath: relative10(folder, project.worktree)
38227
+ name: project.name ?? basename7(project.worktree),
38228
+ relativePath: relative11(folder, project.worktree)
37990
38229
  }))
37991
38230
  }
37992
38231
  };
@@ -37994,10 +38233,10 @@ async function loadFolderData(folder) {
37994
38233
  async function notesFiles(folder, files, origin) {
37995
38234
  return {
37996
38235
  items: await Promise.all(files.map(async (file) => {
37997
- const path = file.path ?? (file.relativePath ? resolve11(folder, file.relativePath) : undefined);
38236
+ const path = file.path ?? (file.relativePath ? resolve12(folder, file.relativePath) : undefined);
37998
38237
  if (!path)
37999
38238
  return origin ? { ...file, folder: origin } : file;
38000
- const content = [".markdown", ".md"].includes(extname6(path).toLowerCase()) ? await readFile9(path, "utf8").catch(() => "") : "";
38239
+ const content = [".markdown", ".md"].includes(extname6(path).toLowerCase()) ? await readFile10(path, "utf8").catch(() => "") : "";
38001
38240
  const title = content ? markdownMetadata(content).title : undefined;
38002
38241
  return {
38003
38242
  ...file,
@@ -38008,6 +38247,31 @@ async function notesFiles(folder, files, origin) {
38008
38247
  }))
38009
38248
  };
38010
38249
  }
38250
+ async function managedNotesFiles(directory) {
38251
+ const notes = await listManagedNotes(directory);
38252
+ return Promise.all(notes.map(async (note) => {
38253
+ const content = await readFile10(note.path, "utf8").catch(() => "");
38254
+ const title = content ? markdownMetadata(content).title : undefined;
38255
+ return {
38256
+ ...note,
38257
+ folder: directory,
38258
+ name: title ?? note.name,
38259
+ openHref: openPathHref(note.path)
38260
+ };
38261
+ }));
38262
+ }
38263
+ var canonicalPath = (path) => realpath7(path).catch(() => path);
38264
+ function insideFolder(path, root) {
38265
+ const local = relative11(root, path);
38266
+ return local === "" || !local.startsWith("..") && !isAbsolute7(local);
38267
+ }
38268
+ async function withoutManagedFiles(items, managedRoot) {
38269
+ if (!managedRoot)
38270
+ return items;
38271
+ const root = await canonicalPath(managedRoot);
38272
+ const outside = await Promise.all(items.map(async (item) => !item.path || !insideFolder(await canonicalPath(item.path), root)));
38273
+ return items.filter((_, index) => outside[index]);
38274
+ }
38011
38275
  async function localProjectSearchCache(cache) {
38012
38276
  if (cache && Date.now() - cache.loadedAt < projectSearchCacheMs)
38013
38277
  return cache;
@@ -38030,16 +38294,16 @@ async function localProjectSearchCache(cache) {
38030
38294
  function mediaTarget(folder, file, lockedTarget) {
38031
38295
  if (!file)
38032
38296
  return;
38033
- const rootReal = realpathSync2(resolve11(folder));
38034
- const path = resolve11(folder, file);
38297
+ const rootReal = realpathSync2(resolve12(folder));
38298
+ const path = resolve12(folder, file);
38035
38299
  let pathReal;
38036
38300
  try {
38037
38301
  pathReal = realpathSync2(path);
38038
38302
  } catch {
38039
38303
  return;
38040
38304
  }
38041
- const rel = relative10(rootReal, pathReal);
38042
- if (rel.startsWith("..") || isAbsolute6(rel))
38305
+ const rel = relative11(rootReal, pathReal);
38306
+ if (rel.startsWith("..") || isAbsolute7(rel))
38043
38307
  return;
38044
38308
  if (lockedTarget && pathReal !== lockedTarget)
38045
38309
  return;
@@ -38078,16 +38342,16 @@ function documentError(response) {
38078
38342
  function documentTarget(folder, file, lockedTarget) {
38079
38343
  if (!file)
38080
38344
  return;
38081
- const rootReal = realpathSync2(resolve11(folder));
38082
- const path = resolve11(folder, file);
38345
+ const rootReal = realpathSync2(resolve12(folder));
38346
+ const path = resolve12(folder, file);
38083
38347
  let pathReal;
38084
38348
  try {
38085
38349
  pathReal = realpathSync2(path);
38086
38350
  } catch {
38087
38351
  return;
38088
38352
  }
38089
- const rel = relative10(rootReal, pathReal);
38090
- if (rel.startsWith("..") || isAbsolute6(rel))
38353
+ const rel = relative11(rootReal, pathReal);
38354
+ if (rel.startsWith("..") || isAbsolute7(rel))
38091
38355
  return;
38092
38356
  if (lockedTarget && pathReal !== lockedTarget)
38093
38357
  return;
@@ -38165,6 +38429,18 @@ function createFolderApi({
38165
38429
  const linkedDiscovery = createLinkedFolderDiscovery(linkedFolderLoader, (folder) => discoveryChanged(folder));
38166
38430
  const linkedState = (folder) => lockedRoot || isMachineRoot(folder) ? { folders: [], status: "ready" } : linkedDiscovery.read(folder);
38167
38431
  const resolveLinkedFolders = (folder) => lockedRoot || isMachineRoot(folder) ? Promise.resolve([]) : linkedDiscovery.folders(folder);
38432
+ const managedNotesFolder = async (folder) => {
38433
+ if (lockedRoot || lockedTarget || isMachineRoot(folder))
38434
+ return;
38435
+ try {
38436
+ if (!(await readRepositoryNotesSettings()).enabled)
38437
+ return;
38438
+ const lookup = await lookupRepositoryNotes(folder);
38439
+ return lookup.status === "registered" ? lookup.notesDirectory : undefined;
38440
+ } catch {
38441
+ return;
38442
+ }
38443
+ };
38168
38444
  const favicon = faviconService();
38169
38445
  return {
38170
38446
  name: "kennel-folder-metadata",
@@ -38207,7 +38483,7 @@ function createFolderApi({
38207
38483
  if (!folder)
38208
38484
  return;
38209
38485
  server.emit({
38210
- data: { path: relative10(folder, path) },
38486
+ data: { path: relative11(folder, path) },
38211
38487
  event: "kennel:metadata-changed",
38212
38488
  type: "custom"
38213
38489
  });
@@ -38290,7 +38566,7 @@ function createFolderApi({
38290
38566
  "Content-Type": asset.mediaType,
38291
38567
  ETag: `"${hash}"`
38292
38568
  });
38293
- response.end(await readFile9(asset.path));
38569
+ response.end(await readFile10(asset.path));
38294
38570
  } catch (error) {
38295
38571
  response.writeHead(404, {
38296
38572
  "Content-Type": "text/plain; charset=utf-8"
@@ -38355,21 +38631,21 @@ function createFolderApi({
38355
38631
  }
38356
38632
  const folder = folderPath(url.searchParams.get("path"), root, lockedRoot);
38357
38633
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer.exe" : "xdg-open";
38358
- await new Promise((done, fail) => execFile4(command, [folder], (error) => error ? fail(error) : done()));
38634
+ await new Promise((done, fail) => execFile5(command, [folder], (error) => error ? fail(error) : done()));
38359
38635
  response.writeHead(204);
38360
38636
  response.end();
38361
38637
  return;
38362
38638
  }
38363
38639
  if (url.pathname === "/api/documents") {
38364
38640
  const folder = folderPath(url.searchParams.get("path"), root, lockedRoot);
38365
- const target = lockedTarget ? documentTarget(folder, relative10(folder, lockedTarget), lockedTarget) : undefined;
38641
+ const target = lockedTarget ? documentTarget(folder, relative11(folder, lockedTarget), lockedTarget) : undefined;
38366
38642
  const dataset = lockedTarget ? {
38367
38643
  root: folder,
38368
38644
  documents: target ? [
38369
38645
  {
38370
- path: relative10(folder, target.path),
38646
+ path: relative11(folder, target.path),
38371
38647
  kind: target.kind,
38372
- content: previewTextKind(target.kind) ? await readFile9(target.path, "utf8") : ""
38648
+ content: previewTextKind(target.kind) ? await readFile10(target.path, "utf8") : ""
38373
38649
  }
38374
38650
  ] : []
38375
38651
  } : await readFolder(folder);
@@ -38385,7 +38661,7 @@ function createFolderApi({
38385
38661
  documentError(response);
38386
38662
  return;
38387
38663
  }
38388
- const details = await stat8(target.path);
38664
+ const details = await stat9(target.path);
38389
38665
  if (!details.isFile()) {
38390
38666
  documentError(response);
38391
38667
  return;
@@ -38397,16 +38673,16 @@ function createFolderApi({
38397
38673
  return;
38398
38674
  }
38399
38675
  watch(folder);
38400
- const content = previewTextKind(target.kind) ? await readFile9(target.path, "utf8") : "";
38676
+ const content = previewTextKind(target.kind) ? await readFile10(target.path, "utf8") : "";
38401
38677
  sendContract(response, url, {
38402
38678
  content,
38403
38679
  kind: target.kind,
38404
- path: relative10(target.root, target.path),
38680
+ path: relative11(target.root, target.path),
38405
38681
  root: folder,
38406
38682
  ...previewTextKind(target.kind) ? {} : {
38407
38683
  rawUrl: `/api/raw?${new URLSearchParams({
38408
38684
  path: folder,
38409
- file: relative10(target.root, target.path)
38685
+ file: relative11(target.root, target.path)
38410
38686
  })}`
38411
38687
  }
38412
38688
  }, {
@@ -38426,7 +38702,7 @@ function createFolderApi({
38426
38702
  documentError(response);
38427
38703
  return;
38428
38704
  }
38429
- const details = await stat8(target.path);
38705
+ const details = await stat9(target.path);
38430
38706
  if (!details.isFile()) {
38431
38707
  documentError(response);
38432
38708
  return;
@@ -38447,10 +38723,10 @@ function createFolderApi({
38447
38723
  ETag: etag,
38448
38724
  "X-Content-Type-Options": "nosniff",
38449
38725
  ...download ? {
38450
- "Content-Disposition": `attachment; filename="${basename6(target.path)}"`
38726
+ "Content-Disposition": `attachment; filename="${basename7(target.path)}"`
38451
38727
  } : {}
38452
38728
  });
38453
- response.end(await readFile9(target.path));
38729
+ response.end(await readFile10(target.path));
38454
38730
  } catch (error) {
38455
38731
  documentError(response);
38456
38732
  }
@@ -38464,7 +38740,7 @@ function createFolderApi({
38464
38740
  documentError(response);
38465
38741
  return;
38466
38742
  }
38467
- const details = await stat8(target.path);
38743
+ const details = await stat9(target.path);
38468
38744
  if (!details.isFile()) {
38469
38745
  documentError(response);
38470
38746
  return;
@@ -38476,7 +38752,7 @@ function createFolderApi({
38476
38752
  return;
38477
38753
  }
38478
38754
  watch(folder);
38479
- const data = await readFile9(target.path);
38755
+ const data = await readFile10(target.path);
38480
38756
  const baseHeaders = {
38481
38757
  "Accept-Ranges": "bytes",
38482
38758
  "Cache-Control": "private, max-age=0, must-revalidate",
@@ -38530,9 +38806,13 @@ function createFolderApi({
38530
38806
  if (!lockedRoot && !isMachineRoot(folder) && request.headers["x-kennel-retry-linked"] === "1")
38531
38807
  linkedDiscovery.retry(folder);
38532
38808
  const discovery = linkedState(folder);
38809
+ const managed = await managedNotesFolder(folder);
38810
+ if (managed)
38811
+ watch(managed);
38533
38812
  const result = await plugin.handle({
38534
38813
  folder,
38535
- linkedFolders: discovery.folders
38814
+ linkedFolders: discovery.folders,
38815
+ ...managed ? { managedFolders: [managed] } : {}
38536
38816
  }, subpath);
38537
38817
  if (result.kind === "unavailable") {
38538
38818
  response.writeHead(200, {
@@ -38635,7 +38915,7 @@ function createFolderApi({
38635
38915
  workspace.breadcrumbs = await workspaceBreadcrumbIcons(workspace.breadcrumbs ?? [], assetFiles);
38636
38916
  const files = [
38637
38917
  workspace.configPath,
38638
- resolve11(workspace.root, "raggle.json")
38918
+ resolve12(workspace.root, "raggle.json")
38639
38919
  ].filter((path) => Boolean(path));
38640
38920
  for (const path of files)
38641
38921
  contexts.add(path);
@@ -38659,7 +38939,14 @@ function createFolderApi({
38659
38939
  const machine = isMachineRoot(folder);
38660
38940
  if (part === "notes") {
38661
38941
  const scope = url.searchParams.get("notesScope");
38942
+ const managed = await managedNotesFolder(folder);
38662
38943
  const localFiles = scope === "linked" ? Promise.resolve({ items: [] }) : (machine ? shallowMetadata(folder).then((data) => data.files.items) : listLocalMarkdownFiles({ folder, limit: 200 })).then((files) => notesFiles(folder, files));
38944
+ const managedFiles = async () => {
38945
+ if (scope === "linked" || !managed)
38946
+ return [];
38947
+ watch(managed);
38948
+ return managedNotesFiles(managed);
38949
+ };
38663
38950
  const linkedFiles = async () => {
38664
38951
  if (scope === "local" || machine || lockedRoot)
38665
38952
  return [];
@@ -38670,20 +38957,25 @@ function createFolderApi({
38670
38957
  throw new Error("Linked notes discovery failed. Retry to try again.");
38671
38958
  return Promise.all(linkedFolders.map(async (linkedFolder) => {
38672
38959
  watch(linkedFolder);
38673
- return notesFiles(linkedFolder, await listLocalMarkdownFiles({
38960
+ const group = await notesFiles(linkedFolder, await listLocalMarkdownFiles({
38674
38961
  folder: linkedFolder,
38675
38962
  limit: 200
38676
38963
  }), linkedFolder);
38964
+ return {
38965
+ items: await withoutManagedFiles(group.items, managed)
38966
+ };
38677
38967
  }));
38678
38968
  };
38679
- const [files, linked] = await Promise.all([
38969
+ const [files, managedItems, linked] = await Promise.all([
38680
38970
  localFiles,
38971
+ managedFiles(),
38681
38972
  linkedFiles()
38682
38973
  ]);
38683
38974
  sendContract(response, url, {
38684
38975
  files: {
38685
38976
  items: [
38686
38977
  ...files.items,
38978
+ ...managedItems,
38687
38979
  ...linked.flatMap((group) => group.items)
38688
38980
  ]
38689
38981
  },
@@ -38782,26 +39074,26 @@ var contentTypes = {
38782
39074
  ".ttf": "font/ttf"
38783
39075
  };
38784
39076
  async function sendFile(request, response, directory, pathname, fallback) {
38785
- const root = await realpath5(directory);
39077
+ const root = await realpath8(directory);
38786
39078
  const inside = (path) => {
38787
- const local = relative11(root, path);
38788
- return local !== ".." && !local.startsWith("../") && !isAbsolute7(local);
39079
+ const local = relative12(root, path);
39080
+ return local !== ".." && !local.startsWith("../") && !isAbsolute8(local);
38789
39081
  };
38790
- let target = resolve12(root, `.${decodeURIComponent(pathname)}`);
39082
+ let target = resolve13(root, `.${decodeURIComponent(pathname)}`);
38791
39083
  if (!inside(target)) {
38792
39084
  response.writeHead(403);
38793
39085
  response.end();
38794
39086
  return;
38795
39087
  }
38796
- if (!(await stat9(target).catch(() => null))?.isFile()) {
39088
+ if (!(await stat10(target).catch(() => null))?.isFile()) {
38797
39089
  if (!fallback) {
38798
39090
  response.writeHead(404);
38799
39091
  response.end();
38800
39092
  return;
38801
39093
  }
38802
- target = resolve12(root, fallback);
39094
+ target = resolve13(root, fallback);
38803
39095
  }
38804
- target = await realpath5(target);
39096
+ target = await realpath8(target);
38805
39097
  if (!inside(target)) {
38806
39098
  response.writeHead(403);
38807
39099
  response.end();
@@ -38811,7 +39103,7 @@ async function sendFile(request, response, directory, pathname, fallback) {
38811
39103
  "Content-Type": contentTypes[extname7(target)] ?? "application/octet-stream",
38812
39104
  "X-Content-Type-Options": "nosniff"
38813
39105
  });
38814
- response.end(request.method === "HEAD" ? undefined : await readFile10(target));
39106
+ response.end(request.method === "HEAD" ? undefined : await readFile11(target));
38815
39107
  }
38816
39108
  function createKennelApi(options) {
38817
39109
  const remote = options.remoteAccess || !isLoopbackServerHost(options.host);