Spaces:
Paused
Paused
frdel commited on
Commit ·
a730828
1
Parent(s): 8226946
messages redesign wip
Browse files- agent.py +4 -14
- python/extensions/before_main_llm_call/.gitkeep +0 -0
- python/extensions/before_main_llm_call/_10_log_for_stream.py +26 -0
- python/extensions/message_loop_prompts_after/_50_recall_memories.py +10 -10
- python/extensions/message_loop_prompts_after/_51_recall_solutions.py +1 -5
- python/extensions/monologue_end/_50_memorize_fragments.py +1 -6
- python/extensions/monologue_end/_51_memorize_solutions.py +2 -7
- python/extensions/reasoning_stream/_10_log_from_stream.py +3 -3
- python/extensions/response_stream/_10_log_from_stream.py +8 -7
- python/extensions/response_stream/_20_live_response.py +1 -1
- python/helpers/tool.py +2 -2
- python/tools/browser_agent.py +1 -1
- python/tools/call_subordinate.py +9 -1
- python/tools/input.py +1 -1
- python/tools/{knowledge_tool.py → knowledge_tool._py} +0 -0
- python/tools/task_done.py +0 -13
- python/tools/{webpage_content_tool.py → webpage_content_tool._py} +0 -0
- webui/components/messages/resize/message-resize-store.js +56 -5
- webui/css/messages.css +646 -625
- webui/index.js +10 -32
- webui/js/messages.js +23 -4
agent.py
CHANGED
|
@@ -300,7 +300,7 @@ class Agent:
|
|
| 300 |
|
| 301 |
# non-config vars
|
| 302 |
self.number = number
|
| 303 |
-
self.agent_name = f"
|
| 304 |
|
| 305 |
self.history = history.History(self)
|
| 306 |
self.last_user_message: history.Message | None = None
|
|
@@ -333,19 +333,8 @@ class Agent:
|
|
| 333 |
# prepare LLM chain (model, system, history)
|
| 334 |
prompt = await self.prepare_prompt(loop_data=self.loop_data)
|
| 335 |
|
| 336 |
-
#
|
| 337 |
-
|
| 338 |
-
bold=True,
|
| 339 |
-
font_color="green",
|
| 340 |
-
padding=True,
|
| 341 |
-
background_color="white",
|
| 342 |
-
).print(f"{self.agent_name}: Generating")
|
| 343 |
-
# create log message right away, more responsive
|
| 344 |
-
self.loop_data.params_temporary["log_item_generating"] = (
|
| 345 |
-
self.context.log.log(
|
| 346 |
-
type="agent", heading=f"{self.agent_name}: Generating..."
|
| 347 |
-
)
|
| 348 |
-
)
|
| 349 |
|
| 350 |
async def reasoning_callback(chunk: str, full: str):
|
| 351 |
if chunk == full:
|
|
@@ -360,6 +349,7 @@ class Agent:
|
|
| 360 |
printer.stream(chunk)
|
| 361 |
await self.handle_response_stream(full)
|
| 362 |
|
|
|
|
| 363 |
agent_response, _reasoning = await self.call_chat_model(
|
| 364 |
messages=prompt,
|
| 365 |
response_callback=stream_callback,
|
|
|
|
| 300 |
|
| 301 |
# non-config vars
|
| 302 |
self.number = number
|
| 303 |
+
self.agent_name = f"A{self.number}"
|
| 304 |
|
| 305 |
self.history = history.History(self)
|
| 306 |
self.last_user_message: history.Message | None = None
|
|
|
|
| 333 |
# prepare LLM chain (model, system, history)
|
| 334 |
prompt = await self.prepare_prompt(loop_data=self.loop_data)
|
| 335 |
|
| 336 |
+
# call before_main_llm_call extensions
|
| 337 |
+
await self.call_extensions("before_main_llm_call", loop_data=self.loop_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
async def reasoning_callback(chunk: str, full: str):
|
| 340 |
if chunk == full:
|
|
|
|
| 349 |
printer.stream(chunk)
|
| 350 |
await self.handle_response_stream(full)
|
| 351 |
|
| 352 |
+
# call main LLM
|
| 353 |
agent_response, _reasoning = await self.call_chat_model(
|
| 354 |
messages=prompt,
|
| 355 |
response_callback=stream_callback,
|
python/extensions/before_main_llm_call/.gitkeep
ADDED
|
File without changes
|
python/extensions/before_main_llm_call/_10_log_for_stream.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from python.helpers import persist_chat, tokens
|
| 2 |
+
from python.helpers.extension import Extension
|
| 3 |
+
from agent import LoopData
|
| 4 |
+
import asyncio
|
| 5 |
+
from python.helpers.log import LogItem
|
| 6 |
+
from python.helpers import log
|
| 7 |
+
import math
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class LogForStream(Extension):
|
| 11 |
+
|
| 12 |
+
async def execute(self, loop_data: LoopData = LoopData(), text: str = "", **kwargs):
|
| 13 |
+
# create log message and store it in loop data temporary params
|
| 14 |
+
if "log_item_generating" not in loop_data.params_temporary:
|
| 15 |
+
loop_data.params_temporary["log_item_generating"] = (
|
| 16 |
+
self.agent.context.log.log(
|
| 17 |
+
type="agent",
|
| 18 |
+
heading=build_default_heading(self.agent),
|
| 19 |
+
)
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
def build_heading(agent, text: str):
|
| 23 |
+
return f"icon://network_intelligence {agent.agent_name}: {text}"
|
| 24 |
+
|
| 25 |
+
def build_default_heading(agent):
|
| 26 |
+
return build_heading(agent, "Generating...")
|
python/extensions/message_loop_prompts_after/_50_recall_memories.py
CHANGED
|
@@ -5,6 +5,7 @@ from agent import LoopData
|
|
| 5 |
|
| 6 |
DATA_NAME_TASK = "_recall_memories_task"
|
| 7 |
|
|
|
|
| 8 |
class RecallMemories(Extension):
|
| 9 |
|
| 10 |
INTERVAL = 3
|
|
@@ -16,13 +17,14 @@ class RecallMemories(Extension):
|
|
| 16 |
|
| 17 |
# every 3 iterations (or the first one) recall memories
|
| 18 |
if loop_data.iteration % RecallMemories.INTERVAL == 0:
|
| 19 |
-
task = asyncio.create_task(
|
|
|
|
|
|
|
| 20 |
else:
|
| 21 |
task = None
|
| 22 |
|
| 23 |
# set to agent to be able to wait for it
|
| 24 |
self.agent.set_data(DATA_NAME_TASK, task)
|
| 25 |
-
|
| 26 |
|
| 27 |
async def search_memories(self, loop_data: LoopData, **kwargs):
|
| 28 |
|
|
@@ -32,12 +34,8 @@ class RecallMemories(Extension):
|
|
| 32 |
del extras["memories"]
|
| 33 |
|
| 34 |
# try:
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
type="info", content="Searching memories...", temp=True
|
| 38 |
-
)
|
| 39 |
-
|
| 40 |
-
# show full util message, this will hide temp message immediately if turned on
|
| 41 |
log_item = self.agent.context.log.log(
|
| 42 |
type="util",
|
| 43 |
heading="Searching memories...",
|
|
@@ -47,7 +45,7 @@ class RecallMemories(Extension):
|
|
| 47 |
# msgs_text = self.agent.concat_messages(
|
| 48 |
# self.agent.history[-RecallMemories.HISTORY :]
|
| 49 |
# ) # only last X messages
|
| 50 |
-
msgs_text = self.agent.history.output_text()[-RecallMemories.HISTORY:]
|
| 51 |
system = self.agent.read_prompt(
|
| 52 |
"memory.memories_query.sys.md", history=msgs_text
|
| 53 |
)
|
|
@@ -59,7 +57,9 @@ class RecallMemories(Extension):
|
|
| 59 |
# call util llm to summarize conversation
|
| 60 |
query = await self.agent.call_utility_model(
|
| 61 |
system=system,
|
| 62 |
-
message=
|
|
|
|
|
|
|
| 63 |
callback=log_callback,
|
| 64 |
)
|
| 65 |
|
|
|
|
| 5 |
|
| 6 |
DATA_NAME_TASK = "_recall_memories_task"
|
| 7 |
|
| 8 |
+
|
| 9 |
class RecallMemories(Extension):
|
| 10 |
|
| 11 |
INTERVAL = 3
|
|
|
|
| 17 |
|
| 18 |
# every 3 iterations (or the first one) recall memories
|
| 19 |
if loop_data.iteration % RecallMemories.INTERVAL == 0:
|
| 20 |
+
task = asyncio.create_task(
|
| 21 |
+
self.search_memories(loop_data=loop_data, **kwargs)
|
| 22 |
+
)
|
| 23 |
else:
|
| 24 |
task = None
|
| 25 |
|
| 26 |
# set to agent to be able to wait for it
|
| 27 |
self.agent.set_data(DATA_NAME_TASK, task)
|
|
|
|
| 28 |
|
| 29 |
async def search_memories(self, loop_data: LoopData, **kwargs):
|
| 30 |
|
|
|
|
| 34 |
del extras["memories"]
|
| 35 |
|
| 36 |
# try:
|
| 37 |
+
|
| 38 |
+
# show full util message
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
log_item = self.agent.context.log.log(
|
| 40 |
type="util",
|
| 41 |
heading="Searching memories...",
|
|
|
|
| 45 |
# msgs_text = self.agent.concat_messages(
|
| 46 |
# self.agent.history[-RecallMemories.HISTORY :]
|
| 47 |
# ) # only last X messages
|
| 48 |
+
msgs_text = self.agent.history.output_text()[-RecallMemories.HISTORY :]
|
| 49 |
system = self.agent.read_prompt(
|
| 50 |
"memory.memories_query.sys.md", history=msgs_text
|
| 51 |
)
|
|
|
|
| 57 |
# call util llm to summarize conversation
|
| 58 |
query = await self.agent.call_utility_model(
|
| 59 |
system=system,
|
| 60 |
+
message=(
|
| 61 |
+
loop_data.user_message.output_text() if loop_data.user_message else ""
|
| 62 |
+
),
|
| 63 |
callback=log_callback,
|
| 64 |
)
|
| 65 |
|
python/extensions/message_loop_prompts_after/_51_recall_solutions.py
CHANGED
|
@@ -32,12 +32,8 @@ class RecallSolutions(Extension):
|
|
| 32 |
del extras["solutions"]
|
| 33 |
|
| 34 |
# try:
|
| 35 |
-
# show temp info message
|
| 36 |
-
self.agent.context.log.log(
|
| 37 |
-
type="info", content="Searching memory for solutions...", temp=True
|
| 38 |
-
)
|
| 39 |
|
| 40 |
-
# show full util message
|
| 41 |
log_item = self.agent.context.log.log(
|
| 42 |
type="util",
|
| 43 |
heading="Searching memory for solutions...",
|
|
|
|
| 32 |
del extras["solutions"]
|
| 33 |
|
| 34 |
# try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
+
# show full util message
|
| 37 |
log_item = self.agent.context.log.log(
|
| 38 |
type="util",
|
| 39 |
heading="Searching memory for solutions...",
|
python/extensions/monologue_end/_50_memorize_fragments.py
CHANGED
|
@@ -13,12 +13,7 @@ class MemorizeMemories(Extension):
|
|
| 13 |
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
|
| 14 |
# try:
|
| 15 |
|
| 16 |
-
# show
|
| 17 |
-
self.agent.context.log.log(
|
| 18 |
-
type="info", content="Memorizing new information...", temp=True
|
| 19 |
-
)
|
| 20 |
-
|
| 21 |
-
# show full util message, this will hide temp message immediately if turned on
|
| 22 |
log_item = self.agent.context.log.log(
|
| 23 |
type="util",
|
| 24 |
heading="Memorizing new information...",
|
|
|
|
| 13 |
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
|
| 14 |
# try:
|
| 15 |
|
| 16 |
+
# show full util message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
log_item = self.agent.context.log.log(
|
| 18 |
type="util",
|
| 19 |
heading="Memorizing new information...",
|
python/extensions/monologue_end/_51_memorize_solutions.py
CHANGED
|
@@ -12,13 +12,8 @@ class MemorizeSolutions(Extension):
|
|
| 12 |
|
| 13 |
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
|
| 14 |
# try:
|
| 15 |
-
|
| 16 |
-
# show
|
| 17 |
-
self.agent.context.log.log(
|
| 18 |
-
type="info", content="Memorizing succesful solutions...", temp=True
|
| 19 |
-
)
|
| 20 |
-
|
| 21 |
-
# show full util message, this will hide temp message immediately if turned on
|
| 22 |
log_item = self.agent.context.log.log(
|
| 23 |
type="util",
|
| 24 |
heading="Memorizing succesful solutions...",
|
|
|
|
| 12 |
|
| 13 |
async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
|
| 14 |
# try:
|
| 15 |
+
|
| 16 |
+
# show full util message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
log_item = self.agent.context.log.log(
|
| 18 |
type="util",
|
| 19 |
heading="Memorizing succesful solutions...",
|
python/extensions/reasoning_stream/_10_log_from_stream.py
CHANGED
|
@@ -5,15 +5,15 @@ import asyncio
|
|
| 5 |
from python.helpers.log import LogItem
|
| 6 |
from python.helpers import log
|
| 7 |
import math
|
| 8 |
-
|
| 9 |
|
| 10 |
class LogFromStream(Extension):
|
| 11 |
|
| 12 |
async def execute(self, loop_data: LoopData = LoopData(), text: str = "", **kwargs):
|
| 13 |
|
| 14 |
# thought length indicator
|
| 15 |
-
|
| 16 |
-
heading =
|
| 17 |
|
| 18 |
# create log message and store it in loop data temporary params
|
| 19 |
if "log_item_generating" not in loop_data.params_temporary:
|
|
|
|
| 5 |
from python.helpers.log import LogItem
|
| 6 |
from python.helpers import log
|
| 7 |
import math
|
| 8 |
+
from python.extensions.before_main_llm_call._10_log_for_stream import build_heading, build_default_heading
|
| 9 |
|
| 10 |
class LogFromStream(Extension):
|
| 11 |
|
| 12 |
async def execute(self, loop_data: LoopData = LoopData(), text: str = "", **kwargs):
|
| 13 |
|
| 14 |
# thought length indicator
|
| 15 |
+
pipes = "|" * math.ceil(math.sqrt(len(text)))
|
| 16 |
+
heading = build_heading(self.agent, f"Reasoning.. {pipes}")
|
| 17 |
|
| 18 |
# create log message and store it in loop data temporary params
|
| 19 |
if "log_item_generating" not in loop_data.params_temporary:
|
python/extensions/response_stream/_10_log_from_stream.py
CHANGED
|
@@ -5,6 +5,7 @@ import asyncio
|
|
| 5 |
from python.helpers.log import LogItem
|
| 6 |
from python.helpers import log
|
| 7 |
import math
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
class LogFromStream(Extension):
|
|
@@ -17,17 +18,17 @@ class LogFromStream(Extension):
|
|
| 17 |
**kwargs,
|
| 18 |
):
|
| 19 |
|
| 20 |
-
heading =
|
| 21 |
if "headline" in parsed:
|
| 22 |
-
heading =
|
| 23 |
elif "thoughts" in parsed:
|
| 24 |
# thought length indicator
|
| 25 |
thoughts = "\n".join(parsed["thoughts"])
|
| 26 |
-
|
| 27 |
-
heading =
|
| 28 |
|
| 29 |
-
if "tool_name" in parsed:
|
| 30 |
-
|
| 31 |
|
| 32 |
# create log message and store it in loop data temporary params
|
| 33 |
if "log_item_generating" not in loop_data.params_temporary:
|
|
@@ -48,4 +49,4 @@ class LogFromStream(Extension):
|
|
| 48 |
kvps.update(parsed)
|
| 49 |
|
| 50 |
# update the log item
|
| 51 |
-
log_item.update(heading=heading, content=text, kvps=kvps)
|
|
|
|
| 5 |
from python.helpers.log import LogItem
|
| 6 |
from python.helpers import log
|
| 7 |
import math
|
| 8 |
+
from python.extensions.before_main_llm_call._10_log_for_stream import build_heading, build_default_heading
|
| 9 |
|
| 10 |
|
| 11 |
class LogFromStream(Extension):
|
|
|
|
| 18 |
**kwargs,
|
| 19 |
):
|
| 20 |
|
| 21 |
+
heading = build_default_heading(self.agent)
|
| 22 |
if "headline" in parsed:
|
| 23 |
+
heading = build_heading(self.agent, parsed['headline'])
|
| 24 |
elif "thoughts" in parsed:
|
| 25 |
# thought length indicator
|
| 26 |
thoughts = "\n".join(parsed["thoughts"])
|
| 27 |
+
pipes = "|" * math.ceil(math.sqrt(len(thoughts)))
|
| 28 |
+
heading = build_heading(self.agent, f"Thinking... {pipes}")
|
| 29 |
|
| 30 |
+
# if "tool_name" in parsed:
|
| 31 |
+
# heading += f" ({parsed['tool_name']})"
|
| 32 |
|
| 33 |
# create log message and store it in loop data temporary params
|
| 34 |
if "log_item_generating" not in loop_data.params_temporary:
|
|
|
|
| 49 |
kvps.update(parsed)
|
| 50 |
|
| 51 |
# update the log item
|
| 52 |
+
log_item.update(heading=heading, content=text, kvps=kvps)
|
python/extensions/response_stream/_20_live_response.py
CHANGED
|
@@ -30,7 +30,7 @@ class LiveResponse(Extension):
|
|
| 30 |
loop_data.params_temporary["log_item_response"] = (
|
| 31 |
self.agent.context.log.log(
|
| 32 |
type="response",
|
| 33 |
-
heading=f"{self.agent.agent_name}: Responding",
|
| 34 |
)
|
| 35 |
)
|
| 36 |
|
|
|
|
| 30 |
loop_data.params_temporary["log_item_response"] = (
|
| 31 |
self.agent.context.log.log(
|
| 32 |
type="response",
|
| 33 |
+
heading=f"icon://chat {self.agent.agent_name}: Responding",
|
| 34 |
)
|
| 35 |
)
|
| 36 |
|
python/helpers/tool.py
CHANGED
|
@@ -42,9 +42,9 @@ class Tool:
|
|
| 42 |
|
| 43 |
def get_log_object(self):
|
| 44 |
if self.method:
|
| 45 |
-
heading = f"{self.agent.agent_name}: Using tool '{self.name}:{self.method}'"
|
| 46 |
else:
|
| 47 |
-
heading = f"{self.agent.agent_name}: Using tool '{self.name}'"
|
| 48 |
return self.agent.context.log.log(type="tool", heading=heading, content="", kvps=self.args)
|
| 49 |
|
| 50 |
def nice_key(self, key:str):
|
|
|
|
| 42 |
|
| 43 |
def get_log_object(self):
|
| 44 |
if self.method:
|
| 45 |
+
heading = f"icon://construction {self.agent.agent_name}: Using tool '{self.name}:{self.method}'"
|
| 46 |
else:
|
| 47 |
+
heading = f"icon://construction {self.agent.agent_name}: Using tool '{self.name}'"
|
| 48 |
return self.agent.context.log.log(type="tool", heading=heading, content="", kvps=self.args)
|
| 49 |
|
| 50 |
def nice_key(self, key:str):
|
python/tools/browser_agent.py
CHANGED
|
@@ -313,7 +313,7 @@ class BrowserAgent(Tool):
|
|
| 313 |
def get_log_object(self):
|
| 314 |
return self.agent.context.log.log(
|
| 315 |
type="browser",
|
| 316 |
-
heading=f"{self.agent.agent_name}:
|
| 317 |
content="",
|
| 318 |
kvps=self.args,
|
| 319 |
)
|
|
|
|
| 313 |
def get_log_object(self):
|
| 314 |
return self.agent.context.log.log(
|
| 315 |
type="browser",
|
| 316 |
+
heading=f"icon://captive_portal {self.agent.agent_name}: Calling Browser Agent",
|
| 317 |
content="",
|
| 318 |
kvps=self.args,
|
| 319 |
)
|
python/tools/call_subordinate.py
CHANGED
|
@@ -31,4 +31,12 @@ class Delegation(Tool):
|
|
| 31 |
result = await subordinate.monologue()
|
| 32 |
|
| 33 |
# result
|
| 34 |
-
return Response(message=result, break_loop=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
result = await subordinate.monologue()
|
| 32 |
|
| 33 |
# result
|
| 34 |
+
return Response(message=result, break_loop=False)
|
| 35 |
+
|
| 36 |
+
def get_log_object(self):
|
| 37 |
+
return self.agent.context.log.log(
|
| 38 |
+
type="tool",
|
| 39 |
+
heading=f"icon://communication {self.agent.agent_name}: Calling Subordinate Agent",
|
| 40 |
+
content="",
|
| 41 |
+
kvps=self.args,
|
| 42 |
+
)
|
python/tools/input.py
CHANGED
|
@@ -20,7 +20,7 @@ class Input(Tool):
|
|
| 20 |
return await cet.execute(**args)
|
| 21 |
|
| 22 |
def get_log_object(self):
|
| 23 |
-
return self.agent.context.log.log(type="code_exe", heading=f"{self.agent.agent_name}: Using tool '{self.name}'", content="", kvps=self.args)
|
| 24 |
|
| 25 |
async def after_execution(self, response, **kwargs):
|
| 26 |
self.agent.hist_add_tool_result(self.name, response.message)
|
|
|
|
| 20 |
return await cet.execute(**args)
|
| 21 |
|
| 22 |
def get_log_object(self):
|
| 23 |
+
return self.agent.context.log.log(type="code_exe", heading=f"icon://keyboard {self.agent.agent_name}: Using tool '{self.name}'", content="", kvps=self.args)
|
| 24 |
|
| 25 |
async def after_execution(self, response, **kwargs):
|
| 26 |
self.agent.hist_add_tool_result(self.name, response.message)
|
python/tools/{knowledge_tool.py → knowledge_tool._py}
RENAMED
|
File without changes
|
python/tools/task_done.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
from python.helpers.tool import Tool, Response
|
| 2 |
-
|
| 3 |
-
class TaskDone(Tool):
|
| 4 |
-
|
| 5 |
-
async def execute(self,**kwargs):
|
| 6 |
-
self.agent.set_data("timeout", 0)
|
| 7 |
-
return Response(message=self.args["text"], break_loop=True)
|
| 8 |
-
|
| 9 |
-
async def before_execution(self, **kwargs):
|
| 10 |
-
self.log = self.agent.context.log.log(type="response", heading=f"{self.agent.agent_name}: Task done", content=self.args.get("text", ""))
|
| 11 |
-
|
| 12 |
-
async def after_execution(self, response, **kwargs):
|
| 13 |
-
pass # do add anything to the history or output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
python/tools/{webpage_content_tool.py → webpage_content_tool._py}
RENAMED
|
File without changes
|
webui/components/messages/resize/message-resize-store.js
CHANGED
|
@@ -14,11 +14,11 @@ const model = {
|
|
| 14 |
_getDefaultSettings() {
|
| 15 |
return {
|
| 16 |
"message-agent": { minimized: true, maximized: false },
|
| 17 |
-
"
|
| 18 |
};
|
| 19 |
},
|
| 20 |
|
| 21 |
-
|
| 22 |
return this.settings[className] || { minimized: false, maximized: false };
|
| 23 |
},
|
| 24 |
|
|
@@ -41,7 +41,7 @@ const model = {
|
|
| 41 |
},
|
| 42 |
|
| 43 |
async minimizeMessageClass(className, event) {
|
| 44 |
-
const set = this.
|
| 45 |
set.minimized = !set.minimized;
|
| 46 |
this._setSetting(className, set);
|
| 47 |
this._applySetting(className, set);
|
|
@@ -49,7 +49,7 @@ const model = {
|
|
| 49 |
},
|
| 50 |
|
| 51 |
async maximizeMessageClass(className, event) {
|
| 52 |
-
const set = this.
|
| 53 |
if (set.minimized) return this.minimizeMessageClass(className, event); // if minimized, unminimize first
|
| 54 |
set.maximized = !set.maximized;
|
| 55 |
this._setSetting(className, set);
|
|
@@ -58,7 +58,58 @@ const model = {
|
|
| 58 |
},
|
| 59 |
|
| 60 |
_applyScroll(event) {
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
},
|
| 63 |
|
| 64 |
_applySetting(className, setting) {
|
|
|
|
| 14 |
_getDefaultSettings() {
|
| 15 |
return {
|
| 16 |
"message-agent": { minimized: true, maximized: false },
|
| 17 |
+
"message-agent-response": { minimized: false, maximized: true },
|
| 18 |
};
|
| 19 |
},
|
| 20 |
|
| 21 |
+
getSetting(className) {
|
| 22 |
return this.settings[className] || { minimized: false, maximized: false };
|
| 23 |
},
|
| 24 |
|
|
|
|
| 41 |
},
|
| 42 |
|
| 43 |
async minimizeMessageClass(className, event) {
|
| 44 |
+
const set = this.getSetting(className);
|
| 45 |
set.minimized = !set.minimized;
|
| 46 |
this._setSetting(className, set);
|
| 47 |
this._applySetting(className, set);
|
|
|
|
| 49 |
},
|
| 50 |
|
| 51 |
async maximizeMessageClass(className, event) {
|
| 52 |
+
const set = this.getSetting(className);
|
| 53 |
if (set.minimized) return this.minimizeMessageClass(className, event); // if minimized, unminimize first
|
| 54 |
set.maximized = !set.maximized;
|
| 55 |
this._setSetting(className, set);
|
|
|
|
| 58 |
},
|
| 59 |
|
| 60 |
_applyScroll(event) {
|
| 61 |
+
if (!event || !event.target) {
|
| 62 |
+
return;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
// Store the element reference to avoid issues with event being modified
|
| 66 |
+
const targetElement = event.target;
|
| 67 |
+
const clickY = event.clientY;
|
| 68 |
+
|
| 69 |
+
// Use requestAnimationFrame for smoother timing with browser rendering
|
| 70 |
+
// requestAnimationFrame(() => {
|
| 71 |
+
try {
|
| 72 |
+
// Get fresh measurements after potential re-renders
|
| 73 |
+
const rect = targetElement.getBoundingClientRect();
|
| 74 |
+
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
|
| 75 |
+
|
| 76 |
+
// Get chat history element
|
| 77 |
+
const chatHistory = document.getElementById('chat-history');
|
| 78 |
+
if (!chatHistory) {
|
| 79 |
+
return;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
// Get chat history position
|
| 83 |
+
const chatRect = chatHistory.getBoundingClientRect();
|
| 84 |
+
|
| 85 |
+
// Calculate element's middle position relative to chat history
|
| 86 |
+
const elementHeight = rect.height;
|
| 87 |
+
const elementMiddle = rect.top + (elementHeight / 2);
|
| 88 |
+
const relativeMiddle = elementMiddle - chatRect.top;
|
| 89 |
+
|
| 90 |
+
// Calculate target scroll position
|
| 91 |
+
let scrollTop;
|
| 92 |
+
|
| 93 |
+
if (typeof clickY === 'number') {
|
| 94 |
+
// Calculate based on click position
|
| 95 |
+
const clickRelativeToChat = clickY - chatRect.top;
|
| 96 |
+
// Add current scroll position and adjust to keep element middle at click position
|
| 97 |
+
scrollTop = chatHistory.scrollTop + relativeMiddle - clickRelativeToChat;
|
| 98 |
+
} else {
|
| 99 |
+
// Position element middle at 50% from the top of chat history viewport (center)
|
| 100 |
+
const targetPosition = chatHistory.clientHeight * 0.5;
|
| 101 |
+
scrollTop = chatHistory.scrollTop + relativeMiddle - targetPosition;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// Apply scroll with instant behavior
|
| 105 |
+
chatHistory.scrollTo({
|
| 106 |
+
top: scrollTop,
|
| 107 |
+
behavior: "auto"
|
| 108 |
+
});
|
| 109 |
+
} catch (e) {
|
| 110 |
+
// Silent error handling
|
| 111 |
+
}
|
| 112 |
+
// });
|
| 113 |
},
|
| 114 |
|
| 115 |
_applySetting(className, setting) {
|
webui/css/messages.css
CHANGED
|
@@ -1,656 +1,677 @@
|
|
| 1 |
/* Chat History */
|
| 2 |
#chat-history {
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
|
| 49 |
/* Message Styles */
|
| 50 |
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
}
|
| 215 |
-
|
| 216 |
-
.msg-kvps th {
|
| 217 |
-
color: var(--color-primary);
|
| 218 |
-
width: 40%;
|
| 219 |
-
}
|
| 220 |
-
|
| 221 |
-
.msg-kvps tr {
|
| 222 |
-
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
|
| 223 |
-
}
|
| 224 |
-
|
| 225 |
-
.msg-heading {
|
| 226 |
-
margin: 0;
|
| 227 |
-
position: relative;
|
| 228 |
-
display: block;
|
| 229 |
-
white-space: nowrap;
|
| 230 |
-
}
|
| 231 |
-
|
| 232 |
-
.msg-heading h4 {
|
| 233 |
-
margin: 0;
|
| 234 |
-
/* width: calc(100% - 4em); */
|
| 235 |
-
margin-right: 4em;
|
| 236 |
-
overflow-y: hidden;
|
| 237 |
-
text-overflow: ellipsis;
|
| 238 |
-
}
|
| 239 |
-
|
| 240 |
-
/* Message Actions */
|
| 241 |
-
.message-actions {
|
| 242 |
-
color: var(--color-text);
|
| 243 |
-
font-size: var(--font-size-small);
|
| 244 |
-
margin-top: var(--spacing-xs);
|
| 245 |
-
}
|
| 246 |
-
|
| 247 |
-
.message-action {
|
| 248 |
-
cursor: pointer;
|
| 249 |
-
opacity: 0.7;
|
| 250 |
-
-webkit-transition: opacity var(--transition-speed) ease-in-out;
|
| 251 |
-
transition: opacity var(--transition-speed) ease-in-out;
|
| 252 |
-
}
|
| 253 |
-
|
| 254 |
-
.message-action:hover {
|
| 255 |
-
opacity: 1;
|
| 256 |
-
}
|
| 257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
|
| 259 |
/* Copy button styles */
|
| 260 |
.copy-button {
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
/* Utility Classes */
|
| 338 |
.kvps-key {
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
|
|
|
| 385 |
|
| 386 |
/* Math (KaTeX) */
|
| 387 |
.katex {
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
|
| 392 |
/* Media Queries */
|
| 393 |
@media (max-width: 640px) {
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
.message-followup {
|
| 397 |
-
/* margin-left: var(--spacing-md); */
|
| 398 |
-
margin-bottom: var(--spacing-md);
|
| 399 |
-
}
|
| 400 |
-
|
| 401 |
-
.msg-kvps {
|
| 402 |
-
display: flex;
|
| 403 |
-
flex-direction: column;
|
| 404 |
-
border-collapse: separate;
|
| 405 |
-
border-spacing: 0 0.5rem;
|
| 406 |
-
}
|
| 407 |
-
|
| 408 |
-
.msg-kvps tr {
|
| 409 |
-
display: flex;
|
| 410 |
-
flex-direction: column;
|
| 411 |
-
margin-top: 0.3rem;
|
| 412 |
-
padding-bottom: 0;
|
| 413 |
-
}
|
| 414 |
-
|
| 415 |
-
.msg-kvps th,
|
| 416 |
-
.msg-kvps td {
|
| 417 |
-
display: block;
|
| 418 |
-
width: 100%;
|
| 419 |
-
text-align: left;
|
| 420 |
-
border-bottom: none;
|
| 421 |
-
padding: 0.25rem 0;
|
| 422 |
-
padding-left: 0 !important;
|
| 423 |
-
}
|
| 424 |
-
|
| 425 |
-
.msg-kvps th {
|
| 426 |
-
color: var(--color-primary);
|
| 427 |
-
margin-bottom: 0.25rem;
|
| 428 |
-
}
|
| 429 |
-
|
| 430 |
-
.kvps-val {
|
| 431 |
-
margin: 0 0 0.4rem 0;
|
| 432 |
-
white-space: pre-wrap;
|
| 433 |
-
word-break: break-word;
|
| 434 |
-
overflow-wrap: anywhere;
|
| 435 |
-
}
|
| 436 |
-
}
|
| 437 |
|
| 438 |
-
.
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
.light-mode .message-default {
|
| 443 |
-
background-color: #f3f3f3;
|
| 444 |
-
color: #1a242f;
|
| 445 |
-
}
|
| 446 |
-
|
| 447 |
-
.light-mode .message-agent {
|
| 448 |
-
background-color: #f3f3f3;
|
| 449 |
-
color: #356ca3;
|
| 450 |
-
}
|
| 451 |
-
|
| 452 |
-
.light-mode .message-agent-response {
|
| 453 |
-
background-color: #f3f3f3;
|
| 454 |
-
color: #188216;
|
| 455 |
-
}
|
| 456 |
-
|
| 457 |
-
.light-mode .message-agent-delegation {
|
| 458 |
-
background-color: #f3f3f3;
|
| 459 |
-
color: #12685e;
|
| 460 |
-
}
|
| 461 |
-
|
| 462 |
-
.light-mode .message-tool {
|
| 463 |
-
background-color: #f3f3f3;
|
| 464 |
-
color: #1c3c88;
|
| 465 |
-
}
|
| 466 |
-
|
| 467 |
-
.light-mode .message-code-exe {
|
| 468 |
-
background-color: #f3f3f3;
|
| 469 |
-
color: #6c43b0;
|
| 470 |
-
}
|
| 471 |
-
|
| 472 |
-
.light-mode .message-browser {
|
| 473 |
-
background-color: #ffffff;
|
| 474 |
-
color: #6c43b0;
|
| 475 |
-
}
|
| 476 |
-
|
| 477 |
-
.light-mode .message-info {
|
| 478 |
-
background-color: #f3f3f3;
|
| 479 |
-
color: #3f3f3f;
|
| 480 |
-
}
|
| 481 |
-
|
| 482 |
-
.light-mode .message-util {
|
| 483 |
-
background-color: #f3f3f3;
|
| 484 |
-
color: #5b5540;
|
| 485 |
-
}
|
| 486 |
-
|
| 487 |
-
.light-mode .message-warning {
|
| 488 |
-
background-color: #f3f3f3;
|
| 489 |
-
color: #8f4800;
|
| 490 |
-
}
|
| 491 |
-
|
| 492 |
-
.light-mode .message-error {
|
| 493 |
-
background-color: #f3f3f3;
|
| 494 |
-
color: #8f1010;
|
| 495 |
-
}
|
| 496 |
-
|
| 497 |
-
.light-mode .message-user {
|
| 498 |
-
background-color: #f3f3f3;
|
| 499 |
-
color: #4e4e4e;
|
| 500 |
}
|
| 501 |
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
.message-agent-response .msg-content {
|
| 508 |
-
font-size: var(--font-size-smaller);
|
| 509 |
-
}
|
| 510 |
-
|
| 511 |
-
.msg-content h1 {
|
| 512 |
-
font-size: 1.25em;
|
| 513 |
-
font-weight: 800;
|
| 514 |
-
margin-bottom: 0.2em;
|
| 515 |
-
}
|
| 516 |
-
|
| 517 |
-
.msg-content h2 {
|
| 518 |
-
font-size: 1.2em;
|
| 519 |
-
font-weight: 700;
|
| 520 |
-
margin-bottom: 0.2em;
|
| 521 |
-
}
|
| 522 |
-
|
| 523 |
-
.msg-content h3 {
|
| 524 |
-
font-size: 1.15em;
|
| 525 |
-
font-weight: 600;
|
| 526 |
-
margin-bottom: 0.2em;
|
| 527 |
-
}
|
| 528 |
-
|
| 529 |
-
.msg-content h4 {
|
| 530 |
-
font-size: 1.1em;
|
| 531 |
-
font-weight: 500;
|
| 532 |
-
margin-bottom: 0.2em;
|
| 533 |
-
}
|
| 534 |
-
|
| 535 |
-
.msg-content h5 {
|
| 536 |
-
font-size: 1.05em;
|
| 537 |
-
font-weight: 500;
|
| 538 |
-
margin-bottom: 0.2em;
|
| 539 |
}
|
| 540 |
-
|
| 541 |
-
.msg-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
margin-
|
|
|
|
| 545 |
}
|
| 546 |
-
|
| 547 |
-
.msg-
|
|
|
|
|
|
|
| 548 |
width: 100%;
|
| 549 |
-
border-collapse: collapse;
|
| 550 |
-
margin: 1em 0;
|
| 551 |
-
font-size: 0.98em;
|
| 552 |
-
background: transparent;
|
| 553 |
-
border-radius: 8px;
|
| 554 |
-
overflow: hidden;
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
.msg-content th,
|
| 558 |
-
.msg-content td {
|
| 559 |
-
padding: 0.55em 1em;
|
| 560 |
-
border: 1px solid rgba(142, 142, 142, 0.1);
|
| 561 |
text-align: left;
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
.msg-content th {
|
| 566 |
-
font-weight: 600;
|
| 567 |
-
background: rgba(142, 142, 142, 0.1);
|
| 568 |
-
}
|
| 569 |
-
|
| 570 |
-
.msg-content tr:nth-child(even) {
|
| 571 |
-
background: rgba(142, 142, 142, 0.1);
|
| 572 |
-
}
|
| 573 |
-
|
| 574 |
-
.msg-content tr:nth-child(odd) {
|
| 575 |
-
background: transparent;
|
| 576 |
-
}
|
| 577 |
-
|
| 578 |
-
.msg-content table {
|
| 579 |
-
box-shadow: none;
|
| 580 |
-
}
|
| 581 |
-
|
| 582 |
-
.msg-content pre:has(code) {
|
| 583 |
-
padding: 0.5em;
|
| 584 |
-
border: 1px solid rgba(142, 142, 142, 0.1);
|
| 585 |
-
border-radius: 0.3em;
|
| 586 |
-
}
|
| 587 |
-
|
| 588 |
-
.msg-min-max-btns {
|
| 589 |
-
opacity: 40%;
|
| 590 |
-
position: absolute;
|
| 591 |
-
top: -0.2em;
|
| 592 |
-
right: -0.2em;
|
| 593 |
-
display: flex;
|
| 594 |
-
gap: 0.3em;
|
| 595 |
-
z-index: 1;
|
| 596 |
}
|
| 597 |
|
| 598 |
-
.
|
| 599 |
-
|
| 600 |
-
margin-bottom:
|
| 601 |
-
display: inline-grid;
|
| 602 |
-
grid-template-columns: minmax(0, max-content);
|
| 603 |
-
grid-auto-rows: auto;
|
| 604 |
-
max-width: 100%;
|
| 605 |
-
width: fit-content;
|
| 606 |
-
}
|
| 607 |
-
|
| 608 |
-
.message-group > * {
|
| 609 |
-
grid-column: 1;
|
| 610 |
-
} /* both children sit in the same column */
|
| 611 |
-
|
| 612 |
-
.message-group-right {
|
| 613 |
-
justify-content: end;
|
| 614 |
-
}
|
| 615 |
-
|
| 616 |
-
.message-group-mid {
|
| 617 |
-
justify-content: center;
|
| 618 |
-
}
|
| 619 |
-
|
| 620 |
-
/* 1. FIRST child’s .message – clear ONLY bottom corners */
|
| 621 |
-
.message-group > *:first-child:not(:last-child) > .message {
|
| 622 |
-
border-bottom-left-radius: var(--spacing-xxs);;
|
| 623 |
-
border-bottom-right-radius: var(--spacing-xxs);;
|
| 624 |
-
}
|
| 625 |
-
|
| 626 |
-
/* 2. MIDDLE children’s .message – clear ALL corners */
|
| 627 |
-
.message-group > *:not(:first-child):not(:last-child) > .message {
|
| 628 |
-
border-radius: var(--spacing-xxs);
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
/* 3. LAST child’s .message – clear ONLY top corners */
|
| 632 |
-
.message-group > *:last-child:not(:first-child) > .message {
|
| 633 |
-
border-top-left-radius: var(--spacing-xxs);;
|
| 634 |
-
border-top-right-radius: var(--spacing-xxs);;
|
| 635 |
}
|
| 636 |
|
| 637 |
-
.
|
| 638 |
-
|
| 639 |
-
-
|
| 640 |
-
margin-bottom: var(--spacing-sm);
|
| 641 |
-
width: 100%;
|
| 642 |
-
max-width: 100%;
|
| 643 |
-
}
|
| 644 |
-
|
| 645 |
-
.message {
|
| 646 |
-
/* background-color: var(--color-message-bg); */
|
| 647 |
-
border-radius: var(--border-radius);
|
| 648 |
-
padding: 0.9rem var(--spacing-sm) 0.7rem var(--spacing-sm);
|
| 649 |
-
overflow-x: auto;
|
| 650 |
-
width: auto;
|
| 651 |
-
max-width: 100%;
|
| 652 |
-
box-sizing: border-box;
|
| 653 |
-
display: block;
|
| 654 |
word-break: break-word;
|
| 655 |
overflow-wrap: anywhere;
|
| 656 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
/* Chat History */
|
| 2 |
#chat-history {
|
| 3 |
+
display: -webkit-flex;
|
| 4 |
+
display: flex;
|
| 5 |
+
flex-direction: column;
|
| 6 |
+
flex-grow: 1;
|
| 7 |
+
width: 100%;
|
| 8 |
+
overflow-y: scroll;
|
| 9 |
+
overflow-x: hidden;
|
| 10 |
+
scroll-behavior: auto !important; /* avoid infinite scrolling! */
|
| 11 |
+
padding: var(--spacing-md) var(--spacing-sm) 0;
|
| 12 |
+
-webkit-transition: all 0.3s ease;
|
| 13 |
+
transition: all 0.3s ease;
|
| 14 |
+
scrollbar-width: thin;
|
| 15 |
+
scrollbar-color: #555 transparent;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
#chat-history > *:first-child {
|
| 19 |
+
margin-top: 4.4em;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
/* Scrollbar styling for Firefox */
|
| 23 |
+
#chat-history::-webkit-scrollbar {
|
| 24 |
+
width: 5px;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
#chat-history::-webkit-scrollbar-track {
|
| 28 |
+
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3);
|
| 29 |
+
border-radius: 3px;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
#chat-history::-webkit-scrollbar-thumb {
|
| 33 |
+
border-radius: 3px;
|
| 34 |
+
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3);
|
| 35 |
+
background-color: #555;
|
| 36 |
+
-webkit-transition: background-color var(--transition-speed) ease-in-out;
|
| 37 |
+
transition: background-color var(--transition-speed) ease-in-out;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
#chat-history::-webkit-scrollbar-thumb:hover {
|
| 41 |
+
background-color: #666;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
#chat-history::-webkit-scrollbar-thumb:active {
|
| 45 |
+
background-color: #888;
|
| 46 |
+
}
|
|
|
|
| 47 |
|
| 48 |
/* Message Styles */
|
| 49 |
|
| 50 |
+
.user-container {
|
| 51 |
+
align-self: flex-end;
|
| 52 |
+
/* margin: var(--spacing-sm) var(--spacing-md); */
|
| 53 |
+
/* margin-bottom: var(--spacing-lg); */
|
| 54 |
+
/* margin-top: var(--spacing-sm); */
|
| 55 |
+
display: flex;
|
| 56 |
+
justify-content: flex-end;
|
| 57 |
+
width: 100%;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.ai-container {
|
| 61 |
+
align-self: flex-start;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.center-container {
|
| 65 |
+
align-self: center;
|
| 66 |
+
max-width: 80%;
|
| 67 |
+
margin: 0;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.center-container .message {
|
| 71 |
+
/* margin-bottom: var(--spacing-sm); */
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
.message-user {
|
| 75 |
+
background-color: #4a4a4a;
|
| 76 |
+
/* border-bottom-right-radius: var(--spacing-xxs); */
|
| 77 |
+
min-width: 195px;
|
| 78 |
+
text-align: end;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
.message-user > div {
|
| 82 |
+
padding-top: var(--spacing-xs);
|
| 83 |
+
font-family: "Roboto Mono", monospace;
|
| 84 |
+
font-optical-sizing: auto;
|
| 85 |
+
-webkit-font-optical-sizing: auto;
|
| 86 |
+
font-size: var(--font-size-small);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.message-ai {
|
| 90 |
+
/* border-bottom-left-radius: var(--spacing-xxs); */
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.message-center {
|
| 94 |
+
align-self: center;
|
| 95 |
+
/* border-bottom-left-radius: unset; */
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
.message-followup {
|
| 99 |
+
/* margin-left: var(--spacing-lg); */
|
| 100 |
+
/* margin-bottom: var(--spacing-lg); */
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
.message-followup .message {
|
| 104 |
+
border-radius: 1.125em; /* 18px */
|
| 105 |
+
/* border-top-left-radius: var(--spacing-xxs); */
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.message-followup + .message-followup {
|
| 109 |
+
margin-bottom: 0;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
/* Update message types for dark mode */
|
| 113 |
+
.message-default,
|
| 114 |
+
.message-agent,
|
| 115 |
+
.message-agent-response,
|
| 116 |
+
.message-agent-delegation,
|
| 117 |
+
.message-tool,
|
| 118 |
+
.message-code-exe,
|
| 119 |
+
.message-browser,
|
| 120 |
+
.message-info,
|
| 121 |
+
.message-util,
|
| 122 |
+
.message-warning,
|
| 123 |
+
.message-error {
|
| 124 |
+
color: #e0e0e0;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
.message-default {
|
| 128 |
+
background-color: #1a242f;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.message-agent {
|
| 132 |
+
background-color: #34506b;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
.message-agent-response {
|
| 136 |
+
min-width: 255px;
|
| 137 |
+
background-color: #1f3c1e;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
.message-agent-delegation {
|
| 141 |
+
background-color: #12685e;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
.message-tool {
|
| 145 |
+
background-color: #2a4170;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
.message-code-exe {
|
| 149 |
+
background-color: #4b3a69;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
.message-code-exe .message-body {
|
| 153 |
+
min-height: 5em;
|
| 154 |
+
width: 100%;
|
| 155 |
+
background-color: var(--color-panel);
|
| 156 |
+
border-radius: 0.5em;
|
| 157 |
+
margin-top: 0.5em;
|
| 158 |
+
padding: 0.3em;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
.message-body .message-markdown-table-wrap {
|
| 162 |
+
display: block;
|
| 163 |
+
width: 100%;
|
| 164 |
+
overflow-x: auto;
|
| 165 |
+
margin-bottom: 1em;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.message-body .message-markdown-table-wrap table {
|
| 169 |
+
width: auto;
|
| 170 |
+
table-layout: auto;
|
| 171 |
+
white-space: nowrap;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
.light-mode .message-code-exe .message-body {
|
| 175 |
+
border: 1px solid var(--color-border);
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
.message-browser {
|
| 179 |
+
background-color: #4b3a69;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
.message-info {
|
| 183 |
+
background-color: var(--color-panel);
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.message-util {
|
| 187 |
+
background-color: #23211a;
|
| 188 |
+
display: none;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
.message-warning {
|
| 192 |
+
background-color: #bc8036;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
.message-error {
|
| 196 |
+
background-color: #af2222;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
/* Agent and AI Info */
|
| 200 |
+
.agent-start {
|
| 201 |
+
color: var(--color-text);
|
| 202 |
+
font-size: var(--font-size-small);
|
| 203 |
+
margin-bottom: var(--spacing-xs);
|
| 204 |
+
opacity: 0.7;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
.msg-kvps {
|
| 208 |
+
font-size: 0.9em;
|
| 209 |
+
margin: 0.5rem 0 0.55rem 0;
|
| 210 |
+
border-collapse: collapse;
|
| 211 |
+
width: 100%;
|
| 212 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
+
.kvps-val pre {
|
| 215 |
+
white-space: pre-wrap; /* keep \n, collapse no spaces, allow wrapping */
|
| 216 |
+
word-break: break-word; /* optional – forces really long “words” to break */
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
.msg-kvps th,
|
| 220 |
+
.msg-kvps td {
|
| 221 |
+
align-content: center;
|
| 222 |
+
padding: 0.25rem;
|
| 223 |
+
padding-left: 0;
|
| 224 |
+
text-align: left;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
.msg-kvps th {
|
| 228 |
+
color: var(--color-primary);
|
| 229 |
+
width: 40%;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
.msg-kvps tr {
|
| 233 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
.msg-heading {
|
| 237 |
+
margin: 0;
|
| 238 |
+
position: relative;
|
| 239 |
+
display: block;
|
| 240 |
+
white-space: nowrap;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
.msg-heading h4 {
|
| 244 |
+
margin: 0;
|
| 245 |
+
/* width: calc(100% - 4em); */
|
| 246 |
+
margin-right: 4em;
|
| 247 |
+
overflow-y: hidden;
|
| 248 |
+
text-overflow: ellipsis;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
/* Message Actions */
|
| 252 |
+
.message-actions {
|
| 253 |
+
color: var(--color-text);
|
| 254 |
+
font-size: var(--font-size-small);
|
| 255 |
+
margin-top: var(--spacing-xs);
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
.message-action {
|
| 259 |
+
cursor: pointer;
|
| 260 |
+
opacity: 0.7;
|
| 261 |
+
-webkit-transition: opacity var(--transition-speed) ease-in-out;
|
| 262 |
+
transition: opacity var(--transition-speed) ease-in-out;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
.message-action:hover {
|
| 266 |
+
opacity: 1;
|
| 267 |
+
}
|
| 268 |
|
| 269 |
/* Copy button styles */
|
| 270 |
.copy-button {
|
| 271 |
+
position: absolute;
|
| 272 |
+
right: 0;
|
| 273 |
+
top: var(--spacing-sm);
|
| 274 |
+
background: none;
|
| 275 |
+
border: none;
|
| 276 |
+
padding: var(--spacing-xs) var(--spacing-sm);
|
| 277 |
+
padding-right: 0;
|
| 278 |
+
cursor: pointer;
|
| 279 |
+
text-decoration: underline;
|
| 280 |
+
text-wrap: nowrap;
|
| 281 |
+
opacity: 0;
|
| 282 |
+
-webkit-transition: opacity var(--transition-speed) ease-in-out;
|
| 283 |
+
transition: opacity var(--transition-speed) ease-in-out;
|
| 284 |
+
color: inherit;
|
| 285 |
+
font-size: 12px;
|
| 286 |
+
font-family: "Rubik", Arial, Helvetica, sans-serif;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
.copy-button:hover {
|
| 290 |
+
opacity: 0.8 !important;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
.msg-content:hover .copy-button,
|
| 294 |
+
.kvps-row:hover .copy-button,
|
| 295 |
+
.message-text:hover .copy-button {
|
| 296 |
+
opacity: 0.6;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.copy-button.copied {
|
| 300 |
+
font-family: "Rubik", Arial, Helvetica, sans-serif !important;
|
| 301 |
+
opacity: 1 !important;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.msg-thoughts .copy-button {
|
| 305 |
+
top: -12px !important;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
.message-user .copy-button {
|
| 309 |
+
top: -15px !important;
|
| 310 |
+
left: -13px !important;
|
| 311 |
+
right: 99% !important;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
.message-agent-response .copy-button {
|
| 315 |
+
top: -22px !important;
|
| 316 |
+
right: 0 !important;
|
| 317 |
+
padding-right: 0px !important;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
.message-info .copy-button {
|
| 321 |
+
top: -22px !important;
|
| 322 |
+
right: 0 !important;
|
| 323 |
+
padding-right: 0px !important;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
.message-tool .copy-button {
|
| 327 |
+
top: -12px !important;
|
| 328 |
+
right: 0 !important;
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
.msg-output .copy-button {
|
| 332 |
+
top: -6px !important;
|
| 333 |
+
right: 0 !important;
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
/* Make message containers relative for absolute positioning of copy buttons */
|
| 337 |
+
.msg-content,
|
| 338 |
+
.kvps-row,
|
| 339 |
+
.message-text {
|
| 340 |
+
position: relative;
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
.message-text pre {
|
| 344 |
+
margin: 0;
|
| 345 |
+
white-space: pre-wrap;
|
| 346 |
+
word-break: break-word;
|
| 347 |
+
overflow-wrap: anywhere;
|
| 348 |
+
}
|
| 349 |
|
| 350 |
/* Utility Classes */
|
| 351 |
.kvps-key {
|
| 352 |
+
font-weight: 500;
|
| 353 |
+
font-size: var(--font-size-small);
|
| 354 |
+
min-width: 7em;
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
.kvps-val {
|
| 358 |
+
margin: 0.65rem 0 0.65rem 0.4rem;
|
| 359 |
+
white-space: pre-wrap;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
.kvps-img {
|
| 363 |
+
width: 8em;
|
| 364 |
+
height: 8em;
|
| 365 |
+
object-fit: cover;
|
| 366 |
+
object-position: top left;
|
| 367 |
+
border-radius: 10%;
|
| 368 |
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
.image-viewer-img {
|
| 372 |
+
width: 100%;
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
.msg-json {
|
| 376 |
+
display: none;
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
.msg-thoughts {
|
| 380 |
+
display: auto;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.msg-thoughts .kvps-val {
|
| 384 |
+
max-height: 20em;
|
| 385 |
+
overflow: auto;
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
.msg-content {
|
| 389 |
+
margin-bottom: 0;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
.message-temp {
|
| 393 |
+
display: none;
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
.message-temp:not([style*="display: none"]):last-of-type {
|
| 397 |
+
display: block; /* or any style you want for visibility */
|
| 398 |
+
}
|
| 399 |
|
| 400 |
/* Math (KaTeX) */
|
| 401 |
.katex {
|
| 402 |
+
line-height: 1.2 !important;
|
| 403 |
+
font-size: 1.1em;
|
| 404 |
+
}
|
| 405 |
|
| 406 |
/* Media Queries */
|
| 407 |
@media (max-width: 640px) {
|
| 408 |
+
/* New styles for mobile messages */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
|
| 410 |
+
.message-followup {
|
| 411 |
+
/* margin-left: var(--spacing-md); */
|
| 412 |
+
margin-bottom: var(--spacing-md);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
}
|
| 414 |
|
| 415 |
+
.msg-kvps {
|
| 416 |
+
display: flex;
|
| 417 |
+
flex-direction: column;
|
| 418 |
+
border-collapse: separate;
|
| 419 |
+
border-spacing: 0 0.5rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 420 |
}
|
| 421 |
+
|
| 422 |
+
.msg-kvps tr {
|
| 423 |
+
display: flex;
|
| 424 |
+
flex-direction: column;
|
| 425 |
+
margin-top: 0.3rem;
|
| 426 |
+
padding-bottom: 0;
|
| 427 |
}
|
| 428 |
+
|
| 429 |
+
.msg-kvps th,
|
| 430 |
+
.msg-kvps td {
|
| 431 |
+
display: block;
|
| 432 |
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 433 |
text-align: left;
|
| 434 |
+
border-bottom: none;
|
| 435 |
+
padding: 0.25rem 0;
|
| 436 |
+
padding-left: 0 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
}
|
| 438 |
|
| 439 |
+
.msg-kvps th {
|
| 440 |
+
color: var(--color-primary);
|
| 441 |
+
margin-bottom: 0.25rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
}
|
| 443 |
|
| 444 |
+
.kvps-val {
|
| 445 |
+
margin: 0 0 0.4rem 0;
|
| 446 |
+
white-space: pre-wrap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
word-break: break-word;
|
| 448 |
overflow-wrap: anywhere;
|
| 449 |
+
}
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
.light-mode .msg-kvps tr {
|
| 453 |
+
border-bottom: 1px solid rgb(192 192 192 / 50%);
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
.light-mode .message-default {
|
| 457 |
+
background-color: #f3f3f3;
|
| 458 |
+
color: #1a242f;
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
.light-mode .message-agent {
|
| 462 |
+
background-color: #f3f3f3;
|
| 463 |
+
color: #356ca3;
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
.light-mode .message-agent-response {
|
| 467 |
+
background-color: #f3f3f3;
|
| 468 |
+
color: #188216;
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
.light-mode .message-agent-delegation {
|
| 472 |
+
background-color: #f3f3f3;
|
| 473 |
+
color: #12685e;
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
.light-mode .message-tool {
|
| 477 |
+
background-color: #f3f3f3;
|
| 478 |
+
color: #1c3c88;
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
.light-mode .message-code-exe {
|
| 482 |
+
background-color: #f3f3f3;
|
| 483 |
+
color: #6c43b0;
|
| 484 |
+
}
|
| 485 |
+
|
| 486 |
+
.light-mode .message-browser {
|
| 487 |
+
background-color: #ffffff;
|
| 488 |
+
color: #6c43b0;
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
.light-mode .message-info {
|
| 492 |
+
background-color: #f3f3f3;
|
| 493 |
+
color: #3f3f3f;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
.light-mode .message-util {
|
| 497 |
+
background-color: #f3f3f3;
|
| 498 |
+
color: #5b5540;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
.light-mode .message-warning {
|
| 502 |
+
background-color: #f3f3f3;
|
| 503 |
+
color: #8f4800;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
.light-mode .message-error {
|
| 507 |
+
background-color: #f3f3f3;
|
| 508 |
+
color: #8f1010;
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
.light-mode .message-user {
|
| 512 |
+
background-color: #f3f3f3;
|
| 513 |
+
color: #4e4e4e;
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
.message-body{
|
| 517 |
+
padding-top:0.5em;
|
| 518 |
+
padding-bottom:0.5em;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
/* Markdown in messages */
|
| 522 |
+
.msg-content {
|
| 523 |
+
font-size: var(--font-size-small);
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
.message-agent-response .msg-content {
|
| 527 |
+
font-size: var(--font-size-smaller);
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
.msg-content h1 {
|
| 531 |
+
font-size: 1.25em;
|
| 532 |
+
font-weight: 800;
|
| 533 |
+
margin-bottom: 0.2em;
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
.msg-content h2 {
|
| 537 |
+
font-size: 1.2em;
|
| 538 |
+
font-weight: 700;
|
| 539 |
+
margin-bottom: 0.2em;
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
.msg-content h3 {
|
| 543 |
+
font-size: 1.15em;
|
| 544 |
+
font-weight: 600;
|
| 545 |
+
margin-bottom: 0.2em;
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
.msg-content h4 {
|
| 549 |
+
font-size: 1.1em;
|
| 550 |
+
font-weight: 500;
|
| 551 |
+
margin-bottom: 0.2em;
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
.msg-content h5 {
|
| 555 |
+
font-size: 1.05em;
|
| 556 |
+
font-weight: 500;
|
| 557 |
+
margin-bottom: 0.2em;
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
.msg-content h6 {
|
| 561 |
+
font-size: 1em;
|
| 562 |
+
font-weight: 500;
|
| 563 |
+
margin-bottom: 0.2em;
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
.msg-content table {
|
| 567 |
+
width: 100%;
|
| 568 |
+
border-collapse: collapse;
|
| 569 |
+
margin: 1em 0;
|
| 570 |
+
font-size: 0.98em;
|
| 571 |
+
background: transparent;
|
| 572 |
+
border-radius: 8px;
|
| 573 |
+
overflow: hidden;
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
.msg-content th,
|
| 577 |
+
.msg-content td {
|
| 578 |
+
padding: 0.55em 1em;
|
| 579 |
+
border: 1px solid rgba(142, 142, 142, 0.1);
|
| 580 |
+
text-align: left;
|
| 581 |
+
background: transparent;
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
.msg-content th {
|
| 585 |
+
font-weight: 600;
|
| 586 |
+
background: rgba(142, 142, 142, 0.1);
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
.msg-content tr:nth-child(even) {
|
| 590 |
+
background: rgba(142, 142, 142, 0.1);
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
.msg-content tr:nth-child(odd) {
|
| 594 |
+
background: transparent;
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
.msg-content table {
|
| 598 |
+
box-shadow: none;
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
.msg-content pre:has(code) {
|
| 602 |
+
padding: 0.5em;
|
| 603 |
+
border: 1px solid rgba(142, 142, 142, 0.1);
|
| 604 |
+
border-radius: 0.3em;
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
.msg-min-max-btns {
|
| 608 |
+
opacity: 40%;
|
| 609 |
+
position: absolute;
|
| 610 |
+
top: -0.2em;
|
| 611 |
+
right: -0.2em;
|
| 612 |
+
display: flex;
|
| 613 |
+
gap: 0.3em;
|
| 614 |
+
z-index: 1;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
.message-group {
|
| 618 |
+
margin-top: 0.5em;
|
| 619 |
+
margin-bottom: 0.5em;
|
| 620 |
+
display: inline-grid;
|
| 621 |
+
grid-template-columns: minmax(0, max-content);
|
| 622 |
+
grid-auto-rows: auto;
|
| 623 |
+
max-width: 100%;
|
| 624 |
+
width: fit-content;
|
| 625 |
+
gap: var(--spacing-xs);
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
.message-group > * {
|
| 629 |
+
grid-column: 1;
|
| 630 |
+
} /* both children sit in the same column */
|
| 631 |
+
|
| 632 |
+
.message-group-right {
|
| 633 |
+
width:100%;
|
| 634 |
+
justify-content: end;
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
.message-group-mid {
|
| 638 |
+
margin-left: 2em;
|
| 639 |
+
}
|
| 640 |
+
|
| 641 |
+
/* 1. FIRST child’s .message – clear ONLY bottom corners */
|
| 642 |
+
.message-group > *:first-child:not(:last-child) > .message {
|
| 643 |
+
border-bottom-left-radius: var(--spacing-xxs);
|
| 644 |
+
border-bottom-right-radius: var(--spacing-xxs);
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
/* 2. MIDDLE children’s .message – clear ALL corners */
|
| 648 |
+
.message-group > *:not(:first-child):not(:last-child) > .message {
|
| 649 |
+
border-radius: var(--spacing-xxs);
|
| 650 |
+
}
|
| 651 |
+
|
| 652 |
+
/* 3. LAST child’s .message – clear ONLY top corners */
|
| 653 |
+
.message-group > *:last-child:not(:first-child) > .message {
|
| 654 |
+
border-top-left-radius: var(--spacing-xxs);
|
| 655 |
+
border-top-right-radius: var(--spacing-xxs);
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
.message-container {
|
| 659 |
+
animation: fadeIn 0.5s;
|
| 660 |
+
-webkit-animation: fadeIn 0.5s;
|
| 661 |
+
/* margin-bottom: var(--spacing-sm); */
|
| 662 |
+
width: 100%;
|
| 663 |
+
max-width: 100%;
|
| 664 |
+
}
|
| 665 |
+
|
| 666 |
+
.message {
|
| 667 |
+
/* background-color: var(--color-message-bg); */
|
| 668 |
+
border-radius: var(--border-radius);
|
| 669 |
+
padding: 0.9rem var(--spacing-sm) 0.7rem var(--spacing-sm);
|
| 670 |
+
overflow-x: auto;
|
| 671 |
+
width: auto;
|
| 672 |
+
max-width: 100%;
|
| 673 |
+
box-sizing: border-box;
|
| 674 |
+
/* display: block; */
|
| 675 |
+
word-break: break-word;
|
| 676 |
+
overflow-wrap: anywhere;
|
| 677 |
+
}
|
webui/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import * as msgs from "./js/messages.js";
|
| 2 |
import { speech } from "./js/speech.js";
|
| 3 |
import * as api from "./js/api.js";
|
|
|
|
| 4 |
|
| 5 |
window.fetchApi = api.fetchApi; // TODO - backward compatibility for non-modular scripts, remove once refactored to alpine
|
| 6 |
|
|
@@ -513,6 +514,8 @@ function updateProgress(progress, active) {
|
|
| 513 |
addClassToElement(progressBar, "shiny-text");
|
| 514 |
}
|
| 515 |
|
|
|
|
|
|
|
| 516 |
if (progressBar.innerHTML != progress) {
|
| 517 |
progressBar.innerHTML = progress;
|
| 518 |
}
|
|
@@ -709,13 +712,11 @@ window.toggleAutoScroll = async function (_autoScroll) {
|
|
| 709 |
};
|
| 710 |
|
| 711 |
window.toggleJson = async function (showJson) {
|
| 712 |
-
|
| 713 |
-
toggleCssProperty(".msg-json", "display", showJson ? "block" : "none");
|
| 714 |
};
|
| 715 |
|
| 716 |
window.toggleThoughts = async function (showThoughts) {
|
| 717 |
-
|
| 718 |
-
toggleCssProperty(
|
| 719 |
".msg-thoughts",
|
| 720 |
"display",
|
| 721 |
showThoughts ? undefined : "none"
|
|
@@ -723,10 +724,11 @@ window.toggleThoughts = async function (showThoughts) {
|
|
| 723 |
};
|
| 724 |
|
| 725 |
window.toggleUtils = async function (showUtils) {
|
| 726 |
-
|
| 727 |
-
|
| 728 |
-
|
| 729 |
-
|
|
|
|
| 730 |
};
|
| 731 |
|
| 732 |
window.toggleDarkMode = function (isDark) {
|
|
@@ -799,30 +801,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
| 799 |
toggleDarkMode(isDarkMode);
|
| 800 |
});
|
| 801 |
|
| 802 |
-
function toggleCssProperty(selector, property, value) {
|
| 803 |
-
// Get the stylesheet that contains the class
|
| 804 |
-
const styleSheets = document.styleSheets;
|
| 805 |
-
|
| 806 |
-
// Iterate through all stylesheets to find the class
|
| 807 |
-
for (let i = 0; i < styleSheets.length; i++) {
|
| 808 |
-
const styleSheet = styleSheets[i];
|
| 809 |
-
const rules = styleSheet.cssRules || styleSheet.rules;
|
| 810 |
-
|
| 811 |
-
for (let j = 0; j < rules.length; j++) {
|
| 812 |
-
const rule = rules[j];
|
| 813 |
-
if (rule.selectorText == selector) {
|
| 814 |
-
// Check if the property is already applied
|
| 815 |
-
if (value === undefined) {
|
| 816 |
-
rule.style.removeProperty(property);
|
| 817 |
-
} else {
|
| 818 |
-
rule.style.setProperty(property, value);
|
| 819 |
-
}
|
| 820 |
-
return;
|
| 821 |
-
}
|
| 822 |
-
}
|
| 823 |
-
}
|
| 824 |
-
}
|
| 825 |
-
|
| 826 |
window.loadChats = async function () {
|
| 827 |
try {
|
| 828 |
const fileContents = await readJsonFiles();
|
|
|
|
| 1 |
import * as msgs from "./js/messages.js";
|
| 2 |
import { speech } from "./js/speech.js";
|
| 3 |
import * as api from "./js/api.js";
|
| 4 |
+
import * as css from "./js/css.js";
|
| 5 |
|
| 6 |
window.fetchApi = api.fetchApi; // TODO - backward compatibility for non-modular scripts, remove once refactored to alpine
|
| 7 |
|
|
|
|
| 514 |
addClassToElement(progressBar, "shiny-text");
|
| 515 |
}
|
| 516 |
|
| 517 |
+
progress = msgs.convertIcons(progress);
|
| 518 |
+
|
| 519 |
if (progressBar.innerHTML != progress) {
|
| 520 |
progressBar.innerHTML = progress;
|
| 521 |
}
|
|
|
|
| 712 |
};
|
| 713 |
|
| 714 |
window.toggleJson = async function (showJson) {
|
| 715 |
+
css.toggleCssProperty(".msg-json", "display", showJson ? "block" : "none");
|
|
|
|
| 716 |
};
|
| 717 |
|
| 718 |
window.toggleThoughts = async function (showThoughts) {
|
| 719 |
+
css.toggleCssProperty(
|
|
|
|
| 720 |
".msg-thoughts",
|
| 721 |
"display",
|
| 722 |
showThoughts ? undefined : "none"
|
|
|
|
| 724 |
};
|
| 725 |
|
| 726 |
window.toggleUtils = async function (showUtils) {
|
| 727 |
+
css.toggleCssProperty(
|
| 728 |
+
".message-util",
|
| 729 |
+
"display",
|
| 730 |
+
showUtils ? undefined : "none"
|
| 731 |
+
);
|
| 732 |
};
|
| 733 |
|
| 734 |
window.toggleDarkMode = function (isDark) {
|
|
|
|
| 801 |
toggleDarkMode(isDarkMode);
|
| 802 |
});
|
| 803 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
window.loadChats = async function () {
|
| 805 |
try {
|
| 806 |
const fileContents = await readJsonFiles();
|
webui/js/messages.js
CHANGED
|
@@ -170,8 +170,8 @@ export function _drawMessage(
|
|
| 170 |
const minMaxBtn = document.createElement("div");
|
| 171 |
minMaxBtn.classList.add("msg-min-max-btns");
|
| 172 |
minMaxBtn.innerHTML = `
|
| 173 |
-
<a href="#" class="msg-min-max-btn" @click.prevent="$store.messageResize.minimizeMessageClass('${mainClass}', $event)"><span class="material-symbols-outlined"
|
| 174 |
-
<a href="#" class="msg-min-max-btn" @click.prevent="$store.messageResize.maximizeMessageClass('${mainClass}', $event)"><span class="material-symbols-outlined"
|
| 175 |
`;
|
| 176 |
headingElement.appendChild(minMaxBtn);
|
| 177 |
}
|
|
@@ -208,6 +208,7 @@ export function _drawMessage(
|
|
| 208 |
|
| 209 |
contentDiv.appendChild(spanElement);
|
| 210 |
addCopyButtonToElement(contentDiv);
|
|
|
|
| 211 |
bodyDiv.appendChild(contentDiv);
|
| 212 |
} else {
|
| 213 |
const preElement = document.createElement("pre");
|
|
@@ -360,7 +361,7 @@ export function drawMessageUser(
|
|
| 360 |
|
| 361 |
const headingElement = document.createElement("h4");
|
| 362 |
headingElement.classList.add("msg-heading");
|
| 363 |
-
headingElement.
|
| 364 |
messageDiv.appendChild(headingElement);
|
| 365 |
|
| 366 |
if (content && content.trim().length > 0) {
|
|
@@ -766,7 +767,7 @@ function convertImgFilePaths(str) {
|
|
| 766 |
return str.replace("img://", "/image_get?path=");
|
| 767 |
}
|
| 768 |
|
| 769 |
-
function convertIcons(str) {
|
| 770 |
return str.replace(
|
| 771 |
/icon:\/\/([a-zA-Z0-9_]+)/g,
|
| 772 |
'<span class="icon material-symbols-outlined">$1</span>'
|
|
@@ -820,6 +821,24 @@ function convertPathsToLinks(str) {
|
|
| 820 |
.join("");
|
| 821 |
}
|
| 822 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 823 |
// function convertPathsToLinksInHtml(htmlString) {
|
| 824 |
// // 1. Parse the input safely
|
| 825 |
// const wrapper = document.createElement("div");
|
|
|
|
| 170 |
const minMaxBtn = document.createElement("div");
|
| 171 |
minMaxBtn.classList.add("msg-min-max-btns");
|
| 172 |
minMaxBtn.innerHTML = `
|
| 173 |
+
<a href="#" class="msg-min-max-btn" @click.prevent="$store.messageResize.minimizeMessageClass('${mainClass}', $event)"><span class="material-symbols-outlined" x-text="$store.messageResize.getSetting('${mainClass}').minimized ? 'expand_content' : 'minimize'"></span></a>
|
| 174 |
+
<a href="#" class="msg-min-max-btn" x-show="!$store.messageResize.getSetting('${mainClass}').minimized" @click.prevent="$store.messageResize.maximizeMessageClass('${mainClass}', $event)"><span class="material-symbols-outlined" x-text="$store.messageResize.getSetting('${mainClass}').maximized ? 'expand' : 'expand_all'"></span></a>
|
| 175 |
`;
|
| 176 |
headingElement.appendChild(minMaxBtn);
|
| 177 |
}
|
|
|
|
| 208 |
|
| 209 |
contentDiv.appendChild(spanElement);
|
| 210 |
addCopyButtonToElement(contentDiv);
|
| 211 |
+
adjustMarkdownRender(contentDiv);
|
| 212 |
bodyDiv.appendChild(contentDiv);
|
| 213 |
} else {
|
| 214 |
const preElement = document.createElement("pre");
|
|
|
|
| 361 |
|
| 362 |
const headingElement = document.createElement("h4");
|
| 363 |
headingElement.classList.add("msg-heading");
|
| 364 |
+
headingElement.innerHTML = "User message <span class='icon material-symbols-outlined'>person</span>";
|
| 365 |
messageDiv.appendChild(headingElement);
|
| 366 |
|
| 367 |
if (content && content.trim().length > 0) {
|
|
|
|
| 767 |
return str.replace("img://", "/image_get?path=");
|
| 768 |
}
|
| 769 |
|
| 770 |
+
export function convertIcons(str) {
|
| 771 |
return str.replace(
|
| 772 |
/icon:\/\/([a-zA-Z0-9_]+)/g,
|
| 773 |
'<span class="icon material-symbols-outlined">$1</span>'
|
|
|
|
| 821 |
.join("");
|
| 822 |
}
|
| 823 |
|
| 824 |
+
function adjustMarkdownRender(element) {
|
| 825 |
+
// find all tables in the element
|
| 826 |
+
const tables = element.querySelectorAll('table');
|
| 827 |
+
|
| 828 |
+
// wrap each table with a div with class message-markdown-table-wrap
|
| 829 |
+
tables.forEach(table => {
|
| 830 |
+
// create wrapper div
|
| 831 |
+
const wrapper = document.createElement('div');
|
| 832 |
+
wrapper.className = 'message-markdown-table-wrap';
|
| 833 |
+
|
| 834 |
+
// insert wrapper before table in the DOM
|
| 835 |
+
table.parentNode.insertBefore(wrapper, table);
|
| 836 |
+
|
| 837 |
+
// move table into wrapper
|
| 838 |
+
wrapper.appendChild(table);
|
| 839 |
+
});
|
| 840 |
+
}
|
| 841 |
+
|
| 842 |
// function convertPathsToLinksInHtml(htmlString) {
|
| 843 |
// // 1. Parse the input safely
|
| 844 |
// const wrapper = document.createElement("div");
|