nudge

frdel committed Dec 3, 2024 at 17:39 UTC e0b0b6f6367841c85dfa9c2156f46db755c88497
4 files changed +58 -15
agent.py
+15 -1
@@ -66,14 +66,28 @@ class AgentContext:
66 context.process.kill()
67 return context
68
69 - def reset(self):
69 + def kill_process(self):
70 if self.process:
71 self.process.kill()
72 +
73 + def reset(self):
74 + self.kill_process()
75 self.log.reset()
76 self.agent0 = Agent(0, self.config, self)
77 self.streaming_agent = None
78 self.paused = False
79
80 + def nudge(self):
81 + self.kill_process()
82 + self.paused = False
83 + if self.streaming_agent:
84 + current_agent = self.streaming_agent
85 + else:
86 + current_agent = self.agent0
87 +
88 + self.process = DeferredTask(current_agent.monologue)
89 + return self.process
90 +
91 def communicate(self, msg: "UserMessage", broadcast_level: int = 1):
92 self.paused = False # unpause if paused
93
python/api/nudge.py new
+21
@@ -0,0 +1,21 @@
1 +from python.helpers.api import ApiHandler
2 +from flask import Request, Response
3 +
4 +from python.helpers import persist_chat
5 +
6 +class Nudge(ApiHandler):
7 + async def process(self, input: dict, request: Request) -> dict | Response:
8 + ctxid = input.get("ctxid", "")
9 + if not ctxid:
10 + raise Exception("No context id provided")
11 +
12 + context = self.get_context(ctxid)
13 + context.nudge()
14 +
15 + msg = "Context reset, agent nudged."
16 + context.log.log(type="info", content=msg)
17 +
18 + return {
19 + "message": msg,
20 + "ctxid": context.id,
21 + }
\ No newline at end of file
webui/index.html
+1 -1
@@ -388,7 +388,7 @@
388 <p>Context</p>
389 </button>
390
391 - <button class="text-button" id="nudges_window" @click="NUDGE_LOGIC()">
391 + <button class="text-button" id="nudges_window" @click="nudge()">
392 <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49 58" fill="currentColor">
393 <path d="m11.97,16.32c-.46,0-.91-.25-1.15-.68-.9-1.63-1.36-3.34-1.36-5.1C9.45,4.73,14.18,0,20,0s10.55,4.73,10.55,10.55c0,.87-.13,1.75-.41,2.76-.19.7-.9,1.13-1.62.93-.7-.19-1.12-.92-.93-1.62.21-.79.31-1.44.31-2.07,0-4.36-3.55-7.91-7.91-7.91s-7.91,3.55-7.91,7.91c0,1.3.35,2.59,1.03,3.82.36.64.13,1.44-.51,1.79-.21.11-.42.17-.64.17Z" stroke-width="0.5" stroke="currentColor"/>
394 <path d="m34.5,58h-6.18c-3.17,0-6.15-1.23-8.39-3.47L1.16,35.75c-1.54-1.54-1.54-4.05,0-5.59,2.4-2.4,6.27-2.68,8.99-.64l4.58,3.44V10.55c0-2.91,2.36-5.27,5.27-5.27s5.27,2.36,5.27,5.27v8.62c.78-.45,1.68-.71,2.64-.71,2.3,0,4.26,1.48,4.98,3.53.84-.56,1.85-.89,2.93-.89,2.3,0,4.26,1.48,4.98,3.53.84-.56,1.85-.89,2.93-.89,2.91,0,5.27,2.36,5.27,5.27v14.5c0,8-6.51,14.5-14.5,14.5ZM6.03,30.79c-1.1,0-2.19.42-3.01,1.23-.51.51-.51,1.35,0,1.86l18.77,18.78c1.74,1.74,4.06,2.7,6.53,2.7h6.18c6.54,0,11.86-5.32,11.86-11.86v-14.5c0-1.45-1.18-2.64-2.64-2.64s-2.64,1.18-2.64,2.64v1.32c0,.73-.59,1.32-1.32,1.32s-1.32-.59-1.32-1.32v-3.95c0-1.45-1.18-2.64-2.64-2.64s-2.64,1.18-2.64,2.64v3.95c0,.73-.59,1.32-1.32,1.32s-1.32-.59-1.32-1.32v-6.59c0-1.45-1.18-2.64-2.64-2.64s-2.64,1.18-2.64,2.64v6.59c0,.73-.59,1.32-1.32,1.32s-1.32-.59-1.32-1.32V10.55c0-1.45-1.18-2.64-2.64-2.64s-2.64,1.18-2.64,2.64v25.05c0,.5-.28.95-.73,1.18s-.98.18-1.38-.12l-6.69-5.02c-.75-.56-1.65-.84-2.54-.84Z" stroke-width="0.5" stroke="currentColor"/>
webui/index.js
+21 -13
@@ -338,8 +338,8 @@ async function poll() {
338 // Update status icon state
339 const timeDate = document.getElementById('time-date-container');
340 if (timeDate) {
341 - const statusIcon = Alpine.$data(timeDate.querySelector('.status-icon'));
342 - statusIcon.connected = true;
341 + const statusIcon = Alpine.$data(timeDate.querySelector('.status-icon'));
342 + statusIcon.connected = true;
343 }
344
345 const chatsAD = Alpine.$data(chatsSection);
@@ -489,6 +489,14 @@ window.toggleSpeech = function (isOn) {
489 if (!isOn) speech.stop()
490 };
491
492 +window.nudge = async function () {
493 + try {
494 + const resp = await sendJsonData("/nudge", { ctxid: getContext() });
495 + } catch (e) {
496 + toast(e.message, "error")
497 + }
498 +}
499 +
500 // Modify this part
501 document.addEventListener('DOMContentLoaded', () => {
502 const isDarkMode = localStorage.getItem('darkMode') !== 'false';
@@ -652,30 +660,30 @@ function removeClassFromElement(element, className) {
660
661 function toast(text, type = 'info') {
662 const toast = document.getElementById('toast');
655 -
663 +
664 // Update the toast content and type
665 toast.querySelector('.toast__message').textContent = text;
666 toast.className = `toast toast--${type}`;
659 -
667 +
668 // Remove any existing animation classes
669 toast.classList.remove('show', 'hide');
662 -
670 +
671 // Show the toast and trigger animation
672 toast.style.display = 'flex';
673 // Force a reflow to ensure the animation triggers
674 void toast.offsetWidth;
675 toast.classList.add('show');
668 -
676 +
677 // Show/hide copy button based on toast type
678 const copyButton = toast.querySelector('.toast__copy');
679 copyButton.style.display = type === 'error' ? 'inline-block' : 'none';
672 -
680 +
681 // Add the close button event listener
682 const closeButton = toast.querySelector('.toast__close');
683 closeButton.onclick = () => {
684 hideToast();
685 };
678 -
686 +
687 // Add the copy button event listener
688 copyButton.onclick = () => {
689 navigator.clipboard.writeText(text);
@@ -684,21 +692,21 @@ function toast(text, type = 'info') {
692 copyButton.textContent = 'Copy';
693 }, 2000);
694 };
687 -
695 +
696 // Clear any existing timeout
697 clearTimeout(toast.timeoutId);
690 -
698 +
699 // Automatically close the toast after 10 seconds
700 toast.timeoutId = setTimeout(() => {
701 hideToast();
702 }, 10000);
703 }
696 -
697 - function hideToast() {
704 +
705 +function hideToast() {
706 const toast = document.getElementById('toast');
707 toast.classList.remove('show');
708 toast.classList.add('hide');
701 -
709 +
710 // Remove the element from display after animation completes
711 setTimeout(() => {
712 toast.style.display = 'none';