arcane-os 0.1.0-dev.5

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 (248) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/COMMERCIAL-LICENSE.md +13 -0
  3. package/LICENSE +661 -0
  4. package/NOTICE +70 -0
  5. package/README.md +448 -0
  6. package/bin/arcane-test.mjs +741 -0
  7. package/bin/arcane.mjs +5 -0
  8. package/docs/architecture.md +234 -0
  9. package/docs/compatibility.md +36 -0
  10. package/docs/event-manager.md +166 -0
  11. package/docs/platform-targets.md +108 -0
  12. package/docs/publishing.md +203 -0
  13. package/docs/reference/README.md +117 -0
  14. package/docs/reference/arcane-ollama.md +288 -0
  15. package/docs/reference/availability-and-normalization.md +123 -0
  16. package/docs/reference/behavioral-testing.md +86 -0
  17. package/docs/reference/cli.md +569 -0
  18. package/docs/reference/core/README.md +62 -0
  19. package/docs/reference/core/arcane-ai-contracts.md +873 -0
  20. package/docs/reference/core/arcane-api.md +601 -0
  21. package/docs/reference/core/arcane-entities.md +65 -0
  22. package/docs/reference/core/arcane-events.md +134 -0
  23. package/docs/reference/core/ollama-module.md +181 -0
  24. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  25. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  26. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  27. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  28. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  29. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  30. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  31. package/docs/reference/event-manager.md +957 -0
  32. package/docs/reference/inventory/package-api.json +2632 -0
  33. package/docs/reference/inventory/runtime-components.json +934 -0
  34. package/docs/reference/inventory/runtime-entities.json +26 -0
  35. package/docs/reference/inventory/runtime-modules.json +1249 -0
  36. package/docs/reference/protocols.md +242 -0
  37. package/docs/reference/runtime-components.md +1098 -0
  38. package/docs/reference/runtime-entities.md +303 -0
  39. package/docs/reference/runtime-modules.md +2010 -0
  40. package/docs/reference/sdk-api.md +4901 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +124 -0
  43. package/node_modules/event-pubsub/CHANGELOG.md +55 -0
  44. package/node_modules/event-pubsub/MIGRATION.md +70 -0
  45. package/node_modules/event-pubsub/README.md +363 -0
  46. package/node_modules/event-pubsub/SECURITY.md +37 -0
  47. package/node_modules/event-pubsub/index.js +141 -0
  48. package/node_modules/event-pubsub/licence +21 -0
  49. package/node_modules/event-pubsub/package.json +59 -0
  50. package/node_modules/strong-type/README.md +408 -0
  51. package/node_modules/strong-type/assets/strong-type-header.png +0 -0
  52. package/node_modules/strong-type/index.js +1151 -0
  53. package/node_modules/strong-type/licence +21 -0
  54. package/node_modules/strong-type/node.js +125 -0
  55. package/node_modules/strong-type/package.json +61 -0
  56. package/package.json +95 -0
  57. package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
  58. package/runtime/arcane/components/app-bar.html +468 -0
  59. package/runtime/arcane/components/assistant-panel.html +715 -0
  60. package/runtime/arcane/components/calculator.html +8 -0
  61. package/runtime/arcane/components/chart.html +655 -0
  62. package/runtime/arcane/components/chat.html +1225 -0
  63. package/runtime/arcane/components/conversation-view.html +13 -0
  64. package/runtime/arcane/components/dashboard-config.html +341 -0
  65. package/runtime/arcane/components/data-maintenance.html +112 -0
  66. package/runtime/arcane/components/data-view.html +92 -0
  67. package/runtime/arcane/components/directory-picker.html +197 -0
  68. package/runtime/arcane/components/document-inspector.html +252 -0
  69. package/runtime/arcane/components/file-drop.html +264 -0
  70. package/runtime/arcane/components/file-inspector.html +293 -0
  71. package/runtime/arcane/components/file-manager.html +1715 -0
  72. package/runtime/arcane/components/header.html +142 -0
  73. package/runtime/arcane/components/integration-settings.html +14 -0
  74. package/runtime/arcane/components/local-ai-status.html +360 -0
  75. package/runtime/arcane/components/markdown-document.html +1048 -0
  76. package/runtime/arcane/components/markdown-editor.html +360 -0
  77. package/runtime/arcane/components/media-embed.html +8 -0
  78. package/runtime/arcane/components/modal.html +402 -0
  79. package/runtime/arcane/components/output-panel.html +259 -0
  80. package/runtime/arcane/components/preferences-form.html +135 -0
  81. package/runtime/arcane/components/record-timeline.html +105 -0
  82. package/runtime/arcane/components/relationship-board.html +116 -0
  83. package/runtime/arcane/components/screen-capture.html +8 -0
  84. package/runtime/arcane/components/source-code-viewer.html +441 -0
  85. package/runtime/arcane/components/source-explanation.html +124 -0
  86. package/runtime/arcane/components/speech.html +365 -0
  87. package/runtime/arcane/components/summary-strip.html +177 -0
  88. package/runtime/arcane/components/table.html +77 -0
  89. package/runtime/arcane/components/task-progress.html +282 -0
  90. package/runtime/arcane/components/terminal-workspace.html +65 -0
  91. package/runtime/arcane/components/theme-editor.html +41 -0
  92. package/runtime/arcane/components/theme-switcher.html +46 -0
  93. package/runtime/arcane/components/unified-inbox.html +20 -0
  94. package/runtime/arcane/components/voice-transcription.html +476 -0
  95. package/runtime/arcane/components/weather-widget.html +8 -0
  96. package/runtime/arcane/components/web-navigator.html +239 -0
  97. package/runtime/arcane/css/communications.css +1 -0
  98. package/runtime/arcane/css/dashboard-config.css +45 -0
  99. package/runtime/arcane/css/document-site.css +981 -0
  100. package/runtime/arcane/css/layout.css +438 -0
  101. package/runtime/arcane/css/primitives.css +321 -0
  102. package/runtime/arcane/css/theme.css +112 -0
  103. package/runtime/arcane/css/utility-workspace.css +1 -0
  104. package/runtime/arcane/entities/ApiModelRecord.js +20 -0
  105. package/runtime/arcane/entities/Calculation.js +13 -0
  106. package/runtime/arcane/entities/Chat.js +581 -0
  107. package/runtime/arcane/entities/CommunicationMessage.js +29 -0
  108. package/runtime/arcane/entities/CommunicationThread.js +21 -0
  109. package/runtime/arcane/entities/Document.js +10 -0
  110. package/runtime/arcane/entities/File.js +143 -0
  111. package/runtime/arcane/entities/Image.js +135 -0
  112. package/runtime/arcane/entities/IntentEnvelope.js +834 -0
  113. package/runtime/arcane/entities/Preference.js +83 -0
  114. package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
  115. package/runtime/arcane/entities/TerminalSession.js +46 -0
  116. package/runtime/arcane/entities/Theme.js +107 -0
  117. package/runtime/arcane/entities/User.js +1046 -0
  118. package/runtime/arcane/entities/Weather.js +23 -0
  119. package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
  120. package/runtime/arcane/img/arrow-left.png +0 -0
  121. package/runtime/arcane/img/arrow-right.png +0 -0
  122. package/runtime/arcane/img/doc.svg +5 -0
  123. package/runtime/arcane/img/folder.svg +4 -0
  124. package/runtime/arcane/img/image.svg +5 -0
  125. package/runtime/arcane/img/refresh.png +0 -0
  126. package/runtime/arcane/img/send.svg +9 -0
  127. package/runtime/arcane/img/trash.svg +5 -0
  128. package/runtime/arcane/img/upload.svg +5 -0
  129. package/runtime/arcane/modules/AI.js +2048 -0
  130. package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
  131. package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
  132. package/runtime/arcane/modules/AIResponseLength.js +42 -0
  133. package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
  134. package/runtime/arcane/modules/AnsiText.js +53 -0
  135. package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
  136. package/runtime/arcane/modules/AppDataScope.js +245 -0
  137. package/runtime/arcane/modules/AppearancePreferences.js +28 -0
  138. package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
  139. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
  140. package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
  141. package/runtime/arcane/modules/AsyncBoundary.js +161 -0
  142. package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
  143. package/runtime/arcane/modules/CalculatorEngine.js +20 -0
  144. package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
  145. package/runtime/arcane/modules/ChartLibrary.js +35 -0
  146. package/runtime/arcane/modules/ChatRecords.js +13 -0
  147. package/runtime/arcane/modules/CommunicationAppController.js +43 -0
  148. package/runtime/arcane/modules/CommunicationHub.js +16 -0
  149. package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
  150. package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
  151. package/runtime/arcane/modules/ComponentContracts.js +586 -0
  152. package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
  153. package/runtime/arcane/modules/ConversationActionItems.js +488 -0
  154. package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
  155. package/runtime/arcane/modules/ConversationTimebox.js +527 -0
  156. package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
  157. package/runtime/arcane/modules/DBLS.js +171 -0
  158. package/runtime/arcane/modules/DBOPFS.js +1154 -0
  159. package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
  160. package/runtime/arcane/modules/DataMaintenance.js +91 -0
  161. package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
  162. package/runtime/arcane/modules/DirectoryPicker.js +109 -0
  163. package/runtime/arcane/modules/DocumentNavigation.js +223 -0
  164. package/runtime/arcane/modules/Errors.js +1025 -0
  165. package/runtime/arcane/modules/GifEncoder.js +29 -0
  166. package/runtime/arcane/modules/HTMLImport.js +114 -0
  167. package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
  168. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
  169. package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
  170. package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
  171. package/runtime/arcane/modules/MD.js +111 -0
  172. package/runtime/arcane/modules/Mail.js +352 -0
  173. package/runtime/arcane/modules/MailTransport.mjs +180 -0
  174. package/runtime/arcane/modules/Marked.min.js +71 -0
  175. package/runtime/arcane/modules/MemoryRecords.js +44 -0
  176. package/runtime/arcane/modules/MessageAdvisory.js +38 -0
  177. package/runtime/arcane/modules/ModelDefinition.js +189 -0
  178. package/runtime/arcane/modules/Ollama.js +74 -0
  179. package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
  180. package/runtime/arcane/modules/OllamaSettings.js +24 -0
  181. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
  182. package/runtime/arcane/modules/PreferenceStore.js +109 -0
  183. package/runtime/arcane/modules/QRCode.min.js +1 -0
  184. package/runtime/arcane/modules/Questionnaire.js +61 -0
  185. package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
  186. package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
  187. package/runtime/arcane/modules/RecordReviewStore.js +94 -0
  188. package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
  189. package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
  190. package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
  191. package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
  192. package/runtime/arcane/modules/ScreenCapture.js +20 -0
  193. package/runtime/arcane/modules/SpeechPlayback.js +581 -0
  194. package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
  195. package/runtime/arcane/modules/SystemAppearance.js +20 -0
  196. package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
  197. package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
  198. package/runtime/arcane/modules/TerminalClient.js +52 -0
  199. package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
  200. package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
  201. package/runtime/arcane/modules/ThemeManager.js +131 -0
  202. package/runtime/arcane/modules/TimeGuard.js +149 -0
  203. package/runtime/arcane/modules/ToolCallRouter.js +83 -0
  204. package/runtime/arcane/modules/WaitForComponent.js +102 -0
  205. package/runtime/arcane/modules/YouTubeMedia.js +16 -0
  206. package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
  207. package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
  208. package/runtime/arcane/modules/uPlot.min.css +1 -0
  209. package/runtime/arcane/security/arcane-network-policy.json +6 -0
  210. package/runtime/strong-type/index.js +352 -0
  211. package/runtime/strong-type/licence +21 -0
  212. package/runtime/strong-type/package.json +45 -0
  213. package/schemas/arcane-app-bundle.schema.json +125 -0
  214. package/schemas/arcane-app.schema.json +329 -0
  215. package/schemas/arcane-lock.schema.json +86 -0
  216. package/schemas/arcane-package.schema.json +224 -0
  217. package/schemas/cli-event.schema.json +122 -0
  218. package/schemas/event-stack.schema.json +152 -0
  219. package/schemas/native-build-plan.schema.json +176 -0
  220. package/schemas/target-adapter.schema.json +117 -0
  221. package/src/app-descriptor.mjs +500 -0
  222. package/src/cli/main.mjs +561 -0
  223. package/src/constants.mjs +31 -0
  224. package/src/dev-server.mjs +718 -0
  225. package/src/doctor.mjs +315 -0
  226. package/src/dom-event-instrumentation.mjs +594 -0
  227. package/src/errors.mjs +75 -0
  228. package/src/event-manager.mjs +1342 -0
  229. package/src/event-queue.mjs +138 -0
  230. package/src/events.mjs +219 -0
  231. package/src/index.mjs +177 -0
  232. package/src/integrated-provider-loader.mjs +432 -0
  233. package/src/native-plan.mjs +698 -0
  234. package/src/native-provider-loader.mjs +1126 -0
  235. package/src/packager/core.mjs +2691 -0
  236. package/src/process.mjs +353 -0
  237. package/src/release-bundle.mjs +2523 -0
  238. package/src/repository.mjs +90 -0
  239. package/src/runtime.mjs +452 -0
  240. package/src/scaffold.mjs +380 -0
  241. package/src/targets/index.mjs +436 -0
  242. package/src/templates/assets/app-icon.png +0 -0
  243. package/src/templates/workspace-template.mjs +388 -0
  244. package/src/testing-loader.mjs +9 -0
  245. package/src/testing.mjs +427 -0
  246. package/src/toolchain.mjs +1335 -0
  247. package/src/update-check.mjs +307 -0
  248. package/src/workspace.mjs +449 -0
@@ -0,0 +1,365 @@
1
+ <link rel="stylesheet" href="./arcane/css/layout.css?v=3" />
2
+ <style>
3
+ button{
4
+ width:16em;
5
+ -webkit-touch-callout: none;
6
+ -webkit-user-select: none;
7
+ -khtml-user-select: none;
8
+ -moz-user-select: none;
9
+ -ms-user-select: none;
10
+ user-select: none;
11
+ }
12
+
13
+ button:active{
14
+ opacity:.5;
15
+ }
16
+
17
+ button.pressed{
18
+ opacity:.6;
19
+ border:.2em;
20
+ border-color:var(--border-color);
21
+ }
22
+
23
+ .end{
24
+ background-color:var(--danger-color);
25
+ margin-left:1em;
26
+ }
27
+
28
+ .mute{
29
+ float:right;
30
+ }
31
+
32
+ @media (max-width: 48em) {
33
+ body {
34
+ grid-template-columns: 2.2em 1fr;
35
+ }
36
+
37
+ button {
38
+ width:100%;
39
+ }
40
+
41
+ .end{
42
+ margin:0;
43
+ }
44
+ }
45
+
46
+
47
+ </style>
48
+
49
+ <p class="hidden">Will auto send after X seconds of silence set in code.</p>
50
+ <button id="recordButton" type="button">Push To Talk</button>
51
+ <button id="stopButton" type="button" class='hidden' disabled>Send</button>
52
+ <button id="endButton" type="button" class="end">Complete</button>
53
+ <button id="muteButton" type="button" class="mute" aria-pressed="true" aria-label="Unmute AI voice">Unmute</button>
54
+
55
+ <script type="module">
56
+ import('../modules/DBLS.js');
57
+ import('../modules/AI.js?v=7');
58
+
59
+ const audioElement = new Audio();
60
+ const host=this;
61
+ const shadowRoot=host.shadowRoot;
62
+ const recordButton = shadowRoot.querySelector('#recordButton');
63
+ const stopButton = shadowRoot.querySelector('#stopButton');
64
+ const muteButton = shadowRoot.querySelector('#muteButton');
65
+ const sourceNodes = [];
66
+ const audioRecordingChunks=[];
67
+ const silenceDuration=0;//2000;
68
+
69
+ let mediaRecorder=null;
70
+ let activeStream=null;
71
+ let audioMessageChunks = '';
72
+ let isSpeaking = false;
73
+ let silenceTimer;
74
+
75
+ /**
76
+ * Configure the initial AI speech state. The default remains muted for
77
+ * compatibility with existing consumers. Apps own preference persistence.
78
+ */
79
+ host.initialMuted=typeof host.initialMuted==='boolean'?host.initialMuted:true;
80
+ host.muted=host.initialMuted;
81
+ host.configure=configure;
82
+ host.setAvailability=setAvailability;
83
+ host.setMuted=setMuted;
84
+ host.availability={
85
+ microphone:Boolean(navigator.mediaDevices?.getUserMedia&&globalThis.MediaRecorder),
86
+ stt:true,
87
+ tts:true
88
+ };
89
+ setAvailability({});
90
+ setMuted(host.initialMuted);
91
+ void observeMicrophonePermission();
92
+ host.componentReady=true;
93
+ host.dispatchEvent(new CustomEvent('speech-ready',{
94
+ bubbles:true,
95
+ composed:true,
96
+ detail:{speech:host}
97
+ }));
98
+
99
+ recordButton.addEventListener(
100
+ 'mousedown',
101
+ record
102
+ );
103
+
104
+ recordButton.addEventListener(
105
+ 'touchstart',
106
+ record
107
+ );
108
+
109
+ recordButton.addEventListener(
110
+ 'mouseup',
111
+ stop
112
+ );
113
+
114
+ recordButton.addEventListener(
115
+ 'touchend',
116
+ stop
117
+ );
118
+
119
+ // recordButton.addEventListener(
120
+ // 'click',
121
+ // record
122
+ // );
123
+
124
+ // stopButton.addEventListener(
125
+ // 'click',
126
+ // stop
127
+ // );
128
+
129
+ muteButton.addEventListener(
130
+ 'click',
131
+ muteToggle
132
+ );
133
+
134
+ shadowRoot.querySelector('#endButton').addEventListener(
135
+ 'click',
136
+ function submitCompletionCommand(event){
137
+ event.target.disabled=true;
138
+ transcribe('End now, run all tool functions.');
139
+ }
140
+ );
141
+
142
+ window.addEventListener(
143
+ 'ai-ready',
144
+ function aiReadyHandler(){
145
+ setMuted(host.muted);
146
+ }
147
+ );
148
+
149
+ if(window.ai?.ready){
150
+ setMuted(host.muted);
151
+ }
152
+
153
+ function configure(options={}){
154
+ if(Object.prototype.hasOwnProperty.call(options,'initialMuted')){
155
+ if(typeof options.initialMuted!=='boolean'){
156
+ throw new TypeError('initialMuted must be boolean');
157
+ }
158
+
159
+ host.initialMuted=options.initialMuted;
160
+ setMuted(host.initialMuted);
161
+ }
162
+
163
+ if(
164
+ Object.prototype.hasOwnProperty.call(options,'stt')
165
+ ||Object.prototype.hasOwnProperty.call(options,'tts')
166
+ ||Object.prototype.hasOwnProperty.call(options,'microphone')
167
+ ){
168
+ setAvailability(options);
169
+ }
170
+
171
+ return host;
172
+ }
173
+
174
+ function setAvailability(input={}){
175
+ const availability={
176
+ microphone:Object.prototype.hasOwnProperty.call(input,'microphone')
177
+ ?Boolean(input.microphone)
178
+ :host.availability.microphone,
179
+ stt:Object.prototype.hasOwnProperty.call(input,'stt')
180
+ ?Boolean(input.stt)
181
+ :host.availability.stt,
182
+ tts:Object.prototype.hasOwnProperty.call(input,'tts')
183
+ ?Boolean(input.tts)
184
+ :host.availability.tts
185
+ };
186
+
187
+ host.availability=availability;
188
+ recordButton.disabled=!availability.stt||!availability.microphone;
189
+ stopButton.disabled=recordButton.disabled;
190
+ recordButton.title=!availability.stt
191
+ ?'The selected transcription service is unavailable.'
192
+ :!availability.microphone
193
+ ?'Microphone access is unavailable. Text chat is still available.'
194
+ :'Push to talk';
195
+ recordButton.setAttribute('aria-label',recordButton.title);
196
+ muteButton.disabled=!availability.tts;
197
+
198
+ if(!availability.tts){
199
+ muteButton.textContent='Voice unavailable';
200
+ muteButton.setAttribute('aria-label','Selected speech service unavailable');
201
+ if(window.ai){
202
+ window.ai.muted=true;
203
+ window.ai.stopAudio?.();
204
+ }
205
+ }else{
206
+ setMuted(host.muted);
207
+ }
208
+
209
+ return {...availability};
210
+ }
211
+
212
+ async function observeMicrophonePermission(){
213
+ if(!navigator.permissions?.query||!navigator.mediaDevices?.getUserMedia){
214
+ return;
215
+ }
216
+
217
+ try{
218
+ const permission=await navigator.permissions.query({name:'microphone'});
219
+ const synchronize=()=>setAvailability({
220
+ microphone:permission.state!=='denied'
221
+ });
222
+ permission.addEventListener?.('change',synchronize);
223
+ synchronize();
224
+ }catch{
225
+ // Some supported browsers do not expose microphone through the
226
+ // Permissions API. getUserMedia remains the authoritative check.
227
+ }
228
+ }
229
+
230
+ function setMuted(muted){
231
+ if(typeof muted!=='boolean'){
232
+ throw new TypeError('muted must be boolean');
233
+ }
234
+
235
+ host.muted=muted;
236
+ if(host.availability.tts){
237
+ muteButton.textContent=muted?'Unmute':'Mute';
238
+ muteButton.setAttribute('aria-pressed',String(muted));
239
+ muteButton.setAttribute('aria-label',muted?'Unmute AI voice':'Mute AI voice');
240
+ }
241
+
242
+ if(window.ai){
243
+ window.ai.muted=host.availability.tts?muted:true;
244
+
245
+ if(muted&&typeof window.ai.stopAudio==='function'){
246
+ window.ai.stopAudio();
247
+ }
248
+ }
249
+
250
+ return host;
251
+ }
252
+
253
+ function muteToggle(){
254
+ const muted=!host.muted;
255
+ setMuted(muted);
256
+
257
+ if(!muted){
258
+ window.ai?.resumeAudio?.();
259
+ }
260
+ }
261
+
262
+ async function transcribe(transcription=''){
263
+ const transcriptionEvent = new CustomEvent(
264
+ 'speech-transcription-complete',
265
+ {
266
+ detail: { text: transcription }
267
+ }
268
+ );
269
+
270
+ host.dispatchEvent(transcriptionEvent);
271
+ }
272
+
273
+ async function record() {
274
+ if(!host.availability.stt||!host.availability.microphone){
275
+ return false;
276
+ }
277
+ ai.stopAudio();
278
+ audioRecordingChunks.splice(0);
279
+ try{
280
+ activeStream=await navigator.mediaDevices.getUserMedia({audio:true});
281
+ }catch(error){
282
+ if(['NotAllowedError','NotFoundError','NotReadableError','SecurityError'].includes(error?.name)){
283
+ setAvailability({microphone:false});
284
+ host.dispatchEvent(new CustomEvent('speech-microphone-unavailable',{
285
+ bubbles:true,
286
+ composed:true,
287
+ detail:{reason:error.name}
288
+ }));
289
+ return false;
290
+ }
291
+ throw error;
292
+ }
293
+ mediaRecorder=new MediaRecorder(activeStream);
294
+
295
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
296
+ const source = audioContext.createMediaStreamSource(activeStream);
297
+ const processor = audioContext.createScriptProcessor(4096, 1, 1);
298
+
299
+ source.connect(processor);
300
+ processor.connect(audioContext.destination);
301
+
302
+ processor.onaudioprocess = function(event) {
303
+ const input = event.inputBuffer.getChannelData(0);
304
+ const isSilent = input.every(sample => Math.abs(sample) < 0.05); // Threshold for silence
305
+
306
+ if (isSilent&&silenceDuration) {
307
+ console.log('silent');
308
+ if(!silenceTimer){
309
+ silenceTimer = setTimeout(() => {
310
+
311
+ //console.log('TIMER SAYS STOPPING');
312
+ stop();
313
+ clearTimeout(silenceTimer);
314
+ }, silenceDuration); // wait for specified milliseconds of silence
315
+ }
316
+ } else {
317
+ clearTimeout(silenceTimer);
318
+ silenceTimer=false;
319
+ }
320
+ };
321
+
322
+ mediaRecorder.ondataavailable = event => {
323
+ audioRecordingChunks.push(event.data);
324
+ };
325
+
326
+ mediaRecorder.onstop = async () => {
327
+ processor.disconnect();
328
+ source.disconnect();
329
+ activeStream?.getTracks().forEach(track=>track.stop());
330
+ activeStream=null;
331
+
332
+ const audioBlob = new Blob(audioRecordingChunks, { type: 'audio/webm; codecs=opus' });
333
+ const audioFile = new File([audioBlob], 'audio.webm', { type: 'audio/webm' });
334
+ //console.log(audioFile)
335
+
336
+ //playBackAudio(audioBlob);
337
+
338
+ const transcription = await ai.fetchSTT(audioFile);
339
+
340
+ transcribe(transcription);
341
+
342
+ console.log(transcription);
343
+ };
344
+
345
+ mediaRecorder.start();
346
+ // recordButton.disabled = true;
347
+ // stopButton.disabled = false;
348
+ }
349
+
350
+ async function stop() {
351
+ if (mediaRecorder && mediaRecorder.state !== 'inactive') {
352
+ mediaRecorder.stop();
353
+ }
354
+ // recordButton.disabled = false;
355
+ // stopButton.disabled = true;
356
+ }
357
+
358
+ async function playBackAudio(audioBlob) {
359
+ const audioUrl = URL.createObjectURL(audioBlob);
360
+ audioElement.src = audioUrl;
361
+ audioElement.play();
362
+ }
363
+
364
+
365
+ </script>
@@ -0,0 +1,177 @@
1
+ <link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
2
+ <style>
3
+ :host{display:block}
4
+ .summary-strip{list-style:none;margin:0;padding:0}
5
+ .summary-strip{
6
+ display:grid;
7
+ gap:1px;
8
+ grid-template-columns:repeat(auto-fit,minmax(min(100%,10rem),1fr));
9
+ overflow:hidden;
10
+ }
11
+ .summary-item{
12
+ background:var(--arcane-surface-raised);
13
+ border:0;
14
+ border-radius:0;
15
+ box-sizing:border-box;
16
+ color:inherit;
17
+ display:grid;
18
+ font:inherit;
19
+ gap:var(--arcane-space-1);
20
+ min-height:6.25rem;
21
+ min-width:0;
22
+ padding:var(--arcane-space-4);
23
+ text-align:start;
24
+ width:100%;
25
+ }
26
+ button.summary-item{cursor:pointer}
27
+ button.summary-item:hover{background:var(--arcane-surface-muted)}
28
+ button.summary-item:focus-visible{outline:3px solid var(--arcane-focus);outline-offset:-3px}
29
+ .summary-value{font-size:clamp(1.35rem,4vw,2rem);font-weight:750;line-height:1.1;overflow-wrap:anywhere}
30
+ .summary-label{font-weight:650;overflow-wrap:anywhere}
31
+ .summary-detail{color:var(--arcane-muted);font-size:.85rem;overflow-wrap:anywhere}
32
+ .summary-status{justify-self:start;margin-top:var(--arcane-space-1)}
33
+ .empty{grid-column:1/-1;margin:0}
34
+ </style>
35
+
36
+ <section id="region" aria-label="Summary" part="region">
37
+ <ul id="items" class="summary-strip arcane-card" part="strip"></ul>
38
+ </section>
39
+
40
+ <script type="module">
41
+ const host=this;
42
+ const root=host.shadowRoot;
43
+ const region=root.querySelector('#region');
44
+ const list=root.querySelector('#items');
45
+ let items=[];
46
+ let options={};
47
+
48
+ host.clear=clear;
49
+ host.configure=configure;
50
+ host.setItems=setItems;
51
+ host.updateItem=updateItem;
52
+
53
+ Object.defineProperties(host,{
54
+ items:{get:getItems,set:setItems},
55
+ options:{get:()=>({...options}),set:configure}
56
+ });
57
+
58
+ list.addEventListener('click',selectItem);
59
+
60
+ function datasetOptions(){
61
+ return {
62
+ ariaLabel:host.dataset.ariaLabel||'Summary',
63
+ emptyLabel:host.dataset.emptyLabel||'No summary available.'
64
+ };
65
+ }
66
+
67
+ function configure(input={}){
68
+ options={...datasetOptions(),...options,...input};
69
+ region.setAttribute('aria-label',`${options.ariaLabel||'Summary'}`);
70
+ render();
71
+ return {...options};
72
+ }
73
+
74
+ function setItems(values=[]){
75
+ items=Array.from(values||[]).map((value,index)=>normalizeItem(value,index));
76
+ render();
77
+ host.dispatchEvent(new CustomEvent('summary-strip-change',{
78
+ bubbles:true,
79
+ composed:true,
80
+ detail:{items:getItems()}
81
+ }));
82
+ return getItems();
83
+ }
84
+
85
+ function updateItem(id,update={}){
86
+ const index=typeof id==='number'?id:items.findIndex(item=>item.id===`${id}`);
87
+ if(index<0||index>=items.length){
88
+ return null;
89
+ }
90
+ items[index]=normalizeItem({...items[index],...update,id:items[index].id},index);
91
+ render();
92
+ return {...items[index]};
93
+ }
94
+
95
+ function normalizeItem(value={},index=0){
96
+ return {
97
+ action:Boolean(value.action||value.actionable),
98
+ detail:`${value.detail??''}`,
99
+ disabled:Boolean(value.disabled),
100
+ id:`${value.id??`summary-${index+1}`}`,
101
+ label:`${value.label??''}`,
102
+ status:`${value.status??''}`,
103
+ value:`${value.value??''}`
104
+ };
105
+ }
106
+
107
+ function render(){
108
+ const fragment=document.createDocumentFragment();
109
+ if(!items.length){
110
+ const empty=document.createElement('li');
111
+ empty.className='empty arcane-state arcane-state--empty';
112
+ empty.innerText=`${options.emptyLabel||'No summary available.'}`;
113
+ fragment.append(empty);
114
+ }
115
+ for(const item of items){
116
+ const row=document.createElement('li');
117
+ const content=document.createElement(item.action?'button':'div');
118
+ const value=document.createElement('span');
119
+ const label=document.createElement('span');
120
+ const detail=document.createElement('span');
121
+
122
+ content.className='summary-item';
123
+ content.setAttribute('part','item');
124
+ content.dataset.summaryId=item.id;
125
+ if(item.action){
126
+ content.type='button';
127
+ content.disabled=item.disabled;
128
+ }
129
+ value.className='summary-value';
130
+ value.setAttribute('part','value');
131
+ value.innerText=item.value;
132
+ label.className='summary-label';
133
+ label.setAttribute('part','label');
134
+ label.innerText=item.label;
135
+ detail.className='summary-detail';
136
+ detail.setAttribute('part','detail');
137
+ detail.innerText=item.detail;
138
+ detail.hidden=!item.detail;
139
+ content.append(value,label,detail);
140
+ if(item.status){
141
+ const status=document.createElement('span');
142
+ status.className='summary-status arcane-badge';
143
+ status.dataset.status=item.status;
144
+ status.innerText=item.status;
145
+ content.append(status);
146
+ }
147
+ row.append(content);
148
+ fragment.append(row);
149
+ }
150
+ list.replaceChildren(fragment);
151
+ }
152
+
153
+ function selectItem(event){
154
+ const target=event.target.closest('button[data-summary-id]');
155
+ const item=items.find(candidate=>candidate.id===target?.dataset.summaryId);
156
+ if(!target||!item||item.disabled){
157
+ return;
158
+ }
159
+ host.dispatchEvent(new CustomEvent('summary-strip-select',{
160
+ bubbles:true,
161
+ composed:true,
162
+ detail:{id:item.id,item:{...item}}
163
+ }));
164
+ }
165
+
166
+ function getItems(){
167
+ return items.map(item=>({...item}));
168
+ }
169
+
170
+ function clear(){
171
+ return setItems([]);
172
+ }
173
+
174
+ configure(datasetOptions());
175
+ host.ready=true;
176
+ host.dispatchEvent(new CustomEvent('summary-strip-ready',{bubbles:true,composed:true}));
177
+ </script>
@@ -0,0 +1,77 @@
1
+ <link rel="stylesheet" href="./arcane/css/layout.css?v=3" />
2
+ <style>
3
+
4
+ input.search-users{
5
+ margin-bottom: 15px;
6
+ }
7
+
8
+ </style>
9
+
10
+ <table id="" class="notes">
11
+ <thead>
12
+
13
+ </thead>
14
+ <tbody>
15
+
16
+ </tbody>
17
+ </table>
18
+
19
+ <script typr="module">
20
+ const host = this;
21
+ const shadowRoot=this.shadowRoot;
22
+ host.buildHeader=buildHeader;
23
+ host.buildTable=buildTable;
24
+ host.ready=false;
25
+
26
+ const tableReady=new CustomEvent(
27
+ 'table-ready', {
28
+ detail: { }
29
+ }
30
+ );
31
+
32
+ const headerUpdate=new CustomEvent(
33
+ 'header-update', {
34
+ detail: { }
35
+ }
36
+ );
37
+
38
+ const bodyUpdate=new CustomEvent(
39
+ 'body-update', {
40
+ detail: { }
41
+ }
42
+ );
43
+
44
+ async function buildHeader(headerArray=['','']){
45
+ const tableHead = shadowRoot.querySelector('thead');
46
+ tableHead.innerHTML = '';
47
+ const th = tableHead.insertRow();
48
+
49
+ headerArray.forEach(
50
+ (header)=>{
51
+ th.insertCell(-1).innerText=header;
52
+ }
53
+ );
54
+ host.dispatchEvent(headerUpdate);
55
+ }
56
+
57
+ async function buildTable(tableArray=[['', ''], ['','']]){
58
+ const tableBody = shadowRoot.querySelector('tbody');
59
+ tableBody.innerHTML = '';
60
+
61
+ tableArray.forEach(
62
+ (row)=>{ console.log('row',row);
63
+ const tr = tableBody.insertRow();
64
+ row.forEach(
65
+ (cellValue)=>{
66
+ tr.insertCell(-1).innerText=cellValue;
67
+ }
68
+ );
69
+ }
70
+ );
71
+ host.dispatchEvent(bodyUpdate);
72
+ }
73
+
74
+ host.ready=true;
75
+ host.dispatchEvent(tableReady);
76
+
77
+ </script>