enhance webui graphics

This commit is contained in:
Ettore Di Giacinto
2024-04-07 00:15:48 +02:00
parent 015b26096f
commit 8ceaab2ac1
4 changed files with 52 additions and 62 deletions

View File

@@ -30,7 +30,7 @@ type Agent struct {
currentReasoning string currentReasoning string
currentState *action.StateResult currentState *action.StateResult
nextAction Action nextAction Action
currentConversation []openai.ChatCompletionMessage currentConversation Messages
selfEvaluationInProgress bool selfEvaluationInProgress bool
newConversations chan openai.ChatCompletionMessage newConversations chan openai.ChatCompletionMessage
@@ -392,7 +392,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
job.Result.Finish(fmt.Errorf("error renderTemplate: %w", err)) job.Result.Finish(fmt.Errorf("error renderTemplate: %w", err))
return return
} }
if !Messages(a.currentConversation).Exist(prompt) { if !a.currentConversation.Exist(prompt) {
a.currentConversation = append([]openai.ChatCompletionMessage{ a.currentConversation = append([]openai.ChatCompletionMessage{
{ {
Role: "system", Role: "system",

View File

@@ -3,5 +3,17 @@ package main
import "fmt" import "fmt"
func chatDiv(content string, color string) string { func chatDiv(content string, color string) string {
return fmt.Sprintf(`<div class="p-2 my-2 rounded bg-%s-100">%s</div>`, color, htmlIfy(content)) return fmt.Sprintf(`<div class="p-2 my-2 rounded bg-%s-600">%s</div>`, color, htmlIfy(content))
}
func loader() string {
return `<div class="loader"></div>`
}
func inputMessageDisabled(disabled bool) string {
if disabled {
return `<script> document.getElementById('inputMessage').disabled = true;</script>`
}
return `<script> document.getElementById('inputMessage').disabled = false;</script>`
} }

View File

@@ -1,5 +1,3 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@@ -22,93 +20,73 @@
.htmx-request .htmx-indicator{ .htmx-request .htmx-indicator{
opacity:1 opacity:1
} }
/* https://cssloaders.github.io/ */
.loader { .loader {
width: 4px; width: 12px;
height: 20px; height: 12px;
border-radius: 4px; border-radius: 50%;
display: block; display: block;
margin: 20px auto; margin:15px auto;
position: relative; position: relative;
background: currentColor; color: #FFF;
color: #FFF; box-sizing: border-box;
box-sizing: border-box; animation: animloader 2s linear infinite;
animation: animloader 0.3s 0.3s linear infinite alternate; }
}
.loader::after, .loader::before { @keyframes animloader {
content: ''; 0% { box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px; }
width: 4px; 25% { box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 2px; }
height: 20px; 50% { box-shadow: 14px 0 0 -2px, 38px 0 0 -2px, -14px 0 0 2px, -38px 0 0 -2px; }
border-radius: 4px; 75% { box-shadow: 14px 0 0 2px, 38px 0 0 -2px, -14px 0 0 -2px, -38px 0 0 -2px; }
background: currentColor; 100% { box-shadow: 14px 0 0 -2px, 38px 0 0 2px, -14px 0 0 -2px, -38px 0 0 -2px; }
position: absolute; }
top: 50%;
transform: translateY(-50%);
left: 20px;
box-sizing: border-box;
animation: animloader 0.3s 0.45s linear infinite alternate;
}
.loader::before {
left: -20px;
animation-delay: 0s;
}
@keyframes animloader {
0% { height: 24px}
100% { height: 2px}
}
</style> </style>
</head> </head>
<body class="bg-gray-100 p-4"> <body class="bg-gray-900 p-4 text-white">
<div class="chat-container bg-white shadow-lg rounded-lg" hx-ext="sse" sse-connect="/sse"> <div class="chat-container bg-gray-800 shadow-lg rounded-lg" hx-ext="sse" sse-connect="/sse">
<!-- Chat Header --> <!-- Chat Header -->
<div class="border-b border-gray-200 p-4"> <div class="border-b border-gray-700 p-4">
<h1 class="text-lg font-semibold">Talk to '{{.Character.Name}}'</h1> <h1 class="text-lg font-semibold">Talk to '{{.Character.Name}}'</h1>
</div> </div>
<!-- Chat Messages --> <!-- Chat Messages -->
<div class="chat-messages p-4"> <div class="chat-messages p-4">
<!-- Client Box --> <!-- Client Box -->
<div class="bg-gray-100 p-4"> <div class="bg-gray-700 p-4">
<h2 class="text-sm font-semibold">Clients:</h2> <h2 class="text-sm font-semibold">Clients:</h2>
<div id="clients" class="text-sm text-gray-700"> <div id="clients" class="text-sm text-gray-300">
<!-- Status updates dynamically here --> <!-- Status updates dynamically here -->
<div sse-swap="clients" ></div> <div sse-swap="clients"></div>
</div> </div>
</div> </div>
<!-- HUD Box --> <!-- HUD Box -->
<div class="bg-gray-100 p-4"> <div class="bg-gray-700 p-4">
<h2 class="text-sm font-semibold">Status:</h2> <h2 class="text-sm font-semibold">Status:</h2>
<div id="hud" class="text-sm text-gray-700"> <div id="hud" class="text-sm text-gray-300">
<!-- Status updates dynamically here --> <!-- Status updates dynamically here -->
<div sse-swap="hud" ></div> <div sse-swap="hud"></div>
</div> </div>
</div> </div>
<!-- https://github.com/bigskysoftware/htmx/issues/1882#issuecomment-1783463192 --> <div sse-swap="messages" hx-swap="beforeend" id="messages" hx-on:htmx:after-settle="document.getElementById('messages').scrollIntoView(false)"></div>
<div sse-swap="messages" hx-swap="beforeend" id="messages" hx-on:htmx:after-settle="document.getElementById('messages').scrollIntoView(false)"></div> <div sse-swap="message_status"></div>
<div sse-swap="message_status" ></div>
</div> </div>
<!-- Agent Status Box --> <!-- Agent Status Box -->
<div class="bg-gray-100 p-4"> <div class="bg-gray-700 p-4">
<h2 class="text-sm font-semibold">Agent:</h2> <h2 class="text-sm font-semibold">Agent:</h2>
<div id="agentStatus" class="text-sm text-gray-700" > <div id="agentStatus" class="text-sm text-gray-300">
<!-- Status updates dynamically here --> <!-- Status updates dynamically here -->
<div sse-swap="status" ></div> <div sse-swap="status" ></div>
</div> </div>
</div> </div>
<!-- Message Input --> <!-- Message Input -->
<div class="p-4 border-t border-gray-200"> <div class="p-4 border-t border-gray-700">
<input id="inputMessage" name="message" type="text" hx-post="/chat" hx-target="#results" hx-indicator=".htmx-indicator" <input id="inputMessage" name="message" type="text" hx-post="/chat" hx-target="#results" hx-indicator=".htmx-indicator"
class="p-2 border rounded w-full" placeholder="Type a message..." _="on htmx:afterRequest set my value to ''"> class="p-2 border rounded w-full bg-gray-600 text-white placeholder-gray-300" placeholder="Type a message..." _="on htmx:afterRequest set my value to ''">
<div class="my-2 htmx-indicator" >Loading...</div> <div class="my-2 htmx-indicator" >Loading...</div>
<div id="results" class="flex justify-center"></div> <div id="results" class="flex justify-center"></div>
</div> </div>
</div> </div>

View File

@@ -181,7 +181,7 @@ func (a *App) Chat(m sse.Manager) func(w http.ResponseWriter, r *http.Request) {
} }
m.Send( m.Send(
sse.NewMessage( sse.NewMessage(
chatDiv(query, "blue"), chatDiv(query, "gray"),
).WithEvent("messages")) ).WithEvent("messages"))
go func() { go func() {
@@ -191,11 +191,11 @@ func (a *App) Chat(m sse.Manager) func(w http.ResponseWriter, r *http.Request) {
fmt.Println("response is", res.Response) fmt.Println("response is", res.Response)
m.Send( m.Send(
sse.NewMessage( sse.NewMessage(
chatDiv(res.Response, "red"), chatDiv(res.Response, "blue"),
).WithEvent("messages")) ).WithEvent("messages"))
m.Send( m.Send(
sse.NewMessage( sse.NewMessage(
"<script> document.getElementById('inputMessage').disabled = false;</script>", inputMessageDisabled(false), // show again the input
).WithEvent("message_status")) ).WithEvent("message_status"))
//result := `<i>done</i>` //result := `<i>done</i>`
@@ -204,7 +204,7 @@ func (a *App) Chat(m sse.Manager) func(w http.ResponseWriter, r *http.Request) {
m.Send( m.Send(
sse.NewMessage( sse.NewMessage(
`<div class="p-2 my-2 rounded bg-gray-100"><span class="loader"></span></div><script> document.getElementById('inputMessage').disabled = true;</script>`, loader() + inputMessageDisabled(true),
).WithEvent("message_status")) ).WithEvent("message_status"))
} }
} }