@readymadeit/mcp 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 (916) hide show
  1. package/README.md +114 -2
  2. package/bundle/LICENSE +201 -0
  3. package/bundle/boards/aggregator-demo-board.json +54 -0
  4. package/bundle/boards/alpaca-board.json +316 -0
  5. package/bundle/boards/animate-board.json +159 -0
  6. package/bundle/boards/ascii-art-demo-board.json +33 -0
  7. package/bundle/boards/ascii-cam-board.json +184 -0
  8. package/bundle/boards/asset-demo-board.json +54 -0
  9. package/bundle/boards/audio-encode-demo-board.json +153 -0
  10. package/bundle/boards/audiolize-board.json +152 -0
  11. package/bundle/boards/batcher-demo-board.json +43 -0
  12. package/bundle/boards/buffer-demo-board.json +53 -0
  13. package/bundle/boards/cache-demo-board.json +59 -0
  14. package/bundle/boards/camera-demo-board.json +28 -0
  15. package/bundle/boards/canvas-demo-board.json +55 -0
  16. package/bundle/boards/changes-demo-board.json +60 -0
  17. package/bundle/boards/court-booking-browser-demo-board.json +221 -0
  18. package/bundle/boards/court-booking-demo-board.json +218 -0
  19. package/bundle/boards/current-time-board.json +32 -0
  20. package/bundle/boards/debounce-demo-board.json +43 -0
  21. package/bundle/boards/decrypt-demo-board.json +47 -0
  22. package/bundle/boards/delay-demo-board.json +28 -0
  23. package/bundle/boards/detect-demo-board.json +64 -0
  24. package/bundle/boards/document-extract-demo-board.json +55 -0
  25. package/bundle/boards/dropitapp-board.json +138 -0
  26. package/bundle/boards/encode-demo-board.json +39 -0
  27. package/bundle/boards/encrypt-board.json +185 -0
  28. package/bundle/boards/encrypt-demo-board.json +39 -0
  29. package/bundle/boards/face-alert-board.json +181 -0
  30. package/bundle/boards/fetcher-demo-board.json +40 -0
  31. package/bundle/boards/fft-demo-board.json +28 -0
  32. package/bundle/boards/filter-demo-board.json +55 -0
  33. package/bundle/boards/flat-map-demo-board.json +42 -0
  34. package/bundle/boards/frame-limit-test-board.json +130 -0
  35. package/bundle/boards/game-board.json +413 -0
  36. package/bundle/boards/game-of-life-board.json +139 -0
  37. package/bundle/boards/game-of-life-demo-board.json +34 -0
  38. package/bundle/boards/gather-demo-board.json +62 -0
  39. package/bundle/boards/group-by-demo-board.json +62 -0
  40. package/bundle/boards/hacker-demo-board.json +45 -0
  41. package/bundle/boards/hacker-news-board.json +741 -0
  42. package/bundle/boards/hash-demo-board.json +40 -0
  43. package/bundle/boards/health-log-browser-demo-board.json +537 -0
  44. package/bundle/boards/health-log-demo-board.json +498 -0
  45. package/bundle/boards/helloworld-board.json +57 -0
  46. package/bundle/boards/hold-demo-board.json +67 -0
  47. package/bundle/boards/hold-scopes-demo-board.json +141 -0
  48. package/bundle/boards/http-client-browser-demo-board.json +379 -0
  49. package/bundle/boards/http-client-demo-board.json +380 -0
  50. package/bundle/boards/image-picker-demo-board.json +22 -0
  51. package/bundle/boards/imap-email-demo-board.json +35 -0
  52. package/bundle/boards/injector-demo-board.json +55 -0
  53. package/bundle/boards/iterator-demo-board.json +55 -0
  54. package/bundle/boards/limit-demo-board.json +66 -0
  55. package/bundle/boards/link-debugger.json +32 -0
  56. package/bundle/boards/live-location-demo-board.json +93 -0
  57. package/bundle/boards/live-radio-cloud-demo-board.json +216 -0
  58. package/bundle/boards/live-radio-cloud-direct-demo-board.json +311 -0
  59. package/bundle/boards/live-radio-demo-board.json +211 -0
  60. package/bundle/boards/live-radio-members-demo-board.json +314 -0
  61. package/bundle/boards/local-storage-demo-board.json +30 -0
  62. package/bundle/boards/lz-compress-demo-board.json +52 -0
  63. package/bundle/boards/map-demo-board.json +46 -0
  64. package/bundle/boards/match-filter-demo-board.json +43 -0
  65. package/bundle/boards/meeting-poll-browser-demo-board.json +649 -0
  66. package/bundle/boards/meeting-poll-demo-board.json +650 -0
  67. package/bundle/boards/microphone-monitor-demo-board.json +28 -0
  68. package/bundle/boards/microphone-speaker-demo-board.json +86 -0
  69. package/bundle/boards/monitor-demo-board.json +52 -0
  70. package/bundle/boards/mounted-endpoint-demo-board-hkp-rt.json +84 -0
  71. package/bundle/boards/mounted-endpoint-demo-board.json +84 -0
  72. package/bundle/boards/nested-rhythm-demo-board.json +1160 -0
  73. package/bundle/boards/next-bus-board.json +52 -0
  74. package/bundle/boards/next-bus-switch-board.json +79 -0
  75. package/bundle/boards/night-groove-demo-board.json +742 -0
  76. package/bundle/boards/noise-alert-board.json +146 -0
  77. package/bundle/boards/offer-followup-demo-board.json +291 -0
  78. package/bundle/boards/offer-intake-demo-board.json +289 -0
  79. package/bundle/boards/offer-intake-hetzner-demo-board.json +286 -0
  80. package/bundle/boards/offer-intake-imap-demo-board.json +289 -0
  81. package/bundle/boards/offer-intake-imap-hetzner-demo-board.json +354 -0
  82. package/bundle/boards/p2p-receiver-demo-board.json +65 -0
  83. package/bundle/boards/p2p-sender-demo-board.json +94 -0
  84. package/bundle/boards/pad-groove-demo-board.json +644 -0
  85. package/bundle/boards/peer-chat-board.json +109 -0
  86. package/bundle/boards/peer-chat-node-board.json +97 -0
  87. package/bundle/boards/qr-code-demo-board.json +22 -0
  88. package/bundle/boards/queue-demo-board.json +239 -0
  89. package/bundle/boards/reduce-demo-board.json +54 -0
  90. package/bundle/boards/remote-named-demo-board-hkp-rt.json +61 -0
  91. package/bundle/boards/remote-named-demo-board.json +61 -0
  92. package/bundle/boards/rss-demo-board.json +530 -0
  93. package/bundle/boards/rss-radio-board.json +515 -0
  94. package/bundle/boards/rss-radio-brief-one-board.json +237 -0
  95. package/bundle/boards/rss-radio-editor-unit-board.json +555 -0
  96. package/bundle/boards/rss-radio-library-unit-board.json +293 -0
  97. package/bundle/boards/rss-radio-unit-board.json +809 -0
  98. package/bundle/boards/rss-radio-voice-unit-board.json +146 -0
  99. package/bundle/boards/runtime-configs/hold-example.json +41 -0
  100. package/bundle/boards/runtime-configs/injector-example.json +23 -0
  101. package/bundle/boards/runtime-configs/speech-to-text-example.json +35 -0
  102. package/bundle/boards/runtime-configs/text-generation-example.json +31 -0
  103. package/bundle/boards/runtime-configs/text-to-speech-example.json +28 -0
  104. package/bundle/boards/runtime-configs/text-to-speech-inflect-example.json +28 -0
  105. package/bundle/boards/runtime-configs/ws-audio-playback-example.json +23 -0
  106. package/bundle/boards/select-demo-board.json +32 -0
  107. package/bundle/boards/send-ntfy-board.json +52 -0
  108. package/bundle/boards/shared-costs-demo-board.json +361 -0
  109. package/bundle/boards/sign-demo-board.json +41 -0
  110. package/bundle/boards/skill-router-demo-board.json +210 -0
  111. package/bundle/boards/smooth-demo-board.json +91 -0
  112. package/bundle/boards/smtp-email-demo-board.json +34 -0
  113. package/bundle/boards/sort-demo-board.json +55 -0
  114. package/bundle/boards/sound-demo-board.json +65 -0
  115. package/bundle/boards/spectral-modifier-board.json +98 -0
  116. package/bundle/boards/speech-synth-demo-board.json +37 -0
  117. package/bundle/boards/speech-to-text-demo-board.json +146 -0
  118. package/bundle/boards/spotify-board.json +75 -0
  119. package/bundle/boards/spread-demo-board.json +35 -0
  120. package/bundle/boards/sql-demo-board.json +56 -0
  121. package/bundle/boards/sql-explorer-board.json +447 -0
  122. package/bundle/boards/sql-explorer-node-board.json +474 -0
  123. package/bundle/boards/sql-import-board.json +156 -0
  124. package/bundle/boards/state-demo-board.json +65 -0
  125. package/bundle/boards/stopper-demo-board.json +40 -0
  126. package/bundle/boards/storage-demo-board.json +193 -0
  127. package/bundle/boards/store-demo-board.json +63 -0
  128. package/bundle/boards/swimlanes-demo-board.json +197 -0
  129. package/bundle/boards/switch-demo-board.json +51 -0
  130. package/bundle/boards/syn-board.json +19 -0
  131. package/bundle/boards/syn-booking-unit-board.json +998 -0
  132. package/bundle/boards/syn-conversations-anthropic-demo-board.json +925 -0
  133. package/bundle/boards/syn-conversations-demo-board.json +925 -0
  134. package/bundle/boards/syn-hotels-unit-board.json +287 -0
  135. package/bundle/boards/syn-mail-desk-board.json +25 -0
  136. package/bundle/boards/syn-mail-desk-unit-board.json +254 -0
  137. package/bundle/boards/telegram-listener-demo-board.json +31 -0
  138. package/bundle/boards/text-generation-anthropic-demo-board.json +66 -0
  139. package/bundle/boards/text-generation-demo-board.json +51 -0
  140. package/bundle/boards/text-generation-local-demo-board.json +80 -0
  141. package/bundle/boards/text-to-speech-demo-board.json +58 -0
  142. package/bundle/boards/timeline-demo-board.json +477 -0
  143. package/bundle/boards/timer-demo-board.json +35 -0
  144. package/bundle/boards/tracks-demo-board.json +95 -0
  145. package/bundle/boards/trigger-pad-demo-board.json +47 -0
  146. package/bundle/boards/triggerpad-board.json +31 -0
  147. package/bundle/boards/triggerpad-recorder-board.json +56 -0
  148. package/bundle/boards/uuid-generator-demo-board.json +166 -0
  149. package/bundle/boards/voice-assistant-demo-board.json +230 -0
  150. package/bundle/boards/voice-assistant-hkp-rt-demo-board.json +239 -0
  151. package/bundle/boards/voice-assistant-local-demo-board.json +232 -0
  152. package/bundle/boards/voice-assistant-skills-demo-board.json +316 -0
  153. package/bundle/boards/voice-assistant-skills-local-demo-board.json +316 -0
  154. package/bundle/boards/xy-pad-demo-board.json +36 -0
  155. package/bundle/docs/content/board-json.md +277 -0
  156. package/bundle/docs/content/boards/alpaca-board.md +56 -0
  157. package/bundle/docs/content/boards/animate-board.md +40 -0
  158. package/bundle/docs/content/boards/ascii-cam-board.md +37 -0
  159. package/bundle/docs/content/boards/audiolize-board.md +47 -0
  160. package/bundle/docs/content/boards/court-booking-browser-demo-board.md +43 -0
  161. package/bundle/docs/content/boards/court-booking-demo-board.md +120 -0
  162. package/bundle/docs/content/boards/current-time-board.md +32 -0
  163. package/bundle/docs/content/boards/dropitapp-board.md +57 -0
  164. package/bundle/docs/content/boards/encrypt-board.md +36 -0
  165. package/bundle/docs/content/boards/face-alert-board.md +50 -0
  166. package/bundle/docs/content/boards/game-board.md +69 -0
  167. package/bundle/docs/content/boards/game-of-life-board.md +47 -0
  168. package/bundle/docs/content/boards/hacker-news-board.md +76 -0
  169. package/bundle/docs/content/boards/health-log-browser-demo-board.md +56 -0
  170. package/bundle/docs/content/boards/health-log-demo-board.md +138 -0
  171. package/bundle/docs/content/boards/helloworld-board.md +40 -0
  172. package/bundle/docs/content/boards/link-debugger.md +31 -0
  173. package/bundle/docs/content/boards/live-radio-cloud-demo-board.md +70 -0
  174. package/bundle/docs/content/boards/live-radio-cloud-direct-demo-board.md +89 -0
  175. package/bundle/docs/content/boards/live-radio-demo-board.md +102 -0
  176. package/bundle/docs/content/boards/live-radio-members-demo-board.md +91 -0
  177. package/bundle/docs/content/boards/meeting-poll-browser-demo-board.md +45 -0
  178. package/bundle/docs/content/boards/meeting-poll-demo-board.md +121 -0
  179. package/bundle/docs/content/boards/mounted-endpoint-demo-board-hkp-rt.md +50 -0
  180. package/bundle/docs/content/boards/nested-rhythm-demo-board.md +165 -0
  181. package/bundle/docs/content/boards/next-bus-board.md +38 -0
  182. package/bundle/docs/content/boards/next-bus-switch-board.md +44 -0
  183. package/bundle/docs/content/boards/night-groove-demo-board.md +110 -0
  184. package/bundle/docs/content/boards/noise-alert-board.md +44 -0
  185. package/bundle/docs/content/boards/pad-groove-demo-board.md +93 -0
  186. package/bundle/docs/content/boards/peer-chat-board.md +49 -0
  187. package/bundle/docs/content/boards/peer-chat-node-board.md +47 -0
  188. package/bundle/docs/content/boards/rss-radio-board.md +221 -0
  189. package/bundle/docs/content/boards/send-ntfy-board.md +33 -0
  190. package/bundle/docs/content/boards/shared-costs-demo-board.md +65 -0
  191. package/bundle/docs/content/boards/spectral-modifier-board.md +55 -0
  192. package/bundle/docs/content/boards/spotify-board.md +46 -0
  193. package/bundle/docs/content/boards/sql-explorer-board.md +70 -0
  194. package/bundle/docs/content/boards/sql-explorer-node-board.md +76 -0
  195. package/bundle/docs/content/boards/sql-import-board.md +37 -0
  196. package/bundle/docs/content/boards/swimlanes-demo-board.md +148 -0
  197. package/bundle/docs/content/boards/syn-mail-desk-board.md +52 -0
  198. package/bundle/docs/content/boards/timeline-demo-board.md +115 -0
  199. package/bundle/docs/content/boards/triggerpad-board.md +32 -0
  200. package/bundle/docs/content/boards/triggerpad-recorder-board.md +52 -0
  201. package/bundle/docs/content/boards/voice-assistant-demo-board.md +51 -0
  202. package/bundle/docs/content/concepts/assets.md +245 -0
  203. package/bundle/docs/content/concepts/blocks.md +300 -0
  204. package/bundle/docs/content/concepts/board-assistant.md +307 -0
  205. package/bundle/docs/content/concepts/board.md +265 -0
  206. package/bundle/docs/content/concepts/cloud-boards.md +803 -0
  207. package/bundle/docs/content/concepts/coordinator.md +297 -0
  208. package/bundle/docs/content/concepts/logging.md +293 -0
  209. package/bundle/docs/content/concepts/mounts.md +314 -0
  210. package/bundle/docs/content/concepts/presets.md +360 -0
  211. package/bundle/docs/content/concepts/remotes.md +423 -0
  212. package/bundle/docs/content/concepts/runtime.md +664 -0
  213. package/bundle/docs/content/concepts/scopes.md +256 -0
  214. package/bundle/docs/content/concepts/service.md +227 -0
  215. package/bundle/docs/content/concepts/units.md +321 -0
  216. package/bundle/docs/content/introduction.md +163 -0
  217. package/bundle/docs/content/llm/circle-text-board.json +55 -0
  218. package/bundle/docs/content/llm/howto-workflow.md +369 -0
  219. package/bundle/docs/content/repository.md +161 -0
  220. package/bundle/docs/content/services/aggregator.md +76 -0
  221. package/bundle/docs/content/services/analyzer.md +44 -0
  222. package/bundle/docs/content/services/ascii-art.md +58 -0
  223. package/bundle/docs/content/services/asset.md +88 -0
  224. package/bundle/docs/content/services/audio-editor.md +57 -0
  225. package/bundle/docs/content/services/audio-encode.md +115 -0
  226. package/bundle/docs/content/services/audio-io.md +173 -0
  227. package/bundle/docs/content/services/batcher.md +49 -0
  228. package/bundle/docs/content/services/board-service.md +48 -0
  229. package/bundle/docs/content/services/browser-sub-service.md +75 -0
  230. package/bundle/docs/content/services/buffer.md +70 -0
  231. package/bundle/docs/content/services/cache.md +92 -0
  232. package/bundle/docs/content/services/camera.md +85 -0
  233. package/bundle/docs/content/services/canvas.md +196 -0
  234. package/bundle/docs/content/services/changes.md +87 -0
  235. package/bundle/docs/content/services/chunked-file-provider.md +63 -0
  236. package/bundle/docs/content/services/communication-dispatcher.md +190 -0
  237. package/bundle/docs/content/services/configurator.md +66 -0
  238. package/bundle/docs/content/services/conversations.md +244 -0
  239. package/bundle/docs/content/services/debounce.md +45 -0
  240. package/bundle/docs/content/services/decrypt.md +53 -0
  241. package/bundle/docs/content/services/delay.md +55 -0
  242. package/bundle/docs/content/services/detect.md +101 -0
  243. package/bundle/docs/content/services/document-extract.md +174 -0
  244. package/bundle/docs/content/services/download.md +67 -0
  245. package/bundle/docs/content/services/encode.md +63 -0
  246. package/bundle/docs/content/services/encrypt.md +53 -0
  247. package/bundle/docs/content/services/fetcher.md +122 -0
  248. package/bundle/docs/content/services/fft.md +96 -0
  249. package/bundle/docs/content/services/file-source.md +67 -0
  250. package/bundle/docs/content/services/filesystem.md +157 -0
  251. package/bundle/docs/content/services/filter.md +133 -0
  252. package/bundle/docs/content/services/flat-map.md +62 -0
  253. package/bundle/docs/content/services/game-of-life.md +93 -0
  254. package/bundle/docs/content/services/gather.md +135 -0
  255. package/bundle/docs/content/services/gif-encoder.md +56 -0
  256. package/bundle/docs/content/services/github.md +85 -0
  257. package/bundle/docs/content/services/group-by.md +54 -0
  258. package/bundle/docs/content/services/hacker.md +79 -0
  259. package/bundle/docs/content/services/hash.md +59 -0
  260. package/bundle/docs/content/services/hold.md +182 -0
  261. package/bundle/docs/content/services/http-relay-client.md +48 -0
  262. package/bundle/docs/content/services/http-uploader.md +62 -0
  263. package/bundle/docs/content/services/http.md +424 -0
  264. package/bundle/docs/content/services/if.md +79 -0
  265. package/bundle/docs/content/services/ifft.md +46 -0
  266. package/bundle/docs/content/services/image-picker.md +50 -0
  267. package/bundle/docs/content/services/imap-email.md +104 -0
  268. package/bundle/docs/content/services/injector.md +129 -0
  269. package/bundle/docs/content/services/input.md +90 -0
  270. package/bundle/docs/content/services/iterator.md +186 -0
  271. package/bundle/docs/content/services/join.md +153 -0
  272. package/bundle/docs/content/services/limit.md +47 -0
  273. package/bundle/docs/content/services/local-storage.md +47 -0
  274. package/bundle/docs/content/services/looper.md +62 -0
  275. package/bundle/docs/content/services/lz-compress.md +52 -0
  276. package/bundle/docs/content/services/map.md +257 -0
  277. package/bundle/docs/content/services/match-filter.md +38 -0
  278. package/bundle/docs/content/services/microphone-monitor.md +66 -0
  279. package/bundle/docs/content/services/monitor.md +67 -0
  280. package/bundle/docs/content/services/ollama.md +116 -0
  281. package/bundle/docs/content/services/openai-prompt.md +74 -0
  282. package/bundle/docs/content/services/output.md +107 -0
  283. package/bundle/docs/content/services/peer-socket.md +61 -0
  284. package/bundle/docs/content/services/qr-code.md +48 -0
  285. package/bundle/docs/content/services/queue.md +201 -0
  286. package/bundle/docs/content/services/reduce.md +51 -0
  287. package/bundle/docs/content/services/rss.md +232 -0
  288. package/bundle/docs/content/services/select.md +47 -0
  289. package/bundle/docs/content/services/sign.md +53 -0
  290. package/bundle/docs/content/services/skill-router.md +154 -0
  291. package/bundle/docs/content/services/smooth.md +59 -0
  292. package/bundle/docs/content/services/smtp-email.md +129 -0
  293. package/bundle/docs/content/services/sort.md +48 -0
  294. package/bundle/docs/content/services/sound.md +87 -0
  295. package/bundle/docs/content/services/speech-synth.md +46 -0
  296. package/bundle/docs/content/services/speech-to-text.md +172 -0
  297. package/bundle/docs/content/services/spotify.md +77 -0
  298. package/bundle/docs/content/services/spread.md +111 -0
  299. package/bundle/docs/content/services/sql.md +491 -0
  300. package/bundle/docs/content/services/state.md +57 -0
  301. package/bundle/docs/content/services/static.md +47 -0
  302. package/bundle/docs/content/services/stopper.md +55 -0
  303. package/bundle/docs/content/services/storage.md +155 -0
  304. package/bundle/docs/content/services/store.md +255 -0
  305. package/bundle/docs/content/services/sub-service.md +152 -0
  306. package/bundle/docs/content/services/switch.md +67 -0
  307. package/bundle/docs/content/services/telegram-listener.md +76 -0
  308. package/bundle/docs/content/services/text-generation.md +390 -0
  309. package/bundle/docs/content/services/text-to-speech.md +130 -0
  310. package/bundle/docs/content/services/timeline.md +333 -0
  311. package/bundle/docs/content/services/timer.md +113 -0
  312. package/bundle/docs/content/services/tracks.md +207 -0
  313. package/bundle/docs/content/services/trigger-pad.md +68 -0
  314. package/bundle/docs/content/services/uuid-generator.md +48 -0
  315. package/bundle/docs/content/services/wav-reader.md +66 -0
  316. package/bundle/docs/content/services/websocket.md +189 -0
  317. package/bundle/docs/content/services/workflow-board-builder.md +65 -0
  318. package/bundle/docs/content/services/xy-pad.md +60 -0
  319. package/bundle/docs/content/targets.md +434 -0
  320. package/bundle/docs/content/testing.md +263 -0
  321. package/bundle/docs/content/vocabulary.md +171 -0
  322. package/bundle/hkp-frontend/src/runtime/browser/BrowserRegistry.tsx +141 -0
  323. package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntime.tsx +202 -0
  324. package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeApi.ts +306 -0
  325. package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeApp.ts +310 -0
  326. package/bundle/hkp-frontend/src/runtime/browser/BrowserRuntimeScope.ts +500 -0
  327. package/bundle/hkp-frontend/src/runtime/browser/UIRegistry.ts +150 -0
  328. package/bundle/hkp-frontend/src/runtime/browser/assetResolver.ts +123 -0
  329. package/bundle/hkp-frontend/src/runtime/browser/pipelineNames.ts +65 -0
  330. package/bundle/hkp-frontend/src/runtime/browser/registry/Default.ts +237 -0
  331. package/bundle/hkp-frontend/src/runtime/browser/services/Aggregator.ts +127 -0
  332. package/bundle/hkp-frontend/src/runtime/browser/services/AggregatorUI.tsx +83 -0
  333. package/bundle/hkp-frontend/src/runtime/browser/services/Analyzer.tsx +43 -0
  334. package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/Bars.tsx +33 -0
  335. package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/HorizontalSpectrogram.tsx +53 -0
  336. package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/VerticalSpectogram.tsx +56 -0
  337. package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/Waveform.tsx +109 -0
  338. package/bundle/hkp-frontend/src/runtime/browser/services/AnalyzerUI/index.tsx +99 -0
  339. package/bundle/hkp-frontend/src/runtime/browser/services/AsciiArt.ts +119 -0
  340. package/bundle/hkp-frontend/src/runtime/browser/services/AsciiArtUI.tsx +131 -0
  341. package/bundle/hkp-frontend/src/runtime/browser/services/Asset.ts +125 -0
  342. package/bundle/hkp-frontend/src/runtime/browser/services/AssetUI.tsx +37 -0
  343. package/bundle/hkp-frontend/src/runtime/browser/services/AudioDeviceSettings.tsx +56 -0
  344. package/bundle/hkp-frontend/src/runtime/browser/services/AudioEditor.ts +129 -0
  345. package/bundle/hkp-frontend/src/runtime/browser/services/AudioEditorUI.tsx +549 -0
  346. package/bundle/hkp-frontend/src/runtime/browser/services/AudioInput.ts +298 -0
  347. package/bundle/hkp-frontend/src/runtime/browser/services/AudioInputUI.tsx +257 -0
  348. package/bundle/hkp-frontend/src/runtime/browser/services/AudioOutput.ts +189 -0
  349. package/bundle/hkp-frontend/src/runtime/browser/services/AudioOutputUI.tsx +63 -0
  350. package/bundle/hkp-frontend/src/runtime/browser/services/Batcher.ts +11 -0
  351. package/bundle/hkp-frontend/src/runtime/browser/services/BoardService.tsx +86 -0
  352. package/bundle/hkp-frontend/src/runtime/browser/services/BoardServiceUI.tsx +410 -0
  353. package/bundle/hkp-frontend/src/runtime/browser/services/BrowserGather.ts +311 -0
  354. package/bundle/hkp-frontend/src/runtime/browser/services/BrowserIterator.ts +167 -0
  355. package/bundle/hkp-frontend/src/runtime/browser/services/BrowserSubService.tsx +583 -0
  356. package/bundle/hkp-frontend/src/runtime/browser/services/BrowserSubServiceUI.tsx +187 -0
  357. package/bundle/hkp-frontend/src/runtime/browser/services/BrowserTracks.tsx +477 -0
  358. package/bundle/hkp-frontend/src/runtime/browser/services/Buffer.ts +11 -0
  359. package/bundle/hkp-frontend/src/runtime/browser/services/Cache.ts +134 -0
  360. package/bundle/hkp-frontend/src/runtime/browser/services/CacheUI.tsx +125 -0
  361. package/bundle/hkp-frontend/src/runtime/browser/services/Camera.ts +90 -0
  362. package/bundle/hkp-frontend/src/runtime/browser/services/CameraUI.tsx +321 -0
  363. package/bundle/hkp-frontend/src/runtime/browser/services/Canvas.ts +139 -0
  364. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/canvasDraw.ts +543 -0
  365. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/canvasUtils.ts +39 -0
  366. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/index.tsx +287 -0
  367. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/canvasDraw.test.ts +355 -0
  368. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/canvasUtils.test.ts +89 -0
  369. package/bundle/hkp-frontend/src/runtime/browser/services/CanvasUI/tests/fullscreen.test.tsx +26 -0
  370. package/bundle/hkp-frontend/src/runtime/browser/services/Changes.ts +201 -0
  371. package/bundle/hkp-frontend/src/runtime/browser/services/ChangesUI.tsx +85 -0
  372. package/bundle/hkp-frontend/src/runtime/browser/services/ChunkedFileProvider.tsx +183 -0
  373. package/bundle/hkp-frontend/src/runtime/browser/services/Configurator.ts +258 -0
  374. package/bundle/hkp-frontend/src/runtime/browser/services/ConfiguratorUI.tsx +83 -0
  375. package/bundle/hkp-frontend/src/runtime/browser/services/ConsideredHacker.tsx +28 -0
  376. package/bundle/hkp-frontend/src/runtime/browser/services/Debounce.ts +75 -0
  377. package/bundle/hkp-frontend/src/runtime/browser/services/DebounceUI.tsx +70 -0
  378. package/bundle/hkp-frontend/src/runtime/browser/services/Decrypt.ts +127 -0
  379. package/bundle/hkp-frontend/src/runtime/browser/services/DecryptUI.tsx +39 -0
  380. package/bundle/hkp-frontend/src/runtime/browser/services/Delay.tsx +110 -0
  381. package/bundle/hkp-frontend/src/runtime/browser/services/Detect.ts +214 -0
  382. package/bundle/hkp-frontend/src/runtime/browser/services/DetectUI.tsx +86 -0
  383. package/bundle/hkp-frontend/src/runtime/browser/services/Download.ts +120 -0
  384. package/bundle/hkp-frontend/src/runtime/browser/services/DownloadUI.tsx +61 -0
  385. package/bundle/hkp-frontend/src/runtime/browser/services/Encode.ts +138 -0
  386. package/bundle/hkp-frontend/src/runtime/browser/services/EncodeUI.tsx +52 -0
  387. package/bundle/hkp-frontend/src/runtime/browser/services/Encrypt.ts +125 -0
  388. package/bundle/hkp-frontend/src/runtime/browser/services/EncryptUI.tsx +39 -0
  389. package/bundle/hkp-frontend/src/runtime/browser/services/FFT.tsx +238 -0
  390. package/bundle/hkp-frontend/src/runtime/browser/services/FFTUI.tsx +112 -0
  391. package/bundle/hkp-frontend/src/runtime/browser/services/FeedbackService.ts +247 -0
  392. package/bundle/hkp-frontend/src/runtime/browser/services/FeedbackServiceUI.tsx +35 -0
  393. package/bundle/hkp-frontend/src/runtime/browser/services/Fetcher.tsx +232 -0
  394. package/bundle/hkp-frontend/src/runtime/browser/services/FetcherUI.tsx +154 -0
  395. package/bundle/hkp-frontend/src/runtime/browser/services/FileSource.tsx +171 -0
  396. package/bundle/hkp-frontend/src/runtime/browser/services/Filter.tsx +18 -0
  397. package/bundle/hkp-frontend/src/runtime/browser/services/FilterUI.tsx +89 -0
  398. package/bundle/hkp-frontend/src/runtime/browser/services/FlatMap.ts +68 -0
  399. package/bundle/hkp-frontend/src/runtime/browser/services/FlatMapUI.tsx +38 -0
  400. package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLife.ts +210 -0
  401. package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeRenderer.ts +182 -0
  402. package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeRendererUI.tsx +48 -0
  403. package/bundle/hkp-frontend/src/runtime/browser/services/GameOfLifeUI.tsx +58 -0
  404. package/bundle/hkp-frontend/src/runtime/browser/services/GatherUI.tsx +84 -0
  405. package/bundle/hkp-frontend/src/runtime/browser/services/GifEncoder.tsx +651 -0
  406. package/bundle/hkp-frontend/src/runtime/browser/services/GithubAPI.ts +294 -0
  407. package/bundle/hkp-frontend/src/runtime/browser/services/GithubComponents.tsx +389 -0
  408. package/bundle/hkp-frontend/src/runtime/browser/services/GithubSink.tsx +109 -0
  409. package/bundle/hkp-frontend/src/runtime/browser/services/GithubSinkUI.tsx +143 -0
  410. package/bundle/hkp-frontend/src/runtime/browser/services/GithubSource.tsx +86 -0
  411. package/bundle/hkp-frontend/src/runtime/browser/services/GithubSourceUI.tsx +162 -0
  412. package/bundle/hkp-frontend/src/runtime/browser/services/GroupBy.ts +11 -0
  413. package/bundle/hkp-frontend/src/runtime/browser/services/HTTPUploader.ts +102 -0
  414. package/bundle/hkp-frontend/src/runtime/browser/services/Hacker.ts +73 -0
  415. package/bundle/hkp-frontend/src/runtime/browser/services/HackerUI.tsx +134 -0
  416. package/bundle/hkp-frontend/src/runtime/browser/services/Hash.ts +134 -0
  417. package/bundle/hkp-frontend/src/runtime/browser/services/HashUI.tsx +45 -0
  418. package/bundle/hkp-frontend/src/runtime/browser/services/Hold.ts +288 -0
  419. package/bundle/hkp-frontend/src/runtime/browser/services/HoldUI.tsx +43 -0
  420. package/bundle/hkp-frontend/src/runtime/browser/services/HttpClient.ts +558 -0
  421. package/bundle/hkp-frontend/src/runtime/browser/services/HttpClientUI.tsx +212 -0
  422. package/bundle/hkp-frontend/src/runtime/browser/services/HttpUploaderTokenInjector.ts +149 -0
  423. package/bundle/hkp-frontend/src/runtime/browser/services/IfService.ts +231 -0
  424. package/bundle/hkp-frontend/src/runtime/browser/services/IfServiceUI.tsx +50 -0
  425. package/bundle/hkp-frontend/src/runtime/browser/services/ImagePicker.tsx +118 -0
  426. package/bundle/hkp-frontend/src/runtime/browser/services/Injector.ts +61 -0
  427. package/bundle/hkp-frontend/src/runtime/browser/services/InjectorUI.tsx +389 -0
  428. package/bundle/hkp-frontend/src/runtime/browser/services/Input.ts +214 -0
  429. package/bundle/hkp-frontend/src/runtime/browser/services/InputUI.tsx +71 -0
  430. package/bundle/hkp-frontend/src/runtime/browser/services/IteratorUI.tsx +59 -0
  431. package/bundle/hkp-frontend/src/runtime/browser/services/LZCompress.ts +63 -0
  432. package/bundle/hkp-frontend/src/runtime/browser/services/Limit.ts +39 -0
  433. package/bundle/hkp-frontend/src/runtime/browser/services/LimitUI.tsx +41 -0
  434. package/bundle/hkp-frontend/src/runtime/browser/services/LocalStorage.ts +65 -0
  435. package/bundle/hkp-frontend/src/runtime/browser/services/LocalStorageUI.tsx +72 -0
  436. package/bundle/hkp-frontend/src/runtime/browser/services/Map.ts +14 -0
  437. package/bundle/hkp-frontend/src/runtime/browser/services/MapUI.tsx +334 -0
  438. package/bundle/hkp-frontend/src/runtime/browser/services/MapUIModeAssist.tsx +61 -0
  439. package/bundle/hkp-frontend/src/runtime/browser/services/MatchFilter.ts +11 -0
  440. package/bundle/hkp-frontend/src/runtime/browser/services/MicrophoneMonitor.ts +190 -0
  441. package/bundle/hkp-frontend/src/runtime/browser/services/MicrophoneMonitorUI.tsx +94 -0
  442. package/bundle/hkp-frontend/src/runtime/browser/services/Monitor.tsx +15 -0
  443. package/bundle/hkp-frontend/src/runtime/browser/services/MonitorUI.tsx +281 -0
  444. package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPrompt.ts +237 -0
  445. package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/BusyIndicator.tsx +18 -0
  446. package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/PromptInput.tsx +71 -0
  447. package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/StreamingPreview.tsx +24 -0
  448. package/bundle/hkp-frontend/src/runtime/browser/services/OllamaPromptUI/index.tsx +156 -0
  449. package/bundle/hkp-frontend/src/runtime/browser/services/OpenAIPrompt.ts +254 -0
  450. package/bundle/hkp-frontend/src/runtime/browser/services/OpenAIPromptUI.tsx +189 -0
  451. package/bundle/hkp-frontend/src/runtime/browser/services/Output.tsx +145 -0
  452. package/bundle/hkp-frontend/src/runtime/browser/services/OutputUI.tsx +118 -0
  453. package/bundle/hkp-frontend/src/runtime/browser/services/PeerChatTemplate.json +43 -0
  454. package/bundle/hkp-frontend/src/runtime/browser/services/PeerConnection.ts +260 -0
  455. package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocket.tsx +268 -0
  456. package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocketReceiverTemplate.json +29 -0
  457. package/bundle/hkp-frontend/src/runtime/browser/services/PeerSocketUI.tsx +341 -0
  458. package/bundle/hkp-frontend/src/runtime/browser/services/PlaceholderUI.tsx +72 -0
  459. package/bundle/hkp-frontend/src/runtime/browser/services/QrCode.ts +63 -0
  460. package/bundle/hkp-frontend/src/runtime/browser/services/QrCodeUI.tsx +197 -0
  461. package/bundle/hkp-frontend/src/runtime/browser/services/Select.ts +40 -0
  462. package/bundle/hkp-frontend/src/runtime/browser/services/SelectUI.tsx +41 -0
  463. package/bundle/hkp-frontend/src/runtime/browser/services/ServiceBase.ts +50 -0
  464. package/bundle/hkp-frontend/src/runtime/browser/services/SetRuntimeVariable.ts +65 -0
  465. package/bundle/hkp-frontend/src/runtime/browser/services/SetRuntimeVariableUI.tsx +50 -0
  466. package/bundle/hkp-frontend/src/runtime/browser/services/Sign.ts +182 -0
  467. package/bundle/hkp-frontend/src/runtime/browser/services/SignUI.tsx +55 -0
  468. package/bundle/hkp-frontend/src/runtime/browser/services/Smooth.ts +101 -0
  469. package/bundle/hkp-frontend/src/runtime/browser/services/SmoothUI.tsx +50 -0
  470. package/bundle/hkp-frontend/src/runtime/browser/services/Sort.ts +59 -0
  471. package/bundle/hkp-frontend/src/runtime/browser/services/SortUI.tsx +61 -0
  472. package/bundle/hkp-frontend/src/runtime/browser/services/Sound.ts +541 -0
  473. package/bundle/hkp-frontend/src/runtime/browser/services/SoundUI.tsx +183 -0
  474. package/bundle/hkp-frontend/src/runtime/browser/services/SpeechSynth.ts +56 -0
  475. package/bundle/hkp-frontend/src/runtime/browser/services/SpeechSynthUI.tsx +108 -0
  476. package/bundle/hkp-frontend/src/runtime/browser/services/Spotify.tsx +111 -0
  477. package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyAPI.ts +113 -0
  478. package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyComponents.tsx +104 -0
  479. package/bundle/hkp-frontend/src/runtime/browser/services/SpotifyUI.tsx +186 -0
  480. package/bundle/hkp-frontend/src/runtime/browser/services/Spread.ts +117 -0
  481. package/bundle/hkp-frontend/src/runtime/browser/services/SpreadUI.tsx +38 -0
  482. package/bundle/hkp-frontend/src/runtime/browser/services/Sql.ts +448 -0
  483. package/bundle/hkp-frontend/src/runtime/browser/services/SqlInspector.tsx +332 -0
  484. package/bundle/hkp-frontend/src/runtime/browser/services/SqlUI.tsx +226 -0
  485. package/bundle/hkp-frontend/src/runtime/browser/services/State.ts +149 -0
  486. package/bundle/hkp-frontend/src/runtime/browser/services/Stopper.ts +29 -0
  487. package/bundle/hkp-frontend/src/runtime/browser/services/Switch.tsx +419 -0
  488. package/bundle/hkp-frontend/src/runtime/browser/services/SwitchUI.tsx +171 -0
  489. package/bundle/hkp-frontend/src/runtime/browser/services/TickRuleDelta.ts +101 -0
  490. package/bundle/hkp-frontend/src/runtime/browser/services/TickRuleDeltaUI.tsx +56 -0
  491. package/bundle/hkp-frontend/src/runtime/browser/services/Timeline.ts +709 -0
  492. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/TimelinePanel.tsx +79 -0
  493. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/TimelineRows.tsx +574 -0
  494. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/Transport.tsx +141 -0
  495. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/index.tsx +119 -0
  496. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/model.ts +425 -0
  497. package/bundle/hkp-frontend/src/runtime/browser/services/TimelineUI/parts.tsx +708 -0
  498. package/bundle/hkp-frontend/src/runtime/browser/services/Timer.ts +15 -0
  499. package/bundle/hkp-frontend/src/runtime/browser/services/TimerUI.tsx +213 -0
  500. package/bundle/hkp-frontend/src/runtime/browser/services/TracksUI.tsx +81 -0
  501. package/bundle/hkp-frontend/src/runtime/browser/services/TriggerPad.ts +108 -0
  502. package/bundle/hkp-frontend/src/runtime/browser/services/TriggerPadUI.tsx +160 -0
  503. package/bundle/hkp-frontend/src/runtime/browser/services/UuidGenerator.ts +74 -0
  504. package/bundle/hkp-frontend/src/runtime/browser/services/UuidGeneratorUI.tsx +59 -0
  505. package/bundle/hkp-frontend/src/runtime/browser/services/WaveformDisplay.tsx +104 -0
  506. package/bundle/hkp-frontend/src/runtime/browser/services/WebsocketClient.ts +114 -0
  507. package/bundle/hkp-frontend/src/runtime/browser/services/WebsocketClientUI.tsx +42 -0
  508. package/bundle/hkp-frontend/src/runtime/browser/services/WorkflowBoardBuilder.ts +499 -0
  509. package/bundle/hkp-frontend/src/runtime/browser/services/WorkflowBoardBuilderUI.tsx +521 -0
  510. package/bundle/hkp-frontend/src/runtime/browser/services/XYPad.ts +68 -0
  511. package/bundle/hkp-frontend/src/runtime/browser/services/XYPadUI.tsx +274 -0
  512. package/bundle/hkp-frontend/src/runtime/browser/services/audio/audioHelper.ts +36 -0
  513. package/bundle/hkp-frontend/src/runtime/browser/services/base/Batcher.ts +76 -0
  514. package/bundle/hkp-frontend/src/runtime/browser/services/base/Buffer.ts +142 -0
  515. package/bundle/hkp-frontend/src/runtime/browser/services/base/Filter.ts +125 -0
  516. package/bundle/hkp-frontend/src/runtime/browser/services/base/GroupBy.ts +101 -0
  517. package/bundle/hkp-frontend/src/runtime/browser/services/base/Map.ts +543 -0
  518. package/bundle/hkp-frontend/src/runtime/browser/services/base/MatchFilter.ts +49 -0
  519. package/bundle/hkp-frontend/src/runtime/browser/services/base/Monitor.ts +75 -0
  520. package/bundle/hkp-frontend/src/runtime/browser/services/base/Reduce.ts +74 -0
  521. package/bundle/hkp-frontend/src/runtime/browser/services/base/Timer.ts +342 -0
  522. package/bundle/hkp-frontend/src/runtime/browser/services/base/bundle.js +7375 -0
  523. package/bundle/hkp-frontend/src/runtime/browser/services/base/eval.ts +208 -0
  524. package/bundle/hkp-frontend/src/runtime/browser/services/base/expressionEval.ts +223 -0
  525. package/bundle/hkp-frontend/src/runtime/browser/services/base/helpers.ts +10 -0
  526. package/bundle/hkp-frontend/src/runtime/browser/services/base/index.ts +37 -0
  527. package/bundle/hkp-frontend/src/runtime/browser/services/camera/videoCapture.ts +78 -0
  528. package/bundle/hkp-frontend/src/runtime/browser/services/changes-modes.ts +9 -0
  529. package/bundle/hkp-frontend/src/runtime/browser/services/colorpalette.ts +26 -0
  530. package/bundle/hkp-frontend/src/runtime/browser/services/detect/DetectionPreview.tsx +76 -0
  531. package/bundle/hkp-frontend/src/runtime/browser/services/detect/mediapipe.ts +34 -0
  532. package/bundle/hkp-frontend/src/runtime/browser/services/detect/models/README.md +14 -0
  533. package/bundle/hkp-frontend/src/runtime/browser/services/detect/models/blaze_face_short_range.tflite +0 -0
  534. package/bundle/hkp-frontend/src/runtime/browser/services/detect-modes.ts +7 -0
  535. package/bundle/hkp-frontend/src/runtime/browser/services/encode-modes.ts +10 -0
  536. package/bundle/hkp-frontend/src/runtime/browser/services/helpers.ts +300 -0
  537. package/bundle/hkp-frontend/src/runtime/browser/services/http-client-methods.ts +10 -0
  538. package/bundle/hkp-frontend/src/runtime/browser/services/sql-database.ts +594 -0
  539. package/bundle/hkp-frontend/src/runtime/browser/services/sql-dump.ts +192 -0
  540. package/bundle/hkp-frontend/src/runtime/browser/services/sql-inspect.ts +130 -0
  541. package/bundle/hkp-frontend/src/runtime/browser/services/sql-inspector.css +155 -0
  542. package/bundle/hkp-frontend/src/runtime/browser/services/sql-modes.ts +27 -0
  543. package/bundle/hkp-frontend/src/runtime/browser/services/tests/TESTING_APPROACH.md +169 -0
  544. package/bundle/hkp-frontend/src/runtime/browser/services/tests/__snapshots__/service-ui.future-enhancements.test.tsx.snap +5 -0
  545. package/bundle/hkp-frontend/src/runtime/browser/services/tests/audio-input-permissions.test.ts +42 -0
  546. package/bundle/hkp-frontend/src/runtime/browser/services/tests/audiolizeLanes.test.ts +70 -0
  547. package/bundle/hkp-frontend/src/runtime/browser/services/tests/browser-scopes.test.ts +305 -0
  548. package/bundle/hkp-frontend/src/runtime/browser/services/tests/cache-service.test.ts +53 -0
  549. package/bundle/hkp-frontend/src/runtime/browser/services/tests/camera-video-capture.test.ts +24 -0
  550. package/bundle/hkp-frontend/src/runtime/browser/services/tests/changes-service.test.ts +133 -0
  551. package/bundle/hkp-frontend/src/runtime/browser/services/tests/crypto-secrets.test.ts +196 -0
  552. package/bundle/hkp-frontend/src/runtime/browser/services/tests/detect-service.test.ts +119 -0
  553. package/bundle/hkp-frontend/src/runtime/browser/services/tests/download.test.ts +100 -0
  554. package/bundle/hkp-frontend/src/runtime/browser/services/tests/expressionEval.test.ts +117 -0
  555. package/bundle/hkp-frontend/src/runtime/browser/services/tests/fetcher-panel.test.tsx +35 -0
  556. package/bundle/hkp-frontend/src/runtime/browser/services/tests/fetcher-service.test.ts +80 -0
  557. package/bundle/hkp-frontend/src/runtime/browser/services/tests/filter-service.test.ts +37 -0
  558. package/bundle/hkp-frontend/src/runtime/browser/services/tests/github-secrets.test.ts +108 -0
  559. package/bundle/hkp-frontend/src/runtime/browser/services/tests/group-by-board.test.ts +42 -0
  560. package/bundle/hkp-frontend/src/runtime/browser/services/tests/hold-service.test.ts +199 -0
  561. package/bundle/hkp-frontend/src/runtime/browser/services/tests/http-client-service.test.ts +474 -0
  562. package/bundle/hkp-frontend/src/runtime/browser/services/tests/http-uploader-token-injector.test.ts +152 -0
  563. package/bundle/hkp-frontend/src/runtime/browser/services/tests/iterator-gather-service.test.ts +277 -0
  564. package/bundle/hkp-frontend/src/runtime/browser/services/tests/map-service.test.ts +1047 -0
  565. package/bundle/hkp-frontend/src/runtime/browser/services/tests/map-ui.test.tsx +70 -0
  566. package/bundle/hkp-frontend/src/runtime/browser/services/tests/nested-rhythm-board.test.ts +311 -0
  567. package/bundle/hkp-frontend/src/runtime/browser/services/tests/night-groove-board.test.ts +290 -0
  568. package/bundle/hkp-frontend/src/runtime/browser/services/tests/pad-groove-board.test.ts +230 -0
  569. package/bundle/hkp-frontend/src/runtime/browser/services/tests/peer-host-discovery.test.ts +77 -0
  570. package/bundle/hkp-frontend/src/runtime/browser/services/tests/peer-socket-discovery.test.ts +69 -0
  571. package/bundle/hkp-frontend/src/runtime/browser/services/tests/pipeline-names.test.ts +63 -0
  572. package/bundle/hkp-frontend/src/runtime/browser/services/tests/secret-canary.test.ts +121 -0
  573. package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-modules.contract.test.ts +229 -0
  574. package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.advanced.test.tsx +670 -0
  575. package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.future-enhancements.test.tsx +219 -0
  576. package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.integration.test.tsx +432 -0
  577. package/bundle/hkp-frontend/src/runtime/browser/services/tests/service-ui.smoke.test.tsx +140 -0
  578. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sound-service.test.ts +293 -0
  579. package/bundle/hkp-frontend/src/runtime/browser/services/tests/spread-service.test.ts +137 -0
  580. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-dump.test.ts +172 -0
  581. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-inspect.test.ts +163 -0
  582. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql-inspector.test.tsx +121 -0
  583. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sql.test.ts +702 -0
  584. package/bundle/hkp-frontend/src/runtime/browser/services/tests/sub-service-in-block.test.tsx +84 -0
  585. package/bundle/hkp-frontend/src/runtime/browser/services/tests/switch-service.test.ts +254 -0
  586. package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-board.test.ts +218 -0
  587. package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-service.test.ts +1002 -0
  588. package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-ui-model.test.ts +230 -0
  589. package/bundle/hkp-frontend/src/runtime/browser/services/tests/timeline-ui.test.tsx +371 -0
  590. package/bundle/hkp-frontend/src/runtime/browser/services/tests/timer-service.test.ts +902 -0
  591. package/bundle/hkp-frontend/src/runtime/browser/services/tests/tracks-service.test.ts +275 -0
  592. package/bundle/hkp-frontend/src/runtime/browser/services/tests/tracks-ui.test.tsx +126 -0
  593. package/bundle/hkp-frontend/src/runtime/browser/services/tests/triggerpad-recorder-board.test.ts +100 -0
  594. package/bundle/hkp-frontend/src/runtime/browser/services/tests/uuid-generator-service.test.ts +214 -0
  595. package/bundle/hkp-frontend/src/runtime/browser/services/timeline-core.ts +410 -0
  596. package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/DefaultWorkflowBoard.ts +90 -0
  597. package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/RefinementSession.ts +121 -0
  598. package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/SystemPromptCatalog.ts +245 -0
  599. package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/catalog/browser-service-specs.json +110 -0
  600. package/bundle/hkp-frontend/src/runtime/browser/services/workflow-prompt/catalog/runtime-capabilities.json +37 -0
  601. package/bundle/hkp-frontend/src/runtime/browser/tests/asset-service.test.ts +73 -0
  602. package/bundle/hkp-frontend/src/runtime/browser/tests/board-persistence.integration.test.tsx +391 -0
  603. package/bundle/hkp-frontend/src/runtime/browser/tests/browser-runtime.identity-binding.test.tsx +81 -0
  604. package/bundle/hkp-frontend/src/runtime/browser/tests/demo-boards.regression.test.tsx +386 -0
  605. package/bundle/hkp-frontend/src/runtime/browser/tests/failed-call-lifecycle.test.ts +56 -0
  606. package/bundle/hkp-frontend/src/runtime/browser/tests/http-client.integration.test.ts +146 -0
  607. package/bundle/hkp-frontend/src/runtime/browser/tests/nested-run.integration.test.ts +415 -0
  608. package/bundle/hkp-frontend/src/runtime/browser/tests/replay-next.test.ts +391 -0
  609. package/bundle/hkp-frontend/src/runtime/browser/tests/rerun.test.ts +71 -0
  610. package/bundle/hkp-frontend/src/runtime/browser/tests/run-no-input.test.ts +72 -0
  611. package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-add.integration.test.tsx +256 -0
  612. package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-operations.integration.test.tsx +310 -0
  613. package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-processing.integration.test.ts +311 -0
  614. package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-removal.integration.test.tsx +454 -0
  615. package/bundle/hkp-frontend/src/runtime/browser/tests/runtime-update.identity.integration.test.tsx +145 -0
  616. package/bundle/hkp-frontend/src/runtime/browser/tests/service-operations.integration.test.tsx +511 -0
  617. package/bundle/hkp-node/src/address.ts +72 -0
  618. package/bundle/hkp-node/src/assets.ts +582 -0
  619. package/bundle/hkp-node/src/auth.ts +369 -0
  620. package/bundle/hkp-node/src/callReport.ts +281 -0
  621. package/bundle/hkp-node/src/coordinator/auth.ts +85 -0
  622. package/bundle/hkp-node/src/coordinator/binaryFrame.ts +189 -0
  623. package/bundle/hkp-node/src/coordinator/boardStore.ts +0 -0
  624. package/bundle/hkp-node/src/coordinator/bridge.ts +242 -0
  625. package/bundle/hkp-node/src/coordinator/bridgeProtocol.ts +200 -0
  626. package/bundle/hkp-node/src/coordinator/coordinator.ts +594 -0
  627. package/bundle/hkp-node/src/coordinator/facadeAccess.ts +426 -0
  628. package/bundle/hkp-node/src/coordinator/fileBoardStore.ts +159 -0
  629. package/bundle/hkp-node/src/coordinator/frameLimits.ts +41 -0
  630. package/bundle/hkp-node/src/coordinator/index.ts +12 -0
  631. package/bundle/hkp-node/src/coordinator/join.ts +62 -0
  632. package/bundle/hkp-node/src/coordinator/logStore.ts +335 -0
  633. package/bundle/hkp-node/src/coordinator/members.ts +133 -0
  634. package/bundle/hkp-node/src/coordinator/mount.ts +124 -0
  635. package/bundle/hkp-node/src/coordinator/participantProtocol.ts +169 -0
  636. package/bundle/hkp-node/src/coordinator/participants.ts +666 -0
  637. package/bundle/hkp-node/src/coordinator/router.ts +416 -0
  638. package/bundle/hkp-node/src/coordinator/session.ts +1610 -0
  639. package/bundle/hkp-node/src/coordinator/types.ts +95 -0
  640. package/bundle/hkp-node/src/coordinatorLinks.ts +712 -0
  641. package/bundle/hkp-node/src/credentialedFetch.ts +122 -0
  642. package/bundle/hkp-node/src/egress.ts +344 -0
  643. package/bundle/hkp-node/src/expressionEval.ts +223 -0
  644. package/bundle/hkp-node/src/index.ts +470 -0
  645. package/bundle/hkp-node/src/instance.ts +172 -0
  646. package/bundle/hkp-node/src/mounts.ts +296 -0
  647. package/bundle/hkp-node/src/origins.ts +201 -0
  648. package/bundle/hkp-node/src/reset.ts +187 -0
  649. package/bundle/hkp-node/src/runtime.ts +1345 -0
  650. package/bundle/hkp-node/src/secrets.ts +292 -0
  651. package/bundle/hkp-node/src/server.ts +2120 -0
  652. package/bundle/hkp-node/src/services/asset.ts +150 -0
  653. package/bundle/hkp-node/src/services/claudeModels.ts +370 -0
  654. package/bundle/hkp-node/src/services/communication-dispatcher.ts +735 -0
  655. package/bundle/hkp-node/src/services/conversations.ts +914 -0
  656. package/bundle/hkp-node/src/services/database.ts +386 -0
  657. package/bundle/hkp-node/src/services/document-extract.ts +575 -0
  658. package/bundle/hkp-node/src/services/expression.ts +417 -0
  659. package/bundle/hkp-node/src/services/fileStore.ts +369 -0
  660. package/bundle/hkp-node/src/services/filesystem.ts +280 -0
  661. package/bundle/hkp-node/src/services/gather.ts +335 -0
  662. package/bundle/hkp-node/src/services/hold.ts +275 -0
  663. package/bundle/hkp-node/src/services/http-client.ts +525 -0
  664. package/bundle/hkp-node/src/services/http-server.ts +1222 -0
  665. package/bundle/hkp-node/src/services/imap-email.ts +627 -0
  666. package/bundle/hkp-node/src/services/injector.ts +135 -0
  667. package/bundle/hkp-node/src/services/iterator.ts +203 -0
  668. package/bundle/hkp-node/src/services/join.ts +226 -0
  669. package/bundle/hkp-node/src/services/map.ts +632 -0
  670. package/bundle/hkp-node/src/services/monitor.ts +128 -0
  671. package/bundle/hkp-node/src/services/nested-pipeline.ts +405 -0
  672. package/bundle/hkp-node/src/services/peer-server.ts +268 -0
  673. package/bundle/hkp-node/src/services/queue-store.ts +301 -0
  674. package/bundle/hkp-node/src/services/queue.ts +316 -0
  675. package/bundle/hkp-node/src/services/recordStore.ts +341 -0
  676. package/bundle/hkp-node/src/services/rss-parse.ts +281 -0
  677. package/bundle/hkp-node/src/services/rss.ts +392 -0
  678. package/bundle/hkp-node/src/services/smtp-email.ts +398 -0
  679. package/bundle/hkp-node/src/services/spread.ts +153 -0
  680. package/bundle/hkp-node/src/services/sql-dump.ts +192 -0
  681. package/bundle/hkp-node/src/services/sql.ts +429 -0
  682. package/bundle/hkp-node/src/services/stopper.ts +69 -0
  683. package/bundle/hkp-node/src/services/storage.ts +332 -0
  684. package/bundle/hkp-node/src/services/store.ts +609 -0
  685. package/bundle/hkp-node/src/services/stream.ts +367 -0
  686. package/bundle/hkp-node/src/services/sub-service.ts +600 -0
  687. package/bundle/hkp-node/src/services/telegram-listener.ts +263 -0
  688. package/bundle/hkp-node/src/services/telegram-sender.ts +136 -0
  689. package/bundle/hkp-node/src/services/text-generation.ts +1249 -0
  690. package/bundle/hkp-node/src/services/timer.ts +273 -0
  691. package/bundle/hkp-node/src/services/tracks.ts +381 -0
  692. package/bundle/hkp-node/src/services/websocket-reader.ts +364 -0
  693. package/bundle/hkp-node/src/types.ts +465 -0
  694. package/bundle/hkp-node/src/wsTickets.ts +77 -0
  695. package/bundle/hkp-node/src/yas.ts +95 -0
  696. package/bundle/hkp-python/src/hkp/__init__.py +1 -0
  697. package/bundle/hkp-python/src/hkp/__main__.py +241 -0
  698. package/bundle/hkp-python/src/hkp/address.py +56 -0
  699. package/bundle/hkp-python/src/hkp/assets.py +439 -0
  700. package/bundle/hkp-python/src/hkp/auth.py +252 -0
  701. package/bundle/hkp-python/src/hkp/binary_frame.py +100 -0
  702. package/bundle/hkp-python/src/hkp/call_report.py +201 -0
  703. package/bundle/hkp-python/src/hkp/coordinator_links.py +667 -0
  704. package/bundle/hkp-python/src/hkp/data.py +118 -0
  705. package/bundle/hkp-python/src/hkp/egress.py +310 -0
  706. package/bundle/hkp-python/src/hkp/mount.py +46 -0
  707. package/bundle/hkp-python/src/hkp/mounts.py +288 -0
  708. package/bundle/hkp-python/src/hkp/origins.py +169 -0
  709. package/bundle/hkp-python/src/hkp/runtime.py +1131 -0
  710. package/bundle/hkp-python/src/hkp/secrets.py +261 -0
  711. package/bundle/hkp-python/src/hkp/server.py +1714 -0
  712. package/bundle/hkp-python/src/hkp/services/__init__.py +0 -0
  713. package/bundle/hkp-python/src/hkp/services/asset.py +123 -0
  714. package/bundle/hkp-python/src/hkp/services/audio_encode.py +190 -0
  715. package/bundle/hkp-python/src/hkp/services/expression.py +942 -0
  716. package/bundle/hkp-python/src/hkp/services/gather.py +266 -0
  717. package/bundle/hkp-python/src/hkp/services/hold.py +246 -0
  718. package/bundle/hkp-python/src/hkp/services/http_client.py +444 -0
  719. package/bundle/hkp-python/src/hkp/services/http_server.py +790 -0
  720. package/bundle/hkp-python/src/hkp/services/iterator.py +141 -0
  721. package/bundle/hkp-python/src/hkp/services/join.py +173 -0
  722. package/bundle/hkp-python/src/hkp/services/map_service.py +452 -0
  723. package/bundle/hkp-python/src/hkp/services/monitor.py +99 -0
  724. package/bundle/hkp-python/src/hkp/services/nested_pipeline.py +278 -0
  725. package/bundle/hkp-python/src/hkp/services/skill_router.py +388 -0
  726. package/bundle/hkp-python/src/hkp/services/speech_to_text.py +186 -0
  727. package/bundle/hkp-python/src/hkp/services/spread.py +114 -0
  728. package/bundle/hkp-python/src/hkp/services/stopper.py +59 -0
  729. package/bundle/hkp-python/src/hkp/services/sub_service.py +417 -0
  730. package/bundle/hkp-python/src/hkp/services/text_generation.py +498 -0
  731. package/bundle/hkp-python/src/hkp/services/text_to_speech.py +237 -0
  732. package/bundle/hkp-python/src/hkp/services/timer.py +267 -0
  733. package/bundle/hkp-python/src/hkp/services/tracks.py +251 -0
  734. package/bundle/hkp-python/src/hkp/types.py +412 -0
  735. package/bundle/hkp-python/src/hkp/ws_tickets.py +54 -0
  736. package/bundle/hkp-python/src/hkp/yas.py +192 -0
  737. package/bundle/hkp-rt/lib/CMakeLists.txt +193 -0
  738. package/bundle/hkp-rt/lib/hkp-bundles/CMakeLists.txt +55 -0
  739. package/bundle/hkp-rt/lib/hkp-bundles/plugin_register.cpp +14 -0
  740. package/bundle/hkp-rt/lib/include/app.h +201 -0
  741. package/bundle/hkp-rt/lib/include/assets.h +239 -0
  742. package/bundle/hkp-rt/lib/include/auth.h +167 -0
  743. package/bundle/hkp-rt/lib/include/call_report.h +197 -0
  744. package/bundle/hkp-rt/lib/include/coordinator_links.h +127 -0
  745. package/bundle/hkp-rt/lib/include/discovery_hooks.h +29 -0
  746. package/bundle/hkp-rt/lib/include/egress.h +379 -0
  747. package/bundle/hkp-rt/lib/include/files.h +275 -0
  748. package/bundle/hkp-rt/lib/include/log_entry.h +131 -0
  749. package/bundle/hkp-rt/lib/include/mounts.h +139 -0
  750. package/bundle/hkp-rt/lib/include/origins.h +363 -0
  751. package/bundle/hkp-rt/lib/include/registry.h +119 -0
  752. package/bundle/hkp-rt/lib/include/secrets.h +414 -0
  753. package/bundle/hkp-rt/lib/include/server.h +122 -0
  754. package/bundle/hkp-rt/lib/include/service.h +190 -0
  755. package/bundle/hkp-rt/lib/include/slot_store.h +41 -0
  756. package/bundle/hkp-rt/lib/include/standalone_config.h +253 -0
  757. package/bundle/hkp-rt/lib/include/types/audio.h +3 -0
  758. package/bundle/hkp-rt/lib/include/types/data.h +152 -0
  759. package/bundle/hkp-rt/lib/include/types/message.h +56 -0
  760. package/bundle/hkp-rt/lib/include/types/models.h +154 -0
  761. package/bundle/hkp-rt/lib/include/types/owns_me.h +19 -0
  762. package/bundle/hkp-rt/lib/include/types/ringbuffer.h +86 -0
  763. package/bundle/hkp-rt/lib/include/types/types.h +33 -0
  764. package/bundle/hkp-rt/lib/include/types/validation.h +205 -0
  765. package/bundle/hkp-rt/lib/src/address.h +88 -0
  766. package/bundle/hkp-rt/lib/src/app.cpp +591 -0
  767. package/bundle/hkp-rt/lib/src/assets.cpp +686 -0
  768. package/bundle/hkp-rt/lib/src/binary_frame.h +154 -0
  769. package/bundle/hkp-rt/lib/src/common/expression.h +1481 -0
  770. package/bundle/hkp-rt/lib/src/common/inja.h +36 -0
  771. package/bundle/hkp-rt/lib/src/common/link_socket.cpp +437 -0
  772. package/bundle/hkp-rt/lib/src/common/link_socket.h +97 -0
  773. package/bundle/hkp-rt/lib/src/common/realtime_wakeup.h +120 -0
  774. package/bundle/hkp-rt/lib/src/common/stream_broadcast.h +250 -0
  775. package/bundle/hkp-rt/lib/src/common/string_util.h +31 -0
  776. package/bundle/hkp-rt/lib/src/common/websocket_client_session.cpp +217 -0
  777. package/bundle/hkp-rt/lib/src/common/websocket_client_session.h +37 -0
  778. package/bundle/hkp-rt/lib/src/common/websocket_config.h +119 -0
  779. package/bundle/hkp-rt/lib/src/common/websocket_protocol.h +32 -0
  780. package/bundle/hkp-rt/lib/src/common/websocket_server.cpp +82 -0
  781. package/bundle/hkp-rt/lib/src/common/websocket_server.h +57 -0
  782. package/bundle/hkp-rt/lib/src/common/websocket_server_listener.cpp +115 -0
  783. package/bundle/hkp-rt/lib/src/common/websocket_server_listener.h +35 -0
  784. package/bundle/hkp-rt/lib/src/common/websocket_server_session.cpp +172 -0
  785. package/bundle/hkp-rt/lib/src/common/websocket_server_session.h +53 -0
  786. package/bundle/hkp-rt/lib/src/common.h +13 -0
  787. package/bundle/hkp-rt/lib/src/coordinator_links.cpp +1142 -0
  788. package/bundle/hkp-rt/lib/src/discovery/discovery.cpp +707 -0
  789. package/bundle/hkp-rt/lib/src/discovery/discovery.h +89 -0
  790. package/bundle/hkp-rt/lib/src/http/auth.cpp +569 -0
  791. package/bundle/hkp-rt/lib/src/http/front_door.cpp +518 -0
  792. package/bundle/hkp-rt/lib/src/http/front_door.h +131 -0
  793. package/bundle/hkp-rt/lib/src/http/server.cpp +1539 -0
  794. package/bundle/hkp-rt/lib/src/http/ws_tickets.h +125 -0
  795. package/bundle/hkp-rt/lib/src/mount.h +63 -0
  796. package/bundle/hkp-rt/lib/src/process_context.h +335 -0
  797. package/bundle/hkp-rt/lib/src/process_depth.h +20 -0
  798. package/bundle/hkp-rt/lib/src/registry.cpp +233 -0
  799. package/bundle/hkp-rt/lib/src/runtime.cpp +986 -0
  800. package/bundle/hkp-rt/lib/src/runtime.h +225 -0
  801. package/bundle/hkp-rt/lib/src/runtime_host.h +180 -0
  802. package/bundle/hkp-rt/lib/src/service.cpp +315 -0
  803. package/bundle/hkp-rt/lib/src/services/asset.h +185 -0
  804. package/bundle/hkp-rt/lib/src/services/audio_encode.cpp +372 -0
  805. package/bundle/hkp-rt/lib/src/services/audio_encode.h +97 -0
  806. package/bundle/hkp-rt/lib/src/services/cache.h +362 -0
  807. package/bundle/hkp-rt/lib/src/services/cache_subservices.h +463 -0
  808. package/bundle/hkp-rt/lib/src/services/core_audio.cpp +384 -0
  809. package/bundle/hkp-rt/lib/src/services/core_audio.h +22 -0
  810. package/bundle/hkp-rt/lib/src/services/core_input.h +337 -0
  811. package/bundle/hkp-rt/lib/src/services/core_output.h +370 -0
  812. package/bundle/hkp-rt/lib/src/services/ffmpeg/detail.cpp +749 -0
  813. package/bundle/hkp-rt/lib/src/services/ffmpeg/detail.h +29 -0
  814. package/bundle/hkp-rt/lib/src/services/ffmpeg/ffmpeg.cpp +193 -0
  815. package/bundle/hkp-rt/lib/src/services/ffmpeg/ffmpeg.h +40 -0
  816. package/bundle/hkp-rt/lib/src/services/ffmpeg/types.h +120 -0
  817. package/bundle/hkp-rt/lib/src/services/fft_service.h +190 -0
  818. package/bundle/hkp-rt/lib/src/services/filesystem.h +309 -0
  819. package/bundle/hkp-rt/lib/src/services/filter.h +208 -0
  820. package/bundle/hkp-rt/lib/src/services/gather.h +272 -0
  821. package/bundle/hkp-rt/lib/src/services/hold.h +304 -0
  822. package/bundle/hkp-rt/lib/src/services/http_client.cpp +347 -0
  823. package/bundle/hkp-rt/lib/src/services/http_client.h +67 -0
  824. package/bundle/hkp-rt/lib/src/services/http_client_impl.h +45 -0
  825. package/bundle/hkp-rt/lib/src/services/http_client_template_examples.md +202 -0
  826. package/bundle/hkp-rt/lib/src/services/http_server/http_listener.cpp +130 -0
  827. package/bundle/hkp-rt/lib/src/services/http_server/http_listener.h +33 -0
  828. package/bundle/hkp-rt/lib/src/services/http_server/http_server.cpp +351 -0
  829. package/bundle/hkp-rt/lib/src/services/http_server/http_server.h +79 -0
  830. package/bundle/hkp-rt/lib/src/services/http_server/http_server_impl.cpp +230 -0
  831. package/bundle/hkp-rt/lib/src/services/http_server/http_server_impl.h +64 -0
  832. package/bundle/hkp-rt/lib/src/services/http_server/http_server_subservices.cpp +950 -0
  833. package/bundle/hkp-rt/lib/src/services/http_server/http_server_subservices.h +253 -0
  834. package/bundle/hkp-rt/lib/src/services/http_server/http_session.cpp +495 -0
  835. package/bundle/hkp-rt/lib/src/services/http_server/http_session.h +169 -0
  836. package/bundle/hkp-rt/lib/src/services/http_server/http_stream_listener.cpp +270 -0
  837. package/bundle/hkp-rt/lib/src/services/http_server/http_stream_listener.h +104 -0
  838. package/bundle/hkp-rt/lib/src/services/http_server/request_decode.h +164 -0
  839. package/bundle/hkp-rt/lib/src/services/if_service.h +210 -0
  840. package/bundle/hkp-rt/lib/src/services/ifft_service.h +198 -0
  841. package/bundle/hkp-rt/lib/src/services/injector.h +162 -0
  842. package/bundle/hkp-rt/lib/src/services/iterator.h +201 -0
  843. package/bundle/hkp-rt/lib/src/services/map.h +641 -0
  844. package/bundle/hkp-rt/lib/src/services/monitor.h +161 -0
  845. package/bundle/hkp-rt/lib/src/services/mp3_frames.h +119 -0
  846. package/bundle/hkp-rt/lib/src/services/mp4_to_wav.cpp +281 -0
  847. package/bundle/hkp-rt/lib/src/services/mp4_to_wav.h +263 -0
  848. package/bundle/hkp-rt/lib/src/services/peer_server/peer_registry.cpp +88 -0
  849. package/bundle/hkp-rt/lib/src/services/peer_server/peer_registry.h +43 -0
  850. package/bundle/hkp-rt/lib/src/services/peer_server/peer_server.h +163 -0
  851. package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_listener.cpp +133 -0
  852. package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_listener.h +46 -0
  853. package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_session.cpp +165 -0
  854. package/bundle/hkp-rt/lib/src/services/peer_server/peer_server_session.h +44 -0
  855. package/bundle/hkp-rt/lib/src/services/peer_server/peer_ws_session.cpp +184 -0
  856. package/bundle/hkp-rt/lib/src/services/peer_server/peer_ws_session.h +55 -0
  857. package/bundle/hkp-rt/lib/src/services/receiver_session.h +172 -0
  858. package/bundle/hkp-rt/lib/src/services/root_certificates.h +3959 -0
  859. package/bundle/hkp-rt/lib/src/services/sha256_openssl.h +49 -0
  860. package/bundle/hkp-rt/lib/src/services/speech_http.h +306 -0
  861. package/bundle/hkp-rt/lib/src/services/speech_to_text.cpp +595 -0
  862. package/bundle/hkp-rt/lib/src/services/speech_to_text.h +69 -0
  863. package/bundle/hkp-rt/lib/src/services/static.cpp +45 -0
  864. package/bundle/hkp-rt/lib/src/services/static.h +41 -0
  865. package/bundle/hkp-rt/lib/src/services/stopper.h +72 -0
  866. package/bundle/hkp-rt/lib/src/services/sub_service.h +286 -0
  867. package/bundle/hkp-rt/lib/src/services/text_generation.cpp +1132 -0
  868. package/bundle/hkp-rt/lib/src/services/text_generation.h +71 -0
  869. package/bundle/hkp-rt/lib/src/services/text_to_speech.cpp +853 -0
  870. package/bundle/hkp-rt/lib/src/services/text_to_speech.h +97 -0
  871. package/bundle/hkp-rt/lib/src/services/timer.h +300 -0
  872. package/bundle/hkp-rt/lib/src/services/tracks.h +397 -0
  873. package/bundle/hkp-rt/lib/src/services/tts_inflect.cpp +149 -0
  874. package/bundle/hkp-rt/lib/src/services/tts_inflect.h +82 -0
  875. package/bundle/hkp-rt/lib/src/services/wav_reader.h +213 -0
  876. package/bundle/hkp-rt/lib/src/services/websocket_client_service.h +182 -0
  877. package/bundle/hkp-rt/lib/src/services/websocket_reader.h +148 -0
  878. package/bundle/hkp-rt/lib/src/services/websocket_server_service.h +196 -0
  879. package/bundle/hkp-rt/lib/src/services/websocket_writer.cpp +641 -0
  880. package/bundle/hkp-rt/lib/src/services/websocket_writer.h +117 -0
  881. package/bundle/hkp-rt/lib/src/sub_runtime.cpp +234 -0
  882. package/bundle/hkp-rt/lib/src/sub_runtime.h +160 -0
  883. package/bundle/hkp-rt/lib/src/types/data.cpp +237 -0
  884. package/bundle/hkp-rt/lib/src/types/message.cpp +148 -0
  885. package/bundle/hkp-rt/lib/src/types/models.cpp +83 -0
  886. package/bundle/hkp-rt/lib/src/types/ringbuffer.cpp +336 -0
  887. package/bundle/hkp-rt/lib/src/uuid.h +12 -0
  888. package/bundle/readymade-mcp-commits.json +5 -0
  889. package/dist/cli.d.ts +3 -0
  890. package/dist/cli.d.ts.map +1 -0
  891. package/dist/cli.js +79 -0
  892. package/dist/git.d.ts +8 -0
  893. package/dist/git.d.ts.map +1 -0
  894. package/dist/git.js +53 -0
  895. package/dist/http.d.ts +17 -0
  896. package/dist/http.d.ts.map +1 -0
  897. package/dist/http.js +130 -0
  898. package/dist/index.d.ts +7 -0
  899. package/dist/index.d.ts.map +1 -0
  900. package/dist/index.js +6 -0
  901. package/dist/repository.d.ts +49 -0
  902. package/dist/repository.d.ts.map +1 -0
  903. package/dist/repository.js +452 -0
  904. package/dist/schemas.d.ts +156 -0
  905. package/dist/schemas.d.ts.map +1 -0
  906. package/dist/schemas.js +43 -0
  907. package/dist/server.d.ts +4 -0
  908. package/dist/server.d.ts.map +1 -0
  909. package/dist/server.js +83 -0
  910. package/dist/types.d.ts +63 -0
  911. package/dist/types.d.ts.map +1 -0
  912. package/dist/types.js +20 -0
  913. package/dist/validation.d.ts +9 -0
  914. package/dist/validation.d.ts.map +1 -0
  915. package/dist/validation.js +101 -0
  916. package/package.json +52 -4
@@ -0,0 +1,942 @@
1
+ """Expression evaluation for services that let a board author write small
2
+ dynamic terms — a Map template's ``key=`` rows, for example.
3
+
4
+ An expression is a single JavaScript-style expression evaluated with the
5
+ incoming data bound to ``params`` and the helper functions below in scope. The
6
+ browser, Node and C++ runtimes evaluate the same sources, so the dialect and the
7
+ helper set are kept aligned: a template authored in the shared Map UI behaves
8
+ the same whichever runtime hosts the service. Helpers that need a browser (DOM,
9
+ vault, AudioContext) have no counterpart here.
10
+
11
+ Supported: literals (number, string, true/false/null), array literals,
12
+ identifiers, member and index access, calls into the builtin table, unary
13
+ ``!``/``-``/``+``, ``* / %``, ``+ -``, ``< <= > >=``, ``== != === !==``,
14
+ ``&& ||`` and the ternary operator. There are no assignments, no statements and
15
+ no lambdas — ``find``/``filter`` take their predicate as an expression string
16
+ with the element bound to ``item`` (and its position to ``index``).
17
+
18
+ Python spellings are accepted alongside the JavaScript ones (``and``/``or``/
19
+ ``not``, ``True``/``False``/``None``) and the builtin table carries the Python
20
+ conversions the previous evaluator exposed, so flat templates written against
21
+ it keep working.
22
+
23
+ expression = Expression.parse("round(params.value * 2)")
24
+ result = expression.evaluate(input) # raises EvaluationError on failure
25
+
26
+ A member of nothing is nothing: ``params.a.b`` with no ``a`` is ``None``, as in
27
+ the browser, Node and C++ runtimes. Whoever wants to know which reads came up
28
+ empty passes ``on_missing``.
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import json as json_module
34
+ import math
35
+ import random
36
+ import re
37
+ import time
38
+ import uuid as uuid_module
39
+ from contextvars import ContextVar
40
+ from dataclasses import dataclass, field
41
+ from datetime import datetime
42
+ from typing import Any, Callable
43
+ from urllib.parse import quote
44
+
45
+
46
+ class ParseError(Exception):
47
+ """Raised when an expression source cannot be parsed."""
48
+
49
+
50
+ class EvaluationError(Exception):
51
+ """Raised when a parsed expression cannot be evaluated."""
52
+
53
+
54
+ # ── Value helpers ──────────────────────────────────────────────────────────────
55
+
56
+
57
+ def is_truthy(value: Any) -> bool:
58
+ if value is None or value is False:
59
+ return False
60
+ if value is True:
61
+ return True
62
+ if isinstance(value, (int, float)):
63
+ return value != 0
64
+ if isinstance(value, str):
65
+ return value != ""
66
+ return True # objects and arrays are truthy, empty or not
67
+
68
+
69
+ def to_number(value: Any) -> float:
70
+ """JS-style numeric coercion. Returns NaN for anything that is not numeric."""
71
+ if isinstance(value, bool):
72
+ return 1.0 if value else 0.0
73
+ if isinstance(value, (int, float)):
74
+ return float(value)
75
+ if value is None:
76
+ return 0.0
77
+ if isinstance(value, str):
78
+ try:
79
+ return float(value.strip())
80
+ except ValueError:
81
+ return math.nan
82
+ return math.nan
83
+
84
+
85
+ def to_text(value: Any) -> str:
86
+ """Renders a value the way JSON.stringify would, so 42 does not become 42.0."""
87
+ if isinstance(value, str):
88
+ return value
89
+ if value is None:
90
+ return "null"
91
+ if value is True:
92
+ return "true"
93
+ if value is False:
94
+ return "false"
95
+ if isinstance(value, float) and value.is_integer():
96
+ return str(int(value))
97
+ if isinstance(value, (int, float)):
98
+ return str(value)
99
+ return json_module.dumps(value, separators=(",", ":"))
100
+
101
+
102
+ def _number(value: float) -> Any:
103
+ """An integral result is stored as an int; NaN has no JSON form and is null."""
104
+ if isinstance(value, float):
105
+ if math.isnan(value) or math.isinf(value):
106
+ return None
107
+ if value.is_integer():
108
+ return int(value)
109
+ return value
110
+
111
+
112
+ # ── Date helpers (moment-style token subset shared with the other runtimes) ────
113
+
114
+ _MONTHS = [
115
+ "January", "February", "March", "April", "May", "June",
116
+ "July", "August", "September", "October", "November", "December",
117
+ ]
118
+
119
+ _WEEKDAYS = [
120
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
121
+ ]
122
+
123
+ # Longest token first, so "MMMM" is matched before "MM".
124
+ _TOKEN_PATTERN = re.compile(
125
+ r"\[([^\]]*)\]|YYYY|YY|MMMM|MMM|MM|M|DD|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|A|a"
126
+ )
127
+
128
+
129
+ def _format_date(value: datetime, fmt: str) -> str:
130
+ weekday = (value.weekday() + 1) % 7 # datetime weeks start on Monday
131
+ hours12 = value.hour % 12 or 12
132
+
133
+ def render(match: re.Match[str]) -> str:
134
+ if match.group(1) is not None:
135
+ return match.group(1)
136
+ token = match.group(0)
137
+ return {
138
+ "YYYY": f"{value.year}",
139
+ "YY": f"{value.year % 100:02d}",
140
+ "MMMM": _MONTHS[value.month - 1],
141
+ "MMM": _MONTHS[value.month - 1][:3],
142
+ "MM": f"{value.month:02d}",
143
+ "M": f"{value.month}",
144
+ "DD": f"{value.day:02d}",
145
+ "D": f"{value.day}",
146
+ "dddd": _WEEKDAYS[weekday],
147
+ "ddd": _WEEKDAYS[weekday][:3],
148
+ "HH": f"{value.hour:02d}",
149
+ "H": f"{value.hour}",
150
+ "hh": f"{hours12:02d}",
151
+ "h": f"{hours12}",
152
+ "mm": f"{value.minute:02d}",
153
+ "m": f"{value.minute}",
154
+ "ss": f"{value.second:02d}",
155
+ "s": f"{value.second}",
156
+ "A": "AM" if value.hour < 12 else "PM",
157
+ "a": "am" if value.hour < 12 else "pm",
158
+ }[token]
159
+
160
+ return _TOKEN_PATTERN.sub(render, fmt)
161
+
162
+
163
+ def _parse_date(text: str, fmt: str) -> datetime | None:
164
+ """Reads a date written in the token subset above, or None when it does not fit."""
165
+ pattern = ""
166
+ captured: list[str] = []
167
+ last = 0
168
+
169
+ for match in _TOKEN_PATTERN.finditer(fmt):
170
+ pattern += re.escape(fmt[last : match.start()])
171
+ last = match.end()
172
+
173
+ if match.group(1) is not None:
174
+ pattern += re.escape(match.group(1))
175
+ continue
176
+
177
+ token = match.group(0)
178
+ captured.append(token)
179
+ if token == "YYYY":
180
+ pattern += r"(\d{4})"
181
+ elif token in ("MMMM", "MMM", "dddd", "ddd"):
182
+ pattern += r"([A-Za-z]+)"
183
+ elif token in ("A", "a"):
184
+ pattern += r"([AaPp][Mm])"
185
+ else:
186
+ pattern += r"(\d{1,2})"
187
+ pattern += re.escape(fmt[last:])
188
+
189
+ if not captured:
190
+ return None
191
+
192
+ match = re.fullmatch(pattern, str(text).strip())
193
+ if not match:
194
+ return None
195
+
196
+ parts = {"year": 1970, "month": 1, "day": 1, "hour": 0, "minute": 0, "second": 0}
197
+ pm = False
198
+ hours12 = False
199
+
200
+ for token, raw in zip(captured, match.groups()):
201
+ if token == "YYYY":
202
+ parts["year"] = int(raw)
203
+ elif token == "YY":
204
+ parts["year"] = 2000 + int(raw)
205
+ elif token in ("MMMM", "MMM"):
206
+ name = raw.lower()
207
+ for index, month in enumerate(_MONTHS):
208
+ if month.lower().startswith(name):
209
+ parts["month"] = index + 1
210
+ break
211
+ elif token in ("MM", "M"):
212
+ parts["month"] = int(raw)
213
+ elif token in ("DD", "D"):
214
+ parts["day"] = int(raw)
215
+ elif token in ("HH", "H"):
216
+ parts["hour"] = int(raw)
217
+ elif token in ("hh", "h"):
218
+ parts["hour"] = int(raw)
219
+ hours12 = True
220
+ elif token in ("mm", "m"):
221
+ parts["minute"] = int(raw)
222
+ elif token in ("ss", "s"):
223
+ parts["second"] = int(raw)
224
+ elif token in ("A", "a"):
225
+ pm = raw.lower() == "pm"
226
+
227
+ if hours12:
228
+ parts["hour"] = (parts["hour"] % 12) + (12 if pm else 0)
229
+
230
+ try:
231
+ return datetime(**parts) # type: ignore[arg-type]
232
+ except ValueError:
233
+ return None
234
+
235
+
236
+ def _to_epoch_millis(value: Any) -> float | None:
237
+ """Milliseconds for anything the other runtimes accept: a number or ISO-8601."""
238
+ if isinstance(value, bool) or value is None:
239
+ return None
240
+ if isinstance(value, (int, float)):
241
+ return float(value)
242
+ if not isinstance(value, str):
243
+ return None
244
+ text = value.strip().replace("Z", "+00:00")
245
+ try:
246
+ return datetime.fromisoformat(text).timestamp() * 1000
247
+ except ValueError:
248
+ return None
249
+
250
+
251
+ def _now_millis() -> int:
252
+ return int(time.time() * 1000)
253
+
254
+
255
+ def _uuid_v7() -> str:
256
+ millis = _now_millis()
257
+ data = bytearray(random.getrandbits(8) for _ in range(16))
258
+ for i in range(6):
259
+ data[i] = (millis >> (8 * (5 - i))) & 0xFF
260
+ data[6] = (data[6] & 0x0F) | 0x70 # version 7
261
+ data[8] = (data[8] & 0x3F) | 0x80 # variant
262
+ return str(uuid_module.UUID(bytes=bytes(data)))
263
+
264
+
265
+ # ── AST ────────────────────────────────────────────────────────────────────────
266
+
267
+
268
+ @dataclass
269
+ class _Node:
270
+ kind: str
271
+ value: Any = None
272
+ name: str = ""
273
+ computed: bool = False
274
+ left: "_Node | None" = None
275
+ right: "_Node | None" = None
276
+ third: "_Node | None" = None
277
+ items: list["_Node"] = field(default_factory=list)
278
+
279
+
280
+ # Lowest precedence first. The Python spellings are aliases for the JS operators.
281
+ _BINARY_LEVELS: list[list[str]] = [
282
+ ["||", "or"],
283
+ ["&&", "and"],
284
+ ["===", "!==", "==", "!="],
285
+ ["<=", ">=", "<", ">"],
286
+ ["+", "-"],
287
+ ["*", "/", "%"],
288
+ ]
289
+
290
+ _WORD_OPERATORS = {"or", "and", "not"}
291
+
292
+ _IDENTIFIER_START = re.compile(r"[A-Za-z_$]")
293
+ _IDENTIFIER_PART = re.compile(r"[A-Za-z0-9_$]")
294
+
295
+
296
+ class _Parser:
297
+ def __init__(self, source: str) -> None:
298
+ self._source = source
299
+ self._pos = 0
300
+
301
+ def parse(self) -> _Node:
302
+ self._skip_space()
303
+ node = self._parse_expression()
304
+ self._skip_space()
305
+ if self._pos != len(self._source):
306
+ raise ParseError(f"unexpected {self._source[self._pos:]!r}")
307
+ return node
308
+
309
+ # ── Grammar ────────────────────────────────────────────────────────────────
310
+
311
+ def _parse_expression(self) -> _Node:
312
+ return self._parse_conditional()
313
+
314
+ def _parse_conditional(self) -> _Node:
315
+ test = self._parse_binary(0)
316
+ self._skip_space()
317
+ if self._peek() != "?":
318
+ return test
319
+ self._pos += 1
320
+ consequent = self._parse_expression()
321
+ self._skip_space()
322
+ self._expect(":")
323
+ alternate = self._parse_expression()
324
+ return _Node("conditional", left=test, right=consequent, third=alternate)
325
+
326
+ def _parse_binary(self, level: int) -> _Node:
327
+ if level >= len(_BINARY_LEVELS):
328
+ return self._parse_unary()
329
+
330
+ left = self._parse_binary(level + 1)
331
+ while True:
332
+ self._skip_space()
333
+ matched = self._match_operator(_BINARY_LEVELS[level])
334
+ if not matched:
335
+ return left
336
+ right = self._parse_binary(level + 1)
337
+ kind = "logical" if matched in ("&&", "||", "and", "or") else "binary"
338
+ left = _Node(kind, name=matched, left=left, right=right)
339
+
340
+ def _match_operator(self, operators: list[str]) -> str | None:
341
+ for operator in operators:
342
+ if not self._source.startswith(operator, self._pos):
343
+ continue
344
+ end = self._pos + len(operator)
345
+ if operator in _WORD_OPERATORS:
346
+ # "and"/"or" are operators, "android" is an identifier.
347
+ if end < len(self._source) and _IDENTIFIER_PART.match(self._source[end]):
348
+ continue
349
+ self._pos = end
350
+ return operator
351
+ return None
352
+
353
+ def _parse_unary(self) -> _Node:
354
+ self._skip_space()
355
+ char = self._peek()
356
+ if char in ("!", "-", "+") and not self._source.startswith("!=", self._pos):
357
+ self._pos += 1
358
+ return _Node("unary", name=char, left=self._parse_unary())
359
+ if self._match_operator(["not"]):
360
+ return _Node("unary", name="!", left=self._parse_unary())
361
+ return self._parse_postfix()
362
+
363
+ def _parse_postfix(self) -> _Node:
364
+ node = self._parse_primary()
365
+ while True:
366
+ self._skip_space()
367
+ char = self._peek()
368
+ if char == ".":
369
+ self._pos += 1
370
+ node = _Node("member", left=node, name=self._parse_identifier())
371
+ elif char == "[":
372
+ self._pos += 1
373
+ index = self._parse_expression()
374
+ self._skip_space()
375
+ self._expect("]")
376
+ node = _Node("member", left=node, right=index, computed=True)
377
+ elif char == "(":
378
+ self._pos += 1
379
+ node = _Node("call", left=node, items=self._parse_arguments(")"))
380
+ else:
381
+ return node
382
+
383
+ def _parse_arguments(self, closing: str) -> list[_Node]:
384
+ args: list[_Node] = []
385
+ self._skip_space()
386
+ if self._peek() == closing:
387
+ self._pos += 1
388
+ return args
389
+
390
+ while True:
391
+ args.append(self._parse_expression())
392
+ self._skip_space()
393
+ if self._peek() == ",":
394
+ self._pos += 1
395
+ continue
396
+ self._expect(closing)
397
+ return args
398
+
399
+ def _parse_primary(self) -> _Node:
400
+ self._skip_space()
401
+ char = self._peek()
402
+
403
+ if char == "":
404
+ raise ParseError("unexpected end of expression")
405
+
406
+ if char == "(":
407
+ self._pos += 1
408
+ node = self._parse_expression()
409
+ self._skip_space()
410
+ self._expect(")")
411
+ return node
412
+
413
+ if char == "[":
414
+ self._pos += 1
415
+ return _Node("array", items=self._parse_arguments("]"))
416
+
417
+ if char in ("'", '"'):
418
+ return _Node("literal", value=self._parse_string(char))
419
+
420
+ if char.isdigit() or (char == "." and self._peek(1).isdigit()):
421
+ return _Node("literal", value=self._parse_number())
422
+
423
+ name = self._parse_identifier()
424
+ if name in ("true", "True"):
425
+ return _Node("literal", value=True)
426
+ if name in ("false", "False"):
427
+ return _Node("literal", value=False)
428
+ if name in ("null", "undefined", "None"):
429
+ return _Node("literal", value=None)
430
+ return _Node("identifier", name=name)
431
+
432
+ def _parse_string(self, quote_char: str) -> str:
433
+ self._pos += 1 # opening quote
434
+ text = ""
435
+ escapes = {"n": "\n", "t": "\t", "r": "\r"}
436
+ while self._pos < len(self._source) and self._source[self._pos] != quote_char:
437
+ char = self._source[self._pos]
438
+ if char == "\\" and self._pos + 1 < len(self._source):
439
+ self._pos += 1
440
+ char = escapes.get(self._source[self._pos], self._source[self._pos])
441
+ text += char
442
+ self._pos += 1
443
+ if self._pos >= len(self._source):
444
+ raise ParseError("unterminated string literal")
445
+ self._pos += 1 # closing quote
446
+ return text
447
+
448
+ def _parse_number(self) -> Any:
449
+ start = self._pos
450
+ while self._pos < len(self._source):
451
+ char = self._source[self._pos]
452
+ previous = self._source[self._pos - 1] if self._pos > start else ""
453
+ if char.isdigit() or char in (".", "e", "E"):
454
+ self._pos += 1
455
+ elif char in ("+", "-") and previous in ("e", "E"):
456
+ self._pos += 1
457
+ else:
458
+ break
459
+
460
+ text = self._source[start : self._pos]
461
+ try:
462
+ return _number(float(text))
463
+ except ValueError as error:
464
+ raise ParseError(f"invalid number {text!r}") from error
465
+
466
+ def _parse_identifier(self) -> str:
467
+ self._skip_space()
468
+ start = self._pos
469
+ if self._pos < len(self._source) and _IDENTIFIER_START.match(self._source[self._pos]):
470
+ self._pos += 1
471
+ while self._pos < len(self._source) and _IDENTIFIER_PART.match(
472
+ self._source[self._pos]
473
+ ):
474
+ self._pos += 1
475
+ if self._pos == start:
476
+ raise ParseError(f"expected an identifier at position {start}")
477
+ return self._source[start : self._pos]
478
+
479
+ # ── Scanning ───────────────────────────────────────────────────────────────
480
+
481
+ def _skip_space(self) -> None:
482
+ while self._pos < len(self._source) and self._source[self._pos].isspace():
483
+ self._pos += 1
484
+
485
+ def _expect(self, char: str) -> None:
486
+ if self._peek() != char:
487
+ raise ParseError(f"expected {char!r}")
488
+ self._pos += 1
489
+
490
+ def _peek(self, offset: int = 0) -> str:
491
+ index = self._pos + offset
492
+ return self._source[index] if index < len(self._source) else ""
493
+
494
+
495
+ def _callee_name(node: _Node | None) -> str | None:
496
+ """Flattens an identifier/member chain into a dotted name, so ``uuid.v4`` can
497
+ be looked up in the builtin table. Returns None for anything else."""
498
+ if node is None:
499
+ return None
500
+ if node.kind == "identifier":
501
+ return node.name
502
+ if node.kind == "member" and not node.computed:
503
+ prefix = _callee_name(node.left)
504
+ return None if prefix is None else f"{prefix}.{node.name}"
505
+ return None
506
+
507
+
508
+ # Told the path of a read that found nothing — ``params.titel`` — during the
509
+ # evaluation that asked for it, and only that one: a find/filter predicate
510
+ # evaluated inside it reports nothing, as in the other runtimes.
511
+ _on_missing: ContextVar[Callable[[str], None] | None] = ContextVar("_on_missing", default=None)
512
+
513
+
514
+ def _path_of(node: _Node | None) -> str:
515
+ """How a read is named when it is reported: ``params.items[0].title``."""
516
+ if node is None:
517
+ return "…"
518
+ if node.kind == "identifier":
519
+ return node.name
520
+ if node.kind == "member":
521
+ obj = _path_of(node.left)
522
+ if not node.computed:
523
+ return f"{obj}.{node.name}"
524
+ if node.right is not None and node.right.kind == "literal":
525
+ return f"{obj}[{json_module.dumps(node.right.value)}]"
526
+ return f"{obj}[…]"
527
+ return "…"
528
+
529
+
530
+ # What a member read returns when nothing is there, told apart from a None that
531
+ # is.
532
+ _MISSING = object()
533
+
534
+
535
+ def _member(obj: Any, key: Any) -> Any:
536
+ """What ``obj[key]`` finds, or ``_MISSING`` when nothing is there.
537
+
538
+ One set of rules for every container, so what a read finds and whether it
539
+ found anything cannot disagree: a list, tuple or string is a sequence — its
540
+ ``length``, or the item at an index within it — and a dict is read by the
541
+ key as text.
542
+ """
543
+ if isinstance(obj, (list, tuple, str)):
544
+ if key == "length":
545
+ return len(obj)
546
+ index = to_number(key)
547
+ if math.isnan(index) or not 0 <= index < len(obj):
548
+ return _MISSING
549
+ return obj[int(index)]
550
+ if isinstance(obj, dict):
551
+ return obj.get(key if isinstance(key, str) else to_text(key), _MISSING)
552
+ return _MISSING
553
+
554
+
555
+ def _read_member(node: _Node, scope: dict[str, Any]) -> tuple[Any, bool]:
556
+ """A member read's value, and whether it found something there.
557
+
558
+ A read past a link that came up empty was reported with it; one past a link
559
+ that is there but None is reported itself. Only a member read can tell the
560
+ two apart, which is why the chain is walked here rather than through
561
+ ``_evaluate_node``.
562
+ """
563
+ if node.left is not None and node.left.kind == "member":
564
+ obj, obj_found = _read_member(node.left, scope)
565
+ else:
566
+ obj, obj_found = _evaluate_node(node.left, scope), True
567
+ key = _evaluate_node(node.right, scope) if node.computed else node.name
568
+ value = _member(obj, key)
569
+ if value is not _MISSING:
570
+ return value, True
571
+ on_missing = _on_missing.get()
572
+ if on_missing is not None and obj_found:
573
+ on_missing(_path_of(node))
574
+ return None, False
575
+
576
+
577
+ def _loose_equals(left: Any, right: Any) -> bool:
578
+ number_types = (int, float)
579
+ if isinstance(left, bool) or isinstance(right, bool):
580
+ return left is right
581
+ if isinstance(left, number_types) and isinstance(right, number_types):
582
+ return float(left) == float(right)
583
+ if isinstance(left, number_types) and isinstance(right, str):
584
+ other = to_number(right)
585
+ return not math.isnan(other) and float(left) == other
586
+ if isinstance(left, str) and isinstance(right, number_types):
587
+ other = to_number(left)
588
+ return not math.isnan(other) and other == float(right)
589
+ return left == right
590
+
591
+
592
+ def _apply_binary(operator: str, left: Any, right: Any) -> Any:
593
+ if operator == "+":
594
+ if isinstance(left, str) or isinstance(right, str):
595
+ return to_text(left) + to_text(right)
596
+ return _number(to_number(left) + to_number(right))
597
+ if operator == "-":
598
+ return _number(to_number(left) - to_number(right))
599
+ if operator == "*":
600
+ return _number(to_number(left) * to_number(right))
601
+ if operator == "/":
602
+ divisor = to_number(right)
603
+ if divisor == 0:
604
+ return None # JS yields Infinity/NaN, neither of which is JSON
605
+ return _number(to_number(left) / divisor)
606
+ if operator == "%":
607
+ divisor = to_number(right)
608
+ if divisor == 0:
609
+ return None
610
+ return _number(math.fmod(to_number(left), divisor))
611
+
612
+ if operator == "==":
613
+ return _loose_equals(left, right)
614
+ if operator == "!=":
615
+ return not _loose_equals(left, right)
616
+ if operator == "===":
617
+ return type(left) is type(right) and left == right
618
+ if operator == "!==":
619
+ return not (type(left) is type(right) and left == right)
620
+
621
+ if isinstance(left, str) and isinstance(right, str):
622
+ values: tuple[Any, Any] = (left, right)
623
+ else:
624
+ values = (to_number(left), to_number(right))
625
+ if any(isinstance(value, float) and math.isnan(value) for value in values):
626
+ return False
627
+
628
+ if operator == "<":
629
+ return values[0] < values[1]
630
+ if operator == "<=":
631
+ return values[0] <= values[1]
632
+ if operator == ">":
633
+ return values[0] > values[1]
634
+ if operator == ">=":
635
+ return values[0] >= values[1]
636
+
637
+ raise EvaluationError(f"unknown operator {operator!r}")
638
+
639
+
640
+ def _evaluate_node(node: _Node | None, scope: dict[str, Any]) -> Any:
641
+ if node is None:
642
+ return None
643
+
644
+ if node.kind == "literal":
645
+ return node.value
646
+
647
+ if node.kind == "identifier":
648
+ if node.name in scope:
649
+ return scope[node.name]
650
+ if node.name in _builtins():
651
+ raise EvaluationError(f"{node.name!r} must be called")
652
+ return None
653
+
654
+ if node.kind == "member":
655
+ return _read_member(node, scope)[0]
656
+
657
+ if node.kind == "array":
658
+ return [_evaluate_node(item, scope) for item in node.items]
659
+
660
+ if node.kind == "call":
661
+ name = _callee_name(node.left)
662
+ if name is None:
663
+ raise EvaluationError("only builtin functions can be called")
664
+ builtin = _builtins().get(name)
665
+ if builtin is None:
666
+ raise EvaluationError(f"unknown function {name!r}")
667
+ return builtin([_evaluate_node(item, scope) for item in node.items])
668
+
669
+ if node.kind == "unary":
670
+ operand = _evaluate_node(node.left, scope)
671
+ if node.name == "!":
672
+ return not is_truthy(operand)
673
+ if node.name == "-":
674
+ return _number(-to_number(operand))
675
+ return _number(to_number(operand))
676
+
677
+ if node.kind == "logical":
678
+ left = _evaluate_node(node.left, scope)
679
+ if node.name in ("&&", "and"):
680
+ return _evaluate_node(node.right, scope) if is_truthy(left) else left
681
+ return left if is_truthy(left) else _evaluate_node(node.right, scope)
682
+
683
+ if node.kind == "binary":
684
+ return _apply_binary(
685
+ node.name,
686
+ _evaluate_node(node.left, scope),
687
+ _evaluate_node(node.right, scope),
688
+ )
689
+
690
+ if node.kind == "conditional":
691
+ return (
692
+ _evaluate_node(node.right, scope)
693
+ if is_truthy(_evaluate_node(node.left, scope))
694
+ else _evaluate_node(node.third, scope)
695
+ )
696
+
697
+ raise EvaluationError(f"unknown node {node.kind!r}")
698
+
699
+
700
+ class Expression:
701
+ """A parsed expression. Parsing happens once — when a service is configured —
702
+ so evaluating per input costs only the tree walk."""
703
+
704
+ def __init__(self, source: str, root: _Node) -> None:
705
+ self.source = source
706
+ self._root = root
707
+
708
+ @staticmethod
709
+ def parse(source: str) -> "Expression":
710
+ return Expression(source, _Parser(source).parse())
711
+
712
+ def evaluate(
713
+ self,
714
+ params: Any = None,
715
+ scope: dict[str, Any] | None = None,
716
+ on_missing: Callable[[str], None] | None = None,
717
+ ) -> Any:
718
+ """``on_missing`` hears about every read that found nothing, once per
719
+ chain: in ``params.a.b.c`` with no ``a``, only ``params.a``."""
720
+ token = _on_missing.set(on_missing)
721
+ try:
722
+ return _evaluate_node(self._root, scope if scope is not None else {"params": params})
723
+ finally:
724
+ _on_missing.reset(token)
725
+
726
+
727
+ # ── Builtins ───────────────────────────────────────────────────────────────────
728
+
729
+
730
+ def _arg(args: list[Any], index: int, default: Any = None) -> Any:
731
+ return args[index] if index < len(args) else default
732
+
733
+
734
+ def _matches(predicate: Expression, item: Any, index: int) -> bool:
735
+ return is_truthy(predicate.evaluate(scope={"item": item, "index": index}))
736
+
737
+
738
+ def _find(args: list[Any]) -> Any:
739
+ array, source = _arg(args, 0), _arg(args, 1)
740
+ if not isinstance(array, list) or not isinstance(source, str):
741
+ return None
742
+ predicate = Expression.parse(source)
743
+ for index, item in enumerate(array):
744
+ if _matches(predicate, item, index):
745
+ return item
746
+ return None
747
+
748
+
749
+ def _filter(args: list[Any]) -> Any:
750
+ array, source = _arg(args, 0), _arg(args, 1)
751
+ if not isinstance(array, list) or not isinstance(source, str):
752
+ return []
753
+ predicate = Expression.parse(source)
754
+ return [item for index, item in enumerate(array) if _matches(predicate, item, index)]
755
+
756
+
757
+ def _slice(args: list[Any]) -> Any:
758
+ array = _arg(args, 0)
759
+ if not isinstance(array, list):
760
+ return []
761
+ offset = int(to_number(_arg(args, 1, 0)) or 0)
762
+ raw_step = to_number(_arg(args, 2, 1))
763
+ step = 1 if math.isnan(raw_step) or raw_step < 1 else int(raw_step)
764
+ raw_end = to_number(_arg(args, 3, len(array)))
765
+ end = len(array) if math.isnan(raw_end) else int(raw_end)
766
+ return array[max(0, offset) : end : step]
767
+
768
+
769
+ # A web address in running text, with whatever label introduced it. The label
770
+ # goes because it is only there to introduce the address: "Article URL:" with
771
+ # nothing after it says less than nothing. Bounded to a short run of words so it
772
+ # cannot swallow a sentence.
773
+ _URL_IN_TEXT = re.compile(
774
+ r"(?:[A-Za-z][\w ]{0,30}:[ \t]*)?(?:https?://|www\.)\S+", re.IGNORECASE
775
+ )
776
+
777
+
778
+ def _without_urls(value: Any) -> str:
779
+ """Text with the web addresses taken out of it.
780
+
781
+ Feeds are written for programs as much as for people, and some of them are
782
+ mostly machinery: a summary reading "Article URL: https://… Comments URL:
783
+ https://… Points: 48" is a fine thing for a reader to show as a link and a
784
+ miserable thing to hear read aloud, where an address becomes a minute of
785
+ punctuation. This is for text on its way to something that speaks or
786
+ summarises it — never for what a board stores or publishes, where the
787
+ address is the useful part.
788
+ """
789
+ # An absent value is empty text, not the word "null": this answers with
790
+ # text, and a board reading a field that is not there wants nothing said.
791
+ text = _URL_IN_TEXT.sub(" ", "" if value is None else to_text(value))
792
+ # What removal leaves behind: doubled spaces, and punctuation adrift from
793
+ # the word it belonged to.
794
+ text = re.sub(r"[ \t]{2,}", " ", text)
795
+ return re.sub(r"\s+([.,;:!?])", r"\1", text).strip()
796
+
797
+
798
+ def _parse_json(args: list[Any]) -> Any:
799
+ value = _arg(args, 0)
800
+ if not isinstance(value, str):
801
+ return "<parse undefined>"
802
+ try:
803
+ return json_module.loads(value)
804
+ except ValueError:
805
+ return None
806
+
807
+
808
+ def _reformat_date(args: list[Any]) -> Any:
809
+ text = to_text(_arg(args, 0))
810
+ parsed = _parse_date(text, to_text(_arg(args, 1)))
811
+ if parsed is None:
812
+ millis = _to_epoch_millis(_arg(args, 0))
813
+ if millis is None:
814
+ return text
815
+ parsed = datetime.fromtimestamp(millis / 1000)
816
+ return _format_date(parsed, to_text(_arg(args, 2)))
817
+
818
+
819
+ def _numeric_list(args: list[Any]) -> list[float] | None:
820
+ array = _arg(args, 0)
821
+ return [to_number(entry) for entry in array] if isinstance(array, list) else None
822
+
823
+
824
+ def _sum(args: list[Any]) -> Any:
825
+ values = _numeric_list(args)
826
+ return _arg(args, 0) if values is None else _number(math.fsum(values))
827
+
828
+
829
+ def _avg(args: list[Any]) -> Any:
830
+ values = _numeric_list(args)
831
+ if values is None:
832
+ return _arg(args, 0)
833
+ return None if not values else _number(math.fsum(values) / len(values))
834
+
835
+
836
+ def _flat_sum(args: list[Any]) -> Any:
837
+ array = _arg(args, 0)
838
+ if not isinstance(array, list):
839
+ return 0
840
+ total = 0.0
841
+ for entry in array:
842
+ if isinstance(entry, list):
843
+ total += math.fsum(to_number(inner) for inner in entry)
844
+ else:
845
+ total += to_number(entry)
846
+ return _number(total)
847
+
848
+
849
+ def _at(args: list[Any]) -> Any:
850
+ array = _arg(args, 0)
851
+ if not isinstance(array, list) or not array:
852
+ return None
853
+ return array[int(abs(round(to_number(_arg(args, 1, 0))))) % len(array)]
854
+
855
+
856
+ def _join(args: list[Any]) -> str:
857
+ """An array's elements as one text; an empty element is nothing, as Array.join has it."""
858
+ array = _arg(args, 0)
859
+ separator = _arg(args, 1)
860
+ separator = "" if separator is None else to_text(separator)
861
+ if isinstance(array, list):
862
+ return separator.join("" if item is None else to_text(item) for item in array)
863
+ return "" if array is None else to_text(array)
864
+
865
+
866
+ _BUILTINS: dict[str, Callable[[list[Any]], Any]] | None = None
867
+
868
+
869
+ def _builtins() -> dict[str, Callable[[list[Any]], Any]]:
870
+ global _BUILTINS
871
+ if _BUILTINS is not None:
872
+ return _BUILTINS
873
+
874
+ _BUILTINS = {
875
+ "print": lambda args: print(to_text(_arg(args, 0))),
876
+ "log": lambda args: print(to_text(_arg(args, 0))),
877
+ "round": lambda args: _number(float(round(to_number(_arg(args, 0))))),
878
+ "sin": lambda args: math.sin(to_number(_arg(args, 0))),
879
+ "min": lambda args: _number(min((to_number(a) for a in args), default=math.nan)),
880
+ "max": lambda args: _number(max((to_number(a) for a in args), default=math.nan)),
881
+ "rand": lambda args: random.random(),
882
+ "number": lambda args: _number(to_number(_arg(args, 0))),
883
+ "string": lambda args: to_text(_arg(args, 0)),
884
+ "stringify": lambda args: json_module.dumps(_arg(args, 0), separators=(",", ":")),
885
+ "parse": _parse_json,
886
+ "concat": lambda args: "".join(to_text(a) for a in args),
887
+ "join": _join,
888
+ "encodeURI": lambda args: quote(to_text(_arg(args, 0)), safe="-_.!~*'();/?:@&=+$,#"),
889
+ "slug": lambda args: re.sub(r"[^a-z0-9_-]", "", to_text(_arg(args, 0)).lower()),
890
+ "withoutUrls": lambda args: _without_urls(_arg(args, 0)),
891
+ "now": lambda args: _now_millis(),
892
+ "range": lambda args: list(range(max(0, int(round(to_number(_arg(args, 0, 0))))))),
893
+ "sum": _sum,
894
+ "avg": _avg,
895
+ "flatSum": _flat_sum,
896
+ "at": _at,
897
+ "slice": _slice,
898
+ "find": _find,
899
+ "filter": _filter,
900
+ "isFuture": lambda args: (lambda ms: ms is not None and ms >= _now_millis())(
901
+ _to_epoch_millis(_arg(args, 0))
902
+ ),
903
+ "isPast": lambda args: (lambda ms: ms is not None and ms < _now_millis())(
904
+ _to_epoch_millis(_arg(args, 0))
905
+ ),
906
+ "formatNow": lambda args: _format_date(datetime.now(), to_text(_arg(args, 0))),
907
+ "reformatDate": _reformat_date,
908
+ "uuid.v4": lambda args: str(uuid_module.uuid4()),
909
+ "uuid.v7": lambda args: _uuid_v7(),
910
+ # Python conversions the previous evaluator exposed, kept so flat
911
+ # templates written against it keep working.
912
+ "len": lambda args: len(_arg(args, 0)) if hasattr(_arg(args, 0), "__len__") else None,
913
+ "str": lambda args: to_text(_arg(args, 0)),
914
+ "int": lambda args: int(to_number(_arg(args, 0))),
915
+ "float": lambda args: to_number(_arg(args, 0)),
916
+ "bool": lambda args: is_truthy(_arg(args, 0)),
917
+ "abs": lambda args: _number(abs(to_number(_arg(args, 0)))),
918
+ "list": lambda args: list(_arg(args, 0)) if isinstance(_arg(args, 0), (list, tuple)) else [],
919
+ }
920
+ return _BUILTINS
921
+
922
+
923
+ def compile_expression(source: Any) -> Callable[[Any], Any]:
924
+ """Compiles an expression source into a callable taking ``params`` and an
925
+ optional ``on_missing``. Non-string sources are constants and are returned
926
+ as-is; a source that does not parse raises when called and carries
927
+ ``parse_error``, so the caller decides how a broken term is reported."""
928
+ if not isinstance(source, str):
929
+ return lambda params, on_missing=None: source
930
+
931
+ try:
932
+ expression = Expression.parse(source)
933
+ except ParseError as error:
934
+ parse_error = f"invalid expression {source!r}: {error}"
935
+
936
+ def broken(params: Any, on_missing: Any = None) -> Any:
937
+ raise EvaluationError(parse_error)
938
+
939
+ broken.parse_error = parse_error # type: ignore[attr-defined]
940
+ return broken
941
+
942
+ return lambda params, on_missing=None: expression.evaluate(params, on_missing=on_missing)