@overcrow/mcp 0.0.0 → 0.1.1

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 (489) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -1
  3. package/dist/audit/index.js +103 -0
  4. package/dist/audit/lexer.js +417 -0
  5. package/dist/audit/project.js +200 -0
  6. package/dist/audit/rules.js +661 -0
  7. package/dist/bootstrap/download.js +229 -0
  8. package/dist/bootstrap/install.js +280 -0
  9. package/dist/bootstrap/pin.js +85 -0
  10. package/dist/bootstrap/pin.json +119 -0
  11. package/dist/bootstrap/zip.js +258 -0
  12. package/dist/cli.js +200 -0
  13. package/dist/confine.js +244 -0
  14. package/dist/content/docs/en/cli.md +768 -0
  15. package/dist/content/docs/en/creator-space.md +78 -0
  16. package/dist/content/docs/en/dev-channel.md +130 -0
  17. package/dist/content/docs/en/elements.md +469 -0
  18. package/dist/content/docs/en/forms.md +328 -0
  19. package/dist/content/docs/en/guide.md +252 -0
  20. package/dist/content/docs/en/index.md +85 -0
  21. package/dist/content/docs/en/limits.md +241 -0
  22. package/dist/content/docs/en/logic.md +446 -0
  23. package/dist/content/docs/en/manifest.md +388 -0
  24. package/dist/content/docs/en/mcp.md +165 -0
  25. package/dist/content/docs/en/package.md +131 -0
  26. package/dist/content/docs/en/publish-a-widget.md +94 -0
  27. package/dist/content/docs/en/publish-keys.md +95 -0
  28. package/dist/content/docs/en/publishing.md +167 -0
  29. package/dist/content/docs/en/reference.md +55 -0
  30. package/dist/content/docs/en/result-shapes.md +332 -0
  31. package/dist/content/docs/en/sdk.md +295 -0
  32. package/dist/content/docs/en/security.md +115 -0
  33. package/dist/content/docs/en/service-reference.md +344 -0
  34. package/dist/content/docs/en/services.md +517 -0
  35. package/dist/content/docs/en/style-properties.md +270 -0
  36. package/dist/content/docs/en/style.md +266 -0
  37. package/dist/content/docs/en/testing.md +400 -0
  38. package/dist/content/docs/en/verified-domain.md +46 -0
  39. package/dist/content/docs/en/view.md +338 -0
  40. package/dist/content/docs/en/widget-listing.md +65 -0
  41. package/dist/content/docs/en/widget-review.md +57 -0
  42. package/dist/content/docs/en/widget-statistics.md +134 -0
  43. package/dist/content/docs/en/widgets.md +76 -0
  44. package/dist/content/docs/fr/cli.md +802 -0
  45. package/dist/content/docs/fr/creator-space.md +83 -0
  46. package/dist/content/docs/fr/dev-channel.md +140 -0
  47. package/dist/content/docs/fr/elements.md +475 -0
  48. package/dist/content/docs/fr/forms.md +341 -0
  49. package/dist/content/docs/fr/guide.md +263 -0
  50. package/dist/content/docs/fr/index.md +90 -0
  51. package/dist/content/docs/fr/limits.md +244 -0
  52. package/dist/content/docs/fr/logic.md +461 -0
  53. package/dist/content/docs/fr/manifest.md +401 -0
  54. package/dist/content/docs/fr/mcp.md +173 -0
  55. package/dist/content/docs/fr/package.md +139 -0
  56. package/dist/content/docs/fr/publish-a-widget.md +101 -0
  57. package/dist/content/docs/fr/publish-keys.md +97 -0
  58. package/dist/content/docs/fr/publishing.md +177 -0
  59. package/dist/content/docs/fr/reference.md +59 -0
  60. package/dist/content/docs/fr/result-shapes.md +333 -0
  61. package/dist/content/docs/fr/sdk.md +301 -0
  62. package/dist/content/docs/fr/security.md +129 -0
  63. package/dist/content/docs/fr/service-reference.md +346 -0
  64. package/dist/content/docs/fr/services.md +540 -0
  65. package/dist/content/docs/fr/style-properties.md +272 -0
  66. package/dist/content/docs/fr/style.md +281 -0
  67. package/dist/content/docs/fr/testing.md +417 -0
  68. package/dist/content/docs/fr/verified-domain.md +49 -0
  69. package/dist/content/docs/fr/view.md +352 -0
  70. package/dist/content/docs/fr/widget-listing.md +69 -0
  71. package/dist/content/docs/fr/widget-review.md +59 -0
  72. package/dist/content/docs/fr/widget-statistics.md +141 -0
  73. package/dist/content/docs/fr/widgets.md +81 -0
  74. package/dist/content/examples/clock/LICENSE +21 -0
  75. package/dist/content/examples/clock/README.md +75 -0
  76. package/dist/content/examples/clock/listing.json +19 -0
  77. package/dist/content/examples/clock/locales/en.json +4 -0
  78. package/dist/content/examples/clock/locales/fr.json +4 -0
  79. package/dist/content/examples/clock/logic.ts +85 -0
  80. package/dist/content/examples/clock/manifest.json +44 -0
  81. package/dist/content/examples/clock/package.json +16 -0
  82. package/dist/content/examples/clock/style.ocss +26 -0
  83. package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
  84. package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
  85. package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
  86. package/dist/content/examples/clock/tests/options.scenario.json +108 -0
  87. package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
  88. package/dist/content/examples/clock/tests/render.scenario.json +94 -0
  89. package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
  90. package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
  91. package/dist/content/examples/clock/tsconfig.json +16 -0
  92. package/dist/content/examples/clock/view.ocml +8 -0
  93. package/dist/content/examples/countdown/LICENSE +20 -0
  94. package/dist/content/examples/countdown/listing.json +10 -0
  95. package/dist/content/examples/countdown/locales/en.json +15 -0
  96. package/dist/content/examples/countdown/locales/fr.json +15 -0
  97. package/dist/content/examples/countdown/logic.ts +179 -0
  98. package/dist/content/examples/countdown/manifest.json +34 -0
  99. package/dist/content/examples/countdown/package.json +15 -0
  100. package/dist/content/examples/countdown/style.ocss +94 -0
  101. package/dist/content/examples/countdown/tsconfig.json +16 -0
  102. package/dist/content/examples/countdown/view.ocml +42 -0
  103. package/dist/content/examples/fps/LICENSE +21 -0
  104. package/dist/content/examples/fps/README.md +64 -0
  105. package/dist/content/examples/fps/listing.json +19 -0
  106. package/dist/content/examples/fps/locales/en.json +11 -0
  107. package/dist/content/examples/fps/locales/fr.json +11 -0
  108. package/dist/content/examples/fps/logic.ts +64 -0
  109. package/dist/content/examples/fps/manifest.json +30 -0
  110. package/dist/content/examples/fps/package.json +16 -0
  111. package/dist/content/examples/fps/style.ocss +31 -0
  112. package/dist/content/examples/fps/submission.json +8 -0
  113. package/dist/content/examples/fps/tests/label.scenario.json +63 -0
  114. package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
  115. package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
  116. package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
  117. package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
  118. package/dist/content/examples/fps/tests/render.scenario.json +96 -0
  119. package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
  120. package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
  121. package/dist/content/examples/fps/tsconfig.json +16 -0
  122. package/dist/content/examples/fps/view.ocml +11 -0
  123. package/dist/content/examples/media/LICENSE +21 -0
  124. package/dist/content/examples/media/README.md +147 -0
  125. package/dist/content/examples/media/listing.json +19 -0
  126. package/dist/content/examples/media/locales/en.json +11 -0
  127. package/dist/content/examples/media/locales/fr.json +11 -0
  128. package/dist/content/examples/media/logic.ts +191 -0
  129. package/dist/content/examples/media/manifest.json +35 -0
  130. package/dist/content/examples/media/package.json +16 -0
  131. package/dist/content/examples/media/style.ocss +148 -0
  132. package/dist/content/examples/media/submission.json +12 -0
  133. package/dist/content/examples/media/tests/covers.scenario.json +144 -0
  134. package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
  135. package/dist/content/examples/media/tests/load-logic.mjs +22 -0
  136. package/dist/content/examples/media/tests/logic.test.mjs +176 -0
  137. package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
  138. package/dist/content/examples/media/tests/preview.scenario.json +52 -0
  139. package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
  140. package/dist/content/examples/media/tests/refused.scenario.json +22 -0
  141. package/dist/content/examples/media/tests/refused.test.mjs +31 -0
  142. package/dist/content/examples/media/tests/render.scenario.json +136 -0
  143. package/dist/content/examples/media/tests/states.scenario.json +257 -0
  144. package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
  145. package/dist/content/examples/media/tsconfig.json +16 -0
  146. package/dist/content/examples/media/view.ocml +41 -0
  147. package/dist/content/examples/notes/LICENSE +21 -0
  148. package/dist/content/examples/notes/README.md +219 -0
  149. package/dist/content/examples/notes/listing.json +19 -0
  150. package/dist/content/examples/notes/locales/en.json +25 -0
  151. package/dist/content/examples/notes/locales/fr.json +25 -0
  152. package/dist/content/examples/notes/logic.ts +799 -0
  153. package/dist/content/examples/notes/manifest.json +40 -0
  154. package/dist/content/examples/notes/package.json +16 -0
  155. package/dist/content/examples/notes/style.ocss +469 -0
  156. package/dist/content/examples/notes/submission.json +12 -0
  157. package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
  158. package/dist/content/examples/notes/tests/create.scenario.json +260 -0
  159. package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
  160. package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
  161. package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
  162. package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
  163. package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
  164. package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
  165. package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
  166. package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
  167. package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
  168. package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
  169. package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
  170. package/dist/content/examples/notes/tests/save.scenario.json +378 -0
  171. package/dist/content/examples/notes/tests/states.scenario.json +640 -0
  172. package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
  173. package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
  174. package/dist/content/examples/notes/tsconfig.json +16 -0
  175. package/dist/content/examples/notes/view.ocml +154 -0
  176. package/dist/content/examples/performance/LICENSE +21 -0
  177. package/dist/content/examples/performance/README.md +134 -0
  178. package/dist/content/examples/performance/listing.json +19 -0
  179. package/dist/content/examples/performance/locales/en.json +20 -0
  180. package/dist/content/examples/performance/locales/fr.json +20 -0
  181. package/dist/content/examples/performance/logic.ts +210 -0
  182. package/dist/content/examples/performance/manifest.json +83 -0
  183. package/dist/content/examples/performance/package.json +16 -0
  184. package/dist/content/examples/performance/style.ocss +75 -0
  185. package/dist/content/examples/performance/submission.json +12 -0
  186. package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
  187. package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
  188. package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
  189. package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
  190. package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
  191. package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
  192. package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
  193. package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
  194. package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
  195. package/dist/content/examples/performance/tests/region.scenario.json +89 -0
  196. package/dist/content/examples/performance/tests/render.scenario.json +112 -0
  197. package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
  198. package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
  199. package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
  200. package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
  201. package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
  202. package/dist/content/examples/performance/tsconfig.json +16 -0
  203. package/dist/content/examples/performance/view.ocml +18 -0
  204. package/dist/content/examples/playervox-journal/LICENSE +21 -0
  205. package/dist/content/examples/playervox-journal/README.md +150 -0
  206. package/dist/content/examples/playervox-journal/listing.json +19 -0
  207. package/dist/content/examples/playervox-journal/locales/en.json +25 -0
  208. package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
  209. package/dist/content/examples/playervox-journal/logic.ts +556 -0
  210. package/dist/content/examples/playervox-journal/manifest.json +19 -0
  211. package/dist/content/examples/playervox-journal/package.json +16 -0
  212. package/dist/content/examples/playervox-journal/style.ocss +142 -0
  213. package/dist/content/examples/playervox-journal/submission.json +12 -0
  214. package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
  215. package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
  216. package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
  217. package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
  218. package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
  219. package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
  220. package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
  221. package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
  222. package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
  223. package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
  224. package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
  225. package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
  226. package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
  227. package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
  228. package/dist/content/examples/playervox-journal/view.ocml +52 -0
  229. package/dist/content/examples/playervox-rating/LICENSE +21 -0
  230. package/dist/content/examples/playervox-rating/README.md +166 -0
  231. package/dist/content/examples/playervox-rating/listing.json +19 -0
  232. package/dist/content/examples/playervox-rating/locales/en.json +35 -0
  233. package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
  234. package/dist/content/examples/playervox-rating/logic.ts +581 -0
  235. package/dist/content/examples/playervox-rating/manifest.json +19 -0
  236. package/dist/content/examples/playervox-rating/package.json +16 -0
  237. package/dist/content/examples/playervox-rating/style.ocss +333 -0
  238. package/dist/content/examples/playervox-rating/submission.json +12 -0
  239. package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
  240. package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
  241. package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
  242. package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
  243. package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
  244. package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
  245. package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
  246. package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
  247. package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
  248. package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
  249. package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
  250. package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
  251. package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
  252. package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
  253. package/dist/content/examples/playervox-rating/view.ocml +62 -0
  254. package/dist/content/examples/playervox-reviews/LICENSE +21 -0
  255. package/dist/content/examples/playervox-reviews/README.md +194 -0
  256. package/dist/content/examples/playervox-reviews/listing.json +19 -0
  257. package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
  258. package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
  259. package/dist/content/examples/playervox-reviews/logic.ts +822 -0
  260. package/dist/content/examples/playervox-reviews/manifest.json +30 -0
  261. package/dist/content/examples/playervox-reviews/package.json +16 -0
  262. package/dist/content/examples/playervox-reviews/style.ocss +260 -0
  263. package/dist/content/examples/playervox-reviews/submission.json +8 -0
  264. package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
  265. package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
  266. package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
  267. package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
  268. package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
  269. package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
  270. package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
  271. package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
  272. package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
  273. package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
  274. package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
  275. package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
  276. package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
  277. package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
  278. package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
  279. package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
  280. package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
  281. package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
  282. package/dist/content/examples/playervox-reviews/view.ocml +110 -0
  283. package/dist/content/examples/playervox-score/LICENSE +21 -0
  284. package/dist/content/examples/playervox-score/README.md +131 -0
  285. package/dist/content/examples/playervox-score/listing.json +19 -0
  286. package/dist/content/examples/playervox-score/locales/en.json +23 -0
  287. package/dist/content/examples/playervox-score/locales/fr.json +23 -0
  288. package/dist/content/examples/playervox-score/logic.ts +430 -0
  289. package/dist/content/examples/playervox-score/manifest.json +47 -0
  290. package/dist/content/examples/playervox-score/package.json +16 -0
  291. package/dist/content/examples/playervox-score/style.ocss +247 -0
  292. package/dist/content/examples/playervox-score/submission.json +8 -0
  293. package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
  294. package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
  295. package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
  296. package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
  297. package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
  298. package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
  299. package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
  300. package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
  301. package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
  302. package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
  303. package/dist/content/examples/playervox-score/tsconfig.json +16 -0
  304. package/dist/content/examples/playervox-score/view.ocml +51 -0
  305. package/dist/content/examples/session/LICENSE +21 -0
  306. package/dist/content/examples/session/README.md +57 -0
  307. package/dist/content/examples/session/listing.json +19 -0
  308. package/dist/content/examples/session/locales/en.json +3 -0
  309. package/dist/content/examples/session/locales/fr.json +3 -0
  310. package/dist/content/examples/session/logic.ts +26 -0
  311. package/dist/content/examples/session/manifest.json +19 -0
  312. package/dist/content/examples/session/package.json +16 -0
  313. package/dist/content/examples/session/style.ocss +16 -0
  314. package/dist/content/examples/session/submission.json +8 -0
  315. package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
  316. package/dist/content/examples/session/tests/load-logic.mjs +22 -0
  317. package/dist/content/examples/session/tests/logic.test.mjs +37 -0
  318. package/dist/content/examples/session/tests/preview.scenario.json +28 -0
  319. package/dist/content/examples/session/tests/refused.scenario.json +20 -0
  320. package/dist/content/examples/session/tests/refused.test.mjs +16 -0
  321. package/dist/content/examples/session/tests/render.scenario.json +95 -0
  322. package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
  323. package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
  324. package/dist/content/examples/session/tsconfig.json +16 -0
  325. package/dist/content/examples/session/view.ocml +11 -0
  326. package/dist/content/examples/stopwatch/LICENSE +21 -0
  327. package/dist/content/examples/stopwatch/README.md +99 -0
  328. package/dist/content/examples/stopwatch/listing.json +19 -0
  329. package/dist/content/examples/stopwatch/locales/en.json +8 -0
  330. package/dist/content/examples/stopwatch/locales/fr.json +8 -0
  331. package/dist/content/examples/stopwatch/logic.ts +93 -0
  332. package/dist/content/examples/stopwatch/manifest.json +19 -0
  333. package/dist/content/examples/stopwatch/package.json +16 -0
  334. package/dist/content/examples/stopwatch/style.ocss +54 -0
  335. package/dist/content/examples/stopwatch/submission.json +12 -0
  336. package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
  337. package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
  338. package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
  339. package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
  340. package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
  341. package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
  342. package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
  343. package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
  344. package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
  345. package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
  346. package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
  347. package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
  348. package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
  349. package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
  350. package/dist/content/examples/stopwatch/tsconfig.json +16 -0
  351. package/dist/content/examples/stopwatch/view.ocml +29 -0
  352. package/dist/content/examples/twitch-chat/LICENSE +21 -0
  353. package/dist/content/examples/twitch-chat/README.md +283 -0
  354. package/dist/content/examples/twitch-chat/listing.json +19 -0
  355. package/dist/content/examples/twitch-chat/locales/en.json +52 -0
  356. package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
  357. package/dist/content/examples/twitch-chat/logic.ts +887 -0
  358. package/dist/content/examples/twitch-chat/manifest.json +33 -0
  359. package/dist/content/examples/twitch-chat/package.json +16 -0
  360. package/dist/content/examples/twitch-chat/style.ocss +544 -0
  361. package/dist/content/examples/twitch-chat/submission.json +12 -0
  362. package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
  363. package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
  364. package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
  365. package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
  366. package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
  367. package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
  368. package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
  369. package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
  370. package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
  371. package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
  372. package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
  373. package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
  374. package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
  375. package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
  376. package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
  377. package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
  378. package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
  379. package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
  380. package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
  381. package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
  382. package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
  383. package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
  384. package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
  385. package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
  386. package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
  387. package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
  388. package/dist/content/examples/twitch-chat/view.ocml +141 -0
  389. package/dist/content/examples/warframe-market/LICENSE +21 -0
  390. package/dist/content/examples/warframe-market/README.md +176 -0
  391. package/dist/content/examples/warframe-market/listing.json +19 -0
  392. package/dist/content/examples/warframe-market/locales/en.json +44 -0
  393. package/dist/content/examples/warframe-market/locales/fr.json +44 -0
  394. package/dist/content/examples/warframe-market/logic.ts +1265 -0
  395. package/dist/content/examples/warframe-market/manifest.json +92 -0
  396. package/dist/content/examples/warframe-market/package.json +16 -0
  397. package/dist/content/examples/warframe-market/style.ocss +422 -0
  398. package/dist/content/examples/warframe-market/submission.json +24 -0
  399. package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
  400. package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
  401. package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
  402. package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
  403. package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
  404. package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
  405. package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
  406. package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
  407. package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
  408. package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
  409. package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
  410. package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
  411. package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
  412. package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
  413. package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
  414. package/dist/content/examples/warframe-market/tsconfig.json +16 -0
  415. package/dist/content/examples/warframe-market/view.ocml +116 -0
  416. package/dist/content/examples/weather/LICENSE +20 -0
  417. package/dist/content/examples/weather/listing.json +10 -0
  418. package/dist/content/examples/weather/locales/en.json +9 -0
  419. package/dist/content/examples/weather/locales/fr.json +9 -0
  420. package/dist/content/examples/weather/logic.ts +62 -0
  421. package/dist/content/examples/weather/manifest.json +51 -0
  422. package/dist/content/examples/weather/package.json +15 -0
  423. package/dist/content/examples/weather/style.ocss +29 -0
  424. package/dist/content/examples/weather/submission.json +17 -0
  425. package/dist/content/examples/weather/tsconfig.json +16 -0
  426. package/dist/content/examples/weather/view.ocml +12 -0
  427. package/dist/content/index.json +3705 -0
  428. package/dist/content/reference/errors.json +1924 -0
  429. package/dist/content/reference/limits.json +1154 -0
  430. package/dist/content/reference/manifest.md +223 -0
  431. package/dist/content/reference/permissions.json +413 -0
  432. package/dist/content/templates/blank/locales/en.json +3 -0
  433. package/dist/content/templates/blank/locales/fr.json +3 -0
  434. package/dist/content/templates/blank/logic.ts +7 -0
  435. package/dist/content/templates/blank/manifest.json +16 -0
  436. package/dist/content/templates/blank/style.ocss +10 -0
  437. package/dist/content/templates/blank/tests/example.scenario.json +10 -0
  438. package/dist/content/templates/blank/view.ocml +6 -0
  439. package/dist/content/templates/chart/locales/en.json +3 -0
  440. package/dist/content/templates/chart/locales/fr.json +3 -0
  441. package/dist/content/templates/chart/logic.ts +27 -0
  442. package/dist/content/templates/chart/manifest.json +16 -0
  443. package/dist/content/templates/chart/style.ocss +27 -0
  444. package/dist/content/templates/chart/tests/example.scenario.json +10 -0
  445. package/dist/content/templates/chart/view.ocml +10 -0
  446. package/dist/content/templates/counter/locales/en.json +4 -0
  447. package/dist/content/templates/counter/locales/fr.json +4 -0
  448. package/dist/content/templates/counter/logic.ts +20 -0
  449. package/dist/content/templates/counter/manifest.json +16 -0
  450. package/dist/content/templates/counter/style.ocss +26 -0
  451. package/dist/content/templates/counter/tests/example.scenario.json +11 -0
  452. package/dist/content/templates/counter/view.ocml +13 -0
  453. package/dist/content/templates/list/locales/en.json +8 -0
  454. package/dist/content/templates/list/locales/fr.json +8 -0
  455. package/dist/content/templates/list/logic.ts +35 -0
  456. package/dist/content/templates/list/manifest.json +16 -0
  457. package/dist/content/templates/list/style.ocss +42 -0
  458. package/dist/content/templates/list/tests/example.scenario.json +10 -0
  459. package/dist/content/templates/list/view.ocml +17 -0
  460. package/dist/content/templates/shared/LICENSE +20 -0
  461. package/dist/content/templates/shared/package.json +14 -0
  462. package/dist/content/templates/shared/tsconfig.json +16 -0
  463. package/dist/content.js +68 -0
  464. package/dist/env.js +156 -0
  465. package/dist/fingerprint.js +32 -0
  466. package/dist/hidden.js +47 -0
  467. package/dist/ids.js +27 -0
  468. package/dist/index.js +82 -0
  469. package/dist/knowledge.js +222 -0
  470. package/dist/npm.js +149 -0
  471. package/dist/prompts.js +47 -0
  472. package/dist/resources.js +82 -0
  473. package/dist/run.js +120 -0
  474. package/dist/server.js +43 -0
  475. package/dist/session.js +205 -0
  476. package/dist/sources.js +218 -0
  477. package/dist/text.js +80 -0
  478. package/dist/texts.js +44 -0
  479. package/dist/tools/audit.js +105 -0
  480. package/dist/tools/build.js +453 -0
  481. package/dist/tools/common.js +122 -0
  482. package/dist/tools/docs.js +196 -0
  483. package/dist/tools/preview.js +87 -0
  484. package/dist/tools/project.js +183 -0
  485. package/dist/tools/setup.js +146 -0
  486. package/dist/tools/submission.js +369 -0
  487. package/dist/version.js +3 -0
  488. package/npm-shrinkwrap.json +402 -0
  489. package/package.json +50 -4
@@ -0,0 +1,283 @@
1
+ # Twitch chat
2
+
3
+ `com.playervox.overcrow.twitch.chat` — the chat of one public Twitch
4
+ channel you choose, over the game. In Interactive mode you pick the
5
+ channel, keep favorites, scroll the history, reply and send messages; in
6
+ Passive mode the last messages show and fade out. OverCrow holds your
7
+ Twitch account, the connection, the channel and the favorites: the widget
8
+ shows what OverCrow sends it and asks for the rest. A built-in of OverCrow,
9
+ written against the public `@overcrow/sdk` and packaged with
10
+ `overcrow-widget` like any creator's widget. MIT.
11
+
12
+ ## What it shows
13
+
14
+ A header row, always: a chat icon, the channel (`#juniper_plays`, or
15
+ "Twitch" without one) and a status dot whose label, also its tooltip, says
16
+ the connection in words. In Interactive mode a joined channel adds the
17
+ favorite star and the "Change channel" and "Disconnect channel" buttons.
18
+
19
+ | State | Shows (EN / FR) |
20
+ | --- | --- |
21
+ | Waiting for OverCrow's first answer | the header alone, a grey dot: "INACTIVE" / "INACTIF" |
22
+ | No channel, Interactive mode | the channel selector: a field "Channel name" / "Nom de la chaîne", "Join chat" / "Rejoindre", the favorites under "Favorites" / "Favoris"; dot "DISCONNECTED" / "DÉCONNECTÉ" |
23
+ | No channel, Passive mode | "No channel selected" / "Aucune chaîne sélectionnée" |
24
+ | Connecting | an amber dot, "CONNECTING" / "CONNEXION EN COURS"; the message field waits: "Waiting for chat…" / "En attente du chat…" |
25
+ | Joined | a green dot, "CONNECTED" / "CONNECTÉ"; the history; the field "Send a message…" / "Envoyer un message…" and "Send" / "Envoyer" |
26
+ | Joined, nothing yet | Interactive: "No messages yet" / "Aucun message pour le moment"; Passive: "No recent messages" / "Aucun message récent" |
27
+ | Reconnecting | an amber dot, "RECONNECTING" / "RECONNEXION"; the history stays, the field waits |
28
+ | The join failed | a red dot and its label under the header: "CHANNEL UNAVAILABLE" / "CHAÎNE INDISPONIBLE", "CONNECTION ERROR" / "ERREUR DE CONNEXION", "TWITCH ERROR" / "ERREUR TWITCH", or "Another widget is using Twitch chat" / "Un autre widget utilise le chat Twitch" |
29
+ | Scrolled away from the end | a button, "1 new message" / "1 nouveau message", "{n} new messages" / "{n} nouveaux messages" |
30
+ | Messages left out of a fast chat | a row, "1 message not shown" / "1 message non affiché", "{n} messages not shown" / "{n} messages non affichés" |
31
+ | A channel or favorite change failed | under the header, in Interactive mode: "Twitch is busy. Try again." / "Twitch est occupé. Réessayez.", "Could not save Twitch widget settings." / "Impossible d’enregistrer les réglages du widget Twitch.", "Favorite channel limit reached." / "Nombre maximal de chaînes favorites atteint." |
32
+ | OverCrow's chat source failed | "Twitch is temporarily unavailable. Retrying automatically." / "Twitch est temporairement indisponible. Nouvelle tentative automatique."; the widget asks again 5 s later |
33
+ | No Twitch account, a sign-in in progress, an expired session | OverCrow's own account panel, over the widget, in both modes (see [Permissions](#permissions)) |
34
+ | No permission to read | "Allow access to Twitch chat in the Control Center." / "Autorisez l’accès au chat Twitch dans le Centre de contrôle.": the widget asks OverCrow nothing |
35
+
36
+ The size is the one you set, 420 × 360 px by default, from 160 × 24 px to
37
+ 900 × 900 px: the history takes what the other rows leave, and a channel
38
+ name too long for the header ends with an ellipsis.
39
+
40
+ ## The channel and the favorites
41
+
42
+ - **Join.** Type a channel in the selector and press Enter or "Join chat".
43
+ A name is accepted as Twitch writes a login: spaces around it and a
44
+ leading `#` are dropped, upper case becomes lower case, and what is left
45
+ is 1 to 25 ASCII letters, digits or `_`. The field takes 26 characters
46
+ (the `#` and 25 more). Anything else leaves "Join chat" off, and Enter
47
+ joins nothing.
48
+ - **Favorites.** Each favorite is a chip in the selector: a click joins it.
49
+ Three rows of chips show; more scroll in that height.
50
+ The star of the header adds the current channel to the favorites or
51
+ removes it ("Add current channel to favorites" / "Ajouter la chaîne
52
+ actuelle aux favoris", "Remove current channel from favorites" / "Retirer
53
+ la chaîne actuelle des favoris"); it is yellow for a favorite. OverCrow
54
+ keeps at most 20: beyond, the star of another channel takes no click and
55
+ says "Favorite channel limit reached". Passive mode shows the star of a
56
+ favorite channel, without a button.
57
+ - **Change channel** opens the selector over the chat, which stays until
58
+ another channel is joined, and closes it again.
59
+ - **Disconnect channel** leaves: OverCrow forgets the channel.
60
+
61
+ Each of these is one call to OverCrow on your gesture (`twitch.chat.join`,
62
+ `twitch.chat.favorite`, `twitch.chat.leave`). The widget stores nothing:
63
+ OverCrow remembers the channel and the favorites of this widget, joins the
64
+ channel again when the widget starts, and tells the widget the channel,
65
+ its state and the favorites through the subscription. What the widget
66
+ shows is what OverCrow last said, never what was typed. The selector's
67
+ field is OverCrow's to edit: a selector that starts over is a new one,
68
+ with an empty field.
69
+
70
+ The channel and the favorites are this widget's own: another widget
71
+ allowed to read Twitch chat has its own, and nothing it does changes
72
+ these. OverCrow connects to one chat at a time, the one joined last: a
73
+ widget whose channel is not that one keeps its channel and its favorites,
74
+ shows "Another widget is using Twitch chat", and gets the chat back when
75
+ the other leaves or stops, or when you join from it again.
76
+
77
+ ## The history and the pace of the chat
78
+
79
+ Each line is the author's name, in bold and in their Twitch colour, then
80
+ the message: text and emotes, as tall as the line and centred on it, each
81
+ with its name as accessible label. OverCrow keeps a colour readable on the panel of the
82
+ current theme (a very dark name is lightened on a dark panel, a very light
83
+ one darkened on a light panel); an author without a colour is grey. A long
84
+ message wraps.
85
+
86
+ - The history keeps the last 200 messages, and fewer when they are long:
87
+ a message has at most 16 runs of text and emotes, and the rows together
88
+ stay within a budget of scene nodes, the oldest leaving first.
89
+ - The list follows its end. Scroll up and it stops following: new messages
90
+ are then counted on the "N new messages" button, which returns to the
91
+ latest; so does scrolling back to the end. This is the `list`'s
92
+ `stick-to-end` attribute and its `stick` event.
93
+ - **OverCrow sends the chat as deltas, at most one every 100 ms**: the new
94
+ messages to append, messages that changed (they replace the message of
95
+ the same ID where it stands) and the IDs of removed ones, which leave at
96
+ once: moderation is never left out. After subscribing, after a change of
97
+ channel or account and when the widget is shown again, one update
98
+ carries the whole list instead.
99
+ - **A chat faster than that is sampled.** OverCrow then leaves messages
100
+ out and says how many: the widget shows "N messages not shown" where
101
+ they would have been, and counts them among the new messages. Two such
102
+ rows in a row are one. Nothing is sent to a hidden widget.
103
+
104
+ ## Replies
105
+
106
+ A message that answers another shows one line of what it answers above it
107
+ ("Author: text", cut with an ellipsis), behind a rail. In Interactive mode,
108
+ with the permission to send, each message has a reply icon at the end of
109
+ its first line, visible under the pointer or with the keyboard on it
110
+ ("Reply to {name}" / "Répondre à {name}"). It makes that message the target of the next send: "Replying to
111
+ {name}" / "Réponse à {name}" shows above the field, with a button to cancel
112
+ ("Cancel reply" / "Annuler la réponse"). The target goes with the accepted
113
+ message, stays when a message is refused, and is dropped when its message
114
+ leaves the history.
115
+
116
+ ## The composer
117
+
118
+ One line, at most 500 characters, and "Send".
119
+
120
+ - **The form is OverCrow's.** The message field is the host-owned control
121
+ of a `form` bound to the `twitch.chat.send` intent: the view gives it no
122
+ `value`, and the logic cannot write a character in it nor submit it.
123
+ OverCrow tells the logic the text through the field's `input` event, so
124
+ that "Send" is on only when there is something to send.
125
+ - **Sending** takes your gesture: Enter in the field or a click on "Send".
126
+ OverCrow sends the text of its own field, with the reply target as the
127
+ form's `target`, and tells the widget the outcome in the form's `submit`
128
+ event. Nothing is sent from an empty field or from spaces, and one
129
+ message is sent at a time: until OverCrow answers, the field still holds
130
+ the message, and Enter or "Send" sends nothing more.
131
+ - **OverCrow empties the field once the message is accepted**, and keeps
132
+ it otherwise, for another try.
133
+ - **There is no local echo.** A sent message shows in the history when
134
+ OverCrow delivers it, like any other. Meanwhile "sending…" / "envoi…"
135
+ shows beside the field; a refused message leaves "not sent" / "non
136
+ envoyé" there and its reason above the field:
137
+
138
+ | Refusal | Message (EN / FR) |
139
+ | --- | --- |
140
+ | Too many messages (OverCrow allows 20 per 30 s) | "Too many messages. Wait a moment, then try again." / "Trop de messages. Attendez un instant, puis réessayez." |
141
+ | The chat does not take this account's messages | "This chat does not accept your messages right now." / "Ce chat n’accepte pas vos messages pour le moment." |
142
+ | Anything else | "Message was not accepted. Try again." / "Le message a été refusé. Réessayez." |
143
+ | The send was abandoned before it left | "Message was not sent. Try again." / "Le message n’a pas été envoyé. Réessayez." |
144
+
145
+ Should OverCrow give no answer at all, the widget says "Message was not
146
+ accepted. Try again." after 40 s.
147
+ - **The draft is kept by OverCrow** while its form stays in the view: in
148
+ Passive mode and while the widget is hidden between two games (the form
149
+ is hidden, not removed), under the channel selector, and while
150
+ OverCrow's chat source is failing. The form's key is the chat's
151
+ `generation`, which changes with the channel or the account: another
152
+ channel is another form, with an empty field. A draft does not outlive
153
+ OverCrow.
154
+
155
+ OverCrow's field gives you the caret, the selection, copy, cut and paste
156
+ through OverCrow, and input methods (IME). Escape is OverCrow's: it leaves
157
+ Interactive mode, and the draft stays.
158
+
159
+ ## Passive mode and the fade
160
+
161
+ Passive mode shows the last 12 messages younger than the lifetime, without
162
+ any control: no selector, no star button, no reply icon, no composer, and
163
+ no row for messages left out. Clicks go through to the game.
164
+
165
+ A message is opaque until two thirds of its lifetime, then fades to nothing
166
+ over the last third, and leaves. `receivedAt`, the time OverCrow received
167
+ the message, gives its age, also after the widget was hidden. The fade is
168
+ stepped: the logic gives a fading row one of 32 opacity classes, one level
169
+ per step (a 32nd of the fade: 313 ms for the default 30 s, never under
170
+ 100 ms). Each step is one frame; the style has no transition, which would
171
+ have OverCrow draw a frame at every refresh for as long as a message
172
+ fades. One timer drives it: it sleeps until the first message starts to
173
+ fade, ticks once per step while one fades, and does not exist when nothing
174
+ shows.
175
+ Interactive mode keeps the whole history, opaque, and runs no timer.
176
+
177
+ ## Menu
178
+
179
+ | Row | Type | Default |
180
+ | --- | --- | --- |
181
+ | Message lifetime in Passive (s) / Durée des messages en mode passif (s) | slider `passive-lifetime`, 5 to 120 s | 30 |
182
+
183
+ ## Permissions
184
+
185
+ - `twitch.chat.read`: join, read and leave the chat of a channel, and keep
186
+ favorite channels. Sensitive.
187
+ - `twitch.chat.compose`: send a message, only through the host-bound form.
188
+ Sensitive. Without it the widget shows the chat with its channel
189
+ controls, and no composer nor reply icon.
190
+
191
+ As sensitive capabilities rule out the network and the clipboard, the
192
+ widget declares neither, and no storage: it reaches Twitch only through
193
+ OverCrow and keeps nothing.
194
+
195
+ **The Twitch account is OverCrow's.** The widget never sees the account's
196
+ name, a sign-in code or a token. Without a session, during a sign-in and
197
+ after a session expired, OverCrow draws its own account panel over the
198
+ widget, in both modes, and no input reaches the widget; the sign-in itself
199
+ happens there and in your browser. Under the panel the widget only says
200
+ "Twitch is disconnected" / "Twitch est déconnecté" or "Twitch connection
201
+ pending" / "Connexion Twitch en attente". While OverCrow holds a session it
202
+ cannot check and retries, it adds its notice at the bottom of the widget.
203
+
204
+ ## Tests
205
+
206
+ - `tests/logic.test.mjs`, `tests/refused.test.mjs`,
207
+ `tests/read-only.test.mjs`: the logic on `@overcrow/sdk/testing`
208
+ (`node --test tests/*.test.mjs`): channel names, the deltas (append,
209
+ replace, remove, reset, messages left out), the history's two bounds,
210
+ the unread count, a change of generation, the reply target, the fade's
211
+ levels, steps and single timer, the send cycle and each refusal, the
212
+ channel and favorite calls and their refusals, every status, the retry of
213
+ a failed subscription, the missing grants, the messages of both
214
+ languages.
215
+ - Scenarios, played in OverCrow's headless runtime
216
+ (`overcrow-widget test --runtime …`), with their reference images in
217
+ `tests/reference/`. The emotes are synthetic images drawn by
218
+ `tests/assets/generate.mjs`; authors and channels are invented.
219
+
220
+ | Scenario | Covers |
221
+ | --- | --- |
222
+ | `states` | Interactive mode: waiting, the selector without and with favorites, connecting, joined and empty, joined, reconnecting and its tooltip; dark English and light French, 100 % and 150 %, 180 px wide |
223
+ | `passive` | Passive mode: waiting, no channel, connecting, joined and empty, the last 12 of 15 messages; light French, 150 %, 180 px wide; clicks and keys reach nothing |
224
+ | `failures` | each failed join, in both modes and languages, with and without history; joined again |
225
+ | `unavailable` | the source failed and came back 5 s later, in both modes and languages; the draft kept |
226
+ | `render` | coloured authors (a very dark and a very light colour), no colour, emotes of three shapes, a wrapped message, a reply, a message of 16 runs, the reply icon and its tooltip; both themes and languages, 100 % and 150 %, 180 px wide, Passive mode |
227
+ | `fade` | the Passive fade in virtual time: opaque, half-way, nearly gone, gone; hidden then shown; a new message; the history in Interactive mode |
228
+ | `lifetime` | the menu row at 120 s, 5 s and 30 s |
229
+ | `burst` | deltas 100 ms apart: messages left out, two such rows merged, a replacement in place, removals, sixty messages in two seconds, a reset; no such row in Passive mode |
230
+ | `unread` | scrolled away, the count (messages left out included, replacements and removals not), the button, scrolling back, a reset |
231
+ | `channel` | an invalid name, 26 characters, Enter and the button, the selector over the chat, a favorite's chip, leaving, each with its call |
232
+ | `favorites` | the star and its calls, its tooltips, the limit of 20, the 20 chips, the star in Passive mode |
233
+ | `channel-refused` | a join, a favorite and a leave refused: busy, not saved, favorites full; English and French |
234
+ | `send` | nothing sent from an empty field or spaces; Enter and the button, with what OverCrow sent; the field emptied once accepted |
235
+ | `reply` | the reply target, cancelled, kept by a refusal, gone with the accepted message, dropped with its message; English and French, 180 px wide |
236
+ | `send-refused` | too fast, a chat that does not take the account's messages, not accepted, then accepted; no answer for 40 s, and nothing more sent meanwhile; English and French |
237
+ | `draft` | a draft through Passive mode, a hidden widget and the selector; another channel empties it |
238
+ | `account` | OverCrow's account panel for a missing, pending and expired session and its offline notice, in both modes, with the wrapper |
239
+ | `frame` | the widget in OverCrow's wrapper |
240
+ | `read-only` | the read grant alone: the chat, the channel controls, nothing that sends |
241
+ | `refused` | no grant: no call |
242
+
243
+ A scenario can expect the fields of a submitted form, not its `target`:
244
+ the unit tests cover the reply target the form carries.
245
+
246
+ ## Cost
247
+
248
+ Measured on 2026-10-01 with OverCrow's release build, on an AMD Ryzen 7
249
+ 5800X3D Linux workstation and in a Windows 11 virtual machine (2 vCPU),
250
+ over a synthetic chat: 200 messages, each a coloured author, text, one of
251
+ eight emotes and more text that wraps, at the default size.
252
+
253
+ | | Linux | Windows (VM) |
254
+ | --- | --- | --- |
255
+ | Widget start, warm, into the overlay's runtime, 200 messages | 10.0–10.1 ms (p50), 11.2 ms at most | VM ready in 17.0–20.8 ms (p50) |
256
+ | VM memory, Interactive mode, 200 messages | 2.6 MiB private; 3.2 MiB while the chat turns over | — |
257
+ | VM memory, Passive mode | 1.7 MiB private, 1.9 MiB PSS | 1.71–1.73 MiB private working set, 2.20–2.23 MiB private commit |
258
+ | Private memory in all (VM, sandbox helpers, overlay share), Interactive mode | 18–21 MB with 200 messages held, 23–26 MB while they turn over | — |
259
+ | Private memory in all, Passive mode | 9–12 MB | — |
260
+ | CPU at rest, 200 messages held | 0.05 % of one core, no frame | — |
261
+ | 1 message a second, Interactive mode | overlay 0.15–0.17 % of one core, VM 0.25–0.28 %; one frame per message, 1.1 ms (p95) | — |
262
+ | 10 messages a second | overlay 1.1 %, VM 2.2 %; ten frames a second, 1.1 ms (p95) | — |
263
+ | 50 messages a second | overlay 1.4–1.5 %, VM 2.3–2.5 %; ten frames a second, 1.3–1.4 ms (p95), 2.8 ms at most | — |
264
+ | 50 messages a second, Passive mode | overlay 1.0–1.1 %, VM 0.6–0.7 %; ten frames a second, 0.8 ms (p95) | — |
265
+ | Passive mode, messages fading (one every 5 s) | overlay 0.13 %, VM 0.07 %; 2 to 3 frames a second | — |
266
+ | Hidden, 50 messages a second | 0.10–0.12 % of one core, one frame in a minute, the VM idle | — |
267
+
268
+ OverCrow sends the chat at most every 100 ms: an update is one turn of the
269
+ widget's logic and one frame, so fifty messages a second cost what ten do,
270
+ and nothing is drawn while nothing arrives. Each update is read before the
271
+ next is sent; a chat beyond 200 messages a second would be sampled. A
272
+ frame of the chat stays under OverCrow's 2 ms goal at the 95th percentile;
273
+ the longest frame of a burst took 2.8 ms. The private memory is above
274
+ OverCrow's 8 MB goal per widget, around its 20 MB threshold in Interactive
275
+ mode, where OverCrow lays out 200 messages, and above it by up to 6 MB
276
+ while they turn over; far under the 80 MB ceiling. The Passive fade is 32
277
+ steps on one timer: a first version with a style transition had OverCrow
278
+ draw 43 frames a second while a message faded, for the same picture. The
279
+ egui widget it replaces painted in the overlay's own process at every
280
+ frame (0.8–1.0 ms with 200 messages) and every 100 ms in Passive mode;
281
+ OverCrow connected to the chat whenever that widget was enabled, and now
282
+ only while this widget subscribes. Scenarios render the same images on
283
+ Linux and Windows, pixel for pixel.
@@ -0,0 +1,19 @@
1
+ {
2
+ "author": "PlayerVox",
3
+ "spdxLicense": "MIT",
4
+ "sourceUrl": "https://github.com/Valhallab/playervox-overcrow-releases/tree/main/widgets/twitch-chat",
5
+ "preview": "assets/preview.png",
6
+ "defaultLocale": "en",
7
+ "localizations": [
8
+ {
9
+ "locale": "en",
10
+ "name": "Twitch chat",
11
+ "description": "Read and send messages in a public Twitch chat you choose: your favorite channels, the scrolling history with emotes and replies in Interactive mode, the last messages fading out in Passive mode. Needs your Twitch account."
12
+ },
13
+ {
14
+ "locale": "fr",
15
+ "name": "Chat Twitch",
16
+ "description": "Lisez et envoyez des messages dans le chat Twitch public de votre choix : vos chaînes favorites, l’historique défilant avec emotes et réponses en mode interactif, les derniers messages qui s’effacent en mode passif. Nécessite votre compte Twitch."
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "label": "Twitch chat",
3
+ "twitch": "Twitch",
4
+ "no-permission": "Allow access to Twitch chat in the Control Center.",
5
+ "unavailable": "Twitch is temporarily unavailable. Retrying automatically.",
6
+ "signed-out": "Twitch is disconnected",
7
+ "pending": "Twitch connection pending",
8
+ "inactive": "INACTIVE",
9
+ "disconnected": "DISCONNECTED",
10
+ "connecting": "CONNECTING",
11
+ "connected": "CONNECTED",
12
+ "reconnecting": "RECONNECTING",
13
+ "channel-unavailable": "CHANNEL UNAVAILABLE",
14
+ "connection-error": "CONNECTION ERROR",
15
+ "twitch-error": "TWITCH ERROR",
16
+ "limit": "Another widget is using Twitch chat",
17
+ "channel-name": "Channel name",
18
+ "join": "Join chat",
19
+ "favorites": "Favorites",
20
+ "favorite-channel": "Favorite channel",
21
+ "favorite": "Favorite #{channel}",
22
+ "unfavorite": "Unfavorite #{channel}",
23
+ "favorite-add": "Add current channel to favorites",
24
+ "favorite-remove": "Remove current channel from favorites",
25
+ "favorite-limit": "Favorite channel limit reached",
26
+ "change-channel": "Change channel",
27
+ "leave-channel": "Disconnect channel",
28
+ "no-channel": "No channel selected",
29
+ "no-messages": "No messages yet",
30
+ "no-recent": "No recent messages",
31
+ "new-message": "1 new message",
32
+ "new-messages": "{count} new messages",
33
+ "skipped-one": "1 message not shown",
34
+ "skipped": "{count} messages not shown",
35
+ "reply": "Reply",
36
+ "reply-to": "Reply to {name}",
37
+ "replying-to": "Replying to {name}",
38
+ "cancel-reply": "Cancel reply",
39
+ "message-label": "Message",
40
+ "send-hint": "Send a message…",
41
+ "waiting-hint": "Waiting for chat…",
42
+ "send": "Send",
43
+ "sending": "sending…",
44
+ "not-sent": "not sent",
45
+ "error-not-accepted": "Message was not accepted. Try again.",
46
+ "error-not-sent": "Message was not sent. Try again.",
47
+ "error-too-fast": "Too many messages. Wait a moment, then try again.",
48
+ "error-restricted": "This chat does not accept your messages right now.",
49
+ "error-busy": "Twitch is busy. Try again.",
50
+ "error-settings": "Could not save Twitch widget settings.",
51
+ "error-favorite-limit": "Favorite channel limit reached."
52
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "label": "Chat Twitch",
3
+ "twitch": "Twitch",
4
+ "no-permission": "Autorisez l’accès au chat Twitch dans le Centre de contrôle.",
5
+ "unavailable": "Twitch est temporairement indisponible. Nouvelle tentative automatique.",
6
+ "signed-out": "Twitch est déconnecté",
7
+ "pending": "Connexion Twitch en attente",
8
+ "inactive": "INACTIF",
9
+ "disconnected": "DÉCONNECTÉ",
10
+ "connecting": "CONNEXION EN COURS",
11
+ "connected": "CONNECTÉ",
12
+ "reconnecting": "RECONNEXION",
13
+ "channel-unavailable": "CHAÎNE INDISPONIBLE",
14
+ "connection-error": "ERREUR DE CONNEXION",
15
+ "twitch-error": "ERREUR TWITCH",
16
+ "limit": "Un autre widget utilise le chat Twitch",
17
+ "channel-name": "Nom de la chaîne",
18
+ "join": "Rejoindre",
19
+ "favorites": "Favoris",
20
+ "favorite-channel": "Chaîne favorite",
21
+ "favorite": "Ajouter #{channel} aux favoris",
22
+ "unfavorite": "Retirer #{channel} des favoris",
23
+ "favorite-add": "Ajouter la chaîne actuelle aux favoris",
24
+ "favorite-remove": "Retirer la chaîne actuelle des favoris",
25
+ "favorite-limit": "Nombre maximal de chaînes favorites atteint",
26
+ "change-channel": "Changer de chaîne",
27
+ "leave-channel": "Quitter la chaîne",
28
+ "no-channel": "Aucune chaîne sélectionnée",
29
+ "no-messages": "Aucun message pour le moment",
30
+ "no-recent": "Aucun message récent",
31
+ "new-message": "1 nouveau message",
32
+ "new-messages": "{count} nouveaux messages",
33
+ "skipped-one": "1 message non affiché",
34
+ "skipped": "{count} messages non affichés",
35
+ "reply": "Répondre",
36
+ "reply-to": "Répondre à {name}",
37
+ "replying-to": "Réponse à {name}",
38
+ "cancel-reply": "Annuler la réponse",
39
+ "message-label": "Message",
40
+ "send-hint": "Envoyer un message…",
41
+ "waiting-hint": "En attente du chat…",
42
+ "send": "Envoyer",
43
+ "sending": "envoi…",
44
+ "not-sent": "non envoyé",
45
+ "error-not-accepted": "Le message a été refusé. Réessayez.",
46
+ "error-not-sent": "Le message n’a pas été envoyé. Réessayez.",
47
+ "error-too-fast": "Trop de messages. Attendez un instant, puis réessayez.",
48
+ "error-restricted": "Ce chat n’accepte pas vos messages pour le moment.",
49
+ "error-busy": "Twitch est occupé. Réessayez.",
50
+ "error-settings": "Impossible d’enregistrer les réglages du widget Twitch.",
51
+ "error-favorite-limit": "Nombre maximal de chaînes favorites atteint."
52
+ }