@vitronai/alethia 0.3.6 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/demo/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # Alethia Demo Pages
2
+
3
+ Ready-to-use local HTML pages for testing Alethia. Open any page in your browser or drive it with `alethia_tell`.
4
+
5
+ ## Pages
6
+
7
+ | Page | What it tests | Key features shown |
8
+ |---|---|---|
9
+ | `signup-form.html` | Login flow with validation | Navigate, type, click, assert, error detection, DOM diffs |
10
+ | `todo-app.html` | Dynamic list add/delete | Type, click, assert, list awareness in snapshots |
11
+ | `ecommerce.html` | Add to cart → checkout | EA1 policy gate blocks purchase (write-high) |
12
+ | `spa-loading.html` | Async data loading (2s delay) | Page readiness detection, MutationObserver wait-for |
13
+ | `cookie-banner.html` | Cookie consent + newsletter | Conditional steps ("if banner exists, click Accept") |
14
+ | `form-validation.html` | Multi-field validation | Smart assertions, error detection, suggested fixes |
15
+
16
+ ## Prompts
17
+
18
+ ### Login flow (signup-form.html)
19
+ ```
20
+ Use alethia_tell to navigate to file:///PATH/demo/signup-form.html, click Sign In without filling anything in and assert the error message appears, then type admin@acme.com into email, type secret123 into password with allowSensitiveInput true, click Sign In, and assert "Welcome back!" is visible.
21
+ ```
22
+
23
+ ### Todo list (todo-app.html)
24
+ ```
25
+ Use alethia_tell to navigate to file:///PATH/demo/todo-app.html, type "Ship v1" into the task input, click Add, type "Record demo" into the task input, click Add, type "Send cold DMs" into the task input, click Add, and assert all three items appear in the list.
26
+ ```
27
+
28
+ ### EA1 policy gate (ecommerce.html)
29
+ ```
30
+ Use alethia_tell to navigate to file:///PATH/demo/ecommerce.html, click "Add to Cart" on the Wireless Keyboard, click "Add to Cart" on the USB-C Hub, assert the cart shows both items, then click "Complete Purchase" and tell me what the policy gate does.
31
+ ```
32
+
33
+ ### Page readiness / SPA loading (spa-loading.html)
34
+ ```
35
+ Use alethia_tell to navigate to file:///PATH/demo/spa-loading.html and assert "1,247" is visible. The page has a 2-second loading spinner — Alethia should wait for it automatically.
36
+ ```
37
+
38
+ ### Conditional steps / cookie banner (cookie-banner.html)
39
+ ```
40
+ Use alethia_tell to navigate to file:///PATH/demo/cookie-banner.html. If the cookie banner exists, click Accept. Then type hello@test.com into the email field and click Subscribe. Assert "Subscribed!" is visible.
41
+ ```
42
+
43
+ ### Form validation / smart assertions (form-validation.html)
44
+ ```
45
+ Use alethia_tell to navigate to file:///PATH/demo/form-validation.html and click Send Message without filling anything. Check what validation errors appear. Then fill in: name "Jane Doe", email "jane@test.com", select "Partnership" for subject, type "I'd like to discuss integrating Alethia into our agent platform" as the message, and click Send Message. Assert "Message Sent!" is visible.
46
+ ```
47
+
48
+ ## Setup
49
+
50
+ Replace `PATH` in the prompts above with the actual path to this demo folder:
51
+
52
+ ```bash
53
+ # Find your path
54
+ npm root -g
55
+ # The demos are at: <global_root>/@vitronai/alethia/demo/
56
+ ```
57
+
58
+ Or clone the repo and use the local path:
59
+ ```bash
60
+ git clone https://github.com/vitron-ai/alethia-mcp.git
61
+ # Demos at: /path/to/alethia-mcp/demo/
62
+ ```
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Blog Post</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; padding: 2rem; }
8
+ h1 { font-size: 1.8rem; margin-bottom: 0.5rem; }
9
+ .meta { color: #64748b; margin-bottom: 1.5rem; font-size: 0.9rem; }
10
+ article { max-width: 640px; line-height: 1.7; }
11
+ article p { margin-bottom: 1rem; color: #cbd5e1; }
12
+ .cookie-banner { position: fixed; bottom: 0; left: 0; right: 0; background: #1e293b; border-top: 1px solid #334155; padding: 1rem 2rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; z-index: 100; }
13
+ .cookie-banner p { color: #94a3b8; font-size: 0.9rem; margin: 0; }
14
+ .cookie-banner button { padding: 0.5rem 1.2rem; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; }
15
+ .accept-btn { background: #3b82f6; color: white; }
16
+ .decline-btn { background: #334155; color: #94a3b8; }
17
+ .hidden { display: none; }
18
+ .newsletter { border: 1px solid #334155; border-radius: 12px; padding: 1.2rem; background: #1e293b; margin-top: 2rem; }
19
+ .newsletter h3 { margin-bottom: 0.5rem; }
20
+ .newsletter input { padding: 0.5rem; border-radius: 6px; border: 1px solid #334155; background: #0f172a; color: #e2e8f0; margin-right: 0.5rem; }
21
+ .newsletter button { padding: 0.5rem 1rem; border-radius: 6px; border: none; background: #3b82f6; color: white; cursor: pointer; }
22
+ .subscribed { color: #34d399; font-weight: 600; display: none; }
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <article>
27
+ <h1>Why Zero-IPC Matters for AI Agents</h1>
28
+ <p class="meta">April 10, 2026 · 5 min read</p>
29
+ <p>When an AI agent generates code and needs to verify it works, every millisecond of automation latency compounds. CDP-based tools add ~580ms of marshalling tax per assertion.</p>
30
+ <p>Zero-IPC eliminates the process boundary between the automation driver and the DOM. The driver touches the DOM the same way the page's own JavaScript does — synchronously, in-process, with no serialization overhead.</p>
31
+ <p>The result: ~13ms per step instead of ~580ms. That's not an optimization — it's a different architecture.</p>
32
+ <div class="newsletter">
33
+ <h3>Subscribe to updates</h3>
34
+ <div id="subscribe-form">
35
+ <input id="email" type="email" placeholder="you@example.com" aria-label="Email address" />
36
+ <button id="subscribe-btn" type="button">Subscribe</button>
37
+ </div>
38
+ <p id="subscribed" class="subscribed">Subscribed! Check your inbox.</p>
39
+ </div>
40
+ </article>
41
+
42
+ <div id="cookie-banner" class="cookie-banner">
43
+ <p>We use cookies to improve your experience. No tracking, no ads.</p>
44
+ <div>
45
+ <button class="decline-btn" id="decline-cookies" type="button">Decline</button>
46
+ <button class="accept-btn" id="accept-cookies" type="button">Accept</button>
47
+ </div>
48
+ </div>
49
+
50
+ <script>
51
+ document.getElementById('accept-cookies').addEventListener('click', function() {
52
+ document.getElementById('cookie-banner').classList.add('hidden');
53
+ });
54
+ document.getElementById('decline-cookies').addEventListener('click', function() {
55
+ document.getElementById('cookie-banner').classList.add('hidden');
56
+ });
57
+ document.getElementById('subscribe-btn').addEventListener('click', function() {
58
+ var email = document.getElementById('email').value;
59
+ if (email && email.includes('@')) {
60
+ document.getElementById('subscribe-form').style.display = 'none';
61
+ document.getElementById('subscribed').style.display = 'block';
62
+ }
63
+ });
64
+ </script>
65
+ </body>
66
+ </html>
@@ -0,0 +1,88 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Acme Store</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; padding: 2rem; }
8
+ h1 { font-size: 1.8rem; margin-bottom: 1.5rem; }
9
+ .products { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 2rem; }
10
+ .product { border: 1px solid #334155; border-radius: 12px; padding: 1.2rem; background: #1e293b; }
11
+ .product h2 { font-size: 1.1rem; margin-bottom: 0.4rem; }
12
+ .product .price { color: #34d399; font-weight: 700; font-size: 1.2rem; }
13
+ .product p { color: #94a3b8; font-size: 0.9rem; margin: 0.4rem 0; }
14
+ button { padding: 0.6rem 1rem; border-radius: 8px; border: none; background: #3b82f6; color: white; font-weight: 600; cursor: pointer; margin-top: 0.5rem; }
15
+ button:hover { background: #2563eb; }
16
+ button:disabled { background: #475569; cursor: not-allowed; }
17
+ .cart { border: 1px solid #334155; border-radius: 12px; padding: 1.2rem; background: #1e293b; max-width: 400px; }
18
+ .cart h2 { margin-bottom: 0.8rem; }
19
+ .cart ul { list-style: none; }
20
+ .cart li { padding: 0.4rem 0; border-bottom: 1px solid #0f172a; display: flex; justify-content: space-between; }
21
+ .cart-total { margin-top: 0.8rem; font-weight: 700; font-size: 1.1rem; color: #34d399; }
22
+ .cart-empty { color: #64748b; }
23
+ .checkout-btn { background: #ef4444; width: 100%; margin-top: 0.8rem; }
24
+ .success { display: none; color: #34d399; font-size: 1.2rem; font-weight: 700; margin-top: 1rem; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <h1>Acme Store</h1>
29
+ <div class="products">
30
+ <div class="product">
31
+ <h2>Wireless Keyboard</h2>
32
+ <p>Mechanical, RGB backlit</p>
33
+ <span class="price">$79</span>
34
+ <br/>
35
+ <button onclick="addToCart('Wireless Keyboard', 79)">Add to Cart</button>
36
+ </div>
37
+ <div class="product">
38
+ <h2>USB-C Hub</h2>
39
+ <p>7-port, 100W passthrough</p>
40
+ <span class="price">$45</span>
41
+ <br/>
42
+ <button onclick="addToCart('USB-C Hub', 45)">Add to Cart</button>
43
+ </div>
44
+ <div class="product">
45
+ <h2>Monitor Stand</h2>
46
+ <p>Adjustable, aluminum</p>
47
+ <span class="price">$120</span>
48
+ <br/>
49
+ <button onclick="addToCart('Monitor Stand', 120)">Add to Cart</button>
50
+ </div>
51
+ </div>
52
+ <div class="cart">
53
+ <h2>Cart</h2>
54
+ <ul id="cart-items"><li class="cart-empty">Your cart is empty</li></ul>
55
+ <p id="cart-total" class="cart-total"></p>
56
+ <button class="checkout-btn" id="checkout-btn" onclick="checkout()" disabled>Complete Purchase</button>
57
+ </div>
58
+ <p id="success" class="success" role="alert">Order confirmed! Thank you for your purchase.</p>
59
+ <script>
60
+ const cart = [];
61
+ function addToCart(name, price) {
62
+ cart.push({ name, price });
63
+ renderCart();
64
+ }
65
+ function renderCart() {
66
+ const list = document.getElementById('cart-items');
67
+ const total = document.getElementById('cart-total');
68
+ const btn = document.getElementById('checkout-btn');
69
+ if (cart.length === 0) {
70
+ list.innerHTML = '<li class="cart-empty">Your cart is empty</li>';
71
+ total.textContent = '';
72
+ btn.disabled = true;
73
+ return;
74
+ }
75
+ list.innerHTML = cart.map(item => '<li><span>' + item.name + '</span><span>$' + item.price + '</span></li>').join('');
76
+ const sum = cart.reduce((s, i) => s + i.price, 0);
77
+ total.textContent = 'Total: $' + sum;
78
+ btn.disabled = false;
79
+ }
80
+ function checkout() {
81
+ document.getElementById('success').style.display = 'block';
82
+ document.getElementById('checkout-btn').disabled = true;
83
+ document.getElementById('checkout-btn').textContent = 'Purchased';
84
+ document.title = 'Order Confirmed — Acme Store';
85
+ }
86
+ </script>
87
+ </body>
88
+ </html>
@@ -0,0 +1,113 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Contact Form</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
8
+ .container { width: 400px; }
9
+ h1 { font-size: 1.8rem; margin-bottom: 1.2rem; }
10
+ form { display: flex; flex-direction: column; gap: 0.8rem; }
11
+ label { font-size: 0.9rem; color: #94a3b8; }
12
+ input, textarea, select { padding: 0.7rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #e2e8f0; font-size: 1rem; font-family: inherit; }
13
+ input::placeholder, textarea::placeholder { color: #64748b; }
14
+ input.invalid, textarea.invalid, select.invalid { border-color: #f87171; }
15
+ .field-error { color: #f87171; font-size: 0.8rem; display: none; }
16
+ .field-error.visible { display: block; }
17
+ textarea { resize: vertical; min-height: 80px; }
18
+ button { padding: 0.75rem; border-radius: 8px; border: none; background: #3b82f6; color: white; font-size: 1rem; font-weight: 600; cursor: pointer; }
19
+ button:hover { background: #2563eb; }
20
+ button:disabled { background: #475569; cursor: not-allowed; }
21
+ .success { display: none; text-align: center; }
22
+ .success h2 { color: #34d399; margin-bottom: 0.5rem; }
23
+ .success p { color: #94a3b8; }
24
+ .char-count { font-size: 0.8rem; color: #64748b; text-align: right; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <div class="container">
29
+ <div id="form-container">
30
+ <h1>Contact Us</h1>
31
+ <form id="contact-form" onsubmit="return false;">
32
+ <div>
33
+ <label for="name">Full Name</label>
34
+ <input id="name" placeholder="Jane Doe" aria-label="Full name" />
35
+ <p id="name-error" class="field-error" role="alert">Name is required</p>
36
+ </div>
37
+ <div>
38
+ <label for="contact-email">Email</label>
39
+ <input id="contact-email" type="email" placeholder="jane@example.com" aria-label="Email" />
40
+ <p id="email-error" class="field-error" role="alert">Please enter a valid email</p>
41
+ </div>
42
+ <div>
43
+ <label for="subject">Subject</label>
44
+ <select id="subject" aria-label="Subject">
45
+ <option value="">Select a topic...</option>
46
+ <option value="general">General inquiry</option>
47
+ <option value="support">Technical support</option>
48
+ <option value="partnership">Partnership</option>
49
+ <option value="licensing">Licensing</option>
50
+ </select>
51
+ <p id="subject-error" class="field-error" role="alert">Please select a subject</p>
52
+ </div>
53
+ <div>
54
+ <label for="message">Message</label>
55
+ <textarea id="message" placeholder="Tell us what's on your mind..." aria-label="Message"></textarea>
56
+ <p class="char-count"><span id="char-count">0</span>/500</p>
57
+ <p id="message-error" class="field-error" role="alert">Message must be at least 10 characters</p>
58
+ </div>
59
+ <button type="button" id="submit-btn">Send Message</button>
60
+ </form>
61
+ </div>
62
+ <div id="success" class="success">
63
+ <h2>Message Sent!</h2>
64
+ <p>Thanks for reaching out. We'll get back to you within 24 hours.</p>
65
+ </div>
66
+ </div>
67
+ <script>
68
+ var messageEl = document.getElementById('message');
69
+ var charCount = document.getElementById('char-count');
70
+ messageEl.addEventListener('input', function() {
71
+ charCount.textContent = messageEl.value.length;
72
+ });
73
+
74
+ document.getElementById('submit-btn').addEventListener('click', function() {
75
+ var name = document.getElementById('name');
76
+ var email = document.getElementById('contact-email');
77
+ var subject = document.getElementById('subject');
78
+ var message = document.getElementById('message');
79
+ var valid = true;
80
+
81
+ // Reset
82
+ [name, email, subject, message].forEach(function(el) { el.classList.remove('invalid'); });
83
+ document.querySelectorAll('.field-error').forEach(function(el) { el.classList.remove('visible'); });
84
+
85
+ if (!name.value.trim()) {
86
+ name.classList.add('invalid');
87
+ document.getElementById('name-error').classList.add('visible');
88
+ valid = false;
89
+ }
90
+ if (!email.value.trim() || !email.value.includes('@')) {
91
+ email.classList.add('invalid');
92
+ document.getElementById('email-error').classList.add('visible');
93
+ valid = false;
94
+ }
95
+ if (!subject.value) {
96
+ subject.classList.add('invalid');
97
+ document.getElementById('subject-error').classList.add('visible');
98
+ valid = false;
99
+ }
100
+ if (message.value.trim().length < 10) {
101
+ message.classList.add('invalid');
102
+ document.getElementById('message-error').classList.add('visible');
103
+ valid = false;
104
+ }
105
+ if (valid) {
106
+ document.getElementById('form-container').style.display = 'none';
107
+ document.getElementById('success').style.display = 'block';
108
+ document.title = 'Message Sent — Contact';
109
+ }
110
+ });
111
+ </script>
112
+ </body>
113
+ </html>
@@ -0,0 +1,70 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Acme Dashboard</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
8
+ .container { width: 360px; }
9
+ h1 { font-size: 1.8rem; margin-bottom: 1.2rem; }
10
+ form { display: flex; flex-direction: column; gap: 0.8rem; }
11
+ input { padding: 0.7rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #e2e8f0; font-size: 1rem; }
12
+ input::placeholder { color: #64748b; }
13
+ button { padding: 0.75rem; border-radius: 8px; border: none; background: #3b82f6; color: white; font-size: 1rem; font-weight: 600; cursor: pointer; }
14
+ button:hover { background: #2563eb; }
15
+ .error { color: #f87171; font-size: 0.9rem; display: none; }
16
+ .error.visible { display: block; }
17
+ #dashboard { display: none; }
18
+ #dashboard h1 { color: #34d399; }
19
+ #dashboard ul { list-style: none; margin-top: 1rem; }
20
+ #dashboard li { padding: 0.5rem 0; border-bottom: 1px solid #1e293b; }
21
+ #dashboard button { background: #ef4444; margin-top: 1rem; }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <div class="container">
26
+ <div id="login">
27
+ <h1>Sign In</h1>
28
+ <div id="error" class="error" role="alert">Please fill in all fields</div>
29
+ <form onsubmit="return false;">
30
+ <input id="email" type="email" placeholder="Email" aria-label="Email" />
31
+ <input id="password" type="password" placeholder="Password" aria-label="Password" />
32
+ <button type="button" id="signin-btn">Sign In</button>
33
+ </form>
34
+ </div>
35
+ <div id="dashboard">
36
+ <h1>Welcome back!</h1>
37
+ <p id="user-greeting"></p>
38
+ <ul id="tasks">
39
+ <li>Deploy v2.1</li>
40
+ <li>Review PR #42</li>
41
+ <li>Update docs</li>
42
+ </ul>
43
+ <button type="button" id="logout-btn">Sign Out</button>
44
+ </div>
45
+ </div>
46
+ <script>
47
+ document.getElementById('signin-btn').addEventListener('click', function() {
48
+ var email = document.getElementById('email').value;
49
+ var password = document.getElementById('password').value;
50
+ var error = document.getElementById('error');
51
+ if (!email || !password) {
52
+ error.classList.add('visible');
53
+ return;
54
+ }
55
+ error.classList.remove('visible');
56
+ document.getElementById('login').style.display = 'none';
57
+ document.getElementById('dashboard').style.display = 'block';
58
+ document.getElementById('user-greeting').textContent = 'Logged in as ' + email;
59
+ document.title = 'Dashboard — Acme';
60
+ });
61
+ document.getElementById('logout-btn').addEventListener('click', function() {
62
+ document.getElementById('login').style.display = 'block';
63
+ document.getElementById('dashboard').style.display = 'none';
64
+ document.getElementById('email').value = '';
65
+ document.getElementById('password').value = '';
66
+ document.title = 'Acme Dashboard';
67
+ });
68
+ </script>
69
+ </body>
70
+ </html>
@@ -0,0 +1,64 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>SPA Dashboard</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
8
+ .container { width: 480px; }
9
+ h1 { font-size: 1.8rem; margin-bottom: 1rem; }
10
+ .spinner { display: inline-block; width: 20px; height: 20px; border: 3px solid #334155; border-top-color: #3b82f6; border-radius: 50%; animation: spin 0.8s linear infinite; margin-right: 0.5rem; vertical-align: middle; }
11
+ @keyframes spin { to { transform: rotate(360deg); } }
12
+ .loading { color: #94a3b8; margin-bottom: 1rem; }
13
+ .card { border: 1px solid #334155; border-radius: 12px; padding: 1.2rem; background: #1e293b; margin-bottom: 0.8rem; }
14
+ .card h3 { margin-bottom: 0.4rem; }
15
+ .card p { color: #94a3b8; font-size: 0.9rem; }
16
+ .stats { display: flex; gap: 1rem; margin-top: 1rem; }
17
+ .stat { text-align: center; }
18
+ .stat-value { font-size: 2rem; font-weight: 700; color: #3b82f6; }
19
+ .stat-label { font-size: 0.8rem; color: #64748b; }
20
+ #content { display: none; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <div class="container">
25
+ <h1>Analytics Dashboard</h1>
26
+ <div id="loading" class="loading" aria-busy="true">
27
+ <span class="spinner"></span>Loading dashboard data...
28
+ </div>
29
+ <div id="content">
30
+ <div class="stats">
31
+ <div class="stat">
32
+ <div class="stat-value">1,247</div>
33
+ <div class="stat-label">Users</div>
34
+ </div>
35
+ <div class="stat">
36
+ <div class="stat-value">89%</div>
37
+ <div class="stat-label">Uptime</div>
38
+ </div>
39
+ <div class="stat">
40
+ <div class="stat-value">3.2s</div>
41
+ <div class="stat-label">Avg Response</div>
42
+ </div>
43
+ </div>
44
+ <div class="card">
45
+ <h3>Recent Activity</h3>
46
+ <p>12 deployments this week. Last deploy: 2 hours ago.</p>
47
+ </div>
48
+ <div class="card">
49
+ <h3>Alerts</h3>
50
+ <p>No active alerts. All systems operational.</p>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <script>
55
+ // Simulate async data loading — 2 second delay
56
+ setTimeout(function() {
57
+ document.getElementById('loading').style.display = 'none';
58
+ document.getElementById('loading').setAttribute('aria-busy', 'false');
59
+ document.getElementById('content').style.display = 'block';
60
+ document.title = 'Analytics Dashboard — Loaded';
61
+ }, 2000);
62
+ </script>
63
+ </body>
64
+ </html>
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Todo App</title>
5
+ <style>
6
+ * { box-sizing: border-box; margin: 0; padding: 0; }
7
+ body { font-family: -apple-system, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
8
+ .container { width: 400px; }
9
+ h1 { font-size: 1.8rem; margin-bottom: 1.2rem; }
10
+ .add-row { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
11
+ input { flex: 1; padding: 0.7rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #e2e8f0; font-size: 1rem; }
12
+ input::placeholder { color: #64748b; }
13
+ button { padding: 0.7rem 1.2rem; border-radius: 8px; border: none; background: #3b82f6; color: white; font-size: 1rem; font-weight: 600; cursor: pointer; }
14
+ button:hover { background: #2563eb; }
15
+ ul { list-style: none; }
16
+ li { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0; border-bottom: 1px solid #1e293b; }
17
+ .delete-btn { background: #ef4444; padding: 0.3rem 0.6rem; font-size: 0.85rem; }
18
+ .count { color: #94a3b8; font-size: 0.9rem; margin-top: 0.8rem; }
19
+ </style>
20
+ </head>
21
+ <body>
22
+ <div class="container">
23
+ <h1>Todo List</h1>
24
+ <div class="add-row">
25
+ <input id="todo-input" placeholder="Add a task..." aria-label="New task" />
26
+ <button type="button" onclick="addTodo()">Add</button>
27
+ </div>
28
+ <ul id="todo-list"></ul>
29
+ <p id="count" class="count"></p>
30
+ </div>
31
+ <script>
32
+ function updateCount() {
33
+ const items = document.querySelectorAll('#todo-list li');
34
+ document.getElementById('count').textContent = items.length + ' item' + (items.length !== 1 ? 's' : '');
35
+ }
36
+ function addTodo() {
37
+ const input = document.getElementById('todo-input');
38
+ const text = input.value.trim();
39
+ if (!text) return;
40
+ const li = document.createElement('li');
41
+ li.innerHTML = '<span>' + text + '</span><button class="delete-btn" onclick="this.parentElement.remove(); updateCount()">Delete</button>';
42
+ document.getElementById('todo-list').appendChild(li);
43
+ input.value = '';
44
+ updateCount();
45
+ }
46
+ document.getElementById('todo-input').addEventListener('keydown', function(e) {
47
+ if (e.key === 'Enter') addTodo();
48
+ });
49
+ </script>
50
+ </body>
51
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitronai/alethia",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "MIT-licensed MCP bridge to the Alethia desktop runtime — the patent-pending zero-IPC E2E test runtime built for AI agents. 45x faster than Playwright on the localhost loop. Local-first, zero telemetry by default. Auto-installs the signed headless runtime on first use.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "dist",
12
+ "demo",
12
13
  "LICENSE",
13
14
  "README.md"
14
15
  ],