kennel 0.2.36 → 0.2.38
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/cli/usage.js +1 -1
- package/dist/core/runtime.js +3 -1
- package/dist/llm/worker.js +3 -1
- package/dist/notes/command.js +3 -1
- package/dist/package/preview.d.ts +1 -0
- package/dist/package/preview.js +64 -18
- package/dist/site/hot-viewer.d.ts +1 -1
- package/dist/site/hot-viewer.js +34 -3
- package/dist/site/terminal.js +10 -6
- package/package.json +2 -2
- package/schemas/config.schema.json +9 -0
- package/web/assets/{abnfDiagram-VRR7QNED-D-wDEOuY.js → abnfDiagram-VRR7QNED-C6_-_jqE.js} +1 -1
- package/web/assets/{arc-DLDOZUl0.js → arc-DaQ6OIoR.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-DNrOiRRh.js → architectureDiagram-ZJ3FMSHR-DTojidQe.js} +1 -1
- package/web/assets/ask-tray-KUTWZ4MV-DvL75aHD.js +24 -0
- package/web/assets/{blockDiagram-677ZJIJ3-Cw-GxdXn.js → blockDiagram-677ZJIJ3-yOJUN_m5.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-CISkVgyv.js → c4Diagram-LMCZKHZV-UjcT-m1T.js} +1 -1
- package/web/assets/channel-C3SEyQYu.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-CoYAPY2m.js → chunk-2Q5K7J3B-CcZzk5ML.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-zcpFrZg7.js → chunk-32BRIVSS-BTSujxFN.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-BlQZuGxc.js → chunk-5VM5RSS4-DPlR3gQv.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-CT1XD_WJ.js → chunk-EX3LRPZG-BRBFgIHS.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-C2-AGbdV.js → chunk-JWPE2WC7-DtbIaf1u.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-EpHbGsdi.js → chunk-MOJQB5TN-9jU0GI-j.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-BYbxuF2f.js → chunk-RYQCIY6F-BixiZOVp.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-DSAAV6N4.js → chunk-V7JOEXUC-BZ2H8ogE.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-ayX5qMZr.js → chunk-VR4S4FIN-BL10DAex.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-45ncruvJ.js → chunk-XXDRQBXY-DcppYjo6.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-BdAXLPse.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-BdAXLPse.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-Bx9S1JXJ.js → cose-bilkent-JH36ORCC-Cgvqo5Vf.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-snxI94-K.js → cynefin-VYW2F7L2-BQ7wt45I.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-D8s6RSSq.js → cynefinDiagram-TSTJHNR4-kkFdZ7zi.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-CqoML5Ji.js → dagre-VKFMJZFB-DEpIkW_K.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-BScsOBc2.js → diagram-FQU43EPY-BVQC0UWP.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-CSXWBABs.js → diagram-G47NLZAW-Cxuq2dO3.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-BrHvegaG.js → diagram-NH7WQ7WH-F6Qesucv.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-DB6G71aV.js → diagram-OA4YK3LP-hepvtqAE.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-Cc5KaH88.js → diagram-WEI45ONY-CfQte2ei.js} +1 -1
- package/web/assets/{ebnfDiagram-CCIWWBDH-Cm9dKWpi.js → ebnfDiagram-CCIWWBDH-BqOulZys.js} +1 -1
- package/web/assets/{entity-search-page-YP4SPMBC-1HMsmBph.js → entity-search-page-YP4SPMBC-BKH9R5nO.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-D9o4-3z_.js → erDiagram-Q63AITRT-BxCO7pVV.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-DlSlSN8b.js → flowDiagram-23GEKE2U-H0w6mn4S.js} +1 -1
- package/web/assets/{ganttDiagram-NO4QXBWP-k01Z0ICp.js → ganttDiagram-NO4QXBWP-1Mvoz0hd.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-Cjp_loRm.js → gitGraphDiagram-IHSO6WYX-B_Zhhqk4.js} +1 -1
- package/web/assets/index-QCajCjwA.css +1 -0
- package/web/assets/index-pXpgbx7D.js +492 -0
- package/web/assets/{infoDiagram-FWYZ7A6U-CIvVYqYA.js → infoDiagram-FWYZ7A6U-BunMdCGy.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-4-sr6Mvi.js → ishikawaDiagram-FXEZZL3T-2tdEVjqs.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BP9GqWiL.js → journeyDiagram-5HDEW3XC-DO-J_T2C.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-Dc7cR6bt.js → kanban-definition-HUTT4EX6-CnoFxqoa.js} +1 -1
- package/web/assets/{linear-CUy1jgIb.js → linear-Ceg6io_2.js} +1 -1
- package/web/assets/{linked-session-header-S55EVSN7-3bK4qoiP.js → linked-session-header-S55EVSN7-P_bjsJir.js} +1 -1
- package/web/assets/{mermaid.core-B-0mplWE.js → mermaid.core-X1Uu4bc2.js} +4 -4
- package/web/assets/{mindmap-definition-LN4V7U3C-B4hH_ssZ.js → mindmap-definition-LN4V7U3C-CVzPnppR.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-DcASm1rV.js → pegDiagram-2B236MQR-DAINu_s_.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-CcH8-R__.js → pieDiagram-ENE6RG2P-B4_nXDis.js} +1 -1
- package/web/assets/{plugin-host-modules-CI2CeYDa.js → plugin-host-modules-LhPofIZf.js} +1 -1
- package/web/assets/{project-search-page-TZG7AZBQ-DFlU6M8G.js → project-search-page-TZG7AZBQ-Bm3ftrZ5.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-BQX_WoM7.js → quadrantDiagram-ABIIQ3AL-DZYBmnrH.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-C8_ZmZc9.js → railroadDiagram-RFXS5EU6-Bz84eqb8.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-BqELfMX7.js → requirementDiagram-TGXJPOKE-64zNrehW.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-Bu5aTMvb.js → sankeyDiagram-HTMAVEWB-Dl_wrA2h.js} +1 -1
- package/web/assets/{selection-popup-RZDT6KZK-D2DH3zcN.js → selection-popup-ABYH3A27-i0uWpyQp.js} +1 -1
- package/web/assets/{sequenceDiagram-DBY2YBRQ-Dbf_tezm.js → sequenceDiagram-DBY2YBRQ-QiicN0_i.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-DPVSvKgC.js → sizeCapture-X5ZJPWSS-UYznseYi.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-DcJtmh_P.js → stateDiagram-2N3HPSRC-BiAHkZb3.js} +1 -1
- package/web/assets/{stateDiagram-v2-6OUMAXLB-CFhOPpxK.js → stateDiagram-v2-6OUMAXLB-DgSGWnq5.js} +1 -1
- package/web/assets/{swimlanes-5IMT3BWC-u0y2iSGe.js → swimlanes-5IMT3BWC-Ccl_OPSL.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-B7Mm_-w4.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-DVzApElo.js → timeline-definition-FHXFAJF6-BfEDp1Tz.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-DKmwS868.js → vennDiagram-L72KCM5P-DipqKATv.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-BAC_uhn9.js → wardleyDiagram-EHGQE667-BRwun2eQ.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-Dx9RDeB9.js → xychartDiagram-FW5EYKEG-48H2tQjU.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/ask-tray-5HAI5ZUG-Bmz1vige.js +0 -23
- package/web/assets/channel-D7IslKH6.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-8egtQzGs.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-8egtQzGs.js +0 -1
- package/web/assets/index-Dt8OzQCe.css +0 -1
- package/web/assets/index-kEVTlQlX.js +0 -451
- package/web/assets/project-search-dialog-OJIM5FZU-CN-CXk-C.js +0 -43
- package/web/assets/swimlanesDiagram-G3AALYLV-C6xJvzKK.js +0 -8
package/dist/cli/usage.js
CHANGED
|
@@ -17,7 +17,7 @@ export function usage() {
|
|
|
17
17
|
kennel notes bind <uuid> [folder] [--json] [--remote <name>] [--replace] [--no-alias]
|
|
18
18
|
kennel notes new-identity [folder] [--json] [--remote <name>]
|
|
19
19
|
kennel serve [folder] [--host <host>] [--port <port>] [--lan|--tailscale]
|
|
20
|
-
kennel share|display [folder] [--lan|--tailscale] [--port <port>] [--dry-run]
|
|
20
|
+
kennel share|display [folder] [--lan|--tailscale] [--password] [--port <port>] [--dry-run]
|
|
21
21
|
kennel dev [path] [--config <json-file>] [--port <port>] [--script <script>] [--dry-run] [-- <args...>]
|
|
22
22
|
kennel extension install
|
|
23
23
|
kennel mcp generate [path] [--config <json-file>] [--data-only|--function-only]
|
package/dist/core/runtime.js
CHANGED
|
@@ -36718,7 +36718,9 @@ class RepositoryNotesError extends Error {
|
|
|
36718
36718
|
}
|
|
36719
36719
|
function kennelConfigHome() {
|
|
36720
36720
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
36721
|
-
|
|
36721
|
+
if (xdg)
|
|
36722
|
+
return xdg;
|
|
36723
|
+
return join2(homedir2(), ".config");
|
|
36722
36724
|
}
|
|
36723
36725
|
function kennelConfigFile() {
|
|
36724
36726
|
return join2(kennelConfigHome(), "kennel", "config.json");
|
package/dist/llm/worker.js
CHANGED
|
@@ -790,7 +790,9 @@ class RepositoryNotesError extends Error {
|
|
|
790
790
|
}
|
|
791
791
|
function kennelConfigHome() {
|
|
792
792
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
793
|
-
|
|
793
|
+
if (xdg)
|
|
794
|
+
return xdg;
|
|
795
|
+
return join3(homedir(), ".config");
|
|
794
796
|
}
|
|
795
797
|
function kennelConfigFile() {
|
|
796
798
|
return join3(kennelConfigHome(), "kennel", "config.json");
|
package/dist/notes/command.js
CHANGED
|
@@ -33,7 +33,9 @@ class RepositoryNotesError extends Error {
|
|
|
33
33
|
}
|
|
34
34
|
function kennelConfigHome() {
|
|
35
35
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
36
|
-
|
|
36
|
+
if (xdg)
|
|
37
|
+
return xdg;
|
|
38
|
+
return join(homedir(), ".config");
|
|
37
39
|
}
|
|
38
40
|
function kennelConfigFile() {
|
|
39
41
|
return join(kennelConfigHome(), "kennel", "config.json");
|
package/dist/package/preview.js
CHANGED
|
@@ -296,11 +296,11 @@ function previewTerminal(url, target, startShare) {
|
|
|
296
296
|
].join(`
|
|
297
297
|
`));
|
|
298
298
|
};
|
|
299
|
-
const shareFolder = async () => {
|
|
299
|
+
const shareFolder = async (password = false) => {
|
|
300
300
|
status = "Preparing a private Tailscale link…";
|
|
301
301
|
render();
|
|
302
302
|
try {
|
|
303
|
-
share ??= startShare();
|
|
303
|
+
share ??= startShare(password);
|
|
304
304
|
let active;
|
|
305
305
|
try {
|
|
306
306
|
active = await share;
|
|
@@ -310,11 +310,14 @@ function previewTerminal(url, target, startShare) {
|
|
|
310
310
|
}
|
|
311
311
|
if (finished)
|
|
312
312
|
return;
|
|
313
|
-
status = `Tailscale link: ${active.url}
|
|
313
|
+
status = active.password ? `Tailscale link: ${active.url}
|
|
314
314
|
Username: ${active.username} · Password: ${active.password}
|
|
315
315
|
Password required. Send the password separately.
|
|
316
316
|
Connect Tailscale on your phone to the same tailnet.
|
|
317
317
|
Trusted HTTPS; no certificate installation required.
|
|
318
|
+
Keep this command running. Ctrl+C stops sharing.` : `Tailscale link: ${active.url}
|
|
319
|
+
Connect Tailscale on your phone to the same tailnet.
|
|
320
|
+
Trusted HTTPS; no password required on the tailnet.
|
|
318
321
|
Keep this command running. Ctrl+C stops sharing.`;
|
|
319
322
|
render();
|
|
320
323
|
try {
|
|
@@ -357,7 +360,8 @@ function previewTerminal(url, target, startShare) {
|
|
|
357
360
|
openPreview(url);
|
|
358
361
|
status = "Browser open requested.";
|
|
359
362
|
} },
|
|
360
|
-
{ label: "Share to another device", shortcut: "s", run: shareFolder },
|
|
363
|
+
{ label: "Share to another device", shortcut: "s", run: () => shareFolder(false) },
|
|
364
|
+
{ label: "Share link with password", shortcut: "p", run: () => shareFolder(true) },
|
|
361
365
|
{ label: "Exit", shortcut: "q", run: close }
|
|
362
366
|
];
|
|
363
367
|
const activate = async () => {
|
|
@@ -38322,7 +38326,9 @@ import { basename as basename5, dirname as dirname6, join as join2, relative as
|
|
|
38322
38326
|
import { promisify } from "node:util";
|
|
38323
38327
|
function kennelConfigHome() {
|
|
38324
38328
|
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
38325
|
-
|
|
38329
|
+
if (xdg)
|
|
38330
|
+
return xdg;
|
|
38331
|
+
return join2(homedir2(), ".config");
|
|
38326
38332
|
}
|
|
38327
38333
|
function kennelConfigFile() {
|
|
38328
38334
|
return join2(kennelConfigHome(), "kennel", "config.json");
|
|
@@ -40843,6 +40849,10 @@ function splitViewerArgs(input) {
|
|
|
40843
40849
|
options.open = true;
|
|
40844
40850
|
continue;
|
|
40845
40851
|
}
|
|
40852
|
+
if (arg === "--password") {
|
|
40853
|
+
options.password = true;
|
|
40854
|
+
continue;
|
|
40855
|
+
}
|
|
40846
40856
|
if (arg === "--no-open") {
|
|
40847
40857
|
options.open = false;
|
|
40848
40858
|
continue;
|
|
@@ -41197,7 +41207,9 @@ var init_tailscale_share = __esm(() => {
|
|
|
41197
41207
|
});
|
|
41198
41208
|
|
|
41199
41209
|
// packages/preview/src/share.ts
|
|
41200
|
-
import { dirname as dirname13, resolve as resolve16 } from "node:path";
|
|
41210
|
+
import { dirname as dirname13, resolve as resolve16, join as join6 } from "node:path";
|
|
41211
|
+
import { homedir as homedir5 } from "node:os";
|
|
41212
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
41201
41213
|
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
41202
41214
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
41203
41215
|
function splitShareArgs(input) {
|
|
@@ -41206,7 +41218,8 @@ function splitShareArgs(input) {
|
|
|
41206
41218
|
lan: false,
|
|
41207
41219
|
tailscale: false,
|
|
41208
41220
|
port: undefined,
|
|
41209
|
-
dryRun: false
|
|
41221
|
+
dryRun: false,
|
|
41222
|
+
password: false
|
|
41210
41223
|
};
|
|
41211
41224
|
let folder;
|
|
41212
41225
|
for (let index = 0;index < input.length; index += 1) {
|
|
@@ -41215,6 +41228,10 @@ function splitShareArgs(input) {
|
|
|
41215
41228
|
options.dryRun = true;
|
|
41216
41229
|
continue;
|
|
41217
41230
|
}
|
|
41231
|
+
if (arg === "--password") {
|
|
41232
|
+
options.password = true;
|
|
41233
|
+
continue;
|
|
41234
|
+
}
|
|
41218
41235
|
if (arg === "--lan") {
|
|
41219
41236
|
options.lan = true;
|
|
41220
41237
|
continue;
|
|
@@ -41270,6 +41287,13 @@ async function runningViewerRoot(port = plainViewerPort) {
|
|
|
41270
41287
|
}
|
|
41271
41288
|
async function startPreviewShare(target) {
|
|
41272
41289
|
const root = realpathSync4(target.root);
|
|
41290
|
+
const configPath = join6(process.env.XDG_CONFIG_HOME?.trim() || join6(homedir5(), ".config"), "kennel", "config.json");
|
|
41291
|
+
let configuredPassword = false;
|
|
41292
|
+
try {
|
|
41293
|
+
const config = JSON.parse(readFileSync2(configPath, "utf8"));
|
|
41294
|
+
configuredPassword = config.linkSharing?.password === true;
|
|
41295
|
+
} catch {}
|
|
41296
|
+
const password = target.password ?? configuredPassword;
|
|
41273
41297
|
const web = resolve16(dirname13(fileURLToPath4(import.meta.url)), "../../web");
|
|
41274
41298
|
if (!existsSync7(resolve16(web, "index.html"))) {
|
|
41275
41299
|
throw new Error("Kennel web app not found. Run the CLI build first.");
|
|
@@ -41287,37 +41311,58 @@ async function startPreviewShare(target) {
|
|
|
41287
41311
|
});
|
|
41288
41312
|
let shared;
|
|
41289
41313
|
let proxy;
|
|
41314
|
+
let localClose;
|
|
41290
41315
|
const close = async () => {
|
|
41291
41316
|
try {
|
|
41292
41317
|
await proxy?.close();
|
|
41293
41318
|
} finally {
|
|
41294
41319
|
try {
|
|
41295
|
-
await
|
|
41320
|
+
await localClose?.();
|
|
41296
41321
|
} finally {
|
|
41297
41322
|
await api.close();
|
|
41298
41323
|
}
|
|
41299
41324
|
}
|
|
41300
41325
|
};
|
|
41301
41326
|
try {
|
|
41302
|
-
|
|
41327
|
+
const handler = (request, response) => {
|
|
41303
41328
|
api.handle(request, response);
|
|
41304
|
-
}
|
|
41305
|
-
|
|
41306
|
-
|
|
41329
|
+
};
|
|
41330
|
+
const local = password ? await startProtectedShare(handler) : await (async () => {
|
|
41331
|
+
const { createServer } = await import("node:http");
|
|
41332
|
+
const server = createServer(handler);
|
|
41333
|
+
await new Promise((resolve, reject) => {
|
|
41334
|
+
server.once("error", reject);
|
|
41335
|
+
server.listen(0, "127.0.0.1", () => resolve());
|
|
41336
|
+
});
|
|
41337
|
+
const address = server.address();
|
|
41338
|
+
if (!address || typeof address === "string")
|
|
41339
|
+
throw new Error("No share server address");
|
|
41340
|
+
return { port: address.port, close: async () => {
|
|
41341
|
+
await new Promise((resolve) => {
|
|
41342
|
+
server.close(() => resolve());
|
|
41343
|
+
server.closeAllConnections();
|
|
41344
|
+
});
|
|
41345
|
+
} };
|
|
41346
|
+
})();
|
|
41347
|
+
localClose = local.close;
|
|
41348
|
+
shared = password ? local : { port: local.port, close: local.close };
|
|
41349
|
+
proxy = await startTailscaleProxy(host, local.port);
|
|
41350
|
+
const path = new URL(popUrl(host, String(local.port), {
|
|
41307
41351
|
dryRun: false,
|
|
41308
41352
|
host: "127.0.0.1",
|
|
41309
41353
|
hot: false,
|
|
41310
41354
|
lan: false,
|
|
41311
41355
|
open: false,
|
|
41312
41356
|
root,
|
|
41313
|
-
port: String(
|
|
41357
|
+
port: String(local.port),
|
|
41314
41358
|
tailscale: false,
|
|
41315
41359
|
watch: false,
|
|
41360
|
+
password: false,
|
|
41316
41361
|
target: target.target
|
|
41317
41362
|
})).pathname;
|
|
41318
41363
|
const url = new URL(path, proxy.origin);
|
|
41319
|
-
const response = await fetch(
|
|
41320
|
-
headers: { Authorization: shared.authorization },
|
|
41364
|
+
const response = await fetch(`http://127.0.0.1:${shared.port}/api/health`, {
|
|
41365
|
+
...shared.authorization ? { headers: { Authorization: shared.authorization } } : {},
|
|
41321
41366
|
signal: AbortSignal.timeout(30000)
|
|
41322
41367
|
});
|
|
41323
41368
|
if (!response.ok)
|
|
@@ -41326,7 +41371,7 @@ async function startPreviewShare(target) {
|
|
|
41326
41371
|
if (health.viewer !== "kennel-core" || health.root !== root) {
|
|
41327
41372
|
throw new Error("The Tailscale share is not serving the selected folder");
|
|
41328
41373
|
}
|
|
41329
|
-
return { url: url.href, username: shared
|
|
41374
|
+
return { url: url.href, username: shared?.username, password: shared?.password, close };
|
|
41330
41375
|
} catch (error) {
|
|
41331
41376
|
await close();
|
|
41332
41377
|
throw error;
|
|
@@ -41341,14 +41386,15 @@ async function share(input) {
|
|
|
41341
41386
|
console.log(`Sharing ${folder}`);
|
|
41342
41387
|
if (options.dryRun) {
|
|
41343
41388
|
const port = options.port ?? "5181";
|
|
41344
|
-
const url = options.tailscale ? `https://<tailnet-name>.ts.net/folder/${Buffer.from(folder).toString("base64url")}/notes` : popUrl(lanHost2(), port, { dryRun: true, host: "0.0.0.0", hot: false, lan: true, open: false, root: folder, port, tailscale: false, watch: false });
|
|
41389
|
+
const url = options.tailscale ? `https://<tailnet-name>.ts.net/folder/${Buffer.from(folder).toString("base64url")}/notes` : popUrl(lanHost2(), port, { dryRun: true, host: "0.0.0.0", hot: false, lan: true, open: false, root: folder, port, tailscale: false, watch: false, password: false });
|
|
41345
41390
|
console.log(url);
|
|
41346
|
-
console.log(`kennel serve --static ${options.tailscale ? "--tailscale" : "--lan"}${options.port ? ` --port ${options.port}` : ""} ${folder}`);
|
|
41391
|
+
console.log(`kennel serve --static ${options.tailscale ? "--tailscale" : "--lan"}${options.password ? " --password" : ""}${options.port ? ` --port ${options.port}` : ""} ${folder}`);
|
|
41347
41392
|
return;
|
|
41348
41393
|
}
|
|
41349
41394
|
await viewer([
|
|
41350
41395
|
"--static",
|
|
41351
41396
|
options.tailscale ? "--tailscale" : "--lan",
|
|
41397
|
+
...options.password ? ["--password"] : [],
|
|
41352
41398
|
...options.port ? ["--port", options.port] : [],
|
|
41353
41399
|
folder
|
|
41354
41400
|
]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type ViewerOptions } from './viewer.js';
|
|
2
2
|
/** The hot viewer runs Vite from a Kennel source checkout; npm installs have none. */
|
|
3
3
|
export declare function hotViewerAvailable(): boolean;
|
|
4
|
-
export declare function hotViewer(options: ViewerOptions): Promise<void>;
|
|
4
|
+
export declare function hotViewer(options: ViewerOptions, restarting?: boolean): Promise<void>;
|
package/dist/site/hot-viewer.js
CHANGED
|
@@ -57,6 +57,10 @@ async function portOpen(host, port) {
|
|
|
57
57
|
socket.setTimeout(250, () => finish(false));
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
+
/** The dev script writes its PID here so the CLI can stop a stale viewer. */
|
|
61
|
+
function viewerPidFile(port) {
|
|
62
|
+
return resolve(tmpdir(), `kennel-hot-viewer-${port}.pid`);
|
|
63
|
+
}
|
|
60
64
|
function startupLock(host, port) {
|
|
61
65
|
const name = `${host}-${port}`.replaceAll(/[^a-zA-Z0-9.-]/g, '-');
|
|
62
66
|
return resolve(tmpdir(), `kennel-hot-viewer-${name}.lock`);
|
|
@@ -94,7 +98,29 @@ async function releaseLock(path, token) {
|
|
|
94
98
|
return;
|
|
95
99
|
await rm(path, { force: true, recursive: true });
|
|
96
100
|
}
|
|
97
|
-
|
|
101
|
+
/** Stop the viewer serving an older plugin set and wait for its port. */
|
|
102
|
+
async function restartStaleViewer(options) {
|
|
103
|
+
const pid = Number((await readFile(viewerPidFile(options.port), 'utf8').catch(() => '')).trim());
|
|
104
|
+
if (!Number.isInteger(pid) || pid <= 1)
|
|
105
|
+
return false;
|
|
106
|
+
try {
|
|
107
|
+
process.kill(pid, 'SIGTERM');
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
// ESRCH means the old viewer already stopped; continue and check the port.
|
|
111
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ESRCH'))
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
// Wait until the old viewer is fully gone so the fresh one can bind the port.
|
|
115
|
+
for (let attempt = 0; attempt < 40; attempt += 1) {
|
|
116
|
+
const status = await viewerStatus(`http://${options.host}:${options.port}`);
|
|
117
|
+
if (status === 'unavailable' && !await portOpen(options.host, options.port))
|
|
118
|
+
return true;
|
|
119
|
+
await new Promise((done) => setTimeout(done, 250));
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
export async function hotViewer(options, restarting = false) {
|
|
98
124
|
if (options.tailscale) {
|
|
99
125
|
throw new Error('The hot viewer is not available through Tailscale. Use kennel serve for remote access.');
|
|
100
126
|
}
|
|
@@ -145,8 +171,13 @@ export async function hotViewer(options) {
|
|
|
145
171
|
throw new Error(`Port ${options.port} runs the static Kennel viewer, not the hot viewer. ${restart}`);
|
|
146
172
|
}
|
|
147
173
|
if (running.kernelKey !== expectedKey) {
|
|
148
|
-
|
|
149
|
-
+ `but the installed plugins are ${expectedKey}. ${restart}
|
|
174
|
+
const stale = `The Kennel hot viewer on port ${options.port} serves plugin set ${running.kernelKey}, `
|
|
175
|
+
+ `but the installed plugins are ${expectedKey}. ${restart}`;
|
|
176
|
+
// Restart the stale viewer automatically so the command proceeds to the
|
|
177
|
+
// preview instead of asking the user to stop it by hand.
|
|
178
|
+
if (!restarting && await restartStaleViewer(options))
|
|
179
|
+
return hotViewer(options, true);
|
|
180
|
+
throw new Error(stale);
|
|
150
181
|
}
|
|
151
182
|
const terminal = previewTerminal(viewerUrl, options);
|
|
152
183
|
if (options.open)
|
package/dist/site/terminal.js
CHANGED
|
@@ -85,11 +85,11 @@ function previewTerminal(url, target, startShare) {
|
|
|
85
85
|
].join(`
|
|
86
86
|
`));
|
|
87
87
|
};
|
|
88
|
-
const shareFolder = async () => {
|
|
88
|
+
const shareFolder = async (password = false) => {
|
|
89
89
|
status = "Preparing a private Tailscale link…";
|
|
90
90
|
render();
|
|
91
91
|
try {
|
|
92
|
-
share ??= startShare();
|
|
92
|
+
share ??= startShare(password);
|
|
93
93
|
let active;
|
|
94
94
|
try {
|
|
95
95
|
active = await share;
|
|
@@ -99,11 +99,14 @@ function previewTerminal(url, target, startShare) {
|
|
|
99
99
|
}
|
|
100
100
|
if (finished)
|
|
101
101
|
return;
|
|
102
|
-
status = `Tailscale link: ${active.url}
|
|
102
|
+
status = active.password ? `Tailscale link: ${active.url}
|
|
103
103
|
Username: ${active.username} · Password: ${active.password}
|
|
104
104
|
Password required. Send the password separately.
|
|
105
105
|
Connect Tailscale on your phone to the same tailnet.
|
|
106
106
|
Trusted HTTPS; no certificate installation required.
|
|
107
|
+
Keep this command running. Ctrl+C stops sharing.` : `Tailscale link: ${active.url}
|
|
108
|
+
Connect Tailscale on your phone to the same tailnet.
|
|
109
|
+
Trusted HTTPS; no password required on the tailnet.
|
|
107
110
|
Keep this command running. Ctrl+C stops sharing.`;
|
|
108
111
|
render();
|
|
109
112
|
try {
|
|
@@ -146,7 +149,8 @@ function previewTerminal(url, target, startShare) {
|
|
|
146
149
|
openPreview(url);
|
|
147
150
|
status = "Browser open requested.";
|
|
148
151
|
} },
|
|
149
|
-
{ label: "Share to another device", shortcut: "s", run: shareFolder },
|
|
152
|
+
{ label: "Share to another device", shortcut: "s", run: () => shareFolder(false) },
|
|
153
|
+
{ label: "Share link with password", shortcut: "p", run: () => shareFolder(true) },
|
|
150
154
|
{ label: "Exit", shortcut: "q", run: close }
|
|
151
155
|
];
|
|
152
156
|
const activate = async () => {
|
|
@@ -207,9 +211,9 @@ function previewTerminal(url, target, startShare) {
|
|
|
207
211
|
|
|
208
212
|
// packages/cli/src/site/terminal.ts
|
|
209
213
|
function previewTerminal2(url, target) {
|
|
210
|
-
return previewTerminal(url, target, async () => {
|
|
214
|
+
return previewTerminal(url, target, async (password = false) => {
|
|
211
215
|
const { startPreviewShare } = await import(new URL("../package/preview.js", import.meta.url).href);
|
|
212
|
-
return startPreviewShare(target);
|
|
216
|
+
return startPreviewShare({ ...target, ...password ? { password: true } : {} });
|
|
213
217
|
});
|
|
214
218
|
}
|
|
215
219
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kennel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.38",
|
|
4
4
|
"description": "Open-source pop-up previews for AI output: markdown, HTML artifacts, email, images, code, tables, notes, and calendars, from the terminal or your agent session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"effect": "^3.19.7",
|
|
70
70
|
"esbuild": "^0.27.0",
|
|
71
71
|
"kennel-mcp": "https://registry.npmjs.org/%40raggle-ai%2fkennel-mcp/-/kennel-mcp-0.1.8.tgz",
|
|
72
|
-
"kennel-plugins": "0.1.
|
|
72
|
+
"kennel-plugins": "0.1.18",
|
|
73
73
|
"koffi": "^3.3.1",
|
|
74
74
|
"lucide-react": "^0.562.0",
|
|
75
75
|
"radix-ui": "^1.6.7",
|
|
@@ -21,6 +21,15 @@
|
|
|
21
21
|
"type": "array",
|
|
22
22
|
"items": { "$ref": "#/$defs/externalPlugin" }
|
|
23
23
|
},
|
|
24
|
+
"linkSharing": {
|
|
25
|
+
"description": "Preferred settings for sharing a viewer link.",
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": false,
|
|
28
|
+
"properties": {
|
|
29
|
+
"mode": { "type": "string", "enum": ["tailscale", "lan"] },
|
|
30
|
+
"password": { "type": "boolean" }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
24
33
|
"repositoryNotes": {
|
|
25
34
|
"description": "Opt-in Markdown notes per Git repository, stored in $XDG_CONFIG_HOME/kennel/repos/<uuid>/ and shown in that repository's Notes view. `kennel notes path` registers a repository only when enabled is true.",
|
|
26
35
|
"type": "object",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-9jU0GI-j.js";import{p as f}from"./chunk-JWPE2WC7-DtbIaf1u.js";import{_ as n,l as o}from"./mermaid.core-X1Uu4bc2.js";import{b as c,M as d}from"./cynefin-VYW2F7L2-BQ7wt45I.js";import"./index-pXpgbx7D.js";import"./react-DELVxLrX.js";import"./markdown-BP-54rPU.js";import"./tanstack-CRaSxWtK.js";var v=c().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),m=t?parseInt(t,10):0,l=s?parseInt(s,10):1/0;return{min:m,max:l}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new d(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},C={parser:R,db:a,renderer:u,styles:p};export{C as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as sn,ab as on,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as sn,ab as on,ac as fn}from"./mermaid.core-X1Uu4bc2.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|