ava-engine 0.0.0-stage → 0.1.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 (98) hide show
  1. package/.env.example +63 -0
  2. package/CLA.md +43 -0
  3. package/COMMERCIAL-LICENSE.md +43 -0
  4. package/LICENSE +73 -0
  5. package/README.md +238 -2
  6. package/THIRD_PARTY_NOTICES.md +38 -0
  7. package/TRADEMARKS.md +31 -0
  8. package/bin/ava-engine.mjs +12 -0
  9. package/lib/asr.mjs +143 -0
  10. package/lib/cli/config.mjs +95 -0
  11. package/lib/cli/main.mjs +152 -0
  12. package/lib/cli/setup.mjs +219 -0
  13. package/lib/fetch-models.mjs +104 -0
  14. package/lib/guard.mjs +92 -0
  15. package/lib/models.mjs +47 -0
  16. package/lib/openrouter.mjs +153 -0
  17. package/lib/ours.mjs +766 -0
  18. package/lib/platforms.mjs +201 -0
  19. package/lib/state.mjs +150 -0
  20. package/lib/stt.mjs +22 -0
  21. package/lib/tts.mjs +178 -0
  22. package/lib/workflow.mjs +18 -0
  23. package/package.json +72 -4
  24. package/public/app.js +1708 -0
  25. package/public/demo.js +420 -0
  26. package/public/favicon.svg +1 -0
  27. package/public/fonts/OFL.txt +96 -0
  28. package/public/fonts/inter-tight-var.woff2 +0 -0
  29. package/public/fonts/inter-var.woff2 +0 -0
  30. package/public/fonts/plex-mono-400.woff2 +0 -0
  31. package/public/fonts/plex-mono-500.woff2 +0 -0
  32. package/public/img/cta-1600.avif +0 -0
  33. package/public/img/cta-1600.webp +0 -0
  34. package/public/img/cta-2400.avif +0 -0
  35. package/public/img/cta-2400.webp +0 -0
  36. package/public/img/cta-960.avif +0 -0
  37. package/public/img/cta-960.webp +0 -0
  38. package/public/img/flows-1600.avif +0 -0
  39. package/public/img/flows-1600.webp +0 -0
  40. package/public/img/flows-2400.avif +0 -0
  41. package/public/img/flows-2400.webp +0 -0
  42. package/public/img/flows-960.avif +0 -0
  43. package/public/img/flows-960.webp +0 -0
  44. package/public/img/hero-1600.avif +0 -0
  45. package/public/img/hero-1600.webp +0 -0
  46. package/public/img/hero-2400.avif +0 -0
  47. package/public/img/hero-2400.webp +0 -0
  48. package/public/img/hero-960.avif +0 -0
  49. package/public/img/hero-960.webp +0 -0
  50. package/public/img/p-csm-480.avif +0 -0
  51. package/public/img/p-csm-480.webp +0 -0
  52. package/public/img/p-csm-800.avif +0 -0
  53. package/public/img/p-csm-800.webp +0 -0
  54. package/public/img/p-docs-480.avif +0 -0
  55. package/public/img/p-docs-480.webp +0 -0
  56. package/public/img/p-docs-800.avif +0 -0
  57. package/public/img/p-docs-800.webp +0 -0
  58. package/public/img/p-quiet-480.avif +0 -0
  59. package/public/img/p-quiet-480.webp +0 -0
  60. package/public/img/p-quiet-800.avif +0 -0
  61. package/public/img/p-quiet-800.webp +0 -0
  62. package/public/img/p-tickets-480.avif +0 -0
  63. package/public/img/p-tickets-480.webp +0 -0
  64. package/public/img/p-tickets-800.avif +0 -0
  65. package/public/img/p-tickets-800.webp +0 -0
  66. package/public/img/p-trial-480.avif +0 -0
  67. package/public/img/p-trial-480.webp +0 -0
  68. package/public/img/p-trial-800.avif +0 -0
  69. package/public/img/p-trial-800.webp +0 -0
  70. package/public/img/sees-1600.avif +0 -0
  71. package/public/img/sees-1600.webp +0 -0
  72. package/public/img/sees-2400.avif +0 -0
  73. package/public/img/sees-2400.webp +0 -0
  74. package/public/img/sees-960.avif +0 -0
  75. package/public/img/sees-960.webp +0 -0
  76. package/public/img/speaks-1600.avif +0 -0
  77. package/public/img/speaks-1600.webp +0 -0
  78. package/public/img/speaks-2400.avif +0 -0
  79. package/public/img/speaks-2400.webp +0 -0
  80. package/public/img/speaks-960.avif +0 -0
  81. package/public/img/speaks-960.webp +0 -0
  82. package/public/img/voice-1600.avif +0 -0
  83. package/public/img/voice-1600.webp +0 -0
  84. package/public/img/voice-2400.avif +0 -0
  85. package/public/img/voice-2400.webp +0 -0
  86. package/public/img/voice-960.avif +0 -0
  87. package/public/img/voice-960.webp +0 -0
  88. package/public/index.html +440 -0
  89. package/public/landing.html +975 -0
  90. package/public/pcm-worklet.js +11 -0
  91. package/public/perceptionWorker.js +103 -0
  92. package/public/rtc.js +60 -0
  93. package/public/specialist.html +92 -0
  94. package/public/specialist.js +132 -0
  95. package/public/style.css +836 -0
  96. package/public/vendor/lenis.min.js +3 -0
  97. package/scripts/fetch-models.sh +15 -0
  98. package/server.mjs +502 -0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,440 @@
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">
6
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml">
7
+ <base href="/">
8
+ <title>Ava · Live session</title>
9
+ <link rel="preload" href="/fonts/inter-tight-var.woff2" as="font" type="font/woff2" crossorigin>
10
+ <link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
11
+ <link rel="stylesheet" href="style.css">
12
+ </head>
13
+ <body class="screen-onboard">
14
+
15
+ <!-- ════════════════ ONBOARD SCREEN (pre-call) ════════════════ -->
16
+ <section id="onboard">
17
+ <!-- left brand panel -->
18
+ <aside class="ob-aside">
19
+ <div class="ob-abrand">
20
+ <svg class="wm" viewBox="0 0 66 27.8" role="img" aria-label="Ava"><path transform="translate(1.9 1.9)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" fill="none" stroke="currentColor" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
21
+ <span class="ob-toptag">Screen-aware voice agent</span>
22
+ </div>
23
+
24
+ <div class="ob-amid">
25
+ <h2>An assistant that sees your screen.</h2>
26
+ <p>Ava joins your call, watches the window you share, and helps you through whatever you're doing — live.</p>
27
+ <ul class="ob-features">
28
+ <li><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>Understands your screen as it changes, in real time</li>
29
+ <li><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>Natural voice that answers in under a second</li>
30
+ <li><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>Sees only the window you share — never the rest of your desktop</li>
31
+ </ul>
32
+ </div>
33
+
34
+ <div class="ob-preview">
35
+ <div class="ob-pvtop">
36
+ <span class="ob-pvava"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.6" stroke-linecap="round"><path transform="translate(2.67 8.4) scale(.3)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" stroke="#FFFFFF" fill="none" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
37
+ <span class="ob-pvid"><span class="ob-pvname">Ava</span><span class="ob-pvstatus">listening</span></span>
38
+ <span class="ob-pvwave"><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span>
39
+ </div>
40
+ <p class="ob-pvcap">"Looks like you're on the billing page — <b>want a hand adding credits?</b>"</p>
41
+ </div>
42
+ </aside>
43
+
44
+ <!-- right form panel -->
45
+ <div class="ob-form">
46
+ <div class="ob-panel">
47
+ <div class="ob-header">
48
+ <h1>Start a session</h1>
49
+ <p>Choose how Ava should work, then check your audio before connecting.</p>
50
+ </div>
51
+
52
+ <div class="ob-section">
53
+ <span class="ob-seclabel">Agent</span>
54
+ <div class="ob-modes" id="obModes"><!-- mode cards injected --></div>
55
+ <div class="ob-platwrap" id="obPlatformBlock" hidden>
56
+ <span class="ob-sublabel">Platform to onboard</span>
57
+ <div class="ob-plats" id="obPlats"><!-- platform cards injected --></div>
58
+ <p class="ob-platnote" id="obPlatNote"></p>
59
+ </div>
60
+ </div>
61
+
62
+ <div class="ob-divider"></div>
63
+
64
+ <div class="ob-section">
65
+ <span class="ob-seclabel">Audio &amp; recognition</span>
66
+ <div class="ob-gear">
67
+ <div class="ob-field">
68
+ <label class="ob-flabel" for="micsel">Microphone</label>
69
+ <div class="ob-fctl">
70
+ <select id="micsel" class="ob-select"><option value="">System default</option></select>
71
+ <button type="button" id="mictest" class="ob-ghost">Test</button>
72
+ </div>
73
+ <div class="miclevel" id="miclevel"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div>
74
+ </div>
75
+ <div class="ob-field">
76
+ <label class="ob-flabel" for="voicesel2">Ava's voice</label>
77
+ <div class="ob-fctl">
78
+ <select id="voicesel2" class="ob-select"></select>
79
+ <button type="button" id="voicetest" class="ob-ghost">Preview</button>
80
+ </div>
81
+ <span class="ob-fnote">Preview also warms the voice, so the call starts fast.</span>
82
+ </div>
83
+ <div class="ob-field ob-field-wide">
84
+ <label class="ob-flabel" for="sttsel">Speech recognition</label>
85
+ <select id="sttsel" class="ob-select"></select>
86
+ <span class="ob-fnote" id="sttnote">Choose before the call.</span>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ <div class="ob-footer">
92
+ <div class="ob-actions">
93
+ <button type="button" id="joinvoice" class="amberbtn ob-bigbtn">
94
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></svg>
95
+ Join with voice
96
+ </button>
97
+ <button type="button" id="jointext" class="ghostbtn ob-bigbtn">Join text-only</button>
98
+ <span class="ob-joinstate" id="joinstate"></span>
99
+ </div>
100
+ <p class="ob-noshare">Screen sharing needs a desktop browser. On this device Ava can still talk you through things and answer questions.</p>
101
+ <p class="ob-priv"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3 5 6v6c0 4.4 3 7.9 7 9 4-1.1 7-4.6 7-9V6l-7-3Z"/></svg> Ava only ever sees the single window you share — never the rest of your desktop.</p>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </section>
106
+
107
+ <!-- ════════════════ CONNECTING SCREEN ════════════════ -->
108
+ <!-- a short dark pre-roll that flows straight into the (dark) call stage -->
109
+ <section id="connecting">
110
+ <div class="cn-brand"><svg class="wm" viewBox="0 0 66 27.8" role="img" aria-label="Ava"><path transform="translate(1.9 1.9)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" fill="none" stroke="currentColor" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
111
+ <div class="cn-stage">
112
+ <span class="cn-rings" aria-hidden="true"><i></i><i></i><i></i>
113
+ <span class="cn-core"><svg width="34" height="34" viewBox="0 0 24 24" aria-hidden="true"><path transform="translate(2.67 8.4) scale(.3)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" stroke="#FFFFFF" fill="none" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
114
+ </span>
115
+ <canvas class="cn-wave" id="cnWave" aria-hidden="true"></canvas>
116
+ <h2 id="cnTitle">Connecting you to Ava…</h2>
117
+ <ol class="cn-steps" id="cnSteps">
118
+ <li data-step="session"><span class="cn-dot"></span>Opening the room</li>
119
+ <li data-step="voice"><span class="cn-dot"></span>Warming Ava's voice</li>
120
+ <li data-step="greet"><span class="cn-dot"></span>Ava is joining</li>
121
+ </ol>
122
+ </div>
123
+ <p class="cn-foot"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3 5 6v6c0 4.4 3 7.9 7 9 4-1.1 7-4.6 7-9V6l-7-3Z"/></svg>Ava only sees the window you choose to share.</p>
124
+ </section>
125
+
126
+ <!-- ════════════════ CALL UI ════════════════ -->
127
+ <header id="topbar">
128
+ <svg class="wm" viewBox="0 0 66 27.8" role="img" aria-label="Ava"><path transform="translate(1.9 1.9)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" fill="none" stroke="currentColor" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
129
+ <span class="vdiv"></span>
130
+ <span class="apptitle" id="apptitle">Flexible Agent</span>
131
+ <span class="mono meta hide-narrow" id="topsub">screen-aware assistant</span>
132
+ <span id="livepill" class="pill standby"><span class="dot"></span><span id="livepilltext">STANDBY</span></span>
133
+ <div class="grow"></div>
134
+ <span id="privacy" class="privacypill" hidden>
135
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#8B8880" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3 5 6v6c0 4.4 3 7.9 7 9 4-1.1 7-4.6 7-9V6l-7-3Z"/></svg>
136
+ <span>Ava sees only <b id="privwin">your window</b></span>
137
+ </span>
138
+ <span id="modelchip" class="chip mono hide-narrow">—</span>
139
+ <span id="timer" class="mono timer">00:00:00</span>
140
+ <button id="pipbtn" class="iconbtn sm" title="Pop out" aria-label="Pop out">
141
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><rect x="12" y="12" width="7" height="5" rx="1"/></svg>
142
+ </button>
143
+ </header>
144
+
145
+ <div id="main">
146
+
147
+ <!-- ── WORKFLOW TRACKER (left) ── -->
148
+ <aside id="workflow" hidden>
149
+ <div class="wf-head">
150
+ <div class="wf-titlerow"><span class="wf-title" id="wfTitle">Getting you set up</span><span class="mono wf-count" id="wfCount">—</span></div>
151
+ <div class="wf-bar"><div class="wf-fill" id="wfFill"></div></div>
152
+ <span class="mono wf-eta" id="wfEta"></span>
153
+ </div>
154
+ <div class="wf-steps" id="wfSteps"></div>
155
+ <div class="wf-foot">
156
+ <div class="wf-handoffbanner" id="wfHandoffBanner" hidden>
157
+ <span class="wf-spin" id="wfSpin"></span>
158
+ <div class="wf-hbcol">
159
+ <span class="wf-hbtext" id="wfHandoffText">Connecting you with a specialist…</span>
160
+ <button type="button" class="wf-hblink mono" id="wfHandoffLink" hidden></button>
161
+ </div>
162
+ </div>
163
+ <div class="wf-agent">
164
+ <span class="wf-agentava"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.6" stroke-linecap="round"><path transform="translate(2.67 8.4) scale(.3)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" stroke="#FFFFFF" fill="none" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
165
+ <div class="wf-agentid"><span class="wf-agentname">Ava is guiding you</span><span class="mono wf-agentstate" id="wfAgentState">connecting</span></div>
166
+ <span class="eq mini" id="wfEq"><i></i><i></i><i></i></span>
167
+ </div>
168
+ <span class="wf-know mono" id="wfKnow" hidden></span>
169
+ <button type="button" id="wfHandoff" class="wf-handoff">Talk to a person</button>
170
+ <p class="mono wf-priv">Ava only sees the window you share — nothing is recorded.</p>
171
+ </div>
172
+ </aside>
173
+
174
+ <!-- ── STAGE COLUMN ── -->
175
+ <main id="stagecol">
176
+
177
+ <!-- mini participant tiles (shown while sharing) -->
178
+ <div id="minitiles" hidden>
179
+ <div class="minitile ava" id="minitileAva">
180
+ <span class="miniicon amber"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.8" stroke-linecap="round"><path transform="translate(2.67 8.4) scale(.3)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" stroke="#FFFFFF" fill="none" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
181
+ <span class="minifoot"><span class="mininame">Ava</span><span class="eq mini" id="eqMini"><i></i><i></i><i></i></span></span>
182
+ </div>
183
+ <div class="minitile" id="minitileYou">
184
+ <span class="miniicon you">YOU</span>
185
+ <span class="minifoot"><span class="mininame dim">You</span><span class="minidot" id="miniShareDot"></span></span>
186
+ </div>
187
+ <div class="grow"></div>
188
+ <span class="mono meta" id="stagelabel">stage · nothing shared</span>
189
+ </div>
190
+
191
+ <!-- stage -->
192
+ <div id="stage">
193
+ <video id="video" autoplay muted playsinline></video>
194
+
195
+ <!-- Google-Meet-style presence grid (joined, not sharing) -->
196
+ <div id="meetgrid" hidden>
197
+ <div class="mtile ava" id="avaBig">
198
+ <span class="mt-badge mono">AVA</span>
199
+ <span class="mt-rethink" id="avaRethink" hidden><i></i>rethinking</span>
200
+ <span class="mt-orb" id="avaOrb" aria-hidden="true"><i></i><i></i><span class="mt-orbcore"><svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.4" stroke-linecap="round"><path transform="translate(2.67 8.4) scale(.3)" d="M0 24L9.5 0L19 24M21.6 0L31.1 24L40.6 0M43.2 24L52.7 0L62.2 24" stroke="#FFFFFF" fill="none" stroke-width="3.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span></span>
201
+ <div class="mt-foot">
202
+ <span class="mt-name">Ava</span>
203
+ <span class="mono mt-status" id="avastatusBig">joining…</span>
204
+ <span class="eq big" id="eqBig"><i></i><i></i><i></i><i></i><i></i></span>
205
+ </div>
206
+ </div>
207
+ <div class="mtile you" id="youBig">
208
+ <span class="mt-badge mono">YOU</span>
209
+ <span class="mt-avatar" id="youAvatar"><span class="mt-level" id="youLevel"></span>YOU</span>
210
+ <div class="mt-foot">
211
+ <span class="mt-name dim">You</span>
212
+ <span class="mono mt-status" id="youstatusBig">mic ready</span>
213
+ </div>
214
+ <button type="button" id="meetShare" class="ghostamber mt-share">
215
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8 21h8M12 17v4M12 12.5V7.5M9.5 10 12 7.5l2.5 2.5"/></svg>
216
+ Share a window
217
+ </button>
218
+ </div>
219
+ </div>
220
+
221
+ <!-- Ava's attention callout -->
222
+ <span id="callout" class="callout" hidden><span class="cdot"></span><span class="mono" id="callouttext"></span></span>
223
+ </div>
224
+
225
+ <!-- live caption -->
226
+ <div id="capwrap" hidden>
227
+ <span class="avarow">
228
+ <span class="mono avalabel">AVA</span>
229
+ <span class="eq" id="eqCap"><i></i><i></i><i></i><i></i><i></i></span>
230
+ </span>
231
+ <p id="cap" aria-live="polite"></p>
232
+ </div>
233
+
234
+ <!-- composer -->
235
+ <div id="composerwrap">
236
+ <form id="composer">
237
+ <input id="input" type="text" placeholder="Tell Ava what you're working on…" aria-label="Message Ava" autocomplete="off">
238
+ <span class="kbd mono">⌘K</span>
239
+ </form>
240
+ <button type="button" id="mic" class="iconbtn lg" title="Talk" aria-label="Talk to Ava">
241
+ <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></svg>
242
+ </button>
243
+ <button type="button" id="sharemain" class="amberbtn">Share a window</button>
244
+ </div>
245
+ </main>
246
+
247
+ <!-- ── SIDE PANEL (transcript / captions) ── -->
248
+ <aside id="people">
249
+ <div class="railhead"><span class="mono sectionlabel">LIVE TRANSCRIPT</span><button type="button" id="agentlog" class="mono railbtn on">agents on</button></div>
250
+ <div id="transcript" role="log" aria-label="Transcript"></div>
251
+
252
+ <!-- hidden presence mirrors (kept for state wiring; presence shows on the stage) -->
253
+ <div class="tile ava" id="avatile" hidden>
254
+ <div class="tilefoot"><div class="tileid"><span class="tilename">Ava</span><span class="mono tilestatus" id="avastatus">standby</span></div><span class="eq big" id="eqTile"><i></i><i></i><i></i><i></i><i></i></span></div>
255
+ </div>
256
+ <div class="tile" id="youtile" hidden>
257
+ <div class="tiletop"><span class="chip mono sm green" id="youshare" hidden><span class="gdot"></span>sharing</span></div>
258
+ <div class="tilefoot"><div class="tileid"><span class="tilename dim">You</span><span class="mono tilestatus" id="youmic">mic off</span></div></div>
259
+ </div>
260
+ </aside>
261
+
262
+ <!-- ── CONSOLE DRAWER ── -->
263
+ <aside id="console" hidden>
264
+ <div class="conhead">
265
+ <span class="conheadleft"><span class="mono conlabel">CONSOLE</span><span class="mono meta" id="conturn">turn 0 · —</span></span>
266
+ <button type="button" id="conclose" class="iconbtn xs" aria-label="Close console">
267
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"><path d="m7 7 10 10M17 7 7 17"/></svg>
268
+ </button>
269
+ </div>
270
+
271
+ <!-- trace -->
272
+ <div class="consec trace">
273
+ <div class="tracehead">
274
+ <div class="tracebig">
275
+ <span class="mono sectionlabel" id="tracelabel">END-TO-END</span>
276
+ <div class="bignum">
277
+ <span id="bigLat" class="null">—.——</span><span class="unit">s</span>
278
+ <span class="mono delta" id="latDelta"></span>
279
+ </div>
280
+ </div>
281
+ <div class="spark" id="spark"></div>
282
+ </div>
283
+ <div class="lanebar" id="lanebar"><div class="laneempty"></div></div>
284
+ <div class="axis mono"><span>0</span><span id="ax1">0.4s</span><span id="ax2">0.8s</span><span id="ax3">1.2s</span></div>
285
+ </div>
286
+
287
+ <!-- crew -->
288
+ <div class="consec crew">
289
+ <div class="crewhead"><span class="mono sectionlabel">CREW</span><span class="mono meta" id="crewcount">0 / 5 RUNNING</span></div>
290
+ <div class="crewrow" id="row-vision"><span class="ldot vision"></span><span class="lname">Vision</span><span class="mono lstate" id="st-vision">waiting for a window</span><span class="mono lms" id="ms-vision">—</span><span class="mono lcalls" id="ca-vision"></span></div>
291
+ <div class="crewrow" id="row-intent"><span class="ldot intent"></span><span class="lname">Intent</span><span class="mono lstate" id="st-intent">waiting for input</span><span class="mono lms" id="ms-intent">—</span><span class="mono lcalls" id="ca-intent"></span></div>
292
+ <div class="crewrow" id="row-router"><span class="ldot router"></span><span class="lname">Router</span><span class="mono lstate" id="st-router">idle</span><span class="mono lms" id="ms-router">—</span><span class="mono lcalls" id="ca-router"></span></div>
293
+ <div class="crewrow" id="row-planner"><span class="ldot planner"></span><span class="lname">Planner</span><span class="mono lstate" id="st-planner">no threads</span><span class="mono lms" id="ms-planner">—</span><span class="mono lcalls" id="ca-planner"></span></div>
294
+ <div class="crewrow" id="row-voice"><span class="ldot voice"></span><span class="lname">Voice</span><span class="mono lstate" id="st-voice">muted</span><span class="mono lms" id="ms-voice">—</span><span class="mono lcalls" id="ca-voice"></span></div>
295
+ </div>
296
+
297
+ <!-- compiled context -->
298
+ <div class="consec ctx">
299
+ <div class="ctxhead"><span class="mono sectionlabel">COMPILED CONTEXT</span><span class="mono" id="ctxtok"><b>—</b> <span class="meta">/ 32k</span></span></div>
300
+ <div class="ctxmeter" id="ctxmeter"><div class="seg sys" style="width:0%"></div><div class="seg screen" style="width:0%"></div><div class="seg talk" style="width:0%"></div></div>
301
+ <div class="ctxlegend mono">
302
+ <span><i class="sq metabg"></i>system</span>
303
+ <span><i class="sq visionbg"></i>screen</span>
304
+ <span><i class="sq intentbg"></i>conversation</span>
305
+ </div>
306
+ <pre id="ctxtext" class="mono">— no turns yet —</pre>
307
+ </div>
308
+
309
+ <!-- spend -->
310
+ <div class="consec spendrow">
311
+ <div class="spendcol">
312
+ <span class="mono sectionlabel">SPEND</span>
313
+ <span class="spendnum null" id="spend">$0.0000</span>
314
+ <span class="mono meta" id="spendrate">$0.000 / hr</span>
315
+ </div>
316
+ <div class="spendcol">
317
+ <span class="mono sectionlabel">GOAL</span>
318
+ <span class="goaltext" id="goal">—</span>
319
+ </div>
320
+ </div>
321
+
322
+ <!-- status strip -->
323
+ <div class="constrip mono">
324
+ <span>TURNS <b id="sTurns">0</b></span>
325
+ <span>TOK <b id="sTok">0</b></span>
326
+ <span>AVG <b id="sAvg">—</b></span>
327
+ <span>VISION <b id="sVision">0/0</b></span>
328
+ <div class="grow"></div>
329
+ <span class="health" id="health"><span class="hdot"></span><span id="healthtext">READY</span></span>
330
+ </div>
331
+ </aside>
332
+ </div>
333
+
334
+ <!-- ── CONTROL BAR ── -->
335
+ <footer id="controlbar">
336
+ <div class="footleft">
337
+ <span class="mono footline" id="footmode">recording off · transcript on</span>
338
+ <span class="mono footline dim">voice out · <select id="voicesel" class="mono" aria-label="Ava's voice"></select></span>
339
+ </div>
340
+
341
+ <div class="footcenter">
342
+ <button type="button" id="mic2" class="ctlbtn" title="Talk" aria-label="Talk to Ava">
343
+ <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3"/></svg>
344
+ </button>
345
+ <button type="button" id="share" class="ctlbtn wide" title="Share screen">
346
+ <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8 21h8M12 17v4M12 12.5V7.5M9.5 10 12 7.5l2.5 2.5"/></svg>
347
+ <span id="sharelabel">Share a window</span>
348
+ </button>
349
+ <button type="button" id="ccbtn" class="ctlbtn on" title="Captions" aria-pressed="true" aria-label="Toggle captions">
350
+ <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="5" width="19" height="14" rx="2.5"/><path d="M10 10.5a2.8 2.8 0 1 0 0 3M17.5 10.5a2.8 2.8 0 1 0 0 3"/></svg>
351
+ </button>
352
+ <button type="button" id="speakbtn" class="ctlbtn on" title="Ava's voice" aria-pressed="true" aria-label="Toggle Ava's voice">
353
+ <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"><path d="M11.5 4.5 6.8 8.6H3.2v6.8h3.6l4.7 4.1V4.5Z"/><path d="M15.4 9.6a3.6 3.6 0 0 1 0 4.8"/><path d="M18 7a7 7 0 0 1 0 10"/></svg>
354
+ </button>
355
+ <input type="checkbox" id="speak" checked hidden>
356
+ </div>
357
+
358
+ <div class="footright">
359
+ <button type="button" id="consolebtn" class="utilbtn">
360
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7.5 8 12l-4 4.5M11 16.5h9"/></svg>
361
+ <span class="mono">Console</span>
362
+ <span class="kbd mono">⌘\</span>
363
+ </button>
364
+ <button type="button" id="endcall" class="leavebtn" disabled>
365
+ <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"><path d="M3.5 14.5c5.5-5 11.5-5 17 0l.5-3c-6-5.5-12-5.5-18 0Z"/></svg>
366
+ Leave
367
+ </button>
368
+ </div>
369
+ </footer>
370
+
371
+ <!-- ════════════════ SESSION REPORT (after Leave) ════════════════ -->
372
+ <div id="report" hidden>
373
+ <div class="rep-card">
374
+ <div class="rep-head">
375
+ <div class="rep-titleblock">
376
+ <span class="mono repeyebrow">SESSION RECAP</span>
377
+ <h2 id="repHeadline">Session complete</h2>
378
+ </div>
379
+ <div class="rep-headmeta">
380
+ <span class="mono" id="repDur">00:00</span>
381
+ <button id="repClose" class="iconbtn xs" aria-label="Close"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"><path d="m7 7 10 10M17 7 7 17"/></svg></button>
382
+ </div>
383
+ </div>
384
+
385
+ <div class="rep-body">
386
+ <div class="rep-left">
387
+ <p id="repSummary" class="rep-summary">Preparing your recap…</p>
388
+ <ul id="repHighlights" class="rep-highlights"></ul>
389
+ <div class="rep-stats" id="repStats"></div>
390
+ </div>
391
+ <div class="rep-right">
392
+ <div class="rep-flowhead mono">HOW THE AGENTS WORKED TOGETHER</div>
393
+ <div class="flow" id="flow">
394
+ <svg class="flow-conn" viewBox="0 0 100 100" preserveAspectRatio="none">
395
+ <line x1="10.5" y1="25" x2="10.5" y2="46"/><line x1="30" y1="25" x2="30" y2="46"/>
396
+ <line x1="50" y1="25" x2="50" y2="46"/><line x1="69.5" y1="25" x2="69.5" y2="46"/>
397
+ <line x1="88.5" y1="25" x2="88.5" y2="46"/><line x1="50" y1="59" x2="50" y2="77"/>
398
+ </svg>
399
+ <div class="fnode vision" id="fn-vision"><b>Perception</b><span>vision</span><em class="fcount" id="fc-vision">0</em></div>
400
+ <div class="fnode intent" id="fn-intent"><b>Intent</b><span>read</span><em class="fcount" id="fc-intent">0</em></div>
401
+ <div class="fnode router" id="fn-router"><b>Router</b><span>code</span><em class="fcount" id="fc-router">0</em></div>
402
+ <div class="fnode planner" id="fn-planner"><b>Planner</b><span>async</span><em class="fcount" id="fc-planner">0</em></div>
403
+ <div class="fnode voice" id="fn-voice"><b>Talker</b><span>speaks</span><em class="fcount" id="fc-voice">0</em></div>
404
+ <div class="fnode bb" id="fn-bb"><b>Compiled context — blackboard</b></div>
405
+ <div class="fnode usern" id="fn-user"><b>User</b><span>voice + screen</span></div>
406
+ </div>
407
+
408
+ <!-- detailed, timestamped agent timeline (Gantt) -->
409
+ <div class="rep-flowhead mono" style="margin-top:4px">WHERE THE TIME WENT — TIMESTAMPED</div>
410
+ <div class="gantt" id="gantt">
411
+ <div class="gantt-rows" id="ganttRows"></div>
412
+ <div class="gantt-axis mono" id="ganttAxis"></div>
413
+ <div class="gantt-head" id="ganttHead"></div>
414
+ </div>
415
+ </div>
416
+ </div>
417
+
418
+ <div class="rep-replay">
419
+ <button id="repPlay" class="amberbtn"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg> Play replay</button>
420
+ <div class="rep-tlwrap">
421
+ <div class="rep-timeline" id="repTimeline"><div class="rep-progress" id="repProgress"></div><div class="rep-playhead" id="repPlayhead"></div></div>
422
+ <div class="rep-now mono" id="repNow">Press play to watch the session unfold, agent by agent.</div>
423
+ </div>
424
+ </div>
425
+
426
+ <div class="rep-foot">
427
+ <span class="mono meta" id="repFootnote">Screen-record this replay for a tech review.</span>
428
+ <button id="repNew" class="ghostbtn">New session</button>
429
+ </div>
430
+ </div>
431
+ </div>
432
+
433
+ <canvas id="capcanvas" hidden></canvas>
434
+ <canvas id="hashcanvas" hidden></canvas>
435
+ <audio id="rtcAudio" autoplay></audio>
436
+ <script src="rtc.js"></script>
437
+ <script src="app.js"></script>
438
+ <script src="demo.js"></script>
439
+ </body>
440
+ </html>