@conversionpros/aiva 1.0.0 → 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 (150) 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/config.js +1 -1
  5. package/lib/constants.js +72 -0
  6. package/lib/launch-agent.js +112 -0
  7. package/lib/prerequisites.js +236 -0
  8. package/lib/process.js +59 -145
  9. package/lib/setup.js +224 -194
  10. package/lib/validate.js +194 -0
  11. package/package.json +7 -32
  12. package/auto-deploy.js +0 -190
  13. package/cli-sync.js +0 -126
  14. package/d2a-prompt-template.txt +0 -106
  15. package/diagnostics-api.js +0 -304
  16. package/docs/ara-dedup-fix-scope.md +0 -112
  17. package/docs/ara-fix-round2-scope.md +0 -61
  18. package/docs/ara-greeting-fix-scope.md +0 -70
  19. package/docs/calendar-date-fix-scope.md +0 -28
  20. package/docs/getting-started.md +0 -115
  21. package/docs/network-architecture-rollout-scope.md +0 -43
  22. package/docs/scope-google-oauth-integration.md +0 -351
  23. package/docs/settings-page-scope.md +0 -50
  24. package/docs/xai-imagine-scope.md +0 -116
  25. package/docs/xai-voice-integration-scope.md +0 -115
  26. package/docs/xai-voice-tools-scope.md +0 -165
  27. package/email-router.js +0 -512
  28. package/follow-up-handler.js +0 -606
  29. package/gateway-monitor.js +0 -158
  30. package/google-email.js +0 -379
  31. package/google-oauth.js +0 -310
  32. package/grok-imagine.js +0 -97
  33. package/health-reporter.js +0 -287
  34. package/invisible-prefix-base.txt +0 -206
  35. package/invisible-prefix-owner.txt +0 -26
  36. package/invisible-prefix-slim.txt +0 -10
  37. package/invisible-prefix.txt +0 -43
  38. package/knowledge-base.js +0 -472
  39. package/lib/cli.js +0 -19
  40. package/lib/server.js +0 -42
  41. package/meta-capi.js +0 -206
  42. package/meta-leads.js +0 -411
  43. package/notion-oauth.js +0 -323
  44. package/public/agent-config.html +0 -241
  45. package/public/aiva-avatar-anime.png +0 -0
  46. package/public/css/docs.css.bak +0 -688
  47. package/public/css/onboarding.css +0 -543
  48. package/public/diagrams/claude-subscription-pool.html +0 -329
  49. package/public/diagrams/claude-subscription-pool.png +0 -0
  50. package/public/docs-icon.png +0 -0
  51. package/public/escalation.html +0 -237
  52. package/public/group-config.html +0 -300
  53. package/public/icon-192.png +0 -0
  54. package/public/icon-512.png +0 -0
  55. package/public/icons/agents.svg +0 -1
  56. package/public/icons/attach.svg +0 -1
  57. package/public/icons/characters.svg +0 -1
  58. package/public/icons/chat.svg +0 -1
  59. package/public/icons/docs.svg +0 -1
  60. package/public/icons/heartbeat.svg +0 -1
  61. package/public/icons/messages.svg +0 -1
  62. package/public/icons/mic.svg +0 -1
  63. package/public/icons/notes.svg +0 -1
  64. package/public/icons/settings.svg +0 -1
  65. package/public/icons/tasks.svg +0 -1
  66. package/public/images/onboarding/p0-communication-layer.png +0 -0
  67. package/public/images/onboarding/p0-infinite-surface.png +0 -0
  68. package/public/images/onboarding/p0-learning-model.png +0 -0
  69. package/public/images/onboarding/p0-meet-aiva.png +0 -0
  70. package/public/images/onboarding/p4-contact-intelligence.png +0 -0
  71. package/public/images/onboarding/p4-context-compounds.png +0 -0
  72. package/public/images/onboarding/p4-message-router.png +0 -0
  73. package/public/images/onboarding/p4-per-contact-rules.png +0 -0
  74. package/public/images/onboarding/p4-send-messages.png +0 -0
  75. package/public/images/onboarding/p6-be-precise.png +0 -0
  76. package/public/images/onboarding/p6-review-escalations.png +0 -0
  77. package/public/images/onboarding/p6-voice-input.png +0 -0
  78. package/public/images/onboarding/p7-completion.png +0 -0
  79. package/public/index.html +0 -11594
  80. package/public/js/onboarding.js +0 -699
  81. package/public/manifest.json +0 -24
  82. package/public/messages-v2.html +0 -2824
  83. package/public/permission-approve.html.bak +0 -107
  84. package/public/permissions.html +0 -150
  85. package/public/styles/design-system.css +0 -68
  86. package/router-db.js +0 -604
  87. package/router-utils.js +0 -28
  88. package/router-v2/adapters/imessage.js +0 -191
  89. package/router-v2/adapters/quo.js +0 -82
  90. package/router-v2/adapters/whatsapp.js +0 -192
  91. package/router-v2/contact-manager.js +0 -234
  92. package/router-v2/conversation-engine.js +0 -498
  93. package/router-v2/data/knowledge-base.json +0 -176
  94. package/router-v2/data/router-v2.db +0 -0
  95. package/router-v2/data/router-v2.db-shm +0 -0
  96. package/router-v2/data/router-v2.db-wal +0 -0
  97. package/router-v2/data/router.db +0 -0
  98. package/router-v2/db.js +0 -457
  99. package/router-v2/escalation-bridge.js +0 -540
  100. package/router-v2/follow-up-engine.js +0 -347
  101. package/router-v2/index.js +0 -441
  102. package/router-v2/ingestion.js +0 -213
  103. package/router-v2/knowledge-base.js +0 -231
  104. package/router-v2/lead-qualifier.js +0 -152
  105. package/router-v2/learning-loop.js +0 -202
  106. package/router-v2/outbound-sender.js +0 -160
  107. package/router-v2/package.json +0 -13
  108. package/router-v2/permission-gate.js +0 -86
  109. package/router-v2/playbook.js +0 -177
  110. package/router-v2/prompts/base.js +0 -52
  111. package/router-v2/prompts/first-contact.js +0 -38
  112. package/router-v2/prompts/lead-qualification.js +0 -37
  113. package/router-v2/prompts/scheduling.js +0 -72
  114. package/router-v2/prompts/style-overrides.js +0 -22
  115. package/router-v2/scheduler.js +0 -301
  116. package/router-v2/scripts/migrate-v1-to-v2.js +0 -215
  117. package/router-v2/scripts/seed-faq.js +0 -67
  118. package/router-v2/seed-knowledge-base.js +0 -39
  119. package/router-v2/utils/ai.js +0 -129
  120. package/router-v2/utils/phone.js +0 -52
  121. package/router-v2/utils/response-validator.js +0 -98
  122. package/router-v2/utils/sanitize.js +0 -222
  123. package/router.js +0 -5005
  124. package/routes/google-calendar.js +0 -186
  125. package/scripts/deploy.sh +0 -62
  126. package/scripts/macos-calendar.sh +0 -232
  127. package/scripts/onboard-device.sh +0 -466
  128. package/server.js +0 -5131
  129. package/start.sh +0 -24
  130. package/templates/AGENTS.md +0 -548
  131. package/templates/IDENTITY.md +0 -15
  132. package/templates/docs-agents.html +0 -132
  133. package/templates/docs-app.html +0 -130
  134. package/templates/docs-home.html +0 -83
  135. package/templates/docs-imessage.html +0 -121
  136. package/templates/docs-tasks.html +0 -123
  137. package/templates/docs-tips.html +0 -175
  138. package/templates/getting-started.html +0 -809
  139. package/templates/invisible-prefix-base.txt +0 -171
  140. package/templates/invisible-prefix-owner.txt +0 -282
  141. package/templates/invisible-prefix.txt +0 -338
  142. package/templates/manifest.json +0 -61
  143. package/templates/memory-org/clients.md +0 -7
  144. package/templates/memory-org/credentials.md +0 -9
  145. package/templates/memory-org/devices.md +0 -7
  146. package/templates/updates.html +0 -464
  147. package/tts-proxy.js +0 -96
  148. package/voice-call-local.js +0 -731
  149. package/voice-call.js +0 -732
  150. 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}`));