@tutti-os/agent-gui 0.0.37 → 0.0.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.
@@ -955,11 +955,26 @@ var PLAIN_SESSION_MENTION_AGENT_LABELS = [
955
955
  "Nexight",
956
956
  "Codex"
957
957
  ];
958
+ var STANDARD_MARKDOWN_LINK_PROTOCOLS = [
959
+ "http",
960
+ "https",
961
+ "irc",
962
+ "ircs",
963
+ "mailto",
964
+ "tel",
965
+ "xmpp"
966
+ ];
967
+ var WINDOWS_DRIVE_HREF_PROTOCOLS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
958
968
  var MARKDOWN_SANITIZE_SCHEMA = {
959
969
  ...defaultSchema,
960
970
  protocols: {
961
971
  ...defaultSchema.protocols,
962
- href: [...defaultSchema.protocols?.href ?? [], "mention"]
972
+ href: [
973
+ ...defaultSchema.protocols?.href ?? [],
974
+ "mention",
975
+ ...STANDARD_MARKDOWN_LINK_PROTOCOLS,
976
+ ...WINDOWS_DRIVE_HREF_PROTOCOLS
977
+ ]
963
978
  }
964
979
  };
965
980
  var EMPTY_WORKSPACE_APP_ICONS = [];
@@ -1025,12 +1040,8 @@ function AgentMessageMarkdown({
1025
1040
  const handleLinkClick = useCallback(
1026
1041
  (href) => {
1027
1042
  if (workspaceLinkSource && onLinkAction && workspaceRoot) {
1028
- const resolvedHref = resolveWorkspaceFileHrefFromMessage(href, stabilizedContent, {
1029
- workspaceRoot,
1030
- basePath
1031
- }) ?? href;
1032
1043
  const action = resolveWorkspaceLinkAction({
1033
- href: resolvedHref,
1044
+ href,
1034
1045
  workspaceRoot,
1035
1046
  basePath,
1036
1047
  source: workspaceLinkSource
@@ -1042,14 +1053,7 @@ function AgentMessageMarkdown({
1042
1053
  }
1043
1054
  onLinkClick?.(href);
1044
1055
  },
1045
- [
1046
- basePath,
1047
- onLinkAction,
1048
- onLinkClick,
1049
- stabilizedContent,
1050
- workspaceLinkSource,
1051
- workspaceRoot
1052
- ]
1056
+ [basePath, onLinkAction, onLinkClick, workspaceLinkSource, workspaceRoot]
1053
1057
  );
1054
1058
  const handleAnchorClickCapture = useCallback(
1055
1059
  (event) => {
@@ -1074,31 +1078,14 @@ function AgentMessageMarkdown({
1074
1078
  previewMode
1075
1079
  }
1076
1080
  ),
1077
- code: (props) => /* @__PURE__ */ jsx2(
1078
- MarkdownCode,
1079
- {
1080
- ...props,
1081
- onLinkClick: handleLinkClick,
1082
- workspaceFileLinksEnabled: Boolean(
1083
- workspaceRoot && workspaceLinkSource
1084
- )
1085
- }
1086
- ),
1081
+ code: (props) => /* @__PURE__ */ jsx2(MarkdownCode, { ...props, onLinkClick: handleLinkClick }),
1087
1082
  img: (props) => /* @__PURE__ */ jsx2(MarkdownMedia, { ...props, enableZoom: enableImageZoom }),
1088
1083
  p: (props) => /* @__PURE__ */ jsx2(MarkdownParagraph, { ...props, inline }),
1089
1084
  ul: MarkdownUnorderedList,
1090
1085
  ol: MarkdownOrderedList,
1091
1086
  li: MarkdownListItem
1092
1087
  }),
1093
- [
1094
- enableImageZoom,
1095
- handleLinkClick,
1096
- inline,
1097
- previewMode,
1098
- workspaceAppIcons,
1099
- workspaceLinkSource,
1100
- workspaceRoot
1101
- ]
1088
+ [enableImageZoom, handleLinkClick, inline, previewMode, workspaceAppIcons]
1102
1089
  );
1103
1090
  return /* @__PURE__ */ jsxs2(
1104
1091
  ContainerTag,
@@ -1406,6 +1393,9 @@ function MarkdownLink({
1406
1393
  }
1407
1394
  );
1408
1395
  }
1396
+ if (!isClickableMarkdownHref(targetHref)) {
1397
+ return /* @__PURE__ */ jsx2(MarkdownLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsx2("span", { className: props.className, title: props.title, children: props.children }) });
1398
+ }
1409
1399
  return /* @__PURE__ */ jsx2(MarkdownLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsx2(
1410
1400
  "a",
1411
1401
  {
@@ -1609,13 +1599,12 @@ function MarkdownCode({
1609
1599
  children,
1610
1600
  className,
1611
1601
  onLinkClick,
1612
- workspaceFileLinksEnabled = false,
1613
1602
  ...props
1614
1603
  }) {
1615
1604
  "use memo";
1616
1605
  const isInsideLink = useContext(MarkdownLinkContext);
1617
1606
  const text = textFromReactNode(children).trim();
1618
- const isLinkablePath = !isInsideLink && onLinkClick && !className && (isLocalAbsolutePath(text) || isHttpUrl(text) || workspaceFileLinksEnabled && isLikelyWorkspaceRelativeFilePath(text));
1607
+ const isLinkablePath = !isInsideLink && onLinkClick && !className && (isExplicitWorkspaceFilePath(text) || isHttpUrl(text));
1619
1608
  if (isLinkablePath) {
1620
1609
  return /* @__PURE__ */ jsx2(PathLink, { href: text, onLinkClick, children });
1621
1610
  }
@@ -1883,6 +1872,46 @@ function isLocalAbsolutePath(path) {
1883
1872
  const candidate = path.trim();
1884
1873
  return candidate.length > 1 && candidate.startsWith("/") && !candidate.startsWith("//") && !candidate.includes("://") && !/\s/.test(candidate);
1885
1874
  }
1875
+ function isHomeRelativePath(path) {
1876
+ const candidate = path.trim();
1877
+ return candidate.length > 0 && !/\s/.test(candidate) && (candidate === "~" || candidate.startsWith("~/") || candidate.startsWith("~\\"));
1878
+ }
1879
+ function isWindowsAbsolutePath2(path) {
1880
+ const candidate = path.trim();
1881
+ return /^[A-Za-z]:[\\/]/.test(candidate) && !/\s/.test(candidate);
1882
+ }
1883
+ function isExplicitWorkspaceFilePath(path) {
1884
+ const candidate = path.trim();
1885
+ if (!candidate || candidate.includes("://")) {
1886
+ return false;
1887
+ }
1888
+ return isLocalAbsolutePath(candidate) || isHomeRelativePath(candidate) || isWindowsAbsolutePath2(candidate);
1889
+ }
1890
+ function isClickableMarkdownHref(href) {
1891
+ const target = href.trim();
1892
+ return Boolean(
1893
+ target && (isStandardMarkdownLinkHref(target) || isRichTextMentionHref(target) || isExplicitWorkspaceFilePath(target))
1894
+ );
1895
+ }
1896
+ function isStandardMarkdownLinkHref(href) {
1897
+ const target = href.trim();
1898
+ if (!target || isExplicitWorkspaceFilePath(target)) {
1899
+ return false;
1900
+ }
1901
+ if (target.startsWith("#")) {
1902
+ return target.length > 1;
1903
+ }
1904
+ let url;
1905
+ try {
1906
+ url = new URL(target);
1907
+ } catch {
1908
+ return false;
1909
+ }
1910
+ const protocol = url.protocol.replace(/:$/, "").toLowerCase();
1911
+ return STANDARD_MARKDOWN_LINK_PROTOCOLS.includes(
1912
+ protocol
1913
+ );
1914
+ }
1886
1915
  function resolveRenderableMarkdownMediaSrc(src) {
1887
1916
  const trimmed = src.trim();
1888
1917
  if (!trimmed) {
@@ -1983,62 +2012,6 @@ function isHttpUrl(value) {
1983
2012
  return false;
1984
2013
  }
1985
2014
  }
1986
- function resolveWorkspaceFileHrefFromMessage(rawPath, messageContent, context) {
1987
- const path = trimTrailingPathPunctuation(rawPath.trim());
1988
- if (!path || isHttpUrl(path) || isLocalAbsolutePath(path) || !isLikelyWorkspaceRelativeFilePath(path)) {
1989
- return null;
1990
- }
1991
- const directoryHrefs = extractWorkspaceDirectoryLinkHrefs(messageContent);
1992
- const candidates = [];
1993
- if (path.includes("/")) {
1994
- candidates.push(path);
1995
- } else {
1996
- for (const directoryHref of directoryHrefs) {
1997
- candidates.push(`${directoryHref}/${path}`);
1998
- }
1999
- candidates.push(path);
2000
- }
2001
- for (const candidate of candidates) {
2002
- if (resolveWorkspaceFilePathCandidate({
2003
- path: candidate,
2004
- workspaceRoot: context.workspaceRoot,
2005
- basePath: context.basePath
2006
- })) {
2007
- return candidate;
2008
- }
2009
- }
2010
- return null;
2011
- }
2012
- function extractWorkspaceDirectoryLinkHrefs(content) {
2013
- const directories = [];
2014
- let index = 0;
2015
- while (index < content.length) {
2016
- const linkEnd = markdownLinkEndIndex(content, index);
2017
- if (linkEnd <= index) {
2018
- index += 1;
2019
- continue;
2020
- }
2021
- const slice = content.slice(index, linkEnd);
2022
- const match = /^\[([^\]]*)\]\(([^)]+)\)$/.exec(slice);
2023
- if (match) {
2024
- const href = match[2]?.trim() ?? "";
2025
- if (href && !isRichTextMentionHref(href) && !href.includes("://")) {
2026
- const normalizedHref = href.replace(/\/+$/g, "");
2027
- if (href.endsWith("/") || !normalizedHref.includes(".") && !normalizedHref.includes(" ")) {
2028
- directories.push(normalizedHref);
2029
- }
2030
- }
2031
- }
2032
- index = linkEnd;
2033
- }
2034
- return [...new Set(directories)];
2035
- }
2036
- function isLikelyWorkspaceRelativeFilePath(path) {
2037
- if (!path || /\s/.test(path) || path.includes("://")) {
2038
- return false;
2039
- }
2040
- return path.includes("/") || /\.[A-Za-z0-9][A-Za-z0-9._-]{0,15}$/.test(path);
2041
- }
2042
2015
  function linkBareLocalAbsolutePaths(content) {
2043
2016
  let out = "";
2044
2017
  for (let index = 0; index < content.length; ) {
@@ -2116,7 +2089,8 @@ function normalizePlainSessionMentionTitle(content) {
2116
2089
  return content;
2117
2090
  }
2118
2091
  function markdownUrlTransform(value) {
2119
- return isRichTextMentionHref(value) ? value : defaultUrlTransform(value);
2092
+ const target = value.trim();
2093
+ return isRichTextMentionHref(target) || isExplicitWorkspaceFilePath(target) || isStandardMarkdownLinkHref(target) ? target : defaultUrlTransform(value);
2120
2094
  }
2121
2095
  function parseMentionLink(href, rawLabel, workspaceAppIcons = [], appFactoryFallbackLabel = "Create app") {
2122
2096
  const mention = parseRichTextMentionHref2(href, rawLabel);
@@ -2761,4 +2735,4 @@ export {
2761
2735
  CustomScrollArea,
2762
2736
  MessageSquareMoreIcon
2763
2737
  };
2764
- //# sourceMappingURL=chunk-UHQDBXGH.js.map
2738
+ //# sourceMappingURL=chunk-44YASHVW.js.map