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';