@conversionpros/aiva 1.0.1 → 2.0.0

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.
Files changed (149) hide show
  1. package/bin/aiva.js +26 -14
  2. package/lib/bluebubbles.js +145 -0
  3. package/lib/config-gen.js +253 -0
  4. package/lib/constants.js +72 -0
  5. package/lib/launch-agent.js +112 -0
  6. package/lib/prerequisites.js +236 -0
  7. package/lib/process.js +59 -145
  8. package/lib/setup.js +224 -194
  9. package/lib/validate.js +194 -0
  10. package/package.json +7 -32
  11. package/auto-deploy.js +0 -190
  12. package/cli-sync.js +0 -126
  13. package/d2a-prompt-template.txt +0 -106
  14. package/diagnostics-api.js +0 -304
  15. package/docs/ara-dedup-fix-scope.md +0 -112
  16. package/docs/ara-fix-round2-scope.md +0 -61
  17. package/docs/ara-greeting-fix-scope.md +0 -70
  18. package/docs/calendar-date-fix-scope.md +0 -28
  19. package/docs/getting-started.md +0 -115
  20. package/docs/network-architecture-rollout-scope.md +0 -43
  21. package/docs/scope-google-oauth-integration.md +0 -351
  22. package/docs/settings-page-scope.md +0 -50
  23. package/docs/xai-imagine-scope.md +0 -116
  24. package/docs/xai-voice-integration-scope.md +0 -115
  25. package/docs/xai-voice-tools-scope.md +0 -165
  26. package/email-router.js +0 -512
  27. package/follow-up-handler.js +0 -606
  28. package/gateway-monitor.js +0 -158
  29. package/google-email.js +0 -379
  30. package/google-oauth.js +0 -310
  31. package/grok-imagine.js +0 -97
  32. package/health-reporter.js +0 -287
  33. package/invisible-prefix-base.txt +0 -206
  34. package/invisible-prefix-owner.txt +0 -26
  35. package/invisible-prefix-slim.txt +0 -10
  36. package/invisible-prefix.txt +0 -43
  37. package/knowledge-base.js +0 -472
  38. package/lib/cli.js +0 -19
  39. package/lib/server.js +0 -42
  40. package/meta-capi.js +0 -206
  41. package/meta-leads.js +0 -411
  42. package/notion-oauth.js +0 -323
  43. package/public/agent-config.html +0 -241
  44. package/public/aiva-avatar-anime.png +0 -0
  45. package/public/css/docs.css.bak +0 -688
  46. package/public/css/onboarding.css +0 -543
  47. package/public/diagrams/claude-subscription-pool.html +0 -329
  48. package/public/diagrams/claude-subscription-pool.png +0 -0
  49. package/public/docs-icon.png +0 -0
  50. package/public/escalation.html +0 -237
  51. package/public/group-config.html +0 -300
  52. package/public/icon-192.png +0 -0
  53. package/public/icon-512.png +0 -0
  54. package/public/icons/agents.svg +0 -1
  55. package/public/icons/attach.svg +0 -1
  56. package/public/icons/characters.svg +0 -1
  57. package/public/icons/chat.svg +0 -1
  58. package/public/icons/docs.svg +0 -1
  59. package/public/icons/heartbeat.svg +0 -1
  60. package/public/icons/messages.svg +0 -1
  61. package/public/icons/mic.svg +0 -1
  62. package/public/icons/notes.svg +0 -1
  63. package/public/icons/settings.svg +0 -1
  64. package/public/icons/tasks.svg +0 -1
  65. package/public/images/onboarding/p0-communication-layer.png +0 -0
  66. package/public/images/onboarding/p0-infinite-surface.png +0 -0
  67. package/public/images/onboarding/p0-learning-model.png +0 -0
  68. package/public/images/onboarding/p0-meet-aiva.png +0 -0
  69. package/public/images/onboarding/p4-contact-intelligence.png +0 -0
  70. package/public/images/onboarding/p4-context-compounds.png +0 -0
  71. package/public/images/onboarding/p4-message-router.png +0 -0
  72. package/public/images/onboarding/p4-per-contact-rules.png +0 -0
  73. package/public/images/onboarding/p4-send-messages.png +0 -0
  74. package/public/images/onboarding/p6-be-precise.png +0 -0
  75. package/public/images/onboarding/p6-review-escalations.png +0 -0
  76. package/public/images/onboarding/p6-voice-input.png +0 -0
  77. package/public/images/onboarding/p7-completion.png +0 -0
  78. package/public/index.html +0 -11594
  79. package/public/js/onboarding.js +0 -699
  80. package/public/manifest.json +0 -24
  81. package/public/messages-v2.html +0 -2824
  82. package/public/permission-approve.html.bak +0 -107
  83. package/public/permissions.html +0 -150
  84. package/public/styles/design-system.css +0 -68
  85. package/router-db.js +0 -604
  86. package/router-utils.js +0 -28
  87. package/router-v2/adapters/imessage.js +0 -191
  88. package/router-v2/adapters/quo.js +0 -82
  89. package/router-v2/adapters/whatsapp.js +0 -192
  90. package/router-v2/contact-manager.js +0 -234
  91. package/router-v2/conversation-engine.js +0 -498
  92. package/router-v2/data/knowledge-base.json +0 -176
  93. package/router-v2/data/router-v2.db +0 -0
  94. package/router-v2/data/router-v2.db-shm +0 -0
  95. package/router-v2/data/router-v2.db-wal +0 -0
  96. package/router-v2/data/router.db +0 -0
  97. package/router-v2/db.js +0 -457
  98. package/router-v2/escalation-bridge.js +0 -540
  99. package/router-v2/follow-up-engine.js +0 -347
  100. package/router-v2/index.js +0 -441
  101. package/router-v2/ingestion.js +0 -213
  102. package/router-v2/knowledge-base.js +0 -231
  103. package/router-v2/lead-qualifier.js +0 -152
  104. package/router-v2/learning-loop.js +0 -202
  105. package/router-v2/outbound-sender.js +0 -160
  106. package/router-v2/package.json +0 -13
  107. package/router-v2/permission-gate.js +0 -86
  108. package/router-v2/playbook.js +0 -177
  109. package/router-v2/prompts/base.js +0 -52
  110. package/router-v2/prompts/first-contact.js +0 -38
  111. package/router-v2/prompts/lead-qualification.js +0 -37
  112. package/router-v2/prompts/scheduling.js +0 -72
  113. package/router-v2/prompts/style-overrides.js +0 -22
  114. package/router-v2/scheduler.js +0 -301
  115. package/router-v2/scripts/migrate-v1-to-v2.js +0 -215
  116. package/router-v2/scripts/seed-faq.js +0 -67
  117. package/router-v2/seed-knowledge-base.js +0 -39
  118. package/router-v2/utils/ai.js +0 -129
  119. package/router-v2/utils/phone.js +0 -52
  120. package/router-v2/utils/response-validator.js +0 -98
  121. package/router-v2/utils/sanitize.js +0 -222
  122. package/router.js +0 -5005
  123. package/routes/google-calendar.js +0 -186
  124. package/scripts/deploy.sh +0 -62
  125. package/scripts/macos-calendar.sh +0 -232
  126. package/scripts/onboard-device.sh +0 -466
  127. package/server.js +0 -5131
  128. package/start.sh +0 -24
  129. package/templates/AGENTS.md +0 -548
  130. package/templates/IDENTITY.md +0 -15
  131. package/templates/docs-agents.html +0 -132
  132. package/templates/docs-app.html +0 -130
  133. package/templates/docs-home.html +0 -83
  134. package/templates/docs-imessage.html +0 -121
  135. package/templates/docs-tasks.html +0 -123
  136. package/templates/docs-tips.html +0 -175
  137. package/templates/getting-started.html +0 -809
  138. package/templates/invisible-prefix-base.txt +0 -171
  139. package/templates/invisible-prefix-owner.txt +0 -282
  140. package/templates/invisible-prefix.txt +0 -338
  141. package/templates/manifest.json +0 -61
  142. package/templates/memory-org/clients.md +0 -7
  143. package/templates/memory-org/credentials.md +0 -9
  144. package/templates/memory-org/devices.md +0 -7
  145. package/templates/updates.html +0 -464
  146. package/tts-proxy.js +0 -96
  147. package/voice-call-local.js +0 -731
  148. package/voice-call.js +0 -732
  149. package/wa-listener.js +0 -354
@@ -1,464 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Updates — AIVA</title>
7
- <style>
8
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
9
-
10
- *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
11
-
12
- :root {
13
- --bg: #0a0a0f;
14
- --bg-elevated: #111118;
15
- --bg-card: rgba(255,255,255,0.03);
16
- --border: rgba(255,255,255,0.06);
17
- --border-hover: rgba(255,255,255,0.12);
18
- --text: #b0b0b8;
19
- --text-secondary: #707078;
20
- --text-heading: #f0f0f5;
21
- --accent: #7b8cff;
22
- --accent-soft: rgba(123,140,255,0.08);
23
- --accent-glow: rgba(123,140,255,0.15);
24
- --radius: 16px;
25
- --radius-sm: 10px;
26
- }
27
-
28
- body {
29
- background: var(--bg);
30
- color: var(--text);
31
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
32
- line-height: 1.7;
33
- -webkit-font-smoothing: antialiased;
34
- -moz-osx-font-smoothing: grayscale;
35
- overflow-x: hidden;
36
- }
37
-
38
- @keyframes fadeUp {
39
- from { opacity: 0; transform: translateY(24px); }
40
- to { opacity: 1; transform: translateY(0); }
41
- }
42
-
43
- .fade-section {
44
- opacity: 0;
45
- transform: translateY(24px);
46
- transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
47
- }
48
- .fade-section.visible {
49
- opacity: 1;
50
- transform: translateY(0);
51
- }
52
-
53
- .page-container {
54
- max-width: 960px;
55
- margin: 0 auto;
56
- padding: 0 1.5rem;
57
- }
58
-
59
- /* ── Hero ── */
60
- .hero {
61
- position: relative;
62
- padding: 6rem 0 4rem;
63
- text-align: center;
64
- overflow: hidden;
65
- }
66
- .hero::before {
67
- content: '';
68
- position: absolute;
69
- top: -40%;
70
- left: 50%;
71
- transform: translateX(-50%);
72
- width: 600px;
73
- height: 600px;
74
- background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%);
75
- border-radius: 50%;
76
- pointer-events: none;
77
- z-index: 0;
78
- }
79
- .hero-content {
80
- position: relative;
81
- z-index: 1;
82
- animation: fadeUp 0.8s ease-out;
83
- }
84
- .hero-badge {
85
- display: inline-flex;
86
- align-items: center;
87
- gap: 6px;
88
- padding: 6px 14px;
89
- border-radius: 100px;
90
- background: var(--accent-soft);
91
- border: 1px solid rgba(123,140,255,0.15);
92
- font-size: 0.8rem;
93
- font-weight: 500;
94
- color: var(--accent);
95
- letter-spacing: 0.03em;
96
- margin-bottom: 1.5rem;
97
- }
98
- .hero h1 {
99
- font-size: clamp(2rem, 5vw, 3.2rem);
100
- font-weight: 800;
101
- color: var(--text-heading);
102
- line-height: 1.15;
103
- letter-spacing: -0.03em;
104
- margin-bottom: 1rem;
105
- }
106
- .hero .subtitle {
107
- font-size: clamp(1rem, 2.5vw, 1.2rem);
108
- color: var(--text-secondary);
109
- max-width: 580px;
110
- margin: 0 auto;
111
- line-height: 1.6;
112
- font-weight: 400;
113
- }
114
-
115
- /* ── Feed ── */
116
- .feed {
117
- padding: 2rem 0 4rem;
118
- }
119
-
120
- .feed-entry {
121
- display: flex;
122
- gap: 2rem;
123
- padding: 2.5rem 0;
124
- }
125
- .feed-entry + .feed-entry {
126
- border-top: 1px solid var(--border);
127
- }
128
-
129
- .feed-date {
130
- flex-shrink: 0;
131
- width: 100px;
132
- padding-top: 0.25rem;
133
- }
134
- .feed-date time {
135
- font-size: 0.82rem;
136
- font-weight: 500;
137
- color: var(--text-secondary);
138
- line-height: 1.4;
139
- }
140
-
141
- .feed-card {
142
- flex: 1;
143
- background: var(--bg-card);
144
- border: 1px solid var(--border);
145
- border-radius: var(--radius);
146
- padding: 2rem;
147
- transition: border-color 0.3s ease, box-shadow 0.3s ease;
148
- }
149
- .feed-card:hover {
150
- border-color: var(--border-hover);
151
- box-shadow: 0 0 40px rgba(123,140,255,0.04);
152
- }
153
-
154
- .feed-category {
155
- display: inline-block;
156
- font-size: 0.72rem;
157
- font-weight: 600;
158
- text-transform: uppercase;
159
- letter-spacing: 0.1em;
160
- color: var(--accent);
161
- background: var(--accent-soft);
162
- padding: 4px 10px;
163
- border-radius: 100px;
164
- margin-bottom: 0.85rem;
165
- }
166
-
167
- .feed-card h2 {
168
- font-size: 1.25rem;
169
- font-weight: 700;
170
- color: var(--text-heading);
171
- letter-spacing: -0.02em;
172
- margin-bottom: 1rem;
173
- line-height: 1.3;
174
- }
175
-
176
- .feed-card ul {
177
- list-style: none;
178
- padding: 0;
179
- margin: 0;
180
- }
181
- .feed-card ul li {
182
- font-size: 0.92rem;
183
- color: var(--text);
184
- padding: 0.35rem 0;
185
- padding-left: 1.1rem;
186
- position: relative;
187
- line-height: 1.65;
188
- }
189
- .feed-card ul li::before {
190
- content: '';
191
- position: absolute;
192
- left: 0;
193
- top: 0.72rem;
194
- width: 5px;
195
- height: 5px;
196
- border-radius: 50%;
197
- background: var(--accent);
198
- opacity: 0.5;
199
- }
200
- .feed-card ul li strong {
201
- color: var(--text-heading);
202
- }
203
-
204
- .feed-card .callout {
205
- margin-top: 1rem;
206
- padding: 0.85rem 1rem;
207
- background: var(--accent-soft);
208
- border-radius: var(--radius-sm);
209
- font-size: 0.88rem;
210
- color: var(--text);
211
- line-height: 1.55;
212
- }
213
- .feed-card .callout strong {
214
- color: var(--text-heading);
215
- }
216
-
217
- /* ── Footer ── */
218
- .page-footer {
219
- padding: 3rem 0;
220
- border-top: 1px solid var(--border);
221
- text-align: center;
222
- margin-top: 2rem;
223
- }
224
- .page-footer p {
225
- font-size: 0.85rem;
226
- color: var(--text-secondary);
227
- }
228
- .page-footer a {
229
- color: var(--accent);
230
- text-decoration: none;
231
- }
232
- .page-footer a:hover {
233
- text-decoration: underline;
234
- }
235
-
236
- /* ── Responsive ── */
237
- @media (max-width: 680px) {
238
- .hero { padding: 4rem 0 3rem; }
239
- .page-container { padding: 0 1.25rem; }
240
- .feed-entry {
241
- flex-direction: column;
242
- gap: 0.75rem;
243
- }
244
- .feed-date {
245
- width: auto;
246
- }
247
- .feed-card {
248
- padding: 1.5rem;
249
- }
250
- }
251
- </style>
252
- </head>
253
- <body>
254
-
255
- <!-- ── Hamburger Nav ── -->
256
- <style>
257
- .nav-hamburger {
258
- position: fixed; top: 20px; left: 20px; z-index: 10000;
259
- width: 44px; height: 44px; border-radius: 12px;
260
- background: var(--bg-elevated); border: 1px solid var(--border);
261
- display: flex; align-items: center; justify-content: center;
262
- cursor: pointer; transition: background 0.2s, border-color 0.2s;
263
- }
264
- .nav-hamburger:hover { background: rgba(255,255,255,0.06); border-color: var(--border-hover); }
265
- .nav-hamburger span { display: block; width: 20px; height: 2px; background: var(--text-heading); position: relative; transition: all 0.3s; }
266
- .nav-hamburger span::before, .nav-hamburger span::after {
267
- content: ''; position: absolute; left: 0; width: 20px; height: 2px;
268
- background: var(--text-heading); transition: all 0.3s;
269
- }
270
- .nav-hamburger span::before { top: -6px; }
271
- .nav-hamburger span::after { top: 6px; }
272
- .nav-hamburger.open span { background: transparent; }
273
- .nav-hamburger.open span::before { top: 0; transform: rotate(45deg); }
274
- .nav-hamburger.open span::after { top: 0; transform: rotate(-45deg); }
275
-
276
- .nav-overlay {
277
- position: fixed; inset: 0; z-index: 9998;
278
- background: rgba(0,0,0,0.5); opacity: 0; pointer-events: none;
279
- transition: opacity 0.3s;
280
- }
281
- .nav-overlay.open { opacity: 1; pointer-events: auto; }
282
-
283
- .nav-drawer {
284
- position: fixed; top: 0; left: 0; z-index: 9999;
285
- width: 280px; height: 100vh; background: var(--bg-elevated);
286
- border-right: 1px solid var(--border);
287
- transform: translateX(-100%); transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
288
- padding: 80px 24px 24px;
289
- }
290
- .nav-drawer.open { transform: translateX(0); }
291
- .nav-drawer a {
292
- display: block; padding: 14px 16px; margin-bottom: 4px;
293
- color: var(--text); text-decoration: none; font-size: 15px;
294
- font-weight: 500; border-radius: var(--radius-sm);
295
- transition: background 0.2s, color 0.2s;
296
- }
297
- .nav-drawer a:hover, .nav-drawer a.active {
298
- background: var(--accent-soft); color: var(--accent);
299
- }
300
- </style>
301
-
302
- <div class="nav-overlay" id="navOverlay"></div>
303
- <div class="nav-drawer" id="navDrawer">
304
- <a href="/getting-started" id="nav-gs">Getting Started</a>
305
- <a href="/updates" id="nav-up">Updates</a>
306
- <a href="/">Back to AIVA App</a>
307
- </div>
308
- <button class="nav-hamburger" id="navHamburger" aria-label="Menu"><span></span></button>
309
-
310
- <script>
311
- (function(){
312
- var btn=document.getElementById('navHamburger'),
313
- drawer=document.getElementById('navDrawer'),
314
- overlay=document.getElementById('navOverlay');
315
- function toggle(){
316
- var open=drawer.classList.toggle('open');
317
- overlay.classList.toggle('open',open);
318
- btn.classList.toggle('open',open);
319
- }
320
- btn.addEventListener('click',toggle);
321
- overlay.addEventListener('click',toggle);
322
- var path=location.pathname;
323
- if(path==='/getting-started') document.getElementById('nav-gs').classList.add('active');
324
- else if(path==='/updates') document.getElementById('nav-up').classList.add('active');
325
- })();
326
- </script>
327
- <!-- ── End Hamburger Nav ── -->
328
-
329
- <!-- ── Hero ── -->
330
- <section class="hero">
331
- <div class="page-container hero-content">
332
- <div class="hero-badge">
333
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
334
- Training Feed
335
- </div>
336
- <h1>AIVA Updates</h1>
337
- <p class="subtitle">Learn how to get the most from your AI assistant. Read from the bottom up to get started.</p>
338
- </div>
339
- </section>
340
-
341
- <div class="page-container">
342
- <div class="feed">
343
-
344
- <!-- Entry 6: Pro Tips -->
345
- <div class="feed-entry fade-section">
346
- <div class="feed-date"><time>Feb 11, 2026</time></div>
347
- <div class="feed-card">
348
- <span class="feed-category">Pro Tips</span>
349
- <h2>Pro Tips for Power Users</h2>
350
- <ul>
351
- <li>Voice messages work great -- AIVA transcribes and acts on them</li>
352
- <li>Be specific with requests -- "Schedule a 30-min call with John Thursday at 2 PM" beats "set something up with John"</li>
353
- <li>Give feedback when AIVA gets something wrong -- she learns and adjusts</li>
354
- <li>Don't repeat requests -- if it's on the task board, it's being handled</li>
355
- <li>Check your task board regularly -- it's the single source of truth</li>
356
- </ul>
357
- </div>
358
- </div>
359
-
360
- <!-- Entry 5: Task Board -->
361
- <div class="feed-entry fade-section">
362
- <div class="feed-date"><time>Feb 11, 2026</time></div>
363
- <div class="feed-card">
364
- <span class="feed-category">Feature Guide</span>
365
- <h2>Your Task Board</h2>
366
- <ul>
367
- <li>Every request you make becomes a task</li>
368
- <li>Tasks flow: To Do, In Progress, Done</li>
369
- <li>Check the Tasks tab in the app to see everything AIVA is working on</li>
370
- <li>You can create tasks directly from the app too</li>
371
- <li>AIVA adds notes to tasks as she works, so you can see progress</li>
372
- </ul>
373
- </div>
374
- </div>
375
-
376
- <!-- Entry 4: iMessage -->
377
- <div class="feed-entry fade-section">
378
- <div class="feed-date"><time>Feb 11, 2026</time></div>
379
- <div class="feed-card">
380
- <span class="feed-category">Feature Guide</span>
381
- <h2>iMessage -- Your Outreach Channel</h2>
382
- <ul>
383
- <li>Messages to your AIVA phone number go to a specialized outreach agent</li>
384
- <li>This agent manages conversations with your contacts on your behalf</li>
385
- <li>It can respond, schedule, and follow up automatically</li>
386
- <li>You control how each contact is handled (respond, ignore, take message only)</li>
387
- <li>Train this channel by giving context about how you want contacts handled</li>
388
- </ul>
389
- <div class="callout"><strong>Important:</strong> This is a separate specialist from your main AIVA.</div>
390
- </div>
391
- </div>
392
-
393
- <!-- Entry 3: The App -->
394
- <div class="feed-entry fade-section">
395
- <div class="feed-date"><time>Feb 11, 2026</time></div>
396
- <div class="feed-card">
397
- <span class="feed-category">Feature Guide</span>
398
- <h2>The AIVA App -- Your Central Brain</h2>
399
- <ul>
400
- <li>This app is your main hub for communicating with AIVA</li>
401
- <li>Brain dump here -- tell AIVA everything, she'll organize and distribute it</li>
402
- <li>Make requests -- scheduling, research, content, anything you need</li>
403
- <li>Voice messages are great for quick brain dumps</li>
404
- <li>AIVA distributes knowledge from here to all your other agents</li>
405
- <li>Think of it as talking to your executive assistant</li>
406
- </ul>
407
- </div>
408
- </div>
409
-
410
- <!-- Entry 2: Meet Your Agents -->
411
- <div class="feed-entry fade-section">
412
- <div class="feed-date"><time>Feb 11, 2026</time></div>
413
- <div class="feed-card">
414
- <span class="feed-category">Getting Started</span>
415
- <h2>Meet Your Agents</h2>
416
- <ul>
417
- <li>AIVA is actually a team of specialized agents working together</li>
418
- <li><strong>Main Agent</strong> -- your central coordinator (lives in this app)</li>
419
- <li><strong>Outreach Agent</strong> -- manages your text messages and conversations</li>
420
- <li><strong>Email Agent</strong> -- monitors and triages your inbox</li>
421
- <li><strong>Research Agent</strong> -- handles deep dives and information gathering</li>
422
- <li><strong>Content Agent</strong> -- creates drafts, copy, and documentation</li>
423
- <li>You don't need to manage them -- just communicate naturally and AIVA routes to the right one</li>
424
- </ul>
425
- </div>
426
- </div>
427
-
428
- <!-- Entry 1: Welcome -->
429
- <div class="feed-entry fade-section">
430
- <div class="feed-date"><time>Feb 11, 2026</time></div>
431
- <div class="feed-card">
432
- <span class="feed-category">Getting Started</span>
433
- <h2>Welcome to AIVA</h2>
434
- <ul>
435
- <li>AIVA (AI Virtual Assistant) is your personal AI-powered assistant</li>
436
- <li>She helps you stay organized, communicate effectively, and get things done</li>
437
- <li>She works 24/7, remembers your preferences, and learns over time</li>
438
- <li>Two main ways to interact: this app (central brain) and iMessage (message management)</li>
439
- <li>Read through these updates to learn how to get the most out of your AIVA</li>
440
- </ul>
441
- </div>
442
- </div>
443
-
444
- </div>
445
-
446
- <footer class="page-footer">
447
- <p><a href="/getting-started">Back to Getting Started</a></p>
448
- </footer>
449
- </div>
450
-
451
- <script>
452
- const observer = new IntersectionObserver((entries) => {
453
- entries.forEach(entry => {
454
- if (entry.isIntersecting) {
455
- entry.target.classList.add('visible');
456
- }
457
- });
458
- }, { threshold: 0.08, rootMargin: '0px 0px -40px 0px' });
459
-
460
- document.querySelectorAll('.fade-section').forEach(el => observer.observe(el));
461
- </script>
462
-
463
- </body>
464
- </html>
package/tts-proxy.js DELETED
@@ -1,96 +0,0 @@
1
- const express = require('express');
2
- const https = require('https');
3
- const fs = require('fs');
4
- const path = require('path');
5
-
6
- const PORT = 3891;
7
- const TARGET = 'api.elevenlabs.io';
8
- const RULES_PATH = path.join(__dirname, 'data', 'tts-pronunciations.json');
9
-
10
- let rules = [];
11
-
12
- function loadRules() {
13
- try {
14
- const data = JSON.parse(fs.readFileSync(RULES_PATH, 'utf8'));
15
- rules = Array.isArray(data.rules) ? data.rules : [];
16
- console.log(`[tts-proxy] Loaded ${rules.length} pronunciation rule(s)`);
17
- } catch (e) {
18
- console.warn(`[tts-proxy] Could not load rules: ${e.message} - using empty rules`);
19
- rules = [];
20
- }
21
- }
22
-
23
- loadRules();
24
- fs.watchFile(RULES_PATH, { interval: 2000 }, loadRules);
25
-
26
- function applyRules(text) {
27
- let result = text;
28
- for (const rule of rules) {
29
- const flags = rule.caseSensitive ? 'g' : 'gi';
30
- const escaped = rule.find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
31
- const re = new RegExp(escaped, flags);
32
- if (re.test(result)) {
33
- console.log(`[tts-proxy] Replaced "${rule.find}" → "${rule.replace}" in TTS text`);
34
- result = result.replace(re, rule.replace);
35
- }
36
- }
37
- return result;
38
- }
39
-
40
- const app = express();
41
-
42
- // TTS endpoints: parse JSON, apply rules, forward
43
- app.post('/v1/text-to-speech/*', (req, res) => {
44
- let chunks = [];
45
- req.on('data', c => chunks.push(c));
46
- req.on('end', () => {
47
- let bodyBuf = Buffer.concat(chunks);
48
- try {
49
- const parsed = JSON.parse(bodyBuf.toString());
50
- if (parsed.text) {
51
- parsed.text = applyRules(parsed.text);
52
- }
53
- bodyBuf = Buffer.from(JSON.stringify(parsed));
54
- } catch (e) {
55
- // If parse fails, forward original
56
- }
57
- proxyRequest(req, res, bodyBuf);
58
- });
59
- });
60
-
61
- // All other requests: pass-through
62
- app.all('*', (req, res) => {
63
- let chunks = [];
64
- req.on('data', c => chunks.push(c));
65
- req.on('end', () => {
66
- proxyRequest(req, res, Buffer.concat(chunks));
67
- });
68
- });
69
-
70
- function proxyRequest(req, res, body) {
71
- const headers = { ...req.headers, host: TARGET };
72
- if (body.length > 0) headers['content-length'] = body.length;
73
-
74
- const opts = {
75
- hostname: TARGET,
76
- port: 443,
77
- path: req.originalUrl,
78
- method: req.method,
79
- headers
80
- };
81
-
82
- const proxy = https.request(opts, (upstream) => {
83
- res.writeHead(upstream.statusCode, upstream.headers);
84
- upstream.pipe(res);
85
- });
86
-
87
- proxy.on('error', (e) => {
88
- console.error(`[tts-proxy] Proxy error: ${e.message}`);
89
- if (!res.headersSent) res.status(502).send('Proxy error');
90
- });
91
-
92
- if (body.length > 0) proxy.write(body);
93
- proxy.end();
94
- }
95
-
96
- app.listen(PORT, () => console.log(`[tts-proxy] Listening on port ${PORT}`));