From b0e8cd6514f27a69b9cc634a79ede32a488b3b00 Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Wed, 11 Mar 2026 03:09:41 +0800 Subject: [PATCH] v0.1.4 --- .../modules/dashboard/BotDashboardModule.tsx | 94 ++++++++++++------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/frontend/src/modules/dashboard/BotDashboardModule.tsx b/frontend/src/modules/dashboard/BotDashboardModule.tsx index f96249a..afa6a59 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.tsx +++ b/frontend/src/modules/dashboard/BotDashboardModule.tsx @@ -395,9 +395,10 @@ function workspaceFileAction(path: string): 'preview' | 'download' | 'unsupporte } const WORKSPACE_LINK_PREFIX = 'https://workspace.local/open/'; -const WORKSPACE_ABS_PATH_PATTERN = /\/root\/\.nanobot\/workspace\/[^\s<>"'`)\],,。!?;:]+/gi; +const WORKSPACE_ABS_PATH_PATTERN = + /\/root\/\.nanobot\/workspace\/[^\n\r<>"'`]+?\.(?:md|markdown|json|txt|log|csv|tsv|yaml|yml|toml|html|htm|pdf|png|jpg|jpeg|gif|webp|svg|mp3|wav|m4a|flac|ogg|opus|aac|amr|wma|mp4|mov|avi|mkv|webm|m4v|3gp|mpeg|mpg|ts|doc|docx|xls|xlsx|xlsm|ppt|pptx|odt|ods|odp|wps)\b/gi; const WORKSPACE_RELATIVE_PATH_PATTERN = - /(^|[\s(\[])(\/[^\s<>"'`)\]]+\.(?:md|markdown|json|txt|log|csv|tsv|yaml|yml|toml|html|htm|pdf|png|jpg|jpeg|gif|webp|svg))(?![A-Za-z0-9_./-])/gim; + /(^|[\s(\[])(\/[^\n\r<>"'`)\]]+?\.(?:md|markdown|json|txt|log|csv|tsv|yaml|yml|toml|html|htm|pdf|png|jpg|jpeg|gif|webp|svg|mp3|wav|m4a|flac|ogg|opus|aac|amr|wma|mp4|mov|avi|mkv|webm|m4v|3gp|mpeg|mpg|ts|doc|docx|xls|xlsx|xlsm|ppt|pptx|odt|ods|odp|wps))(?![A-Za-z0-9_./-])/gim; function buildWorkspaceLink(path: string) { return `${WORKSPACE_LINK_PREFIX}${encodeURIComponent(path)}`; @@ -415,28 +416,55 @@ function parseWorkspaceLink(href: string): string | null { } } -function decorateWorkspacePathsForMarkdown(text: string) { - const source = String(text || ''); - const normalizedExistingLinks = source.replace( - /\[(\/root\/\.nanobot\/workspace\/[^\]]+)\]\s*\n?\s*\((https:\/\/workspace\.local\/open\/[^)\r\n]*)\)/gi, - (_full, markdownPath: string) => { - const normalized = normalizeDashboardAttachmentPath(markdownPath); - if (!normalized) return String(_full || ''); - return `[${markdownPath}](${buildWorkspaceLink(normalized)})`; - }, - ); - const withAbsoluteLinks = normalizedExistingLinks.replace(WORKSPACE_ABS_PATH_PATTERN, (fullPath) => { +function decorateWorkspacePathsInPlainChunk(source: string): string { + if (!source) return source; + const protectedLinks: string[] = []; + const withProtectedAbsoluteLinks = source.replace(WORKSPACE_ABS_PATH_PATTERN, (fullPath) => { const normalized = normalizeDashboardAttachmentPath(fullPath); if (!normalized) return fullPath; - return `[${fullPath}](${buildWorkspaceLink(normalized)})`; + const token = `@@WS_PATH_LINK_${protectedLinks.length}@@`; + protectedLinks.push(`[${fullPath}](${buildWorkspaceLink(normalized)})`); + return token; }); - return withAbsoluteLinks.replace(WORKSPACE_RELATIVE_PATH_PATTERN, (full, prefix: string, rawPath: string) => { - const normalized = normalizeDashboardAttachmentPath(rawPath); - if (!normalized) return full; - return `${prefix}[${rawPath}](${buildWorkspaceLink(normalized)})`; + const withRelativeLinks = withProtectedAbsoluteLinks.replace( + WORKSPACE_RELATIVE_PATH_PATTERN, + (full, prefix: string, rawPath: string) => { + const normalized = normalizeDashboardAttachmentPath(rawPath); + if (!normalized) return full; + return `${prefix}[${rawPath}](${buildWorkspaceLink(normalized)})`; + }, + ); + return withRelativeLinks.replace(/@@WS_PATH_LINK_(\d+)@@/g, (_full, idxRaw: string) => { + const idx = Number(idxRaw); + if (!Number.isFinite(idx) || idx < 0 || idx >= protectedLinks.length) return String(_full || ''); + return protectedLinks[idx]; }); } +function decorateWorkspacePathsForMarkdown(text: string) { + const source = String(text || ''); + if (!source) return source; + + // Keep existing Markdown links unchanged; only decorate plain text segments. + const markdownLinkPattern = /\[[^\]]*?\]\((?:[^)(]|\([^)(]*\))*\)/g; + let result = ''; + let last = 0; + let match = markdownLinkPattern.exec(source); + while (match) { + const idx = Number(match.index || 0); + if (idx > last) { + result += decorateWorkspacePathsInPlainChunk(source.slice(last, idx)); + } + result += match[0]; + last = idx + match[0].length; + match = markdownLinkPattern.exec(source); + } + if (last < source.length) { + result += decorateWorkspacePathsInPlainChunk(source.slice(last)); + } + return result; +} + function normalizeAttachmentPaths(raw: unknown): string[] { if (!Array.isArray(raw)) return []; return raw @@ -3117,6 +3145,21 @@ export function BotDashboardModule({ ) : null} ) : null} + {isUploadingAttachments ? ( +
+
+
+
+ + {attachmentUploadPercent === null + ? t.uploadingFile + : `${t.uploadingFile} ${attachmentUploadPercent}%`} + +
+ ) : null}
- {isUploadingAttachments ? ( -
-
-
-
- - {attachmentUploadPercent === null - ? t.uploadingFile - : `${t.uploadingFile} ${attachmentUploadPercent}%`} - -
- ) : null} {!canChat ? (