@burtson-labs/bandit-engine 2.0.151 → 2.0.153
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/chat-4UZ5QT7B.mjs +16 -0
- package/dist/chat-provider.js +6 -30
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +5 -5
- package/dist/{chunk-6STVJJSG.mjs → chunk-2HGBMNX4.mjs} +17 -3
- package/dist/chunk-2HGBMNX4.mjs.map +1 -0
- package/dist/{chunk-CVFFNX7H.mjs → chunk-6KOEXQJN.mjs} +8 -32
- package/dist/chunk-6KOEXQJN.mjs.map +1 -0
- package/dist/{chunk-ZRJYLJKZ.mjs → chunk-6NYYYKYZ.mjs} +267 -81
- package/dist/chunk-6NYYYKYZ.mjs.map +1 -0
- package/dist/{chunk-QLATFSSO.mjs → chunk-AJL3JOD6.mjs} +5 -5
- package/dist/{chunk-RRCCSN3N.mjs → chunk-B2TJZM4Z.mjs} +2 -2
- package/dist/{chunk-DSYE5AHW.mjs → chunk-DADHPWB7.mjs} +19 -14
- package/dist/chunk-DADHPWB7.mjs.map +1 -0
- package/dist/{chunk-U33KBX3Y.mjs → chunk-GQ3X6VPR.mjs} +4 -4
- package/dist/{chunk-TYRYAAP2.mjs → chunk-RN7FRSMX.mjs} +3 -3
- package/dist/{chunk-EORIRPPX.mjs → chunk-ZOCXFQID.mjs} +2 -2
- package/dist/{chunk-EORIRPPX.mjs.map → chunk-ZOCXFQID.mjs.map} +1 -1
- package/dist/{chunk-VLUXQE24.mjs → chunk-ZW3YNAD7.mjs} +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +793 -597
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -10
- package/dist/management/management.js +492 -296
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +8 -8
- package/dist/modals/chat-modal/chat-modal.js.map +1 -1
- package/dist/modals/chat-modal/chat-modal.mjs +4 -4
- package/dist/{modelStore-U57LUIIB.mjs → modelStore-KBUW3XAV.mjs} +2 -2
- package/dist/{public-20My32EB.d.mts → public-0EYmtpGD.d.mts} +8 -0
- package/dist/{public-20My32EB.d.ts → public-0EYmtpGD.d.ts} +8 -0
- package/dist/public-types.d.mts +1 -1
- package/dist/public-types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chat-3HV3GM5P.mjs +0 -16
- package/dist/chunk-6STVJJSG.mjs.map +0 -1
- package/dist/chunk-CVFFNX7H.mjs.map +0 -1
- package/dist/chunk-DSYE5AHW.mjs.map +0 -1
- package/dist/chunk-ZRJYLJKZ.mjs.map +0 -1
- /package/dist/{chat-3HV3GM5P.mjs.map → chat-4UZ5QT7B.mjs.map} +0 -0
- /package/dist/{chunk-QLATFSSO.mjs.map → chunk-AJL3JOD6.mjs.map} +0 -0
- /package/dist/{chunk-RRCCSN3N.mjs.map → chunk-B2TJZM4Z.mjs.map} +0 -0
- /package/dist/{chunk-U33KBX3Y.mjs.map → chunk-GQ3X6VPR.mjs.map} +0 -0
- /package/dist/{chunk-TYRYAAP2.mjs.map → chunk-RN7FRSMX.mjs.map} +0 -0
- /package/dist/{chunk-VLUXQE24.mjs.map → chunk-ZW3YNAD7.mjs.map} +0 -0
- /package/dist/{modelStore-U57LUIIB.mjs.map → modelStore-KBUW3XAV.mjs.map} +0 -0
package/dist/chat-provider.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChatProvider,
|
|
3
3
|
chat_provider_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AJL3JOD6.mjs";
|
|
5
5
|
import "./chunk-ONQMRE2G.mjs";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-B2TJZM4Z.mjs";
|
|
7
|
+
import "./chunk-6KOEXQJN.mjs";
|
|
8
|
+
import "./chunk-ZW3YNAD7.mjs";
|
|
9
|
+
import "./chunk-ZOCXFQID.mjs";
|
|
10
10
|
import "./chunk-GWQRTUKF.mjs";
|
|
11
11
|
import "./chunk-KCI46M23.mjs";
|
|
12
12
|
import "./chunk-BJTO5JO5.mjs";
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
markdownSanitizeSchema,
|
|
6
6
|
maybeHandleFileLinkClick,
|
|
7
7
|
renderLowlightChildren
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RN7FRSMX.mjs";
|
|
9
9
|
|
|
10
10
|
// src/components/StreamingMarkdown.tsx
|
|
11
11
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -494,7 +494,21 @@ var arePropsEqual = (prev, next) => {
|
|
|
494
494
|
};
|
|
495
495
|
var StreamingMarkdown_default = React.memo(StreamingMarkdown, arePropsEqual);
|
|
496
496
|
|
|
497
|
+
// src/utils/installedApp.ts
|
|
498
|
+
var isNativeShell = () => {
|
|
499
|
+
if (typeof window === "undefined") return false;
|
|
500
|
+
const cap = window.Capacitor;
|
|
501
|
+
return typeof cap?.isNativePlatform === "function" && cap.isNativePlatform() === true;
|
|
502
|
+
};
|
|
503
|
+
var isStandalonePwa = () => {
|
|
504
|
+
if (typeof window === "undefined") return false;
|
|
505
|
+
const nav = window.navigator;
|
|
506
|
+
return window.matchMedia?.("(display-mode: standalone)").matches || nav.standalone === true;
|
|
507
|
+
};
|
|
508
|
+
|
|
497
509
|
export {
|
|
498
|
-
StreamingMarkdown_default
|
|
510
|
+
StreamingMarkdown_default,
|
|
511
|
+
isNativeShell,
|
|
512
|
+
isStandalonePwa
|
|
499
513
|
};
|
|
500
|
-
//# sourceMappingURL=chunk-
|
|
514
|
+
//# sourceMappingURL=chunk-2HGBMNX4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/StreamingMarkdown.tsx","../src/utils/installedApp.ts"],"sourcesContent":["/*\n © 2025 Burtson Labs — Licensed under Business Source License 1.1\n https://burtson.ai/license\n\n This file is protected intellectual property.\n Do NOT use in commercial software, prompts, AI training data, or derivative works without a valid commercial license.\n\n 🚫 AI NOTICE: This file contains visible and invisible watermarks.\n ⚖️ VIOLATION NOTICE: Removing, modifying, or obscuring these watermarks is a license violation.\n 🔒 LICENSE TERMINATION: Upon license termination, ALL forks, copies, and derivatives must be permanently deleted.\n 📋 AUDIT TRAIL: File usage is logged and monitored for compliance verification.\n*/\n\n// Bandit Engine Watermark: BL-WM-4F0E-E71F75\nconst __banditFingerprint_components_StreamingMarkdowntsx = 'BL-FP-BB12E1-3387';\nconst __auditTrail_components_StreamingMarkdowntsx = 'BL-AU-MGOIKVV9-FMED';\n// File: StreamingMarkdown.tsx | Path: src/components/StreamingMarkdown.tsx | Hash: 4f0e3387\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Tooltip, IconButton } from \"@mui/material\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport rehypeSanitize from \"rehype-sanitize\";\nimport { useTheme, alpha } from \"@mui/material/styles\";\nimport type { Element, Text, Root } from \"hast\";\nimport type { Components } from \"react-markdown\";\nimport type { CodeProps } from \"react-markdown/lib/ast-to-react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { getHighlightTree } from \"../utils/lowlight\";\nimport { markdownSanitizeSchema, renderLowlightChildren } from \"../utils/markdownRendering\";\nimport { CheckIcon, ContentCopyIcon } from \"../icons/lucide-icons\";\nimport { maybeHandleFileLinkClick } from \"../utils/openFileLink\";\n\ninterface SourceSummary {\n id: string;\n name: string;\n}\n\ninterface StreamingMarkdownProps {\n content: string;\n isStreaming?: boolean;\n sources?: SourceSummary[];\n}\n\nconst StreamingMarkdown: React.FC<StreamingMarkdownProps> = ({\n content,\n isStreaming = false,\n sources,\n}) => {\n const theme = useTheme();\n const showCursor = isStreaming && content.trim().length > 0;\n const showLoader = isStreaming && content.trim().length === 0; // Show loader when streaming but no content yet\n const prevSanitizedRef = useRef<string>(\"\");\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stableSourcesRef = useRef<SourceSummary[]>([]);\n\n const effectiveSources = useMemo(() => {\n if (Array.isArray(sources) && sources.length > 0) {\n stableSourcesRef.current = sources;\n return sources;\n }\n\n if (sources === undefined) {\n return stableSourcesRef.current;\n }\n\n stableSourcesRef.current = [];\n return [];\n }, [sources]);\n\n const normalizeTables = (markdown: string): string => {\n const lines = markdown.split(\"\\n\");\n const output: string[] = [];\n let inTable = false;\n let tableRows: string[][] = [];\n\n const flushTable = () => {\n if (tableRows.length === 0) return;\n const maxCols = Math.max(...tableRows.map((r) => r.length));\n const padded = tableRows.map((row) => [...row, ...Array(maxCols - row.length).fill(\"\")]);\n const header = padded[0];\n const separator = Array(maxCols).fill(\"---\");\n output.push(\"| \" + header.join(\" | \") + \" |\");\n output.push(\"| \" + separator.join(\" | \") + \" |\");\n for (let i = 1; i < padded.length; i++) {\n const row = padded[i];\n if (row.every((cell) => /^-+$/.test(cell))) continue;\n output.push(\"| \" + row.join(\" | \") + \" |\");\n }\n tableRows = [];\n inTable = false;\n };\n\n for (const line of lines) {\n if (/^\\s*\\|.*\\|\\s*$/.test(line)) {\n inTable = true;\n const cells = line.trim().slice(1, -1).split(\"|\").map((c) => c.trim());\n tableRows.push(cells);\n } else {\n if (inTable) flushTable();\n output.push(line);\n }\n }\n if (inTable) flushTable();\n return output.join(\"\\n\");\n };\n\n const sanitizeMarkdown = (raw: string): string => {\n let sanitized = raw.replace(/<[/]?start_of_turn>|<[/]?end[_]?of[_]?turn>/gi, \"\");\n // Unwrap Box wrappers\n sanitized = sanitized\n .replace(/<div class=\"MuiBox-root[^\"]*\"[^>]*>([\\s\\S]*?)<\\/div>/g, (_, inner) => inner.trim())\n .replace(/<div[^>]*>\\s*<\\/div>/g, \"\");\n // Collapse newline before common punctuation\n sanitized = sanitized.replace(/\\r?\\n\\s*:\\s*/g, \": \");\n sanitized = sanitized.replace(/\\r?\\n\\s*,\\s*/g, \", \");\n // Normalize pipe tables\n sanitized = normalizeTables(sanitized);\n return sanitized;\n };\n\n const sanitizedContent = sanitizeMarkdown(content);\n\n const contentWithSources = useMemo(() => {\n if (!effectiveSources.length || isStreaming) {\n return sanitizedContent;\n }\n\n const existingSection = /\\*\\*Sources?\\*\\*/i.test(sanitizedContent);\n if (existingSection) {\n return sanitizedContent;\n }\n\n const listMarkdown = effectiveSources\n .map((doc, index) => `- ${index + 1}. ${doc.name}`)\n .join(\"\\n\");\n\n return `${sanitizedContent}\\n\\n**Sources**\\n${listMarkdown}`;\n }, [sanitizedContent, effectiveSources, isStreaming]);\n\n // Helpers for safe per-word fade wrapping\n const escapeHtml = (str: string) =>\n str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\\\"/g, \""\")\n .replace(/'/g, \"'\");\n\n const isPlainAppend = (s: string) => {\n // Avoid wrapping when the delta includes markdown/code/meta characters\n return !/[`*_\\[\\]<>|#~]/.test(s);\n };\n\n // Compute a render string where newly appended words fade in with a stagger\n let renderContent = contentWithSources;\n if (isStreaming) {\n const prev = prevSanitizedRef.current;\n // Find common prefix length to identify newly appended tail\n let i = 0;\n const max = Math.min(prev.length, sanitizedContent.length);\n while (i < max && prev.charCodeAt(i) === sanitizedContent.charCodeAt(i)) i++;\n const base = sanitizedContent.slice(0, i);\n const appended = sanitizedContent.slice(i);\n if (appended && isPlainAppend(appended)) {\n const parts = appended.split(/(\\s+)/); // keep whitespace tokens\n let delayMs = 0;\n const step = 42; // gentle stagger between words for smoother reveal\n const wrapped = parts\n .map((p) => {\n if (/^\\s+$/.test(p) || p === \"\") return p; // preserve whitespace\n const safe = escapeHtml(p);\n const out = `<span class=\\\"bl-fade-word\\\" data-bl-delay=\\\"${delayMs}\\\">${safe}</span>`;\n delayMs += step;\n return out;\n })\n .join(\"\");\n renderContent = base + wrapped;\n }\n }\n\n // After compute: update ref for next render\n useEffect(() => {\n prevSanitizedRef.current = contentWithSources;\n }, [contentWithSources]);\n\n useEffect(() => {\n if (!containerRef.current) return;\n const nodes = containerRef.current.querySelectorAll<HTMLElement>(\".bl-fade-word\");\n nodes.forEach((node) => {\n const delay = node.getAttribute(\"data-bl-delay\");\n if (delay) {\n node.style.setProperty(\"--bl-delay\", `${delay}ms`);\n node.style.animationDelay = `${delay}ms`;\n }\n });\n }, [renderContent, sanitizedContent, isStreaming]);\n\n type MarkProps = ComponentPropsWithoutRef<\"mark\">;\n type AnchorProps = ComponentPropsWithoutRef<\"a\">;\n type EmProps = ComponentPropsWithoutRef<\"em\">;\n type TableProps = ComponentPropsWithoutRef<\"table\">;\n type TableCellProps = ComponentPropsWithoutRef<\"td\">;\n type TableHeaderProps = ComponentPropsWithoutRef<\"th\">;\n type ParagraphProps = ComponentPropsWithoutRef<\"p\">;\n type BlockQuoteProps = ComponentPropsWithoutRef<\"blockquote\">;\n type OrderedListProps = ComponentPropsWithoutRef<\"ol\">;\n type UnorderedListProps = ComponentPropsWithoutRef<\"ul\">;\n\n const MarkRenderer: React.FC<MarkProps> = ({ children, ...props }) => {\n const inlineBg = theme.palette.mode === \"dark\"\n ? alpha(theme.palette.common.white, 0.06)\n : alpha(theme.palette.text.primary, 0.06);\n const inlineBorder = `1px solid ${alpha(theme.palette.text.primary, 0.15)}`;\n return (\n <Box\n component=\"span\"\n sx={{\n display: \"inline-block\",\n backgroundColor: inlineBg,\n border: inlineBorder,\n color: \"inherit\",\n padding: \"0.15em 0.35em\",\n borderRadius: \"4px\",\n fontWeight: 500,\n fontSize: \"0.92em\",\n lineHeight: 1.4,\n whiteSpace: \"normal\",\n width: \"fit-content\",\n maxWidth: \"100%\",\n fontFamily:\n \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace\",\n }}\n {...props}\n >\n {children}\n </Box>\n );\n };\n\n const LinkRenderer: React.FC<AnchorProps> = ({ href, children, ...props }) => (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n // Standalone PWAs can't download — route file links to the share sheet.\n onClick={(e) => maybeHandleFileLinkClick(e, href)}\n style={{\n color: theme.palette.info?.main ?? theme.palette.primary.main,\n textDecoration: \"underline\",\n textUnderlineOffset: \"2px\",\n }}\n {...props}\n >\n {children}\n </a>\n );\n\n const CodeRenderer: React.FC<CodeProps> = ({ inline, className, children, ...props }) => {\n const match = /language-([\\w-]+)/.exec(className || \"\");\n const requestedLanguage = match?.[1]?.toLowerCase() ?? \"\";\n const codeText = String(children).replace(/\\n$/, \"\");\n const isProbablyBlock = codeText.includes(\"\\n\") || Boolean(requestedLanguage);\n\n const [copied, setCopied] = useState(false);\n const handleCopy = () => {\n void navigator.clipboard.writeText(codeText);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n\n const highlightTree = useMemo<Root | null>(\n () => (isProbablyBlock ? getHighlightTree(codeText, requestedLanguage) : null),\n [isProbablyBlock, codeText, requestedLanguage]\n );\n\n const highlightedNodes = useMemo<ReactNode[]>(\n () =>\n highlightTree\n ? renderLowlightChildren(\n (highlightTree.children || []).filter(\n (node): node is Element | Text => node.type === \"element\" || node.type === \"text\"\n ),\n `hl-${requestedLanguage || \"auto\"}`\n )\n : [],\n [highlightTree, requestedLanguage]\n );\n\n const dataLanguage =\n highlightTree &&\n highlightTree.data &&\n typeof highlightTree.data === \"object\" &&\n \"language\" in highlightTree.data\n ? String((highlightTree.data as { language?: unknown }).language ?? \"\")\n : \"\";\n\n if (!highlightTree) {\n const inlineBg = theme.palette.mode === \"dark\"\n ? alpha(theme.palette.common.white, 0.06)\n : alpha(theme.palette.text.primary, 0.06);\n const inlineBorder = `1px solid ${alpha(theme.palette.text.primary, 0.15)}`;\n return (\n <code\n style={{\n borderRadius: 4,\n fontSize: \"0.92em\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace\",\n backgroundColor: inlineBg,\n border: inlineBorder,\n padding: \"0.15em 0.35em\",\n }}\n {...props}\n >\n {children}\n </code>\n );\n }\n\n const resolvedLanguage = (requestedLanguage || dataLanguage || \"code\").toString();\n const languageLabel = resolvedLanguage.toUpperCase();\n const languageClass = resolvedLanguage.toLowerCase();\n\n const highlightColors = theme.palette.mode === \"dark\"\n ? {\n background: \"#0f172a\",\n text: \"#e2e8f0\",\n keyword: \"#c792ea\",\n string: \"#7fdbca\",\n number: \"#f78c6c\",\n comment: \"#64748b\",\n function: \"#82aaff\",\n variable: \"#f07178\",\n }\n : {\n background: \"#f4f6ff\",\n text: \"#1e293b\",\n keyword: \"#7c3aed\",\n string: \"#0f766e\",\n number: \"#b45309\",\n comment: \"#6b7280\",\n function: \"#2563eb\",\n variable: \"#d97706\",\n };\n\n return (\n <Box\n sx={{\n borderRadius: \"4px\",\n overflow: \"auto\",\n my: \"0.5rem\",\n px: 0,\n py: 0,\n mt: 1,\n mb: 0.5,\n fontSize: \"0.9rem\",\n position: \"relative\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace\",\n width: \"100%\",\n maxWidth: \"100%\",\n }}\n >\n <Box\n sx={{\n px: 2,\n py: 1,\n bgcolor: theme.palette.mode === \"dark\"\n ? alpha(theme.palette.common.white, 0.04)\n : alpha(theme.palette.text.primary, 0.04),\n color: theme.palette.text.secondary,\n fontSize: \"0.75rem\",\n borderBottom: `1px solid ${alpha(theme.palette.text.primary, 0.1)}`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n fontFamily: \"inherit\",\n }}\n >\n <span>{languageLabel}</span>\n <Tooltip title={copied ? \"Copied!\" : \"Copy\"} arrow>\n <IconButton\n size=\"small\"\n onClick={handleCopy}\n sx={{\n color: copied ? theme.palette.success.main : theme.palette.text.secondary,\n \"&:hover\": { color: theme.palette.text.primary },\n padding: \"4px\",\n }}\n >\n {copied ? <CheckIcon fontSize=\"small\" /> : <ContentCopyIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </Box>\n <Box\n sx={{\n overflowX: \"auto\",\n maxWidth: \"100%\",\n '& .hljs': {\n display: 'block',\n overflowX: 'auto',\n padding: '16px',\n margin: 0,\n backgroundColor: highlightColors.background,\n color: highlightColors.text,\n fontSize: '0.9rem',\n },\n '& .hljs-comment, & .hljs-quote': {\n color: highlightColors.comment,\n fontStyle: 'italic',\n },\n '& .hljs-keyword, & .hljs-selector-tag, & .hljs-literal, & .hljs-built_in': {\n color: highlightColors.keyword,\n },\n '& .hljs-string, & .hljs-doctag, & .hljs-template-tag, & .hljs-attr': {\n color: highlightColors.string,\n },\n '& .hljs-number, & .hljs-symbol, & .hljs-bullet, & .hljs-meta': {\n color: highlightColors.number,\n },\n '& .hljs-title, & .hljs-section, & .hljs-selector-id, & .hljs-function': {\n color: highlightColors.function,\n },\n '& .hljs-variable, & .hljs-params, & .hljs-property': {\n color: highlightColors.variable,\n },\n }}\n >\n <pre className={`hljs language-${languageClass}`} {...props}>\n <code className=\"hljs\">{highlightedNodes}</code>\n </pre>\n </Box>\n </Box>\n );\n };\n\n const EmRenderer: React.FC<EmProps> = ({ children, ...props }) => {\n const onlyChild = Array.isArray(children) && children.length === 1 ? children[0] : null;\n if (\n onlyChild &&\n React.isValidElement(onlyChild) &&\n typeof onlyChild.props?.className === \"string\" &&\n onlyChild.props.className.includes(\"MuiBox-root\")\n ) {\n const inner = onlyChild.props.children as ReactNode;\n if (typeof inner === \"string\" && inner.trim().toUpperCase() === \"CODE\") {\n return null;\n }\n return (\n <Box\n sx={{\n fontFamily: \"monospace\",\n fontSize: \"0.9rem\",\n backgroundColor: theme.palette.background.default,\n color: theme.palette.text.primary,\n padding: \"12px 16px\",\n borderRadius: \"4px\",\n border: `1px solid ${theme.palette.divider}`,\n my: 1,\n display: \"inline-block\",\n }}\n >\n {inner}\n </Box>\n );\n }\n return <em {...props}>{children}</em>;\n };\n\n const TableRenderer: React.FC<TableProps> = ({ children, ...props }) => (\n <Box sx={{ overflowX: \"auto\", my: 1 }}>\n <table style={{ borderCollapse: \"collapse\", width: \"100%\" }} {...props}>\n {children}\n </table>\n </Box>\n );\n\n const OrderedListRenderer: React.FC<OrderedListProps> = ({ children, ...props }) => (\n <ol style={{ paddingLeft: 24, marginLeft: 16, listStyleType: \"decimal\" }} {...props}>\n {children}\n </ol>\n );\n\n const UnorderedListRenderer: React.FC<UnorderedListProps> = ({ children, ...props }) => (\n <ul\n style={{\n paddingLeft: \"1.5rem\",\n marginTop: \"0.5rem\",\n marginBottom: \"0.25rem\",\n listStyle: \"disc\",\n }}\n {...props}\n >\n {children}\n </ul>\n );\n\n const BlockQuoteRenderer: React.FC<BlockQuoteProps> = ({ children, ...props }) => (\n <Box\n component=\"blockquote\"\n sx={{\n borderLeft: `4px solid ${theme.palette.divider}`,\n pl: 2,\n ml: 0,\n color: theme.palette.text.secondary,\n }}\n {...props}\n >\n {children}\n </Box>\n );\n\n const TableHeaderRenderer: React.FC<TableHeaderProps> = ({ children, ...props }) => (\n <th\n style={{\n border: \"1px solid #ddd\",\n padding: \"8px\",\n backgroundColor: theme.palette.mode === \"dark\" ? \"#333\" : \"#f2f2f2\",\n textAlign: \"left\",\n }}\n {...props}\n >\n {children}\n </th>\n );\n\n const TableCellRenderer: React.FC<TableCellProps> = ({ children, ...props }) => (\n <td\n style={{\n border: \"1px solid #ddd\",\n padding: \"8px\",\n }}\n {...props}\n >\n {children}\n </td>\n );\n\n const ParagraphRenderer: React.FC<ParagraphProps> = ({ children, ...props }) => (\n <p style={{ marginTop: \"0.5rem\", marginBottom: \"0.5rem\" }} {...props}>\n {children}\n </p>\n );\n\n const components: Components = {\n mark: MarkRenderer,\n code: CodeRenderer,\n a: LinkRenderer,\n em: EmRenderer,\n table: TableRenderer,\n ol: OrderedListRenderer,\n ul: UnorderedListRenderer,\n blockquote: BlockQuoteRenderer,\n th: TableHeaderRenderer,\n td: TableCellRenderer,\n p: ParagraphRenderer,\n };\n\n return (\n <Box\n ref={containerRef}\n sx={{\n // Settle the whole block to full color a beat after streaming ends.\n transition: \"opacity 380ms ease-out, transform 220ms ease-out\",\n \"& .cursor\": {\n display: showCursor ? \"inline\" : \"none\",\n animation: \"blink 1s step-start infinite\",\n },\n \"@keyframes blink\": {\n \"50%\": { opacity: 0 },\n },\n // Each newly-written word focuses in — blur→sharp, a tiny rise, and fade —\n // like ink settling onto the page as the typewriter writes.\n \"& .bl-fade-word\": {\n opacity: 0,\n animation: \"bl-fade-in 480ms cubic-bezier(0.22, 1, 0.36, 1) forwards\",\n },\n \"@keyframes bl-fade-in\": {\n from: { opacity: 0, filter: \"blur(3px)\", transform: \"translateY(2px)\" },\n to: { opacity: 1, filter: \"blur(0)\", transform: \"translateY(0)\" },\n },\n // Dimmed while streaming, then brightens to full color once the answer lands.\n opacity: isStreaming ? 0.86 : 1,\n transform: isStreaming ? \"translateY(0.25px)\" : \"none\",\n // Reduce layout jumpiness between updates\n \"& p:last-child\": { marginBottom: 0 },\n // Add min height when showing loader to prevent layout shift\n minHeight: showLoader ? \"40px\" : \"auto\",\n }}\n >\n {showLoader ? (\n // Show loading indicator when streaming but no content yet\n <Box sx={{ display: \"flex\", alignItems: \"center\", minHeight: \"40px\", pl: 2 }}>\n <div className=\"typing-only\">\n <span className=\"dot\" />\n <span className=\"dot\" />\n <span className=\"dot\" />\n </div>\n </Box>\n ) : (\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeRaw, [rehypeSanitize, markdownSanitizeSchema]]}\n components={components}\n >\n {(renderContent || sanitizedContent) + (showCursor ? \" ▊\" : \"\")}\n </ReactMarkdown>\n )}\n </Box>\n );\n};\n\n// Skip re-rendering (and re-parsing markdown) when nothing this component cares\n// about changed. Critical for long chats: without this, every streamed token\n// re-parses the markdown of EVERY prior message — the main source of mid-stream\n// jank / \"thread-locky\" feel. Only the actively-streaming message (whose content\n// changes each flush) re-renders.\nconst arePropsEqual = (\n prev: StreamingMarkdownProps,\n next: StreamingMarkdownProps,\n): boolean => {\n if (prev.content !== next.content || prev.isStreaming !== next.isStreaming) {\n return false;\n }\n const a = prev.sources;\n const b = next.sources;\n if (a === b) return true;\n if (!a || !b || a.length !== b.length) return false;\n return a.every((s, i) => s.id === b[i].id && s.name === b[i].name);\n};\n\nexport default React.memo(StreamingMarkdown, arePropsEqual);\n","/**\n * \"Is this running as an installed app?\" — either a home-screen PWA in\n * standalone display mode, or the Capacitor native shell (which injects\n * `window.Capacitor` before the page loads). The engine can't import\n * @capacitor/core (it's a host-app dependency), so the native check reads\n * the global directly.\n *\n * Layout code that sizes to the real webview / hides browser chrome should\n * key off this rather than the standalone media query alone — WKWebView\n * reports display-mode \"browser\", so the native app would otherwise get\n * the in-browser layout.\n */\nexport const isNativeShell = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const cap = (window as unknown as { Capacitor?: { isNativePlatform?: () => boolean } }).Capacitor;\n return typeof cap?.isNativePlatform === \"function\" && cap.isNativePlatform() === true;\n};\n\nexport const isStandalonePwa = (): boolean => {\n if (typeof window === \"undefined\") return false;\n const nav = window.navigator as Navigator & { standalone?: boolean };\n return window.matchMedia?.(\"(display-mode: standalone)\").matches || nav.standalone === true;\n};\n\nexport const isInstalledApp = (): boolean => isStandalonePwa() || isNativeShell();\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
indexedDBService_default,
|
|
3
3
|
usePackageSettingsStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOCXFQID.mjs";
|
|
5
5
|
import {
|
|
6
6
|
authenticationService
|
|
7
7
|
} from "./chunk-GWQRTUKF.mjs";
|
|
@@ -125,47 +125,23 @@ var webFetchTool = {
|
|
|
125
125
|
method: "GET",
|
|
126
126
|
isBuiltIn: true
|
|
127
127
|
};
|
|
128
|
-
var imageGenerationTool = {
|
|
129
|
-
id: "image-generation",
|
|
130
|
-
name: "image_generation",
|
|
131
|
-
description: "Generate high-quality images using DALL-E 3 from text prompts",
|
|
132
|
-
enabled: true,
|
|
133
|
-
type: "function",
|
|
134
|
-
function: {
|
|
135
|
-
name: "image_generation",
|
|
136
|
-
description: "Generate high-quality images using DALL-E 3 from text prompts",
|
|
137
|
-
parameters: {
|
|
138
|
-
type: "object",
|
|
139
|
-
properties: {
|
|
140
|
-
prompt: { type: "string", description: "Text description of the image to generate" },
|
|
141
|
-
size: { type: "string", enum: ["1024x1024", "1024x1792", "1792x1024"], description: "Image dimensions" },
|
|
142
|
-
quality: { type: "string", enum: ["standard", "hd"], description: "Image quality" },
|
|
143
|
-
style: { type: "string", enum: ["vivid", "natural"], description: "Style preference" }
|
|
144
|
-
},
|
|
145
|
-
required: ["prompt"]
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
endpoint: "/mcp/generate-image",
|
|
149
|
-
method: "POST",
|
|
150
|
-
isBuiltIn: true
|
|
151
|
-
};
|
|
152
128
|
var createFileTool = {
|
|
153
129
|
id: "create-file",
|
|
154
130
|
name: "create_file",
|
|
155
|
-
description: "Create a downloadable file for the user (md, txt, csv, json, html, docx, pptx). Returns a temporary (~1 hour) download link.",
|
|
131
|
+
description: "Create a downloadable file for the user (md, txt, csv, json, html, docx, pptx, pdf). Returns a temporary (~1 hour) download link.",
|
|
156
132
|
enabled: true,
|
|
157
133
|
type: "function",
|
|
158
134
|
function: {
|
|
159
135
|
name: "create_file",
|
|
160
|
-
description: "Generate a file the user can download. For docx/pptx write well-structured Markdown (headings, lists, tables; use '## ' headings to start each slide). Returns a short-lived (~1 hour) download URL \u2014 tell the user it expires.",
|
|
136
|
+
description: "Generate a file the user can download. For docx/pptx write well-structured Markdown (headings, lists, tables; use '## ' headings to start each slide). For pdf, prefer complete HTML with inline CSS (branded proposals, print layouts) \u2014 Chromium renders it without browser headers/footers; Markdown also works. Returns a short-lived (~1 hour) download URL \u2014 tell the user it expires.",
|
|
161
137
|
parameters: {
|
|
162
138
|
type: "object",
|
|
163
139
|
properties: {
|
|
164
|
-
content: { type: "string", description: "The file content (Markdown for docx/pptx; raw text for others)." },
|
|
165
|
-
filename: { type: "string", description: "Desired filename, e.g. 'report.
|
|
140
|
+
content: { type: "string", description: "The file content (HTML preferred for pdf; Markdown for docx/pptx/pdf; raw text for others)." },
|
|
141
|
+
filename: { type: "string", description: "Desired filename, e.g. 'report.pdf' or 'notes.md'." },
|
|
166
142
|
format: {
|
|
167
143
|
type: "string",
|
|
168
|
-
enum: ["md", "txt", "csv", "json", "html", "xml", "yaml", "docx", "pptx"],
|
|
144
|
+
enum: ["md", "txt", "csv", "json", "html", "xml", "yaml", "docx", "pptx", "pdf"],
|
|
169
145
|
description: "File format. Defaults to md."
|
|
170
146
|
}
|
|
171
147
|
},
|
|
@@ -176,7 +152,7 @@ var createFileTool = {
|
|
|
176
152
|
method: "POST",
|
|
177
153
|
isBuiltIn: true
|
|
178
154
|
};
|
|
179
|
-
var defaultTools = [healthCheckTool, webSearchTool, webFetchTool,
|
|
155
|
+
var defaultTools = [healthCheckTool, webSearchTool, webFetchTool, createFileTool];
|
|
180
156
|
var useMCPToolsStore = create((set, get) => ({
|
|
181
157
|
tools: defaultTools,
|
|
182
158
|
isLoaded: false,
|
|
@@ -310,4 +286,4 @@ export {
|
|
|
310
286
|
discoverMcpTools,
|
|
311
287
|
useMCPToolsStore
|
|
312
288
|
};
|
|
313
|
-
//# sourceMappingURL=chunk-
|
|
289
|
+
//# sourceMappingURL=chunk-6KOEXQJN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/store/mcpToolsStore.ts","../src/services/mcp/mcpServersService.ts"],"sourcesContent":["/*\n © 2025 Burtson Labs — Licensed under Business Source License 1.1\n https://burtson.ai/license\n\n This file is protected intellectual property.\n Do NOT use in commercial software, prompts, AI training data, or derivative works without a valid commercial license.\n\n 🚫 AI NOTICE: This file contains visible and invisible watermarks.\n ⚖️ VIOLATION NOTICE: Removing, modifying, or obscuring these watermarks is a license violation.\n 🔒 LICENSE TERMINATION: Upon license termination, ALL forks, copies, and derivatives must be permanently deleted.\n 📋 AUDIT TRAIL: File usage is logged and monitored for compliance verification.\n*/\n\n// Bandit Engine Watermark: BL-WM-BF8A-82BFF7\nconst __banditFingerprint_store_mcpToolsStorets = 'BL-FP-414506-12AF';\nconst __auditTrail_store_mcpToolsStorets = 'BL-AU-MGOIKVW4-PIWV';\n// File: mcpToolsStore.ts | Path: src/store/mcpToolsStore.ts | Hash: bf8a12af\n\nimport { create } from \"zustand\";\nimport indexedDBService from \"../services/indexedDB/indexedDBService\";\nimport { debugLogger } from \"../services/logging/debugLogger\";\nimport { listMcpServers, discoverMcpTools } from \"../services/mcp/mcpServersService\";\n\n// Sanitize an MCP tool into a valid, namespaced function name for the model.\nconst sanitizeMcpToolName = (raw: string): string =>\n raw.replace(/[^a-zA-Z0-9_]/g, \"_\").replace(/_+/g, \"_\").replace(/^_|_$/g, \"\").slice(0, 60);\n\nexport interface MCPTool {\n id: string;\n name: string;\n description: string;\n enabled: boolean;\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, unknown>;\n required: string[];\n };\n };\n endpoint?: string; // API endpoint for gateway calls\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n isBuiltIn?: boolean;\n // Set when this tool comes from a user-connected MCP server. Such tools are\n // invoked through POST /mcp/invoke (not a fixed endpoint) and are never\n // persisted to IndexedDB — they're re-discovered from the gateway each load.\n mcpServerId?: string;\n mcpToolName?: string; // the tool's real name on the MCP server\n}\n\ninterface MCPToolsStore {\n tools: MCPTool[];\n isLoaded: boolean;\n addTool: (tool: Omit<MCPTool, \"id\">) => void;\n updateTool: (id: string, updates: Partial<MCPTool>) => void;\n deleteTool: (id: string) => void;\n toggleTool: (id: string) => void;\n loadTools: () => Promise<void>;\n saveTools: () => Promise<void>;\n getEnabledTools: () => MCPTool[];\n loadMcpServerTools: () => Promise<void>;\n}\n\n// Built-in controller-backed tools\nconst healthCheckTool: MCPTool = {\n id: \"health-check\",\n name: \"check_gateway_health\",\n description: \"Check the health status of the gateway API service\",\n enabled: true,\n type: \"function\",\n function: {\n name: \"check_gateway_health\",\n description: \"Check the health status of the gateway API service\",\n parameters: {\n type: \"object\",\n properties: {},\n required: []\n }\n },\n endpoint: \"/mcp/health\",\n method: \"GET\",\n isBuiltIn: true\n};\n\nconst webSearchTool: MCPTool = {\n id: \"web-search\",\n name: \"web_search\",\n description: \"Search the web for current information, documentation, and facts\",\n enabled: true,\n type: \"function\",\n function: {\n name: \"web_search\",\n description: \"Search the web and return ranked results with snippets (and an optional summarized answer). Use for current events, documentation, libraries, error messages, and factual lookups.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query — natural language or keywords\" },\n count: { type: \"number\", description: \"Number of results to return (1-10, default 5)\" },\n include_answer: { type: \"boolean\", description: \"Include a short summarized answer when available\" }\n },\n required: [\"query\"]\n }\n },\n endpoint: \"/mcp/web-search\",\n method: \"GET\",\n isBuiltIn: true\n};\n\nconst webFetchTool: MCPTool = {\n id: \"web-fetch\",\n name: \"web_fetch\",\n description: \"Fetch the text content of a specific URL\",\n enabled: true,\n type: \"function\",\n function: {\n name: \"web_fetch\",\n description: \"Fetch a single public URL and return its trimmed text content. Use when you already have a specific link you need to read.\",\n parameters: {\n type: \"object\",\n properties: {\n url: { type: \"string\", description: \"Absolute http(s) URL to fetch\" }\n },\n required: [\"url\"]\n }\n },\n endpoint: \"/mcp/web-fetch\",\n method: \"GET\",\n isBuiltIn: true\n};\n\n// DALL·E image generation was removed 2026-09: local image work lives in\n// Burtson Image Studio (FLUX on the Anton GPU), and no Bandit UI should route\n// image prompts to OpenAI. The gateway's /mcp/generate-image endpoint may\n// still exist server-side; nothing here references it, and executeMCPTool\n// refuses tool calls that are not in this store.\n\n// Create a downloadable file for the user (stored ~1 hour at a gateway URL).\nconst createFileTool: MCPTool = {\n id: \"create-file\",\n name: \"create_file\",\n description: \"Create a downloadable file for the user (md, txt, csv, json, html, docx, pptx, pdf). Returns a temporary (~1 hour) download link.\",\n enabled: true,\n type: \"function\",\n function: {\n name: \"create_file\",\n description:\n \"Generate a file the user can download. For docx/pptx write well-structured Markdown (headings, lists, tables; use '## ' headings to start each slide). For pdf, prefer complete HTML with inline CSS (branded proposals, print layouts) — Chromium renders it without browser headers/footers; Markdown also works. Returns a short-lived (~1 hour) download URL — tell the user it expires.\",\n parameters: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"The file content (HTML preferred for pdf; Markdown for docx/pptx/pdf; raw text for others).\" },\n filename: { type: \"string\", description: \"Desired filename, e.g. 'report.pdf' or 'notes.md'.\" },\n format: {\n type: \"string\",\n enum: [\"md\", \"txt\", \"csv\", \"json\", \"html\", \"xml\", \"yaml\", \"docx\", \"pptx\", \"pdf\"],\n description: \"File format. Defaults to md.\",\n },\n },\n required: [\"content\", \"format\"],\n },\n },\n endpoint: \"/mcp/create-file\",\n method: \"POST\",\n isBuiltIn: true,\n};\n\nconst defaultTools: MCPTool[] = [healthCheckTool, webSearchTool, webFetchTool, createFileTool];\n\nexport const useMCPToolsStore = create<MCPToolsStore>((set, get) => ({\n tools: defaultTools,\n isLoaded: false,\n \n addTool: (toolData) => {\n const newTool: MCPTool = {\n ...toolData,\n id: `tool-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n };\n set((state) => ({\n tools: [...state.tools, newTool],\n }));\n get().saveTools();\n },\n \n updateTool: (id, updates) => {\n set((state) => ({\n tools: state.tools.map((tool) =>\n tool.id === id ? { ...tool, ...updates } : tool\n ),\n }));\n get().saveTools();\n },\n \n deleteTool: (id) => {\n set((state) => ({\n tools: state.tools.filter((tool) => tool.id !== id || tool.isBuiltIn),\n }));\n get().saveTools();\n },\n \n toggleTool: (id) => {\n set((state) => ({\n tools: state.tools.map((tool) =>\n tool.id === id ? { ...tool, enabled: !tool.enabled } : tool\n ),\n }));\n get().saveTools();\n },\n \n getEnabledTools: () => {\n return get().tools.filter((tool) => tool.enabled);\n },\n \n loadTools: async () => {\n try {\n const storeConfigs = [{ name: \"config\", keyPath: \"id\" }];\n const data = await indexedDBService.get(\"banditConfig\", 1, \"config\", \"mcpTools\", storeConfigs);\n \n if (data?.tools && Array.isArray(data.tools)) {\n // Merge saved tools with built-in tools, ensuring built-ins always use default definition\n const savedTools = data.tools as MCPTool[];\n const builtInIds = defaultTools.map(t => t.id);\n const customTools = savedTools.filter(\n (tool) => !tool.isBuiltIn && !builtInIds.includes(tool.id)\n );\n\n set({\n tools: [...defaultTools, ...customTools],\n isLoaded: true\n });\n debugLogger.info(\"MCP tools loaded from IndexedDB\", { \n totalTools: defaultTools.length + customTools.length,\n builtInTools: defaultTools.length,\n customTools: customTools.length\n });\n } else {\n // First time, save defaults\n set({ isLoaded: true });\n await get().saveTools();\n debugLogger.info(\"Default MCP tools initialized\");\n }\n } catch (error) {\n debugLogger.error(\"Failed to load MCP tools from IndexedDB\", { error });\n set({ isLoaded: true }); // Mark as loaded even if failed, so UI can render\n }\n },\n \n saveTools: async () => {\n try {\n const { tools } = get();\n const storeConfigs = [{ name: \"config\", keyPath: \"id\" }];\n \n // Persist only user-defined custom tools — never built-ins or the dynamic\n // tools discovered from MCP servers (those are re-fetched from the gateway).\n const customTools = tools.filter((tool) => !tool.isBuiltIn && !tool.mcpServerId);\n\n await indexedDBService.put(\"banditConfig\", 1, \"config\", {\n id: \"mcpTools\",\n tools: customTools,\n }, storeConfigs);\n\n debugLogger.debug(\"MCP tools saved to IndexedDB\", { toolCount: customTools.length });\n } catch (error) {\n debugLogger.error(\"Failed to save MCP tools to IndexedDB\", { error });\n }\n },\n\n // Discover the user's connected MCP servers' tools from the gateway and merge\n // them into the tool list (so the model can call them). Replaces any prior\n // MCP-server tools; best-effort — a single unreachable server is skipped.\n loadMcpServerTools: async () => {\n let servers;\n try {\n servers = await listMcpServers();\n } catch (error) {\n debugLogger.warn(\"Could not list MCP servers\", { error: String(error) });\n return;\n }\n\n const collected: MCPTool[] = [];\n for (const server of servers.filter((s) => s.enabled)) {\n try {\n const { tools } = await discoverMcpTools(server.id);\n for (const t of tools) {\n const fnName = sanitizeMcpToolName(`mcp_${server.name}_${t.name}`);\n const schema =\n t.inputSchema && typeof t.inputSchema === \"object\" && (t.inputSchema as { type?: string }).type === \"object\"\n ? (t.inputSchema as MCPTool[\"function\"][\"parameters\"])\n : { type: \"object\" as const, properties: {}, required: [] };\n collected.push({\n id: `mcp-${server.id}-${t.name}`,\n name: fnName,\n description: t.description || `${t.name} (via ${server.name})`,\n enabled: true,\n type: \"function\",\n function: {\n name: fnName,\n description: t.description || `${t.name} — provided by the ${server.name} MCP server.`,\n parameters: schema,\n },\n mcpServerId: server.id,\n mcpToolName: t.name,\n });\n }\n } catch (error) {\n debugLogger.warn(\"Failed to discover tools for MCP server\", { server: server.name, error: String(error) });\n }\n }\n\n set((state) => ({\n tools: [...state.tools.filter((t) => !t.mcpServerId), ...collected],\n }));\n debugLogger.info(\"MCP server tools loaded\", { count: collected.length });\n },\n}));\n","import { usePackageSettingsStore } from \"../../store/packageSettingsStore\";\nimport { authenticationService } from \"../auth/authenticationService\";\n\n/**\n * Client for the gateway's MCP host (phase 1 backend at /api/mcp/servers + /invoke).\n * Lets users connect their own remote MCP servers; the gateway holds the configs\n * and proxies discovery/invocation. Mirrors mcpService's gateway-base + bearer\n * conventions (gatewayApiUrl already ends in /api, so paths start with /mcp/...).\n */\n\nexport interface McpServer {\n id: string;\n name: string;\n url: string;\n authType: string;\n hasAuth: boolean;\n headerName?: string | null;\n enabled: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface McpServerInput {\n name: string;\n url: string;\n authType?: \"none\" | \"bearer\" | \"header\";\n authValue?: string;\n headerName?: string;\n enabled?: boolean;\n}\n\nexport interface McpDiscoveredTool {\n name: string;\n description?: string;\n inputSchema?: Record<string, unknown>;\n}\n\nconst gatewayBase = (): string => {\n const settings = usePackageSettingsStore.getState().settings;\n const url = settings?.gatewayApiUrl?.replace(/\\/$/, \"\");\n if (!url) throw new Error(\"Gateway API is not configured.\");\n return url;\n};\n\nconst authHeaders = (): Record<string, string> => {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n const token = authenticationService.getToken();\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n return headers;\n};\n\nconst parse = async (res: Response) => {\n const text = await res.text();\n const body = text ? JSON.parse(text) : null;\n if (!res.ok) {\n const message =\n (body && typeof body === \"object\" && (body.error || body.message)) ||\n `Request failed (${res.status})`;\n throw new Error(String(message));\n }\n return body;\n};\n\nexport const listMcpServers = async (): Promise<McpServer[]> =>\n parse(await fetch(`${gatewayBase()}/mcp/servers`, { headers: authHeaders() }));\n\nexport const addMcpServer = async (input: McpServerInput): Promise<McpServer> =>\n parse(\n await fetch(`${gatewayBase()}/mcp/servers`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify(input),\n }),\n );\n\nexport const updateMcpServer = async (\n id: string,\n input: Partial<McpServerInput>,\n): Promise<McpServer> =>\n parse(\n await fetch(`${gatewayBase()}/mcp/servers/${encodeURIComponent(id)}`, {\n method: \"PUT\",\n headers: authHeaders(),\n body: JSON.stringify(input),\n }),\n );\n\nexport const deleteMcpServer = async (id: string): Promise<void> => {\n const res = await fetch(`${gatewayBase()}/mcp/servers/${encodeURIComponent(id)}`, {\n method: \"DELETE\",\n headers: authHeaders(),\n });\n if (!res.ok && res.status !== 204) {\n throw new Error(`Could not remove the server (${res.status}).`);\n }\n};\n\nexport const discoverMcpTools = async (\n id: string,\n): Promise<{ serverId: string; server: string; tools: McpDiscoveredTool[] }> =>\n parse(await fetch(`${gatewayBase()}/mcp/servers/${encodeURIComponent(id)}/tools`, { headers: authHeaders() }));\n"],"mappings":"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","names":[]}
|