mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-05-14 16:42:12 +00:00
commitf7b3e2540cAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Dec 8 19:42:17 2024 +0100 knowledge import/reload commit4e028a3ce4Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Dec 8 11:28:47 2024 +0100 Memory recall speedup commit8ec3b24696Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Dec 8 00:17:02 2024 +0100 keyboard input tool commita76a302f3fAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Sat Dec 7 23:28:03 2024 +0100 solutions cleanup commit884007cdb0Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sat Dec 7 21:51:14 2024 +0100 console print edits for docker commit927c234d69Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sat Dec 7 20:40:28 2024 +0100 openai azure model func name fix commit53a46288f9Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 15:17:58 2024 +0100 mistral fix, error text output commit6aa37744fcAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 14:58:10 2024 +0100 toast fix commitf0be03ea77Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 14:33:28 2024 +0100 toast errors commit8434682812Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 11:30:34 2024 +0100 warnings cleanup commit2b94af895dAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 10:54:06 2024 +0100 Preload fix commit7f270d4a14Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 09:44:13 2024 +0100 Server startup log msg commitf9c9b5c933Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 07:50:15 2024 +0100 Update run_ui.py commitf3ca7e0742Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Dec 6 06:21:14 2024 +0100 Update run_ui.py commit21975c5a7cAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Dec 5 20:45:51 2024 +0100 local models docker url commitf0a8b07c4fAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Dec 5 16:40:49 2024 +0100 Server addr notice commit656612726aMerge:49594fe7c2866cAuthor: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Thu Dec 5 16:11:23 2024 +0100 Merge pull request #260 from 3clyp50/development fix: toast handling, mobile breakpoint commit7c2866ca61Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Dec 4 19:37:50 2024 +0100 fix: toast handling, mobile breakpoint `toast.css` and `index.js` - fixed toasts disappearing right after showing - simplified toast animation `index.css` - set 2ⁿᵈ mobile breakpoint at 640px commit49594fe6ecMerge:f69775470b1fa3Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Wed Dec 4 10:39:58 2024 +0100 Merge pull request #259 from 3clyp50/development CSS refactor and toasts commit70b1fa385aAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Dec 4 02:17:50 2024 +0100 refactor: css, style: toasts, fix: z-index - organized structure - consolidated selectors and states - shorthand everywhere - modern toasts - bigger action buttons for mobile commitf6977546c1Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 22:42:36 2024 +0100 call subordinate fix commitfbe47ac03eAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 21:19:03 2024 +0100 Minor fixes commit961dbc405aAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 21:10:45 2024 +0100 restart commit357909c16aAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 19:41:29 2024 +0100 whisper remote preload commite0b0b6f636Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 17:39:56 2024 +0100 nudge commit9fae02b2a5Merge:0ebc142fedf2d4Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 14:57:18 2024 +0100 Merge pull request #256 from 3clyp50/development feature: copy text button, nudge & fix: various styles commit0ebc142124Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 14:56:33 2024 +0100 ssh connection retry commitdeae13d383Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 14:38:57 2024 +0100 root pass fix commit9109fcbf60Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 14:28:53 2024 +0100 root password change fix commit46689d6477Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Dec 3 14:22:18 2024 +0100 RFC & SSH exchange for development commitfedf2d4bdcAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Tue Dec 3 04:03:14 2024 +0100 feature: copy text button, nudge & fix: various styles - Copy button for all messages - Nudge button front-end - Fixed various non-styled light mode elements to do -> css cleanup and whisper loading commit19f50d6d95Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Dec 1 20:50:17 2024 +0100 attachments, files, prompt extras, prompt caching, refactors, cleanups commitc99b1a47d4Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 29 08:55:27 2024 +0100 Alpine fix version, STT fixes commit81e653ba2dMerge:857f8b689b8483Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Thu Nov 28 23:08:09 2024 +0100 Merge pull request #255 from 3clyp50/development feature: speech to text settings commit857f8b6d82Author: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Nov 28 23:05:17 2024 +0100 download and remove folders in browser commit89b848312bAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 28 16:07:50 2024 +0100 feature: speech to text settings - initial commit: voice settings - Settings section for STT commitb3a27bb442Merge:5e8d6b1bb980eaAuthor: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Thu Nov 28 08:39:01 2024 +0100 Merge pull request #254 from 3clyp50/development fix: file browser bugs + final ui polishing commitbb980ea6b9Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 28 01:13:56 2024 +0100 fix: file browser deletion bug + parent directory Underscore matters! - fixed both bugs for the browser Extra: - style for toasts quickfix generic modals commitf0126a6ef8Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 27 23:44:20 2024 +0100 style: polishing and consistency commit5e8d6b1c7dAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Wed Nov 27 22:16:13 2024 +0100 Minor fixes commit184f8dcf53Author: frdel <38891707+frdel@users.noreply.github.com> Date: Wed Nov 27 22:05:23 2024 +0100 Pause button fix commit969f142af1Author: frdel <38891707+frdel@users.noreply.github.com> Date: Wed Nov 27 22:01:06 2024 +0100 RFC fix, history bugfixes commit733b8de516Merge:f2057d36a83e79Author: frdel <38891707+frdel@users.noreply.github.com> Date: Wed Nov 27 20:57:15 2024 +0100 Merge branch 'pr/253' into development commit6a83e79d5aAuthor: Alessandro <real.eclypso@gmail.com> Date: Wed Nov 27 20:41:53 2024 +0100 fix: bigger modals commitf2057d3901Author: frdel <38891707+frdel@users.noreply.github.com> Date: Wed Nov 27 17:30:19 2024 +0100 Squashed commit of the following: commite626817332Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 27 12:51:22 2024 +0100 refactor: modals css Modals now get the base styles from modals.css, with any spec in the individual files (settings.css, file_manager.css, ecc). commit306db0ca39Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 27 03:17:20 2024 +0100 style: new action buttons + ghost buttons Updated styles for buttons, switches, and overall UI graphic improvement commitc95a379bb5Author: Alessandro <real.eclypso@gmail.com> Date: Tue Nov 26 20:17:18 2024 +0100 fix: status-icon commiteddafa8798Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Fri Nov 22 01:28:04 2024 +0100 cleanup: webui folder cleanup (history) cleanup: webui sidebar, icons, modals commite626817332Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 27 12:51:22 2024 +0100 refactor: modals css Modals now get the base styles from modals.css, with any spec in the individual files (settings.css, file_manager.css, ecc). commit306db0ca39Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 27 03:17:20 2024 +0100 style: new action buttons + ghost buttons Updated styles for buttons, switches, and overall UI graphic improvement commitc95a379bb5Author: Alessandro <real.eclypso@gmail.com> Date: Tue Nov 26 20:17:18 2024 +0100 fix: status-icon commiteddafa8798Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Fri Nov 22 01:28:04 2024 +0100 cleanup: webui folder cleanup (history) cleanup: webui sidebar, icons, modals commit22ecfd660cAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 25 22:14:17 2024 +0100 intervention message fix commitea9c8bf63bAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 25 20:48:52 2024 +0100 minor context window fixes commit489ca317c5Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 25 19:01:01 2024 +0100 settings auth fix commita0ff118ad1Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 25 17:39:42 2024 +0100 Context window management, work in progress commitc0947e30c7Author: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Nov 21 18:47:40 2024 +0100 API separation commit8db8d3fa18Merge:50348920735bb9Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Thu Nov 21 15:29:20 2024 +0100 Merge pull request #249 from 3clyp50/development feature: work_dir file manager commit0735bb9ae8Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 21 11:28:56 2024 +0100 fix: SVG optimization Thanks SVGO! removal: settings.svg (not used) commit9c968ba1cfAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 21 10:58:20 2024 +0100 feature: work_dir file manager Implemented the file browser for work_dir, we need to: - move endpoints away from run_ui.py - make the "Up" (parent dir) button work Extra: - Now when under 768px in width, you can touch outside of the sidebar to collapse it. commit50348926dfAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 21:56:50 2024 +0100 version info fix commit040de30ef2Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 21:21:47 2024 +0100 removed bundles, tests commit020c16ef86Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 20:46:08 2024 +0100 git+docker improvements version, build branch commit06260ed4a6Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 13:11:54 2024 +0100 searxng fix, ui animation commit41dc7ae146Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 11:05:33 2024 +0100 Nodejs eval require path fix commit970db9adc9Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 10:37:49 2024 +0100 Whisper fix commitf59ac2b485Author: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 09:34:00 2024 +0100 docker /a0 mount fix commitc7046fa97bAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 00:43:15 2024 +0100 docker volume map fix commit0ce8344f0bAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Nov 19 00:23:08 2024 +0100 dockerfile, compose, smart cache commitbad3951646Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 18 21:41:39 2024 +0100 RFC error messages commit05cbaa0f4dAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 18 21:16:50 2024 +0100 RFC password RFC password protection work in progress commit9d1d2be897Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 18 16:18:31 2024 +0100 Dockerfile updates commita7a40ac18fAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 18 10:50:24 2024 +0100 dotenv fix, knowledge tool fic commitba3422d452Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 18 09:01:23 2024 +0100 dotenv fix, gitignore update commit9c7339042fAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Nov 17 23:12:19 2024 +0100 Squashed commit of the following: commit b05d44bb4bc9e07cfc0b584ab39e8624bae771fb Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Nov 17 23:12:00 2024 +0100 searxng, RFC, docker runtime commit c90fd4026e644d22e6c7dc29639c85eee6026828 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sat Nov 16 21:21:49 2024 +0100 Remote function calling commit f71d45ec7dbff4e2d3209f0efe97804f6e602fe7 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 13:13:09 2024 +0100 Fix for bool arg parsing commit 936768d1d8efc9060494334b87f400c933d78048 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 13:01:28 2024 +0100 Dynamic runtime args parsing commit 00c915fc6c1f8f00f8176fbf5b77af32fa312d18 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 12:13:58 2024 +0100 API key fix commit 504a7f91789caa16578af8bae9b7936a9d7fbbb7 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 11:59:41 2024 +0100 API keys JIT loading commit 5678a2fce2d333454bb1a2e94ca2b5916d321b41 Author: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 11:27:12 2024 +0100 Update dotenv.py commite469f6d7baAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 09:57:49 2024 +0100 Docker runtime preload commit66f1ab7bafAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Fri Nov 15 09:49:23 2024 +0100 Docker runtime - SSH, runtime args commit02cb41b2fdAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Nov 14 21:49:45 2024 +0100 WIP: docker runtime commitb33b48057dAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Nov 14 21:28:14 2024 +0100 WIP: docker runtime commit7fc17b39c5Author: frdel <38891707+frdel@users.noreply.github.com> Date: Thu Nov 14 20:27:43 2024 +0100 Docker runtime in progress work in progress container manager script runtime image with autostart commit2bf24b76d9Merge:92d94b4a57f0c1Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Tue Nov 12 15:38:30 2024 +0100 Merge pull request #239 from 3clyp50/development feature: attachments preview and sending (file, code, imgs) commita57f0c1198Author: Alessandro <real.eclypso@gmail.com> Date: Tue Nov 12 15:02:25 2024 +0100 feature: attachments preview and sending (file, code, imgs) commit92d94b4d86Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Nov 10 23:44:15 2024 +0100 TTS prototype TTS with default browser API commit1a91334a42Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Nov 10 20:57:49 2024 +0100 STT continued Dialogue mode and state managed for STT commit22f1a2b744Author: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Nov 10 14:25:20 2024 +0100 speech recognition prototype using xenova web only tts commita0b042cfb2Merge:22db39f82ca0d8Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Sun Nov 10 08:52:32 2024 +0100 Merge pull request #235 from 3clyp50/development feature: openai-whisper voice input commit22db39f731Merge:d39beba2b1aa09Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Sun Nov 10 08:52:15 2024 +0100 Merge pull request #236 from linuztx/development Add Free Cloudflare Tunnel Support for Remote Access commit2b1aa09840Author: linuztx <linuztx@gmail.com> Date: Sun Nov 10 14:56:52 2024 +0800 Add auto-downloading cloudflared tunnel manager commitcca85d7f5dAuthor: linuztx <linuztx@gmail.com> Date: Sun Nov 10 14:54:52 2024 +0800 Integrate Cloudflare tunnel support in web UI commit433f44522cAuthor: linuztx <linuztx@gmail.com> Date: Sun Nov 10 14:54:19 2024 +0800 Add USE_CLOUDFLARE environment variable commitd94c3b0467Author: linuztx <linuztx@gmail.com> Date: Sun Nov 10 14:53:45 2024 +0800 Cloudflared binaries commit451fdb08c4Author: linuztx <linuztx@gmail.com> Date: Sun Nov 10 14:52:24 2024 +0800 Add bin directory for cloudflared downloads commit82ca0d800aAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Sun Nov 10 00:37:41 2024 +0100 feature: openai-whisper voice input This also reverts commit 92a904d4411a203c482bc1231dee1438d7279b62. commit3c6a5bee64Author: Alessandro <real.eclypso@gmail.com> Date: Fri Nov 8 01:46:29 2024 +0100 feature: attachment setup missing - double user message when sending imgs - base 64 images implementation fix: fonts consistency commitd39beba374Merge:2eb497c9d6b769Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Thu Nov 7 08:31:52 2024 +0100 Merge pull request #234 from 3clyp50/development UI Knowledge import, attachments, voice input and scroll fix commit9d6b769dc2Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 7 05:40:40 2024 +0100 UI Knowledge import missing - image attachment - work_dir browser (backend implemented, WIP) - WHISPER (hurry up) commit3c40c86d07Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Thu Nov 7 03:40:06 2024 +0100 Revert index.js scrolling logic + css infinite scroll fix commitd84469dff6Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Nov 6 11:17:56 2024 +0100 Mic js and embedding menu + styles commit2eb497c8d2Merge:ef1cdac21933bcAuthor: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Tue Nov 5 21:33:32 2024 +0100 Merge pull request #233 from 3clyp50/development Animation, KaTeX fix and mobile improvements commit21933bce2fAuthor: Alessandro <real.eclypso@gmail.com> Date: Tue Nov 5 21:07:50 2024 +0100 KaTeX fix and mobile improvements commitef1cdacea2Merge:9626c04553f7bfAuthor: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Tue Nov 5 17:54:14 2024 +0100 Merge pull request #232 from 3clyp50/development LaTeX, old browser support, new buttons and attachments commit553f7bf039Merge:fc03a799626c04Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Tue Nov 5 14:48:53 2024 +0100 Merge remote-tracking branch 'upstream/development' into development commitfc03a7922eAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Tue Nov 5 00:59:25 2024 +0100 Browsers support, new text buttons + attachments - Firefox/old browsers support and new text buttons + attachments - LaTeX support! commit9626c044d5Author: frdel <38891707+frdel@users.noreply.github.com> Date: Mon Nov 4 22:55:56 2024 +0100 UI and settings merge commit255baf0780Merge:1c026ee61b5b83Author: Jan Tomášek <38891707+frdel@users.noreply.github.com> Date: Mon Nov 4 22:26:57 2024 +0100 Merge pull request #229 from 3clyp50/development UI update commit61b5b8389aAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Mon Nov 4 22:26:07 2024 +0100 other things + Embedding Model selection commit6ff3df03deAuthor: Alessandro <real.eclypso@gmail.com> Date: Mon Nov 4 21:06:48 2024 +0100 toast! commite6ac772a2eAuthor: Alessandro <real.eclypso@gmail.com> Date: Mon Nov 4 20:58:55 2024 +0100 Mobile and UX update commit1a0ceebcafAuthor: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Mon Nov 4 15:18:06 2024 +0100 Modal styling WIP commitf28a05d739Author: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Wed Oct 23 00:18:59 2024 +0200 Improved UI/UX in WebUI - Collapsible pref section 👍 - Monospace font - UX focus on user feedback and accessibility - Mobile and input section QoL - Other minor refinements commit1c026ee75fAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Tue Oct 29 19:39:54 2024 +0100 Behaviour prompt Prototype of adjustable behaviour system prompt commita5d671904dAuthor: frdel <38891707+frdel@users.noreply.github.com> Date: Sun Oct 27 18:04:40 2024 +0100 Settings prototype Settings modal window managed from python - work in progress
872 lines
No EOL
26 KiB
JavaScript
872 lines
No EOL
26 KiB
JavaScript
import * as msgs from "./js/messages.js";
|
|
import { speech } from "./js/speech.js";
|
|
|
|
const leftPanel = document.getElementById('left-panel');
|
|
const rightPanel = document.getElementById('right-panel');
|
|
const container = document.querySelector('.container');
|
|
const chatInput = document.getElementById('chat-input');
|
|
const chatHistory = document.getElementById('chat-history');
|
|
const sendButton = document.getElementById('send-button');
|
|
const inputSection = document.getElementById('input-section');
|
|
const statusSection = document.getElementById('status-section');
|
|
const chatsSection = document.getElementById('chats-section');
|
|
const progressBar = document.getElementById('progress-bar');
|
|
const autoScrollSwitch = document.getElementById('auto-scroll-switch');
|
|
const timeDate = document.getElementById('time-date-container');
|
|
|
|
|
|
let autoScroll = true;
|
|
let context = "";
|
|
let connectionStatus = false
|
|
|
|
|
|
// Initialize the toggle button
|
|
setupSidebarToggle();
|
|
|
|
function isMobile() {
|
|
return window.innerWidth <= 768;
|
|
}
|
|
|
|
function toggleSidebar(show) {
|
|
const overlay = document.getElementById('sidebar-overlay');
|
|
if (typeof show === 'boolean') {
|
|
leftPanel.classList.toggle('hidden', !show);
|
|
rightPanel.classList.toggle('expanded', !show);
|
|
overlay.classList.toggle('visible', show);
|
|
} else {
|
|
leftPanel.classList.toggle('hidden');
|
|
rightPanel.classList.toggle('expanded');
|
|
overlay.classList.toggle('visible', !leftPanel.classList.contains('hidden'));
|
|
}
|
|
}
|
|
|
|
function handleResize() {
|
|
const overlay = document.getElementById('sidebar-overlay');
|
|
if (isMobile()) {
|
|
leftPanel.classList.add('hidden');
|
|
rightPanel.classList.add('expanded');
|
|
overlay.classList.remove('visible');
|
|
} else {
|
|
leftPanel.classList.remove('hidden');
|
|
rightPanel.classList.remove('expanded');
|
|
overlay.classList.remove('visible');
|
|
}
|
|
}
|
|
|
|
window.addEventListener('load', handleResize);
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const overlay = document.getElementById('sidebar-overlay');
|
|
overlay.addEventListener('click', () => {
|
|
if (isMobile()) {
|
|
toggleSidebar(false);
|
|
}
|
|
});
|
|
});
|
|
|
|
function setupSidebarToggle() {
|
|
const leftPanel = document.getElementById('left-panel');
|
|
const rightPanel = document.getElementById('right-panel');
|
|
const toggleSidebarButton = document.getElementById('toggle-sidebar');
|
|
if (toggleSidebarButton) {
|
|
toggleSidebarButton.addEventListener('click', toggleSidebar);
|
|
} else {
|
|
console.error('Toggle sidebar button not found');
|
|
setTimeout(setupSidebarToggle, 100);
|
|
}
|
|
}
|
|
document.addEventListener('DOMContentLoaded', setupSidebarToggle);
|
|
|
|
export async function sendMessage() {
|
|
try {
|
|
const message = chatInput.value.trim();
|
|
const inputAD = Alpine.$data(inputSection);
|
|
const attachments = inputAD.attachments;
|
|
const hasAttachments = attachments && attachments.length > 0;
|
|
|
|
if (message || hasAttachments) {
|
|
let response;
|
|
const messageId = generateGUID();
|
|
|
|
// Include attachments in the user message
|
|
if (hasAttachments) {
|
|
const attachmentsWithUrls = attachments.map(attachment => {
|
|
if (attachment.type === 'image') {
|
|
return {
|
|
...attachment,
|
|
url: URL.createObjectURL(attachment.file)
|
|
};
|
|
} else {
|
|
return {
|
|
...attachment
|
|
};
|
|
}
|
|
});
|
|
|
|
// Render user message with attachments
|
|
setMessage(messageId, 'user', '', message, false, {
|
|
attachments: attachmentsWithUrls
|
|
});
|
|
|
|
const formData = new FormData();
|
|
formData.append('text', message);
|
|
formData.append('context', context);
|
|
formData.append('message_id', messageId);
|
|
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
formData.append('attachments', attachments[i].file);
|
|
}
|
|
|
|
response = await fetch('/message_async', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
} else {
|
|
// For text-only messages
|
|
const data = {
|
|
text: message,
|
|
context,
|
|
message_id: messageId
|
|
};
|
|
response = await fetch('/message_async', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
}
|
|
|
|
// Handle response
|
|
const jsonResponse = await response.json();
|
|
if (!jsonResponse) {
|
|
toast("No response returned.", "error");
|
|
}
|
|
// else if (!jsonResponse.ok) {
|
|
// if (jsonResponse.message) {
|
|
// toast(jsonResponse.message, "error");
|
|
// } else {
|
|
// toast("Undefined error.", "error");
|
|
// }
|
|
// }
|
|
else {
|
|
setContext(jsonResponse.context);
|
|
}
|
|
|
|
// Clear input and attachments
|
|
chatInput.value = '';
|
|
inputAD.attachments = [];
|
|
inputAD.hasAttachments = false;
|
|
adjustTextareaHeight();
|
|
}
|
|
} catch (e) {
|
|
toastFetchError("Error sending message", e)
|
|
}
|
|
}
|
|
|
|
function toastFetchError(text, error) {
|
|
if (getConnectionStatus()) {
|
|
toast(`${text}: ${error.message}`, "error");
|
|
} else {
|
|
toast(`${text} (it seems the backend is not running): ${error.message}`, "error");
|
|
}
|
|
console.error(text, error);
|
|
}
|
|
window.toastFetchError = toastFetchError
|
|
|
|
chatInput.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
sendMessage();
|
|
}
|
|
});
|
|
|
|
sendButton.addEventListener('click', sendMessage);
|
|
|
|
|
|
export function updateChatInput(text) {
|
|
console.log('updateChatInput called with:', text);
|
|
|
|
// Append text with proper spacing
|
|
const currentValue = chatInput.value;
|
|
const needsSpace = currentValue.length > 0 && !currentValue.endsWith(' ');
|
|
chatInput.value = currentValue + (needsSpace ? ' ' : '') + text + ' ';
|
|
|
|
// Adjust height and trigger input event
|
|
adjustTextareaHeight();
|
|
chatInput.dispatchEvent(new Event('input'));
|
|
|
|
console.log('Updated chat input value:', chatInput.value);
|
|
}
|
|
|
|
function updateUserTime() {
|
|
const now = new Date();
|
|
const hours = now.getHours();
|
|
const minutes = now.getMinutes();
|
|
const seconds = now.getSeconds();
|
|
const ampm = hours >= 12 ? 'pm' : 'am';
|
|
const formattedHours = hours % 12 || 12;
|
|
|
|
// Format the time
|
|
const timeString = `${formattedHours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')} ${ampm}`;
|
|
|
|
// Format the date
|
|
const options = { year: 'numeric', month: 'short', day: 'numeric' };
|
|
const dateString = now.toLocaleDateString(undefined, options);
|
|
|
|
// Update the HTML
|
|
const userTimeElement = document.getElementById('time-date');
|
|
userTimeElement.innerHTML = `${timeString}<br><span id="user-date">${dateString}</span>`;
|
|
}
|
|
|
|
updateUserTime();
|
|
setInterval(updateUserTime, 1000);
|
|
|
|
|
|
function setMessage(id, type, heading, content, temp, kvps = null) {
|
|
// Search for the existing message container by id
|
|
let messageContainer = document.getElementById(`message-${id}`);
|
|
|
|
if (messageContainer) {
|
|
// Don't re-render user messages
|
|
if (type === 'user') {
|
|
return; // Skip re-rendering
|
|
}
|
|
// For other types, update the message
|
|
messageContainer.innerHTML = '';
|
|
} else {
|
|
// Create a new container if not found
|
|
const sender = type === 'user' ? 'user' : 'ai';
|
|
messageContainer = document.createElement('div');
|
|
messageContainer.id = `message-${id}`;
|
|
messageContainer.classList.add('message-container', `${sender}-container`);
|
|
if (temp) messageContainer.classList.add("message-temp");
|
|
}
|
|
|
|
const handler = msgs.getHandler(type);
|
|
handler(messageContainer, id, type, heading, content, temp, kvps);
|
|
|
|
// If the container was found, it was already in the DOM, no need to append again
|
|
if (!document.getElementById(`message-${id}`)) {
|
|
chatHistory.appendChild(messageContainer);
|
|
}
|
|
|
|
if (autoScroll) chatHistory.scrollTop = chatHistory.scrollHeight;
|
|
}
|
|
|
|
|
|
window.loadKnowledge = async function () {
|
|
const input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.accept = '.txt,.pdf,.csv,.html,.json,.md';
|
|
input.multiple = true;
|
|
|
|
input.onchange = async () => {
|
|
try{
|
|
const formData = new FormData();
|
|
for (let file of input.files) {
|
|
formData.append('files[]', file);
|
|
}
|
|
|
|
formData.append('ctxid', getContext());
|
|
|
|
const response = await fetch('/import_knowledge', {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
toast(await response.text(), "error");
|
|
} else {
|
|
const data = await response.json();
|
|
toast("Knowledge files imported: " + data.filenames.join(", "), "success");
|
|
}
|
|
} catch (e) {
|
|
toastFetchError("Error loading knowledge", e)
|
|
}
|
|
};
|
|
|
|
input.click();
|
|
}
|
|
|
|
|
|
function adjustTextareaHeight() {
|
|
chatInput.style.height = 'auto';
|
|
chatInput.style.height = (chatInput.scrollHeight) + 'px';
|
|
}
|
|
|
|
export const sendJsonData = async function (url, data) {
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const error = await response.text();
|
|
throw new Error(error);
|
|
}
|
|
const jsonResponse = await response.json();
|
|
return jsonResponse;
|
|
}
|
|
window.sendJsonData = sendJsonData
|
|
|
|
function generateGUID() {
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
var r = Math.random() * 16 | 0;
|
|
var v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
return v.toString(16);
|
|
});
|
|
}
|
|
|
|
function getConnectionStatus() {
|
|
return connectionStatus
|
|
}
|
|
|
|
function setConnectionStatus(connected) {
|
|
connectionStatus = connected
|
|
const statusIcon = Alpine.$data(timeDate.querySelector('.status-icon'));
|
|
statusIcon.connected = connected
|
|
}
|
|
|
|
let lastLogVersion = 0;
|
|
let lastLogGuid = ""
|
|
let lastSpokenNo = 0
|
|
|
|
async function poll() {
|
|
let updated = false
|
|
try {
|
|
const response = await sendJsonData("/poll", { log_from: lastLogVersion, context });
|
|
//console.log(response)
|
|
|
|
if (!context) setContext(response.context)
|
|
if (response.context != context) return //skip late polls after context change
|
|
|
|
if (lastLogGuid != response.log_guid) {
|
|
chatHistory.innerHTML = ""
|
|
lastLogVersion = 0
|
|
}
|
|
|
|
if (lastLogVersion != response.log_version) {
|
|
updated = true
|
|
for (const log of response.logs) {
|
|
const messageId = log.id || log.no; // Use log.id if available
|
|
setMessage(messageId, log.type, log.heading, log.content, log.temp, log.kvps);
|
|
}
|
|
afterMessagesUpdate(response.logs)
|
|
}
|
|
|
|
updateProgress(response.log_progress, response.log_progress_active)
|
|
|
|
//set ui model vars from backend
|
|
const inputAD = Alpine.$data(inputSection);
|
|
inputAD.paused = response.paused;
|
|
|
|
// Update status icon state
|
|
setConnectionStatus(true)
|
|
|
|
const chatsAD = Alpine.$data(chatsSection);
|
|
chatsAD.contexts = response.contexts;
|
|
|
|
lastLogVersion = response.log_version;
|
|
lastLogGuid = response.log_guid;
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
setConnectionStatus(false)
|
|
}
|
|
|
|
return updated
|
|
}
|
|
|
|
function afterMessagesUpdate(logs) {
|
|
if (localStorage.getItem('speech') == 'true') {
|
|
speakMessages(logs)
|
|
}
|
|
}
|
|
|
|
function speakMessages(logs) {
|
|
// log.no, log.type, log.heading, log.content
|
|
for (let i = logs.length - 1; i >= 0; i--) {
|
|
const log = logs[i]
|
|
if (log.type == "response") {
|
|
if (log.no > lastSpokenNo) {
|
|
lastSpokenNo = log.no
|
|
speech.speak(log.content)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateProgress(progress, active) {
|
|
if (!progress) progress = ""
|
|
|
|
if (!active) {
|
|
removeClassFromElement(progressBar, "shiny-text")
|
|
} else {
|
|
addClassToElement(progressBar, "shiny-text")
|
|
}
|
|
|
|
if (progressBar.innerHTML != progress) {
|
|
progressBar.innerHTML = progress
|
|
}
|
|
}
|
|
|
|
window.pauseAgent = async function (paused) {
|
|
try {
|
|
const resp = await sendJsonData("/pause", { paused: paused, context });
|
|
} catch (e) {
|
|
window.toastFetchError("Error pausing agent", e)
|
|
}
|
|
}
|
|
|
|
window.resetChat = async function () {
|
|
try {
|
|
const resp = await sendJsonData("/chat_reset", { context });
|
|
updateAfterScroll()
|
|
} catch (e) {
|
|
window.toastFetchError("Error resetting chat", e)
|
|
}
|
|
}
|
|
|
|
window.newChat = async function () {
|
|
try {
|
|
setContext(generateGUID());
|
|
updateAfterScroll()
|
|
} catch (e) {
|
|
window.toastFetchError("Error creating new chat", e)
|
|
}
|
|
}
|
|
|
|
window.killChat = async function (id) {
|
|
try {
|
|
const chatsAD = Alpine.$data(chatsSection);
|
|
let found, other
|
|
for (let i = 0; i < chatsAD.contexts.length; i++) {
|
|
if (chatsAD.contexts[i].id == id) {
|
|
found = true
|
|
} else {
|
|
other = chatsAD.contexts[i]
|
|
}
|
|
if (found && other) break
|
|
}
|
|
|
|
if (context == id && found) {
|
|
if (other) setContext(other.id)
|
|
else setContext(generateGUID())
|
|
}
|
|
|
|
if (found) sendJsonData("/chat_remove", { context: id });
|
|
|
|
updateAfterScroll()
|
|
|
|
} catch (e) {
|
|
window.toastFetchError("Error creating new chat", e)
|
|
}
|
|
}
|
|
|
|
window.selectChat = async function (id) {
|
|
setContext(id)
|
|
updateAfterScroll()
|
|
}
|
|
|
|
export const setContext = function (id) {
|
|
if (id == context) return
|
|
context = id
|
|
lastLogGuid = ""
|
|
lastLogVersion = 0
|
|
lastSpokenNo = 0
|
|
const chatsAD = Alpine.$data(chatsSection);
|
|
chatsAD.selected = id
|
|
}
|
|
|
|
export const getContext = function () {
|
|
return context
|
|
}
|
|
|
|
window.toggleAutoScroll = async function (_autoScroll) {
|
|
autoScroll = _autoScroll;
|
|
}
|
|
|
|
window.toggleJson = async function (showJson) {
|
|
// add display:none to .msg-json class definition
|
|
toggleCssProperty('.msg-json', 'display', showJson ? 'block' : 'none');
|
|
}
|
|
|
|
window.toggleThoughts = async function (showThoughts) {
|
|
// add display:none to .msg-json class definition
|
|
toggleCssProperty('.msg-thoughts', 'display', showThoughts ? undefined : 'none');
|
|
}
|
|
|
|
window.toggleUtils = async function (showUtils) {
|
|
// add display:none to .msg-json class definition
|
|
toggleCssProperty('.message-util', 'display', showUtils ? undefined : 'none');
|
|
// toggleCssProperty('.message-util .msg-kvps', 'display', showUtils ? undefined : 'none');
|
|
// toggleCssProperty('.message-util .msg-content', 'display', showUtils ? undefined : 'none');
|
|
}
|
|
|
|
window.toggleDarkMode = function (isDark) {
|
|
if (isDark) {
|
|
document.body.classList.remove('light-mode');
|
|
} else {
|
|
document.body.classList.add('light-mode');
|
|
}
|
|
console.log("Dark mode:", isDark);
|
|
localStorage.setItem('darkMode', isDark);
|
|
};
|
|
|
|
window.toggleSpeech = function (isOn) {
|
|
console.log("Speech:", isOn);
|
|
localStorage.setItem('speech', isOn);
|
|
if (!isOn) speech.stop()
|
|
};
|
|
|
|
window.nudge = async function () {
|
|
try {
|
|
const resp = await sendJsonData("/nudge", { ctxid: getContext() });
|
|
} catch (e) {
|
|
toastFetchError("Error nudging agent", e)
|
|
}
|
|
}
|
|
|
|
window.restart = async function () {
|
|
try {
|
|
if (!getConnectionStatus()) {
|
|
toast("Backend disconnected, cannot restart.", "error");
|
|
return
|
|
}
|
|
// First try to initiate restart
|
|
const resp = await sendJsonData("/restart", {});
|
|
} catch (e) {
|
|
// Show restarting message
|
|
toast("Restarting...", "info", 0);
|
|
|
|
let retries = 0;
|
|
const maxRetries = 60; // Maximum number of retries (15 seconds with 250ms interval)
|
|
|
|
while (retries < maxRetries) {
|
|
try {
|
|
const resp = await sendJsonData("/health", {});
|
|
// Server is back up, show success message
|
|
await new Promise(resolve => setTimeout(resolve, 250));
|
|
hideToast();
|
|
await new Promise(resolve => setTimeout(resolve, 400));
|
|
toast("Restarted", "success", 5000);
|
|
return;
|
|
} catch (e) {
|
|
// Server still down, keep waiting
|
|
retries++;
|
|
await new Promise(resolve => setTimeout(resolve, 250));
|
|
}
|
|
}
|
|
|
|
// If we get here, restart failed or took too long
|
|
hideToast();
|
|
await new Promise(resolve => setTimeout(resolve, 400));
|
|
toast("Restart timed out or failed", "error", 5000);
|
|
}
|
|
}
|
|
|
|
// Modify this part
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const isDarkMode = localStorage.getItem('darkMode') !== 'false';
|
|
toggleDarkMode(isDarkMode);
|
|
});
|
|
|
|
window.toggleDarkMode = function (isDark) {
|
|
if (isDark) {
|
|
document.body.classList.remove('light-mode');
|
|
} else {
|
|
document.body.classList.add('light-mode');
|
|
}
|
|
console.log("Dark mode:", isDark);
|
|
localStorage.setItem('darkMode', isDark);
|
|
};
|
|
|
|
function toggleCssProperty(selector, property, value) {
|
|
// Get the stylesheet that contains the class
|
|
const styleSheets = document.styleSheets;
|
|
|
|
// Iterate through all stylesheets to find the class
|
|
for (let i = 0; i < styleSheets.length; i++) {
|
|
const styleSheet = styleSheets[i];
|
|
const rules = styleSheet.cssRules || styleSheet.rules;
|
|
|
|
for (let j = 0; j < rules.length; j++) {
|
|
const rule = rules[j];
|
|
if (rule.selectorText == selector) {
|
|
// Check if the property is already applied
|
|
if (value === undefined) {
|
|
rule.style.removeProperty(property);
|
|
} else {
|
|
rule.style.setProperty(property, value);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
window.loadChats = async function () {
|
|
try {
|
|
const fileContents = await readJsonFiles();
|
|
const response = await sendJsonData("/chat_load", { chats: fileContents });
|
|
|
|
if (!response) {
|
|
toast("No response returned.", "error")
|
|
}
|
|
// else if (!response.ok) {
|
|
// if (response.message) {
|
|
// toast(response.message, "error")
|
|
// } else {
|
|
// toast("Undefined error.", "error")
|
|
// }
|
|
// }
|
|
else {
|
|
setContext(response.ctxids[0])
|
|
toast("Chats loaded.", "success")
|
|
}
|
|
|
|
} catch (e) {
|
|
toastFetchError("Error loading chats", e)
|
|
}
|
|
}
|
|
|
|
window.saveChat = async function () {
|
|
try {
|
|
const response = await sendJsonData("/chat_export", { ctxid: context });
|
|
|
|
if (!response) {
|
|
toast("No response returned.", "error")
|
|
}
|
|
// else if (!response.ok) {
|
|
// if (response.message) {
|
|
// toast(response.message, "error")
|
|
// } else {
|
|
// toast("Undefined error.", "error")
|
|
// }
|
|
// }
|
|
else {
|
|
downloadFile(response.ctxid + ".json", response.content)
|
|
toast("Chat file downloaded.", "success")
|
|
}
|
|
|
|
} catch (e) {
|
|
toastFetchError("Error saving chat", e)
|
|
}
|
|
}
|
|
|
|
function downloadFile(filename, content) {
|
|
// Create a Blob with the content to save
|
|
const blob = new Blob([content], { type: 'application/json' });
|
|
|
|
// Create a link element
|
|
const link = document.createElement('a');
|
|
|
|
// Create a URL for the Blob
|
|
const url = URL.createObjectURL(blob);
|
|
link.href = url;
|
|
|
|
// Set the file name for download
|
|
link.download = filename;
|
|
|
|
// Programmatically click the link to trigger the download
|
|
link.click();
|
|
|
|
// Clean up by revoking the object URL
|
|
setTimeout(() => {
|
|
URL.revokeObjectURL(url);
|
|
}, 0);
|
|
}
|
|
|
|
|
|
function readJsonFiles() {
|
|
return new Promise((resolve, reject) => {
|
|
// Create an input element of type 'file'
|
|
const input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.accept = '.json'; // Only accept JSON files
|
|
input.multiple = true; // Allow multiple file selection
|
|
|
|
// Trigger the file dialog
|
|
input.click();
|
|
|
|
// When files are selected
|
|
input.onchange = async () => {
|
|
const files = input.files;
|
|
if (!files.length) {
|
|
resolve([]); // Return an empty array if no files are selected
|
|
return;
|
|
}
|
|
|
|
// Read each file as a string and store in an array
|
|
const filePromises = Array.from(files).map(file => {
|
|
return new Promise((fileResolve, fileReject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = () => fileResolve(reader.result);
|
|
reader.onerror = fileReject;
|
|
reader.readAsText(file);
|
|
});
|
|
});
|
|
|
|
try {
|
|
const fileContents = await Promise.all(filePromises);
|
|
resolve(fileContents);
|
|
} catch (error) {
|
|
reject(error); // In case of any file reading error
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
function addClassToElement(element, className) {
|
|
element.classList.add(className);
|
|
}
|
|
|
|
function removeClassFromElement(element, className) {
|
|
element.classList.remove(className);
|
|
}
|
|
|
|
|
|
function toast(text, type = 'info', timeout = 5000) {
|
|
const toast = document.getElementById('toast');
|
|
const isVisible = toast.classList.contains('show');
|
|
|
|
// Clear any existing timeout immediately
|
|
if (toast.timeoutId) {
|
|
clearTimeout(toast.timeoutId);
|
|
toast.timeoutId = null;
|
|
}
|
|
|
|
// Function to update toast content and show it
|
|
const updateAndShowToast = () => {
|
|
// Update the toast content and type
|
|
const title = type.charAt(0).toUpperCase() + type.slice(1);
|
|
toast.querySelector('.toast__title').textContent = title;
|
|
toast.querySelector('.toast__message').textContent = text;
|
|
|
|
// Remove old classes and add new ones
|
|
toast.classList.remove('toast--success', 'toast--error', 'toast--info');
|
|
toast.classList.add(`toast--${type}`);
|
|
|
|
// Show/hide copy button based on toast type
|
|
const copyButton = toast.querySelector('.toast__copy');
|
|
copyButton.style.display = type === 'error' ? 'inline-block' : 'none';
|
|
|
|
// Add the close button event listener
|
|
const closeButton = document.querySelector('.toast__close');
|
|
closeButton.onclick = () => {
|
|
hideToast();
|
|
};
|
|
|
|
// Add the copy button event listener
|
|
copyButton.onclick = () => {
|
|
navigator.clipboard.writeText(text);
|
|
copyButton.textContent = 'Copied!';
|
|
setTimeout(() => {
|
|
copyButton.textContent = 'Copy';
|
|
}, 2000);
|
|
};
|
|
|
|
// Show the toast
|
|
toast.style.display = 'flex';
|
|
// Force a reflow to ensure the animation triggers
|
|
void toast.offsetWidth;
|
|
toast.classList.add('show');
|
|
|
|
// Set timeout if specified
|
|
if (timeout) {
|
|
const minTimeout = Math.max(timeout, 5000);
|
|
toast.timeoutId = setTimeout(() => {
|
|
hideToast();
|
|
}, minTimeout);
|
|
}
|
|
};
|
|
|
|
if (isVisible) {
|
|
// If a toast is visible, hide it first then show the new one
|
|
toast.classList.remove('show');
|
|
toast.classList.add('hide');
|
|
|
|
// Wait for hide animation to complete before showing new toast
|
|
setTimeout(() => {
|
|
toast.classList.remove('hide');
|
|
updateAndShowToast();
|
|
}, 400); // Match this with CSS transition duration
|
|
} else {
|
|
// If no toast is visible, show the new one immediately
|
|
updateAndShowToast();
|
|
}
|
|
}
|
|
|
|
function hideToast() {
|
|
const toast = document.getElementById('toast');
|
|
|
|
// Clear any existing timeout
|
|
if (toast.timeoutId) {
|
|
clearTimeout(toast.timeoutId);
|
|
toast.timeoutId = null;
|
|
}
|
|
|
|
toast.classList.remove('show');
|
|
toast.classList.add('hide');
|
|
|
|
// Wait for the hide animation to complete before removing from display
|
|
setTimeout(() => {
|
|
toast.style.display = 'none';
|
|
toast.classList.remove('hide');
|
|
}, 400); // Match this with CSS transition duration
|
|
}
|
|
|
|
function scrollChanged(isAtBottom) {
|
|
const inputAS = Alpine.$data(autoScrollSwitch);
|
|
inputAS.autoScroll = isAtBottom
|
|
// autoScrollSwitch.checked = isAtBottom
|
|
}
|
|
|
|
function updateAfterScroll() {
|
|
// const toleranceEm = 1; // Tolerance in em units
|
|
// const tolerancePx = toleranceEm * parseFloat(getComputedStyle(document.documentElement).fontSize); // Convert em to pixels
|
|
const tolerancePx = 50;
|
|
const chatHistory = document.getElementById('chat-history');
|
|
const isAtBottom = (chatHistory.scrollHeight - chatHistory.scrollTop) <= (chatHistory.clientHeight + tolerancePx);
|
|
|
|
scrollChanged(isAtBottom);
|
|
}
|
|
|
|
chatHistory.addEventListener('scroll', updateAfterScroll);
|
|
|
|
chatInput.addEventListener('input', adjustTextareaHeight);
|
|
|
|
// setInterval(poll, 250);
|
|
|
|
async function startPolling() {
|
|
const shortInterval = 25
|
|
const longInterval = 250
|
|
const shortIntervalPeriod = 100
|
|
let shortIntervalCount = 0
|
|
|
|
async function _doPoll() {
|
|
let nextInterval = longInterval
|
|
|
|
try {
|
|
const result = await poll();
|
|
if (result) shortIntervalCount = shortIntervalPeriod; // Reset the counter when the result is true
|
|
if (shortIntervalCount > 0) shortIntervalCount--; // Decrease the counter on each call
|
|
nextInterval = shortIntervalCount > 0 ? shortInterval : longInterval;
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
}
|
|
|
|
// Call the function again after the selected interval
|
|
setTimeout(_doPoll.bind(this), nextInterval);
|
|
}
|
|
|
|
_doPoll();
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", startPolling); |