From 0e2d26304e80c704c296c98f8eecec1559482f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?m=C3=BCde?= Date: Sun, 17 May 2026 23:32:37 +0200 Subject: [PATCH] path linkify: require last segment to look like name.ext (skips dir refs) --- hive-c0re/assets/app.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hive-c0re/assets/app.js b/hive-c0re/assets/app.js index 18f9c4d..3364cee 100644 --- a/hive-c0re/assets/app.js +++ b/hive-c0re/assets/app.js @@ -48,13 +48,18 @@ // perspective (we'd need to know which agent the message is about // to translate it). Prefer `/agents//state/...` in agent // outputs and the link will resolve. - // Each branch insists the tail is at least one segment AND the - // last character is `[\w.-]` (not `/`), so trailing-slash paths - // — i.e. plain directories — don't linkify. The /api/state-file - // endpoint also refuses non-files; this is the front-end peer so - // the operator doesn't see a dead link they'll just get an error - // from on click. - const PATH_RE = /(\/var\/lib\/hyperhive\/agents\/[\w.-]+\/state\/(?:[\w.-]+\/)*[\w.-]+|\/var\/lib\/hyperhive\/shared\/(?:[\w.-]+\/)*[\w.-]+|\/agents\/[\w.-]+\/state\/(?:[\w.-]+\/)*[\w.-]+|\/shared\/(?:[\w.-]+\/)*[\w.-]+)/g; + // Each branch insists the final segment looks like a filename: + // at least one non-dot char, a literal dot, then an extension + // (`[\w-]+\.[\w.-]+`). That catches the common case (`notes.md`, + // `2026-01.log`, `foo.bar.baz`) while skipping bare directory + // names like `/agents/foo/state/notes` whether or not they carry + // a trailing slash. Misses extensionless files (`README`, + // `Makefile`) — accepted trade-off; the /api/state-file endpoint + // still serves them if the operator types the path manually. + // The endpoint also refuses non-files at the server level; this + // is the front-end peer so the operator doesn't see a dead link + // they'll just get an error from on click. + const PATH_RE = /(\/var\/lib\/hyperhive\/agents\/[\w.-]+\/state\/(?:[\w.-]+\/)*[\w-]+\.[\w.-]+|\/var\/lib\/hyperhive\/shared\/(?:[\w.-]+\/)*[\w-]+\.[\w.-]+|\/agents\/[\w.-]+\/state\/(?:[\w.-]+\/)*[\w-]+\.[\w.-]+|\/shared\/(?:[\w.-]+\/)*[\w-]+\.[\w.-]+)/g; async function fetchStateFile(path) { const resp = await fetch('/api/state-file?path=' + encodeURIComponent(path)); const text = await resp.text();