985 lines
47 KiB
HTML
985 lines
47 KiB
HTML
<!DOCTYPE html>
|
|
<!--
|
|
PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
|
|
Copyright 2025 TimeHexOn & foxhop & russell@unturf
|
|
https://www.permacomputer.com
|
|
-->
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="theme-color" content="#43a047">
|
|
<meta name="color-scheme" content="light dark">
|
|
<title>Demo Free LLM & Text To Speech Artificial Intelligence Service | uncloseai.com</title>
|
|
|
|
<!-- PicoCSS -->
|
|
<link rel="stylesheet" href="/css/pico.classless.min.css">
|
|
<!-- ChunkFive Font -->
|
|
<link rel="stylesheet" href="/css/chunkfive/stylesheet.css" type="text/css" charset="utf-8" />
|
|
|
|
<style>
|
|
body {
|
|
max-width: 960px;
|
|
margin: 0 auto;
|
|
}
|
|
</style>
|
|
|
|
<!-- Highlight.js for syntax highlighting -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/a11y-dark.min.css" />
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
|
|
|
|
<!-- Theme Switcher Script -->
|
|
<script>
|
|
function switchTheme(theme) {
|
|
if (theme === "auto") {
|
|
document.documentElement.removeAttribute('data-theme');
|
|
} else {
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
}
|
|
}
|
|
|
|
// Disable custom styling for uncloseai.js - use PicoCSS instead
|
|
window.UNCLOSEAI_CUSTOM_STYLING = false;
|
|
|
|
// Disable the floating button
|
|
window.UNCLOSEAI_FLOATING_BUTTON = false;
|
|
</script>
|
|
|
|
<script src="https://uncloseai.com/uncloseai.js" type="module"></script>
|
|
|
|
<!-- Demo: System Message Customization -->
|
|
<script type="module">
|
|
import { setSystemMessageAppend } from './src/config.js';
|
|
|
|
setSystemMessageAppend(`
|
|
Additional context for this demo page:
|
|
- You're helping users explore and test AI features on uncloseai.com
|
|
- This is a demonstration page showing various AI capabilities
|
|
- Encourage users to try different features like TTS, translation, and the Hermes chat
|
|
- Be enthusiastic and helpful when explaining how the features work
|
|
- If users ask about implementation, reference the code examples on this page
|
|
`);
|
|
</script>
|
|
|
|
<!--
|
|
<script defer data-domain="ai.unturf.com" src="https://analytics.unturf.com/js/plausible.js"></script>
|
|
-->
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<header>
|
|
<hgroup>
|
|
<a href="https://uncloseai.com"><h1 class="unturf" style="font-family: 'ChunkFiveRegular';">uncloseai.</h1></a>
|
|
<p>Welcome to uncloseai.com - Free LLM & Text To Speech Artificial Intelligence Service</p>
|
|
</hgroup>
|
|
<nav>
|
|
<ul>
|
|
<li><a href="#" onclick="switchTheme('auto')">Auto</a></li>
|
|
<li><a href="#" onclick="switchTheme('light')">Light</a></li>
|
|
<li><a href="#" onclick="switchTheme('dark')">Dark</a></li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
|
|
<main>
|
|
<h2>Hermes AI Integration Demo</h2>
|
|
<p>This page demonstrates all the ways you can integrate Hermes AI into your website using uncloseai.js. Each example is isolated and can be used independently.</p>
|
|
|
|
<!-- Table of Contents -->
|
|
<section>
|
|
<h3>📋 Table of Contents</h3>
|
|
<nav>
|
|
<ol>
|
|
<li><a href="#basic-installation">Basic Installation</a></li>
|
|
<li><a href="#configuration-options">Configuration Options</a></li>
|
|
<li><a href="#system-message-customization">System Message Customization</a></li>
|
|
<li><a href="#full-interface">Full AI Interface</a></li>
|
|
<li><a href="#chat-only">Chat Interface Only</a></li>
|
|
<li><a href="#feature-buttons">Feature Buttons Only</a></li>
|
|
<li><a href="#tts-only">Text-to-Speech Options</a></li>
|
|
<li><a href="#translate-only">Translation Options</a></li>
|
|
<li><a href="#translation">Translation API</a></li>
|
|
<li><a href="#read-page">Read Page Functionality</a></li>
|
|
<li><a href="#direct-api">Direct API Usage</a></li>
|
|
<li><a href="#custom-examples">Custom API Examples</a></li>
|
|
</ol>
|
|
</nav>
|
|
</section>
|
|
|
|
<!-- 1. Basic Installation -->
|
|
<section id="basic-installation">
|
|
<h3>1. 📦 Basic Installation</h3>
|
|
<p>The simplest way to add AI features to your website:</p>
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Installation Code</strong></summary>
|
|
<p>Add this single line to your HTML to get a floating AI button:</p>
|
|
<pre><code class="html"><script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>This page demonstrates the basic installation - notice the floating AI button in the bottom right corner!</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<p><strong>✅ Active Demo:</strong> The floating Hermes button on this page is created by the basic installation code above.</p>
|
|
<p>Try clicking the floating button to test the AI chat functionality!</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 2. Configuration Options -->
|
|
<section id="configuration-options">
|
|
<h3>2. ⚙️ Configuration Options</h3>
|
|
<p>Customize the behavior before loading the script:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Configuration Code</strong></summary>
|
|
<p>Customize the behavior before loading the script:</p>
|
|
<pre><code class="html"><script>
|
|
// Disable custom styling (use your CSS framework)
|
|
window.UNCLOSEAI_CUSTOM_STYLING = false;
|
|
|
|
// Disable floating button (API functions only)
|
|
window.UNCLOSEAI_FLOATING_BUTTON = false;
|
|
</script>
|
|
<script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>This page uses these configuration options:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<p><strong>✅ Active Demo:</strong> This page has:</p>
|
|
<ul>
|
|
<li><code>UNCLOSEAI_CUSTOM_STYLING = false</code> - Uses PicoCSS styling instead</li>
|
|
<li><code>UNCLOSEAI_FLOATING_BUTTON = false</code> - Floating button disabled for embedded examples</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 3. System Message Customization -->
|
|
<section id="system-message-customization">
|
|
<h3>3. 💬 System Message Customization</h3>
|
|
<p>Customize the AI's behavior by appending additional instructions:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>System Message Customization Code</strong></summary>
|
|
<p>Customize the AI's behavior by appending instructions:</p>
|
|
<pre><code class="html"><script type="module">
|
|
import { setSystemMessageAppend } from './src/config.js';
|
|
|
|
setSystemMessageAppend(`
|
|
Additional context for this demo page:
|
|
- You're helping users test AI features
|
|
- Provide clear, helpful examples
|
|
- Be encouraging about trying different features
|
|
`);
|
|
</script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>This page uses custom system message instructions:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<p><strong>✅ Active Demo:</strong> The AI on this page has been customized to:</p>
|
|
<ul>
|
|
<li>Help users explore and test AI features</li>
|
|
<li>Provide clear, helpful examples</li>
|
|
<li>Be encouraging about trying different features</li>
|
|
</ul>
|
|
<p>Try asking the AI about the features on this page to see the customization in action!</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 4. Full AI Interface -->
|
|
<section id="full-interface">
|
|
<h3>4. 🤖 Full AI Interface</h3>
|
|
<p>Complete AI chat with all features enabled:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Full Interface Code</strong></summary>
|
|
<p>Embed a complete AI interface with all features:</p>
|
|
<pre><code class="html"><div class="uncloseai" data-features="full"></div></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>Try the full AI interface below:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<div class="uncloseai" data-features="full" id="demo-full"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 5. Chat Interface Only -->
|
|
<section id="chat-only">
|
|
<h3>5. 💬 Chat Interface Only</h3>
|
|
<p>Pure chat interface without extra buttons:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Chat Only Code</strong></summary>
|
|
<p>Embed just the chat interface:</p>
|
|
<pre><code class="html"><div class="uncloseai" data-features="chat"></div></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>Try the chat-only interface below:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<div class="uncloseai" data-features="chat" id="demo-chat"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 6. Feature Buttons Only -->
|
|
<section id="feature-buttons">
|
|
<h3>6. 🔧 Feature Buttons Only</h3>
|
|
<p>Add specific feature buttons without the full chat interface:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>How to add specific feature buttons</strong></summary>
|
|
<p>Mix and match any features you want:</p>
|
|
<pre><code class="html"><!-- TTS and Read buttons only -->
|
|
<div class="uncloseai" data-features="tts,read"></div>
|
|
|
|
<!-- Just TTS button -->
|
|
<div class="uncloseai" data-features="tts"></div>
|
|
|
|
<!-- Just translation button -->
|
|
<div class="uncloseai" data-features="translate"></div>
|
|
|
|
<!-- Multiple features -->
|
|
<div class="uncloseai" data-features="tts,translate,read"></div></code></pre>
|
|
|
|
<p><strong>Available features:</strong> <code>chat</code>, <code>tts</code>, <code>translate</code>, <code>read</code>, <code>full</code></p>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>Try the feature buttons below:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<div class="uncloseai" data-features="tts,read" id="demo-buttons"></div>
|
|
<p><strong>Available features:</strong> Text-to-Speech and Read Page buttons</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 7. Text-to-Speech Options -->
|
|
<section id="tts-only">
|
|
<h3>7. 🔊 Text-to-Speech Options</h3>
|
|
<p>Two ways to add TTS functionality to your website:</p>
|
|
|
|
<h4>📄 Code Examples</h4>
|
|
<details open>
|
|
<summary><strong>How to implement both TTS options</strong></summary>
|
|
|
|
<h5>Option 1: TTS Widget Button</h5>
|
|
<pre><code class="html"><div class="uncloseai" data-features="tts"></div></code></pre>
|
|
|
|
<h5>Option 2: TTS Modal Button</h5>
|
|
<pre><code class="html"><button onclick="openTTSModal()">🔊 Text to Speech</button></code></pre>
|
|
|
|
<p><strong>Note:</strong> Both require the uncloseai.js script to be loaded first:</p>
|
|
<pre><code class="html"><script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Examples</h4>
|
|
|
|
<div style="display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));">
|
|
<!-- TTS Widget Button -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🔊 TTS Widget Button</h5>
|
|
<p>Embedded TTS button for any content:</p>
|
|
<div class="uncloseai" data-features="tts" id="demo-tts"></div>
|
|
<p><strong>Best for:</strong> Adding TTS to specific content areas</p>
|
|
</div>
|
|
|
|
<!-- TTS Modal Button -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🎤 TTS Anything Modal</h5>
|
|
<p>Standalone modal for any text input:</p>
|
|
<button onclick="openTTSModal()" style="padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">🔊 Open TTS Modal</button>
|
|
<p><strong>Best for:</strong> General-purpose text-to-speech tool</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 8. Translation Options -->
|
|
<section id="translate-only">
|
|
<h3>8. 🌐 Translation Options</h3>
|
|
<p>Two ways to add translation functionality to your website:</p>
|
|
|
|
<h4>📄 Code Examples</h4>
|
|
<details open>
|
|
<summary><strong>How to implement both translation options</strong></summary>
|
|
|
|
<h5>Option 1: Translation Widget Button</h5>
|
|
<pre><code class="html"><div class="uncloseai" data-features="translate"></div></code></pre>
|
|
|
|
<h5>Option 2: Translation Modal Button</h5>
|
|
<pre><code class="html"><button onclick="openTranslateModal()">🌐 Translate</button></code></pre>
|
|
|
|
<p><strong>Translation Features:</strong></p>
|
|
<ul>
|
|
<li>📝 Custom text translation into 19 languages</li>
|
|
<li>📄 Full page translation with preserved formatting</li>
|
|
<li>⚙️ Advanced options and language selection</li>
|
|
<li>📋 Copy and preview translated content</li>
|
|
</ul>
|
|
|
|
<p><strong>Note:</strong> Both require the uncloseai.js script to be loaded first:</p>
|
|
<pre><code class="html"><script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Examples</h4>
|
|
|
|
<div style="display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));">
|
|
<!-- Translation Widget Button -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🌐 Translation Widget Button</h5>
|
|
<p>Embedded translation button for content:</p>
|
|
<div class="uncloseai" data-features="translate" id="demo-translate-modal"></div>
|
|
<p><strong>Best for:</strong> Adding translation to specific content areas</p>
|
|
</div>
|
|
|
|
<!-- Translation Modal Button -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🔄 Translation Modal</h5>
|
|
<p>Standalone modal for translation tasks:</p>
|
|
<button onclick="openTranslateModal()" style="padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">🌐 Open Translation Modal</button>
|
|
<p><strong>Best for:</strong> General-purpose translation tool</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!--
|
|
Smart Dropdown section commented out - not working yet
|
|
|
|
<div style="display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));">
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🌐 Translation Modal</h5>
|
|
<p>Traditional modal interface for translations:</p>
|
|
<div class="uncloseai" data-features="translate" id="demo-translate-modal"></div>
|
|
</div>
|
|
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🤖 Smart AI Dropdown</h5>
|
|
<p>AI-powered quick translation:</p>
|
|
<div class="uncloseai" data-features="smart-translate" id="demo-translate-smart"></div>
|
|
</div>
|
|
</div>
|
|
-->
|
|
</section>
|
|
|
|
<!-- 9. Translation -->
|
|
<section id="translation">
|
|
<h3>9. 🌐 Translation</h3>
|
|
<p>Translate page content or custom text into 19 languages with code block preservation:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Translation Code</strong></summary>
|
|
<p>Add translation capabilities to any interface:</p>
|
|
<pre><code class="javascript">// Import translation functions
|
|
import { translateText, translateCurrentPage, SUPPORTED_LANGUAGES } from './src/translation.js';
|
|
|
|
// Translate custom text
|
|
const translatedText = await translateText('Hello world!', 'es'); // Spanish
|
|
|
|
// Translate current page content
|
|
const translatedPage = await translateCurrentPage('fr'); // French
|
|
|
|
// Available languages
|
|
console.log(SUPPORTED_LANGUAGES);
|
|
// { 'en': 'English', 'es': 'Spanish', 'fr': 'French', ... }</code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>Try the translation feature below - it preserves code blocks and formatting:</p>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<div class="uncloseai" data-features="full" id="demo-translation"></div>
|
|
<p><strong>💡 Tip:</strong> The translation feature automatically detects and preserves:</p>
|
|
<ul>
|
|
<li>Code blocks (```code```)</li>
|
|
<li>Inline code (`code`)</li>
|
|
<li>URLs and links</li>
|
|
<li>HTML tags</li>
|
|
<li>Technical formatting</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 10. Read Page Functionality -->
|
|
<section id="read-page">
|
|
<h3>10. 📖 Read Page Functionality</h3>
|
|
<p>Let AI read the entire webpage aloud with natural voice synthesis:</p>
|
|
|
|
<h4>📄 Code Examples</h4>
|
|
<details open>
|
|
<summary><strong>How to add read page functionality</strong></summary>
|
|
|
|
<h5>Option 1: Read Page Button in Widget</h5>
|
|
<pre><code class="html"><div class="uncloseai" data-features="read"></div></code></pre>
|
|
|
|
<h5>Option 2: Standalone Read Page Button</h5>
|
|
<pre><code class="html"><button onclick="readPageWithHermes()">📖 Read Page</button></code></pre>
|
|
|
|
<h5>Option 3: Custom JavaScript Integration</h5>
|
|
<pre><code class="javascript">// Call read page function programmatically
|
|
await readPageWithHermes();
|
|
|
|
// Or import and use directly
|
|
import { readPageWithHermes } from './src/page-reader.js';
|
|
await readPageWithHermes();</code></pre>
|
|
|
|
<p><strong>Note:</strong> Requires the uncloseai.js script to be loaded first:</p>
|
|
<pre><code class="html"><script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<div style="border: 2px dashed #43a047; padding: 20px; margin: 15px 0; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<button onclick="readPageWithHermes()" style="padding: 15px 30px; background: #4CAF50; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; font-weight: bold;">📖 Read This Page Aloud</button>
|
|
<p><strong>What it does:</strong></p>
|
|
<ul>
|
|
<li>🤖 AI processes page content for optimal speech</li>
|
|
<li>🔊 Converts to natural-sounding audio</li>
|
|
<li>⏯️ Provides play/pause controls</li>
|
|
<li>💾 Option to download MP3 file</li>
|
|
<li>📱 Works on mobile and desktop</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 11. Direct API Usage -->
|
|
<section id="direct-api">
|
|
<h3>11. 🛠️ Direct API Usage</h3>
|
|
<p>Call uncloseai.js functions from your own JavaScript:</p>
|
|
|
|
<h4>📄 Code Example</h4>
|
|
<details open>
|
|
<summary><strong>Direct API Code</strong></summary>
|
|
<p>Call uncloseai.js functions from your own JavaScript:</p>
|
|
<pre><code class="javascript">// Send a message to AI
|
|
for await (const chunk of sendMessage('Your question here')) {
|
|
console.log(chunk);
|
|
}
|
|
|
|
// Convert text to speech
|
|
const result = await speakText('Hello world', 'alloy', 0.9);
|
|
document.body.appendChild(result.audio);
|
|
|
|
// Upload and analyze files - COMMENTED OUT: Not working
|
|
// const response = await uploadFile(fileInput.files[0]);
|
|
// console.log(response);
|
|
|
|
// Read page content with AI
|
|
await readPageWithHermes();</code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Example</h4>
|
|
<p>The custom API examples below demonstrate direct API usage:</p>
|
|
</section>
|
|
|
|
<!-- 12. Custom API Examples -->
|
|
<section id="custom-examples">
|
|
<h3>12. 🎨 Custom API Examples</h3>
|
|
<p>Build your own interface using uncloseai.js functions:</p>
|
|
|
|
<h4>📄 Code Examples</h4>
|
|
<details open>
|
|
<summary><strong>How to build custom interfaces with Direct API</strong></summary>
|
|
|
|
<h5>Custom Chat Interface</h5>
|
|
<pre><code class="javascript">// Custom chat implementation with isolated state
|
|
async function customChatExample() {
|
|
const input = document.getElementById('custom-chat-input');
|
|
const display = document.getElementById('custom-chat-display');
|
|
const message = input.value.trim();
|
|
|
|
if (!message) return;
|
|
|
|
// Add user message to display
|
|
display.innerHTML += `<div><strong>You:</strong> ${message}</div>`;
|
|
input.value = '';
|
|
|
|
// Add AI thinking indicator
|
|
const thinkingDiv = document.createElement('div');
|
|
thinkingDiv.innerHTML = '<strong>Hermes:</strong> <em>thinking...</em>';
|
|
display.appendChild(thinkingDiv);
|
|
|
|
try {
|
|
// Import and use sendMessage function
|
|
const { sendMessage } = await import('./src/chat.js');
|
|
let response = '';
|
|
for await (const chunk of sendMessage(message)) {
|
|
response += chunk;
|
|
thinkingDiv.innerHTML = `<strong>Hermes:</strong> ${response}`;
|
|
}
|
|
} catch (error) {
|
|
thinkingDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}</code></pre>
|
|
|
|
<h5>Custom TTS Interface</h5>
|
|
<pre><code class="javascript">// Custom TTS with voice selection
|
|
async function customTTSExample() {
|
|
const text = document.getElementById('custom-tts-text').value.trim();
|
|
const voice = document.getElementById('voice-select').value;
|
|
const resultDiv = document.getElementById('custom-tts-result');
|
|
|
|
if (!text) {
|
|
alert('Please enter some text first!');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Import and use speakTextDirect function
|
|
const { speakTextDirect } = await import('./src/tts.js');
|
|
const result = await speakTextDirect(text, voice, 1.0);
|
|
|
|
// Create custom audio controls
|
|
const playPauseBtn = document.createElement('button');
|
|
playPauseBtn.textContent = '⏸️ Pause';
|
|
|
|
const downloadBtn = document.createElement('button');
|
|
downloadBtn.textContent = '💾 Download';
|
|
downloadBtn.onclick = () => {
|
|
const a = document.createElement('a');
|
|
a.href = URL.createObjectURL(result.blob);
|
|
a.download = `custom-tts-${Date.now()}.mp3`;
|
|
a.click();
|
|
};
|
|
|
|
// Auto-play and handle controls
|
|
result.audio.play();
|
|
playPauseBtn.onclick = () => {
|
|
if (result.audio.paused) {
|
|
result.audio.play();
|
|
playPauseBtn.textContent = '⏸️ Pause';
|
|
} else {
|
|
result.audio.pause();
|
|
playPauseBtn.textContent = '▶️ Play';
|
|
}
|
|
};
|
|
|
|
resultDiv.appendChild(playPauseBtn);
|
|
resultDiv.appendChild(downloadBtn);
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}</code></pre>
|
|
|
|
<h5>Custom Page Analysis</h5>
|
|
<pre><code class="javascript">// Custom page analysis with user prompt
|
|
async function customPageAnalysis() {
|
|
const prompt = document.getElementById('page-analysis-prompt').value.trim();
|
|
const resultDiv = document.getElementById('page-analysis-result');
|
|
|
|
if (!prompt) {
|
|
alert('Please enter a question about this page!');
|
|
return;
|
|
}
|
|
|
|
resultDiv.style.display = 'block';
|
|
resultDiv.innerHTML = '<em>Analyzing page...</em>';
|
|
|
|
try {
|
|
// Get page content and combine with user prompt
|
|
const { sendMessage } = await import('./src/chat.js');
|
|
const pageContent = document.body.innerText.substring(0, 3000);
|
|
const fullPrompt = `Based on this page content: "${pageContent}"\\n\\nUser question: ${prompt}`;
|
|
|
|
let response = '';
|
|
for await (const chunk of sendMessage(fullPrompt)) {
|
|
response += chunk;
|
|
resultDiv.innerHTML = `<strong>Analysis:</strong><br><div>${response}</div>`;
|
|
}
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}</code></pre>
|
|
|
|
<h5>Custom Translation Interface</h5>
|
|
<pre><code class="javascript">// Custom translation with code preservation
|
|
async function customTranslateExample() {
|
|
const text = document.getElementById('custom-translate-text').value.trim();
|
|
const targetLanguage = document.getElementById('translate-language').value;
|
|
const resultDiv = document.getElementById('custom-translate-result');
|
|
|
|
if (!text) {
|
|
alert('Please enter some text to translate!');
|
|
return;
|
|
}
|
|
|
|
resultDiv.style.display = 'block';
|
|
resultDiv.textContent = 'Translating...';
|
|
|
|
try {
|
|
// Import and use translation function
|
|
const { translateText } = await import('./src/translation.js');
|
|
const translatedText = await translateText(text, targetLanguage);
|
|
|
|
resultDiv.textContent = translatedText;
|
|
} catch (error) {
|
|
resultDiv.textContent = `Translation failed: ${error.message}`;
|
|
}
|
|
}</code></pre>
|
|
|
|
<p><strong>Available API Functions:</strong></p>
|
|
<ul>
|
|
<li><code>sendMessage(message)</code> - Chat with AI (returns async generator)</li>
|
|
<li><code>speakTextDirect(text, voice, speed)</code> - Convert text to speech</li>
|
|
<li><code>translateText(text, targetLanguage)</code> - Translate text</li>
|
|
<li><code>readPageWithHermes()</code> - Read page content aloud</li>
|
|
<li><code>openTTSModal()</code> - Open TTS modal</li>
|
|
<li><code>openTranslateModal()</code> - Open translation modal</li>
|
|
</ul>
|
|
|
|
<p><strong>Note:</strong> All functions require uncloseai.js to be loaded first:</p>
|
|
<pre><code class="html"><script src="https://uncloseai.com/uncloseai.js" type="module"></script></code></pre>
|
|
</details>
|
|
|
|
<h4>🎯 Live Examples</h4>
|
|
<p>Try these custom implementations built with the Direct API:</p>
|
|
|
|
<div style="display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));">
|
|
<!-- Custom Chat Example -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>💬 Custom AI Chat</h5>
|
|
<p>Your own chat interface:</p>
|
|
<div style="border: 1px solid #eee; height: 200px; padding: 10px; margin: 10px 0; overflow-y: auto; background: #fafafa;" id="custom-chat-display"></div>
|
|
<input type="text" id="custom-chat-input" placeholder="Ask anything..." style="width: 100%; margin: 5px 0;">
|
|
<button onclick="customChatExample()" style="width: 100%;">Send Message</button>
|
|
</div>
|
|
|
|
<!-- Custom TTS Example -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🔊 Custom Text-to-Speech</h5>
|
|
<p>Your own TTS interface:</p>
|
|
<textarea id="custom-tts-text" placeholder="Enter text to speak..." style="width: 100%; height: 80px; margin: 5px 0;"></textarea>
|
|
<select id="voice-select" style="width: 100%; margin: 5px 0;">
|
|
<option value="alloy">Alloy</option>
|
|
<option value="echo">Echo</option>
|
|
<option value="fable">Fable</option>
|
|
<option value="onyx">Onyx</option>
|
|
<option value="nova">Nova</option>
|
|
<option value="shimmer">Shimmer</option>
|
|
</select>
|
|
<button onclick="customTTSExample()" style="width: 100%;">Generate Speech</button>
|
|
<div id="custom-tts-result" style="margin: 10px 0;"></div>
|
|
</div>
|
|
|
|
<!-- Custom File Upload Example - DISABLED: Upload functionality under development -->
|
|
<div style="border: 2px dashed #ccc; padding: 20px; border-radius: 8px; background: rgba(128, 128, 128, 0.05); opacity: 0.6;">
|
|
<h5>📁 Custom File Analysis <span style="color: #999; font-size: 0.8em;">(Under Development)</span></h5>
|
|
<p>File upload interface (temporarily disabled):</p>
|
|
<input type="file" id="custom-file-input" style="width: 100%; margin: 5px 0;" disabled>
|
|
<button onclick="alert('File upload feature is under development')" style="width: 100%;" disabled>Analyze File (Coming Soon)</button>
|
|
<div id="custom-file-result" style="margin: 10px 0; padding: 10px; background: #f9f9f9; border-radius: 5px; display: none;"></div>
|
|
</div>
|
|
|
|
<!-- Page Analysis Example -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>📖 Custom Page Analysis</h5>
|
|
<p>Analyze page content with custom prompts:</p>
|
|
<input type="text" id="page-analysis-prompt" placeholder="What would you like to know about this page?" style="width: 100%; margin: 5px 0;">
|
|
<button onclick="customPageAnalysis()" style="width: 100%;">Analyze Page</button>
|
|
<div id="page-analysis-result" style="margin: 10px 0; padding: 10px; background: #f9f9f9; border-radius: 5px; display: none;"></div>
|
|
</div>
|
|
|
|
<!-- Custom Translation Example -->
|
|
<div style="border: 2px dashed #43a047; padding: 20px; border-radius: 8px; background: rgba(67, 160, 71, 0.05);">
|
|
<h5>🌐 Custom Translation</h5>
|
|
<p>Translate text with code preservation:</p>
|
|
<textarea id="custom-translate-text" placeholder="Enter text to translate (try including code like `function test()` or ```code blocks```)" style="width: 100%; height: 80px; margin: 5px 0;"></textarea>
|
|
<select id="translate-language" style="width: 100%; margin: 5px 0;">
|
|
<option value="es">Spanish</option>
|
|
<option value="zh">Chinese (Simplified)</option>
|
|
<option value="hi">Hindi</option>
|
|
<option value="fr">French</option>
|
|
<option value="ar">Arabic</option>
|
|
<option value="bn">Bengali</option>
|
|
<option value="ru">Russian</option>
|
|
<option value="pt">Portuguese</option>
|
|
<option value="ur">Urdu</option>
|
|
<option value="id">Indonesian</option>
|
|
<option value="de">German</option>
|
|
<option value="ja">Japanese</option>
|
|
<option value="sw">Swahili</option>
|
|
<option value="mr">Marathi</option>
|
|
<option value="te">Telugu</option>
|
|
<option value="tr">Turkish</option>
|
|
<option value="zh-tw">Chinese (Traditional)</option>
|
|
<option value="ko">Korean</option>
|
|
</select>
|
|
<button onclick="customTranslateExample()" style="width: 100%;">Translate Text</button>
|
|
<div id="custom-translate-result" style="margin: 10px 0; padding: 10px; background: #f9f9f9; border-radius: 5px; display: none; white-space: pre-wrap;"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<script>
|
|
// Custom chat implementation with isolated state
|
|
async function customChatExample() {
|
|
const input = document.getElementById('custom-chat-input');
|
|
const display = document.getElementById('custom-chat-display');
|
|
const message = input.value.trim();
|
|
|
|
if (!message) return;
|
|
|
|
// Add user message
|
|
display.innerHTML += `<div style="margin: 5px 0; padding: 5px; background: #e3f2fd; border-radius: 3px;"><strong>You:</strong> ${message}</div>`;
|
|
input.value = '';
|
|
|
|
// Add AI thinking indicator
|
|
const thinkingDiv = document.createElement('div');
|
|
thinkingDiv.style.cssText = 'margin: 5px 0; padding: 5px; background: #f5f5f5; border-radius: 3px;';
|
|
thinkingDiv.innerHTML = '<strong>Hermes:</strong> <em>thinking...</em>';
|
|
display.appendChild(thinkingDiv);
|
|
display.scrollTop = display.scrollHeight;
|
|
|
|
try {
|
|
const { sendMessage } = await import('./src/chat.js');
|
|
let response = '';
|
|
for await (const chunk of sendMessage(message)) {
|
|
response += chunk;
|
|
thinkingDiv.innerHTML = `<strong>Hermes:</strong> ${response}`;
|
|
display.scrollTop = display.scrollHeight;
|
|
}
|
|
} catch (error) {
|
|
thinkingDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}
|
|
|
|
// Custom TTS with voice selection
|
|
async function customTTSExample() {
|
|
const text = document.getElementById('custom-tts-text').value.trim();
|
|
const voice = document.getElementById('voice-select').value;
|
|
const resultDiv = document.getElementById('custom-tts-result');
|
|
const button = event.target;
|
|
|
|
if (!text) {
|
|
alert('Please enter some text first!');
|
|
return;
|
|
}
|
|
|
|
button.textContent = 'Processing...';
|
|
button.disabled = true;
|
|
resultDiv.innerHTML = '<em>Generating speech...</em>';
|
|
|
|
try {
|
|
const { speakTextDirect } = await import('./src/tts.js');
|
|
const result = await speakTextDirect(text, voice, 1.0);
|
|
|
|
// Create play/pause button
|
|
const playPauseBtn = document.createElement('button');
|
|
playPauseBtn.textContent = '⏸️ Pause';
|
|
playPauseBtn.style.margin = '2px';
|
|
|
|
const downloadBtn = document.createElement('button');
|
|
downloadBtn.textContent = '💾 Download';
|
|
downloadBtn.style.margin = '2px';
|
|
downloadBtn.onclick = () => downloadCustomAudio();
|
|
|
|
const controls = document.createElement('div');
|
|
controls.style.margin = '10px 0';
|
|
controls.appendChild(playPauseBtn);
|
|
controls.appendChild(downloadBtn);
|
|
|
|
resultDiv.innerHTML = '';
|
|
resultDiv.appendChild(controls);
|
|
|
|
// Auto-play the audio
|
|
result.audio.play();
|
|
|
|
// Handle play/pause button
|
|
playPauseBtn.onclick = () => {
|
|
if (result.audio.paused) {
|
|
result.audio.play();
|
|
playPauseBtn.textContent = '⏸️ Pause';
|
|
} else {
|
|
result.audio.pause();
|
|
playPauseBtn.textContent = '▶️ Play';
|
|
}
|
|
};
|
|
|
|
// Handle audio end
|
|
result.audio.onended = () => {
|
|
playPauseBtn.textContent = '▶️ Play';
|
|
};
|
|
|
|
window.customAudioBlob = result.blob;
|
|
button.textContent = 'Generate Speech';
|
|
button.disabled = false;
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
button.textContent = 'Generate Speech';
|
|
button.disabled = false;
|
|
}
|
|
}
|
|
|
|
// Custom file upload with isolated state
|
|
async function customFileExample() {
|
|
const fileInput = document.getElementById('custom-file-input');
|
|
const resultDiv = document.getElementById('custom-file-result');
|
|
|
|
if (!fileInput.files[0]) {
|
|
alert('Please select a file first!');
|
|
return;
|
|
}
|
|
|
|
resultDiv.style.display = 'block';
|
|
resultDiv.innerHTML = '<em>Analyzing file...</em>';
|
|
|
|
try {
|
|
const { uploadFile } = await import('./src/file-upload.js');
|
|
const response = await uploadFile(fileInput.files[0]);
|
|
resultDiv.innerHTML = `<strong>Analysis Result:</strong><br><div style="white-space: pre-wrap;">${response}</div>`;
|
|
fileInput.value = '';
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}
|
|
|
|
// Custom page analysis with user prompt
|
|
async function customPageAnalysis() {
|
|
const promptInput = document.getElementById('page-analysis-prompt');
|
|
const resultDiv = document.getElementById('page-analysis-result');
|
|
const prompt = promptInput.value.trim();
|
|
|
|
if (!prompt) {
|
|
alert('Please enter a question about this page!');
|
|
return;
|
|
}
|
|
|
|
resultDiv.style.display = 'block';
|
|
resultDiv.innerHTML = '<em>Analyzing page...</em>';
|
|
|
|
try {
|
|
const { sendMessage } = await import('./src/chat.js');
|
|
const pageContent = document.body.innerText.substring(0, 3000);
|
|
const fullPrompt = `Based on this page content: "${pageContent}"\n\nUser question: ${prompt}`;
|
|
|
|
let response = '';
|
|
for await (const chunk of sendMessage(fullPrompt)) {
|
|
response += chunk;
|
|
resultDiv.innerHTML = `<strong>Analysis:</strong><br><div style="white-space: pre-wrap;">${response}</div>`;
|
|
}
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
|
|
}
|
|
}
|
|
|
|
// Utility functions
|
|
function downloadCustomAudio() {
|
|
if (window.customAudioBlob) {
|
|
const a = document.createElement('a');
|
|
a.href = URL.createObjectURL(window.customAudioBlob);
|
|
a.download = `custom-tts-${Date.now()}.mp3`;
|
|
a.click();
|
|
}
|
|
}
|
|
|
|
// Custom translation example
|
|
async function customTranslateExample() {
|
|
const textArea = document.getElementById('custom-translate-text');
|
|
const languageSelect = document.getElementById('translate-language');
|
|
const resultDiv = document.getElementById('custom-translate-result');
|
|
const button = event.target;
|
|
|
|
const text = textArea.value.trim();
|
|
const targetLanguage = languageSelect.value;
|
|
|
|
if (!text) {
|
|
alert('Please enter some text to translate!');
|
|
return;
|
|
}
|
|
|
|
button.textContent = 'Processing...';
|
|
button.disabled = true;
|
|
resultDiv.style.display = 'block';
|
|
resultDiv.textContent = 'Translating...';
|
|
|
|
try {
|
|
const { translateText } = await import('./src/translation.js');
|
|
const translatedText = await translateText(text, targetLanguage);
|
|
|
|
resultDiv.textContent = translatedText;
|
|
|
|
} catch (error) {
|
|
resultDiv.textContent = `Translation failed: ${error.message}`;
|
|
} finally {
|
|
button.textContent = 'Translate Text';
|
|
button.disabled = false;
|
|
}
|
|
}
|
|
|
|
// Add Enter key support for chat input
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const chatInput = document.getElementById('custom-chat-input');
|
|
if (chatInput) {
|
|
chatInput.addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
customChatExample();
|
|
}
|
|
});
|
|
}
|
|
|
|
const pageInput = document.getElementById('page-analysis-prompt');
|
|
if (pageInput) {
|
|
pageInput.addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
customPageAnalysis();
|
|
}
|
|
});
|
|
}
|
|
|
|
const translateInput = document.getElementById('custom-translate-text');
|
|
if (translateInput) {
|
|
translateInput.addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter' && e.ctrlKey) {
|
|
customTranslateExample();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Ensure all modal and widget functions are available for demos
|
|
document.addEventListener('DOMContentLoaded', async function() {
|
|
try {
|
|
// Import and make all widget functions available globally
|
|
const { openTranslateModal } = await import('./src/translate-modal.js');
|
|
const { openTTSModal } = await import('./src/tts-modal.js');
|
|
const { readPageWithHermes } = await import('./src/page-reader.js');
|
|
|
|
window.openTranslateModal = openTranslateModal;
|
|
window.openTTSModal = openTTSModal;
|
|
window.readPageWithHermes = readPageWithHermes;
|
|
|
|
console.log('All modal and widget functions loaded successfully');
|
|
} catch (error) {
|
|
console.error('Failed to load widget functions:', error);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<h2>Open Source & Public Domain</h2>
|
|
|
|
<p><strong>uncloseai.</strong> is completely <strong>public domain</strong> - free as in beer, free as in freedom. AI for all, internet for all, open web for everyone.</p>
|
|
|
|
<p>📦 <strong>Source Code:</strong> <a href="https://git.unturf.com/engineering/unturf/uncloseai.com" target="_blank">https://git.unturf.com/engineering/unturf/uncloseai.com</a></p>
|
|
|
|
<p>📄 <strong>Full Documentation:</strong> See README.rst in the repository for complete technical details, architecture, and contribution guidelines.</p>
|
|
|
|
</main>
|
|
|
|
<footer>
|
|
<small>© uncloseai. 2025</small>
|
|
<br>
|
|
<small>Stylesheets by <a href="https://picocss.com" target="_blank">PicoCSS</a></small>
|
|
<small>& <a href="https://highlightjs.org/" target="_blank">highlight.js</a></small>
|
|
<br>
|
|
<small><a href="/privacy-policy.html">Privacy Policy</a> | <a href="/terms-of-use.html">Terms of Use</a></small>
|
|
</footer>
|
|
|
|
</body>
|
|
|
|
</html>
|