Merge branch 'arc53:main' into main

This commit is contained in:
Abhishek Malviya
2025-10-10 15:44:40 +05:30
committed by GitHub
17 changed files with 294 additions and 137 deletions

View File

@@ -193,6 +193,43 @@ class BaseAnswerResource:
data = json.dumps({"type": "end"})
yield f"data: {data}\n\n"
except GeneratorExit:
# Client aborted the connection
logger.info(
f"Stream aborted by client for question: {question[:50]}... "
)
# Save partial response to database before exiting
if should_save_conversation and response_full:
try:
if isNoneDoc:
for doc in source_log_docs:
doc["source"] = "None"
llm = LLMCreator.create_llm(
settings.LLM_PROVIDER,
api_key=settings.API_KEY,
user_api_key=user_api_key,
decoded_token=decoded_token,
)
self.conversation_service.save_conversation(
conversation_id,
question,
response_full,
thought,
source_log_docs,
tool_calls,
llm,
self.gpt_model,
decoded_token,
index=index,
api_key=user_api_key,
agent_id=agent_id,
is_shared_usage=is_shared_usage,
shared_token=shared_token,
attachment_ids=attachment_ids,
)
except Exception as e:
logger.error(f"Error saving partial response: {str(e)}", exc_info=True)
raise
except Exception as e:
logger.error(f"Error in stream: {str(e)}", exc_info=True)
data = json.dumps(

View File

@@ -46,5 +46,9 @@ class AnthropicLLM(BaseLLM):
stream=True,
)
for completion in stream_response:
yield completion.completion
try:
for completion in stream_response:
yield completion.completion
finally:
if hasattr(stream_response, 'close'):
stream_response.close()

View File

@@ -121,11 +121,19 @@ class DocsGPTAPILLM(BaseLLM):
model="docsgpt", messages=messages, stream=stream, **kwargs
)
for line in response:
if len(line.choices) > 0 and line.choices[0].delta.content is not None and len(line.choices[0].delta.content) > 0:
yield line.choices[0].delta.content
elif len(line.choices) > 0:
yield line.choices[0]
try:
for line in response:
if (
len(line.choices) > 0
and line.choices[0].delta.content is not None
and len(line.choices[0].delta.content) > 0
):
yield line.choices[0].delta.content
elif len(line.choices) > 0:
yield line.choices[0]
finally:
if hasattr(response, 'close'):
response.close()
def _supports_tools(self):
return True

View File

@@ -373,17 +373,21 @@ class GoogleLLM(BaseLLM):
config=config,
)
for chunk in response:
if hasattr(chunk, "candidates") and chunk.candidates:
for candidate in chunk.candidates:
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
if part.function_call:
yield part
elif part.text:
yield part.text
elif hasattr(chunk, "text"):
yield chunk.text
try:
for chunk in response:
if hasattr(chunk, "candidates") and chunk.candidates:
for candidate in chunk.candidates:
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
if part.function_call:
yield part
elif part.text:
yield part.text
elif hasattr(chunk, "text"):
yield chunk.text
finally:
if hasattr(response, 'close'):
response.close()
def _supports_tools(self):
"""Return whether this LLM supports function calling."""

View File

@@ -170,15 +170,19 @@ class OpenAILLM(BaseLLM):
response = self.client.chat.completions.create(**request_params)
for line in response:
if (
len(line.choices) > 0
and line.choices[0].delta.content is not None
and len(line.choices[0].delta.content) > 0
):
yield line.choices[0].delta.content
elif len(line.choices) > 0:
yield line.choices[0]
try:
for line in response:
if (
len(line.choices) > 0
and line.choices[0].delta.content is not None
and len(line.choices[0].delta.content) > 0
):
yield line.choices[0].delta.content
elif len(line.choices) > 0:
yield line.choices[0]
finally:
if hasattr(response, 'close'):
response.close()
def _supports_tools(self):
return True

View File

@@ -1,4 +1,6 @@
# Please put appropriate value
VITE_BASE_URL=http://localhost:5173
VITE_API_HOST=http://127.0.0.1:7091
VITE_API_STREAMING=true
VITE_API_STREAMING=true
VITE_NOTIFICATION_TEXT="What's new in 0.14.0 — Changelog"
VITE_NOTIFICATION_LINK="#"

View File

@@ -15,7 +15,7 @@
"i18next": "^25.5.3",
"i18next-browser-languagedetector": "^8.0.2",
"lodash": "^4.17.21",
"mermaid": "^11.6.0",
"mermaid": "^11.12.0",
"prop-types": "^15.8.1",
"react": "^19.1.0",
"react-chartjs-2": "^5.3.0",
@@ -90,22 +90,22 @@
}
},
"node_modules/@antfu/install-pkg": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.0.0.tgz",
"integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
"integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
"license": "MIT",
"dependencies": {
"package-manager-detector": "^0.2.8",
"tinyexec": "^0.3.2"
"package-manager-detector": "^1.3.0",
"tinyexec": "^1.0.1"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@antfu/utils": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz",
"integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==",
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-9.3.0.tgz",
"integrity": "sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
@@ -957,18 +957,18 @@
"license": "MIT"
},
"node_modules/@iconify/utils": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz",
"integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.0.2.tgz",
"integrity": "sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==",
"license": "MIT",
"dependencies": {
"@antfu/install-pkg": "^1.0.0",
"@antfu/utils": "^8.1.0",
"@antfu/install-pkg": "^1.1.0",
"@antfu/utils": "^9.2.0",
"@iconify/types": "^2.0.0",
"debug": "^4.4.0",
"globals": "^15.14.0",
"debug": "^4.4.1",
"globals": "^15.15.0",
"kolorist": "^1.8.0",
"local-pkg": "^1.0.0",
"local-pkg": "^1.1.1",
"mlly": "^1.7.4"
}
},
@@ -1053,9 +1053,9 @@
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"node_modules/@mermaid-js/parser": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.4.0.tgz",
"integrity": "sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz",
"integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==",
"license": "MIT",
"dependencies": {
"langium": "3.3.1"
@@ -2856,9 +2856,9 @@
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -4141,15 +4141,16 @@
}
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"version": "1.11.18",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -5326,9 +5327,9 @@
}
},
"node_modules/exsolve": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz",
"integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
"integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
"license": "MIT"
},
"node_modules/extend": {
@@ -6909,13 +6910,14 @@
}
},
"node_modules/katex": {
"version": "0.16.21",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz",
"integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==",
"version": "0.16.23",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.23.tgz",
"integrity": "sha512-7VlC1hsEEolL9xNO05v9VjrvWZePkCVBJqj8ruICxYjZfHaHbaU53AlP+PODyFIXEnaEIEWi3wJy7FPZ95JAVg==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
"license": "MIT",
"dependencies": {
"commander": "^8.3.0"
},
@@ -7280,14 +7282,14 @@
}
},
"node_modules/local-pkg": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
"integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
"integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
"license": "MIT",
"dependencies": {
"mlly": "^1.7.4",
"pkg-types": "^2.0.1",
"quansync": "^0.2.8"
"pkg-types": "^2.3.0",
"quansync": "^0.2.11"
},
"engines": {
"node": ">=14"
@@ -7483,15 +7485,15 @@
}
},
"node_modules/marked": {
"version": "15.0.7",
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz",
"integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==",
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.0.tgz",
"integrity": "sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 18"
"node": ">= 20"
}
},
"node_modules/math-intrinsics": {
@@ -7927,14 +7929,14 @@
}
},
"node_modules/mermaid": {
"version": "11.6.0",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.6.0.tgz",
"integrity": "sha512-PE8hGUy1LDlWIHWBP05SFdqUHGmRcCcK4IzpOKPE35eOw+G9zZgcnMpyunJVUEOgb//KBORPjysKndw8bFLuRg==",
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.0.tgz",
"integrity": "sha512-ZudVx73BwrMJfCFmSSJT84y6u5brEoV8DOItdHomNLz32uBjNrelm7mg95X7g+C6UoQH/W6mBLGDEDv73JdxBg==",
"license": "MIT",
"dependencies": {
"@braintree/sanitize-url": "^7.0.4",
"@iconify/utils": "^2.1.33",
"@mermaid-js/parser": "^0.4.0",
"@braintree/sanitize-url": "^7.1.1",
"@iconify/utils": "^3.0.1",
"@mermaid-js/parser": "^0.6.2",
"@types/d3": "^7.4.3",
"cytoscape": "^3.29.3",
"cytoscape-cose-bilkent": "^4.1.0",
@@ -7942,12 +7944,12 @@
"d3": "^7.9.0",
"d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.11",
"dayjs": "^1.11.13",
"dompurify": "^3.2.4",
"katex": "^0.16.9",
"dayjs": "^1.11.18",
"dompurify": "^3.2.5",
"katex": "^0.16.22",
"khroma": "^2.1.0",
"lodash-es": "^4.17.21",
"marked": "^15.0.7",
"marked": "^16.2.1",
"roughjs": "^4.6.6",
"stylis": "^4.3.6",
"ts-dedent": "^2.2.0",
@@ -8606,15 +8608,15 @@
}
},
"node_modules/mlly": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz",
"integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==",
"license": "MIT",
"dependencies": {
"acorn": "^8.14.0",
"pathe": "^2.0.1",
"pkg-types": "^1.3.0",
"ufo": "^1.5.4"
"acorn": "^8.15.0",
"pathe": "^2.0.3",
"pkg-types": "^1.3.1",
"ufo": "^1.6.1"
}
},
"node_modules/mlly/node_modules/confbox": {
@@ -8923,13 +8925,10 @@
}
},
"node_modules/package-manager-detector": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
"integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==",
"license": "MIT",
"dependencies": {
"quansync": "^0.2.7"
}
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.4.0.tgz",
"integrity": "sha512-rRZ+pR1Usc+ND9M2NkmCvE/LYJS+8ORVV9X0KuNSY/gFsp7RBHJM/ADh9LYq4Vvfq6QkKrW6/weuh8SMEtN5gw==",
"license": "MIT"
},
"node_modules/parent-module": {
"version": "1.0.1",
@@ -9084,13 +9083,13 @@
}
},
"node_modules/pkg-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",
"integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
"license": "MIT",
"dependencies": {
"confbox": "^0.2.1",
"exsolve": "^1.0.1",
"confbox": "^0.2.2",
"exsolve": "^1.0.7",
"pathe": "^2.0.3"
}
},
@@ -9302,9 +9301,9 @@
}
},
"node_modules/quansync": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
"integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
"funding": [
{
"type": "individual",
@@ -10539,9 +10538,9 @@
"dev": true
},
"node_modules/tinyexec": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
"license": "MIT"
},
"node_modules/tinyglobby": {
@@ -10791,9 +10790,9 @@
}
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
"license": "MIT"
},
"node_modules/unbox-primitive": {

View File

@@ -26,7 +26,7 @@
"i18next": "^25.5.3",
"i18next-browser-languagedetector": "^8.0.2",
"lodash": "^4.17.21",
"mermaid": "^11.6.0",
"mermaid": "^11.12.0",
"prop-types": "^15.8.1",
"react": "^19.1.0",
"react-chartjs-2": "^5.3.0",

View File

@@ -15,6 +15,7 @@ import useTokenAuth from './hooks/useTokenAuth';
import Navigation from './Navigation';
import PageNotFound from './PageNotFound';
import Setting from './settings';
import Notification from './components/Notification';
function AuthWrapper({ children }: { children: React.ReactNode }) {
const { isAuthLoading } = useTokenAuth();
@@ -52,11 +53,27 @@ function MainLayout() {
}
export default function App() {
const [, , componentMounted] = useDarkTheme();
const [showNotification, setShowNotification] = useState<boolean>(() => {
const saved = localStorage.getItem('showNotification');
return saved ? JSON.parse(saved) : true;
});
const notificationText = import.meta.env.VITE_NOTIFICATION_TEXT;
const notificationLink = import.meta.env.VITE_NOTIFICATION_LINK;
if (!componentMounted) {
return <div />;
}
return (
<div className="relative h-full overflow-hidden">
{notificationLink && notificationText && showNotification && (
<Notification
notificationText={notificationText}
notificationLink={notificationLink}
handleCloseNotification={() => {
setShowNotification(false);
localStorage.setItem('showNotification', 'false');
}}
/>
)}
<Routes>
<Route
element={

View File

@@ -399,7 +399,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
{conversations?.loading && !isDeletingConversation && (
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 transform">
<img
src={isDarkTheme ? SpinnerDark : Spinner}
src={isDarkTheme ? Spinner : SpinnerDark}
className="animate-spin cursor-pointer bg-transparent"
alt="Loading conversations"
/>

View File

@@ -2,6 +2,12 @@ import AgentImage from '../components/AgentImage';
import { Agent } from './types';
export default function SharedAgentCard({ agent }: { agent: Agent }) {
// Check if shared metadata exists and has properties (type is 'any' so we validate it's a non-empty object)
const hasSharedMetadata =
agent.shared_metadata &&
typeof agent.shared_metadata === 'object' &&
agent.shared_metadata !== null &&
Object.keys(agent.shared_metadata).length > 0;
return (
<div className="border-dark-gray dark:border-grey flex w-full max-w-[720px] flex-col rounded-3xl border p-6 shadow-xs sm:w-fit sm:min-w-[480px]">
<div className="flex items-center gap-3">
@@ -20,7 +26,7 @@ export default function SharedAgentCard({ agent }: { agent: Agent }) {
</p>
</div>
</div>
{agent.shared_metadata && (
{hasSharedMetadata && (
<div className="mt-4 flex items-center gap-8">
{agent.shared_metadata?.shared_by && (
<p className="text-eerie-black text-xs font-light sm:text-sm dark:text-[#E0E0E0]">

View File

@@ -0,0 +1,3 @@
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.0303 7.03033C13.3232 6.73744 13.3232 6.26256 13.0303 5.96967L8.25736 1.1967C7.96447 0.903806 7.48959 0.903806 7.1967 1.1967C6.90381 1.48959 6.90381 1.96447 7.1967 2.25736L11.4393 6.5L7.1967 10.7426C6.90381 11.0355 6.90381 11.5104 7.1967 11.8033C7.48959 12.0962 7.96447 12.0962 8.25736 11.8033L13.0303 7.03033ZM0.5 6.5V7.25H12.5V6.5V5.75H0.5V6.5Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -7,11 +7,9 @@ import userService from '../api/services/userService';
import AlertIcon from '../assets/alert.svg';
import ClipIcon from '../assets/clip.svg';
import ExitIcon from '../assets/exit.svg';
import PaperPlane from '../assets/paper_plane.svg';
import SendArrowIcon from './SendArrowIcon';
import SourceIcon from '../assets/source.svg';
import DocumentationDark from '../assets/documentation-dark.svg';
import SpinnerDark from '../assets/spinner-dark.svg';
import Spinner from '../assets/spinner.svg';
import ToolIcon from '../assets/tool.svg';
import {
addAttachment,
@@ -19,7 +17,7 @@ import {
selectAttachments,
updateAttachment,
} from '../upload/uploadSlice';
import { useDarkTheme } from '../hooks';
import { ActiveState } from '../models/misc';
import {
selectSelectedDocs,
@@ -29,6 +27,7 @@ import Upload from '../upload/Upload';
import { getOS, isTouchDevice } from '../utils/browserUtils';
import SourcesPopup from './SourcesPopup';
import ToolsPopup from './ToolsPopup';
import { handleAbort } from '../conversation/conversationSlice';
type MessageInputProps = {
onSubmit: (text: string) => void;
@@ -46,7 +45,6 @@ export default function MessageInput({
autoFocus = true,
}: MessageInputProps) {
const { t } = useTranslation();
const [isDarkTheme] = useDarkTheme();
const [value, setValue] = useState('');
const inputRef = useRef<HTMLTextAreaElement>(null);
const sourceButtonRef = useRef<HTMLButtonElement>(null);
@@ -256,6 +254,11 @@ export default function MessageInput({
setValue('');
}
};
const handleCancel = () => {
handleAbort();
};
return (
<div className="mx-2 flex w-full flex-col">
<div className="border-dark-gray bg-lotion dark:border-grey relative flex w-full flex-col rounded-[23px] border dark:bg-transparent">
@@ -427,26 +430,33 @@ export default function MessageInput({
{/* Additional badges can be added here in the future */}
</div>
<button
onClick={loading ? undefined : handleSubmit}
aria-label={loading ? t('loading') : t('send')}
className={`flex h-7 w-7 items-center justify-center rounded-full sm:h-9 sm:w-9 ${loading || !value.trim() ? 'bg-black opacity-60 dark:bg-[#F0F3F4] dark:opacity-80' : 'bg-black opacity-100 dark:bg-[#F0F3F4]'} ml-auto shrink-0`}
disabled={loading}
>
{loading ? (
<img
src={isDarkTheme ? SpinnerDark : Spinner}
className="mx-auto my-auto block h-3.5 w-3.5 animate-spin sm:h-4 sm:w-4"
alt={t('loading')}
{loading ? (
<button
onClick={handleCancel}
aria-label={t('cancel')}
className={`ml-auto flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-[#7F54D6] text-white sm:h-9 sm:w-9`}
disabled={!loading}
>
<div className="flex h-3 w-3 items-center justify-center rounded-[3px] bg-white sm:h-3.5 sm:w-3.5" />
</button>
) : (
<button
onClick={handleSubmit}
aria-label={t('send')}
className={`ml-auto flex h-7 w-7 shrink-0 items-center justify-center rounded-full transition-colors duration-300 ease-in-out sm:h-9 sm:w-9 ${
value.trim() && !loading
? 'bg-purple-30 text-white'
: 'bg-[#EDEDED] text-[#959595] dark:bg-[#37383D] dark:text-[#77787D]'
}`}
disabled={!value.trim() || loading}
>
<SendArrowIcon
className="mx-auto my-auto block h-3.5 w-3.5 sm:h-4 sm:w-4"
aria-label={t('send')}
role="img"
/>
) : (
<img
className={`mx-auto my-auto block h-3.5 w-3.5 translate-x-[-0.9px] translate-y-[1.1px] sm:h-4 sm:w-4 ${isDarkTheme ? 'invert filter' : ''}`}
src={PaperPlane}
alt={t('send')}
/>
)}
</button>
</button>
)}
</div>
</div>

View File

@@ -0,0 +1,45 @@
import close from '../assets/cross.svg';
import rightArrow from '../assets/arrow-full-right.svg';
import bg from '../assets/notification-bg.jpg';
interface NotificationProps {
notificationText: string;
notificationLink: string;
handleCloseNotification: () => void;
}
export default function Notification({
notificationText,
notificationLink,
handleCloseNotification,
}: NotificationProps) {
return (
<a
className="absolute right-2 bottom-6 z-20 flex w-3/4 items-center justify-center gap-2 rounded-lg bg-cover bg-center bg-no-repeat px-2 py-4 sm:right-4 md:w-2/5 lg:w-1/3 xl:w-1/4 2xl:w-1/5"
style={{ backgroundImage: `url(${bg})` }}
href={notificationLink}
target="_blank"
aria-label="Notification"
rel="noreferrer"
>
<p className="text-white-3000 text-xs leading-6 font-semibold xl:text-sm xl:leading-7">
{notificationText}
</p>
<span>
<img className="w-full" src={rightArrow} alt="" />
</span>
<button
className="absolute top-2 right-2 z-30 h-4 w-4 hover:opacity-70"
aria-label="Close notification"
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleCloseNotification();
}}
>
<img className="w-full" src={close} alt="Close notification" />
</button>
</a>
);
}

View File

@@ -0,0 +1,17 @@
import { SVGProps } from 'react';
const SendArrowIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
width="11"
height="14"
viewBox="0 0 11 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M0.292786 6.20676C0.105315 6.01923 -3.59956e-07 5.76492 -3.71547e-07 5.49976C-3.83138e-07 5.23459 0.105315 4.98028 0.292786 4.79276L4.79279 0.292756C4.98031 0.105284 5.23462 -3.07464e-05 5.49979 -3.0758e-05C5.76495 -3.07696e-05 6.01926 0.105284 6.20679 0.292756L10.7068 4.79276C10.8889 4.98136 10.9897 5.23396 10.9875 5.49616C10.9852 5.75835 10.88 6.00917 10.6946 6.19457C10.5092 6.37998 10.2584 6.48515 9.99619 6.48743C9.73399 6.48971 9.48139 6.38891 9.29279 6.20676L6.49979 3.49976L6.49979 12.9998C6.49979 13.265 6.39443 13.5193 6.20689 13.7069C6.01936 13.8944 5.765 13.9998 5.49979 13.9998C5.23457 13.9998 4.98022 13.8944 4.79268 13.7069C4.60514 13.5193 4.49979 13.265 4.49979 12.9998L4.49979 3.49976L1.70679 6.20676C1.51926 6.39423 1.26495 6.49954 0.999786 6.49954C0.734622 6.49954 0.480314 6.39423 0.292786 6.20676Z"
fill="currentColor"
/>
</svg>
);
export default SendArrowIcon;

View File

@@ -202,6 +202,7 @@ export default function Conversation() {
queries[queries.length - 1].response && setLastQueryReturnedErr(false);
}
}, [queries[queries.length - 1]]);
return (
<div className="flex h-full flex-col justify-end gap-1">
<ConversationMessages