@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,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "lib": ["ES2023"],
5
+ "types": [],
6
+ "module": "ES2022",
7
+ "moduleResolution": "bundler",
8
+ "strict": true,
9
+ "noEmit": true,
10
+ "isolatedModules": true,
11
+ "verbatimModuleSyntax": true,
12
+ "noUncheckedIndexedAccess": true,
13
+ "exactOptionalPropertyTypes": true
14
+ },
15
+ "include": ["logic.ts"]
16
+ }
@@ -0,0 +1,141 @@
1
+ <!-- Twitch chat: the chat of one public Twitch channel (parity sheet:
2
+ playervox-overcrow docs/builtin-parity/twitch-chat.md).
3
+ OverCrow holds the account, the connection, the channel and the
4
+ favorites. The composer is a form bound to the `twitch.chat.send`
5
+ intent: its message field belongs to OverCrow, which keeps the text,
6
+ sends it and empties it once accepted; it takes no `value` here. The
7
+ form's key is the chat's generation: another channel or account is
8
+ another form, without the previous text. -->
9
+ <box class="chat" label={t("label")}>
10
+ <box class="header">
11
+ <icon class="mark" name="message-square" label={t("twitch")}/>
12
+ <if test={phase(state) == "chat"}>
13
+ <if test={state.interactive}>
14
+ <button class={starClass(state)} label={favoriteLabel(state)} tooltip={t(favoriteTip(state))} disabled={favoriteFull(state)} on:activate={toggleFavorite}>
15
+ <icon name="star"/>
16
+ </button>
17
+ </if>
18
+ <else-if test={isFavorite(state)}>
19
+ <icon class="star-mark" name="star" label={t("favorite-channel")}/>
20
+ </else-if>
21
+ </if>
22
+ <text class="heading">{heading(state)}</text>
23
+ <box class={dotClass(state)} label={t(statusKey(state))} tooltip={t(statusKey(state))}/>
24
+ <if test={state.interactive && phase(state) == "chat"}>
25
+ <button class="icon-button" label={t("change-channel")} tooltip={t("change-channel")} on:activate={toggleSelector}>
26
+ <icon name="chevron-right"/>
27
+ </button>
28
+ <button class="icon-button" label={t("leave-channel")} tooltip={t("leave-channel")} on:activate={leave}>
29
+ <icon name="x"/>
30
+ </button>
31
+ </if>
32
+ </box>
33
+ <if test={failureKey(state) != ""}>
34
+ <text class="error">{t(failureKey(state))}</text>
35
+ </if>
36
+ <if test={state.interactive && state.notice != ""}>
37
+ <text class="error">{t(state.notice)}</text>
38
+ </if>
39
+ <if test={phase(state) == "permission"}>
40
+ <text class="status">{t("no-permission")}</text>
41
+ </if>
42
+ <if test={phase(state) == "unavailable"}>
43
+ <text class="status">{t("unavailable")}</text>
44
+ </if>
45
+ <if test={phase(state) == "signed-out"}>
46
+ <text class="status">{t("signed-out")}</text>
47
+ </if>
48
+ <if test={phase(state) == "pending"}>
49
+ <text class="status">{t("pending")}</text>
50
+ </if>
51
+ <if test={phase(state) == "no-channel" && !state.interactive}>
52
+ <text class="status">{t("no-channel")}</text>
53
+ </if>
54
+ <if test={selecting(state)}>
55
+ <!-- The selector's key changes when it starts over: its field is
56
+ OverCrow's to edit, and a new field is an empty one. -->
57
+ <for each={selectors(state)} as="selector" key={selector}>
58
+ <form class="selector" on:submit={join}>
59
+ <field class="input channel" max-length="26" autofocus placeholder={t("channel-name")} label={t("channel-name")} on:input={channelTyped(event.value)}/>
60
+ <button class="action" submit disabled={!canJoin(state)}>
61
+ <text class="action-label">{t("join")}</text>
62
+ </button>
63
+ </form>
64
+ </for>
65
+ <if test={state.favorites.length > 0}>
66
+ <text class="eyebrow">{t("favorites")}</text>
67
+ <scroll class="chips">
68
+ <for each={state.favorites} as="favorite" key={favorite}>
69
+ <button class="chip" on:activate={joinFavorite(favorite)}>
70
+ <text class="chip-label">#{favorite}</text>
71
+ </button>
72
+ </for>
73
+ </scroll>
74
+ </if>
75
+ </if>
76
+ <if test={phase(state) == "chat"}>
77
+ <if test={state.shown.length == 0}>
78
+ <text class="empty">{t(emptyKey(state))}</text>
79
+ </if>
80
+ <list class="history" stick-to-end={state.following} item-height="20" label={heading(state)} on:stick={stuck(event.stuck)}>
81
+ <for each={state.shown} as="row" key={row.key}>
82
+ <if test={row.gap > 0}>
83
+ <text class="gap">{gapText(row.gap)}</text>
84
+ </if>
85
+ <else>
86
+ <box class={row.cls}>
87
+ <if test={row.context != ""}>
88
+ <text class="context">{row.context}</text>
89
+ </if>
90
+ <text class="message">
91
+ <span class="author" color={row.color}>{row.author}</span>
92
+ <for each={row.parts} as="part" key={part.key}>
93
+ <if test={part.emote != ""}>
94
+ <image class="emote" src={part.emote} label={part.text}/>
95
+ </if>
96
+ <else>
97
+ <span>{part.text}</span>
98
+ </else>
99
+ </for>
100
+ </text>
101
+ <if test={composing(state)}>
102
+ <icon class="reply" name="reply" label={t("reply")} tooltip={row.tip} on:activate={replyTo(row.id)}/>
103
+ </if>
104
+ </box>
105
+ </else>
106
+ </for>
107
+ </list>
108
+ <if test={state.interactive && state.unread > 0}>
109
+ <button class="unread" on:activate={latest}>
110
+ <text class="unread-label">{unreadText(state.unread)}</text>
111
+ </button>
112
+ </if>
113
+ </if>
114
+ <!-- The composer stays in the view whatever shows above it, hidden when
115
+ nothing can be composed: OverCrow keeps the text of its field through
116
+ Passive mode and a failed subscription. -->
117
+ <for each={composers(state)} as="composer" key={composer}>
118
+ <form class={composerClass(state)} intent="twitch.chat.send" target={replyTarget(state)} on:submit={submitted(event.outcome, event.error)}>
119
+ <if test={state.reply}>
120
+ <box class="replying">
121
+ <text class="replying-label">{replyingTo(state)}</text>
122
+ <button class="icon-button small" label={t("cancel-reply")} tooltip={t("cancel-reply")} on:activate={cancelReply}>
123
+ <icon name="x"/>
124
+ </button>
125
+ </box>
126
+ </if>
127
+ <if test={state.sendError != ""}>
128
+ <text class="error">{t(state.sendError)}</text>
129
+ </if>
130
+ <box class="compose">
131
+ <field class="input message-field" name="message" max-length="500" placeholder={t(composerHint(state))} label={t("message-label")} disabled={!state.canSend} on:input={drafted(event.value)} on:keydown={keyed(event.key)}/>
132
+ <if test={sendMark(state) != ""}>
133
+ <text class={sendMarkClass(state)}>{t(sendMark(state))}</text>
134
+ </if>
135
+ <button class="action" submit disabled={!canSubmit(state)} on:activate={sendPressed}>
136
+ <text class="action-label">{t("send")}</text>
137
+ </button>
138
+ </box>
139
+ </form>
140
+ </for>
141
+ </box>
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Valhallab SASU
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,176 @@
1
+ # Warframe Market
2
+
3
+ `com.playervox.overcrow.warframe.market` — searches the public PC item
4
+ catalog of [warframe.market](https://warframe.market), shows the online
5
+ sellers and buyers of one item in two tabs and copies a trade whisper when
6
+ you click. A
7
+ PlayerVox widget of the catalog, not a built-in: written against the public
8
+ `@overcrow/sdk` and packaged with `overcrow-widget` like any creator's
9
+ widget. MIT. Version 3.0.0 replaced the Web widget (2.0.6) of the retired
10
+ runtime, under the same ID; 3.1.0 shows every online offer instead of the
11
+ five best, in tabs, with a refresh button and an optional auto refresh.
12
+
13
+ Warframe and related names remain trademarks of their respective owners
14
+ ([trademarks](../../TRADEMARKS.md)); this widget is not affiliated with
15
+ them or with warframe.market.
16
+
17
+ ## What it shows
18
+
19
+ | State | Shows |
20
+ | --- | --- |
21
+ | Loading | "Loading catalog…" until the stored or downloaded catalog is ready |
22
+ | Search | Up to 12 items whose English name or slug holds the text, in catalog order |
23
+ | Selected item | Lowest sell and highest buy price per item, then two tabs, Sellers (first) and Buyers, each with its count: every visible PC offer of a player in game or online, sellers by rising and buyers by falling price per item, the best 150 shown and "+N more" below them: price, trader followed by a dot for the player's state (green in game, amber online, named on hover and for screen readers; a long name is cut before the dot), quantity and variant (rank, charges, stars, subtype). A legend of the dots stays at the bottom, out of the scroll |
24
+ | Refresh | The button beside "Back" reloads the item's offers; it is off while they load. The offers shown stay until the new ones arrive ("Refreshing offers…"); a failed refresh keeps them ("Refresh failed · showing the previous offers") |
25
+ | Copy | "Whisper" writes `/w <trader> Hi, WTB <item> (<variant>) for <price>p` (WTS for a buyer; `n x … total` for several items) to the clipboard; the button then says "Copied", or "Retry" when it failed |
26
+ | Passive mode | The last results, with "Switch to interactive mode to search" |
27
+ | Errors | Catalog unavailable (with or without a cached catalog), orders unavailable, storage unavailable |
28
+
29
+ The interface is in English and French; item names stay in English, as the
30
+ provider sends them, and so does the whisper, which goes to the game's
31
+ trade chat. Prices use the user's number format.
32
+
33
+ ## Permissions
34
+
35
+ | Permission | Why |
36
+ | --- | --- |
37
+ | `network` | Three `GET` routes of `https://api.warframe.market`, each with its response bound: `/v2/versions` (4 KiB; its answer is about 0.5 KB), `/v2/items` (3 MiB; the catalog is 1.6 MB and the default 1 MiB bound is too small) and `/v2/orders/item/{slug}`, the slug checked as a `slug` parameter of at most 96 bytes (2 MiB; the orders of users seen in the last seven days, 0.4 to 1 MB for popular items on 2026-10-08) |
38
+ | `storage` | The saved search and the compact catalog with its version, in at most four keys and about 70 KB of the 256 KiB quota |
39
+ | `clipboardWrite` | The whisper, on a click in interactive mode only |
40
+
41
+ No capability: the widget reads nothing about the user or the game.
42
+
43
+ ## Options menu
44
+
45
+ | Row | Values |
46
+ | --- | --- |
47
+ | Auto refresh | Off (default), every 30 s, every minute: the shown item's offers reload on their own. Only with an item shown, never while a request runs, paused while the widget or the overlay is hidden (a reload that fell due runs when it shows again), and each failure in a row doubles the wait, up to eight times. Off by default: every 30 s, a popular item costs about 1.75 MB of download a minute |
48
+
49
+ ## How it works
50
+
51
+ - **Catalog.** At start the widget reads the stored catalog, then asks
52
+ `/v2/versions` for the catalog's version. It downloads `/v2/items` only
53
+ when nothing is stored or the version changed; a failed download keeps
54
+ the stored catalog.
55
+ - **Turns.** The catalog is downloaded as text and read in slices of 250
56
+ items, one host timer (100 ms) apart: each item is parsed alone and
57
+ checked (slug `[a-z0-9_-]`, name without control characters, cut to 96
58
+ characters). The stored copy is written and read back the same way. No
59
+ VM turn handles the whole catalog, so none nears the turn budget, even
60
+ under the VM's CPU ceiling.
61
+ - **Storage.** One line per item: the name, followed by a tab and the slug
62
+ when the slug does not derive from the name (83 of 3,892 items). The
63
+ lines fill chunks of at most 60 KB (two for today's catalog, three at
64
+ most). The index key is removed before the chunks are written and set
65
+ last, so an interrupted write is never read back as a catalog.
66
+ - **Orders.** An item's answer is read as text, 300 orders per VM turn, one
67
+ host timer (100 ms) apart: rows are cut where `},{"id":"` starts the next
68
+ one and each slice is parsed by the engine's `JSON.parse`, so a wrong cut
69
+ fails, never silently, and a slice beyond 512 KB, a malformed envelope or
70
+ more than 20,000 rows refuse the answer ("Orders unavailable"). Parsing a
71
+ 1 MB answer in one turn would exceed the turn budget under the VM's CPU
72
+ ceiling. Only visible PC orders of players in game or online are kept.
73
+ - **Requests.** The provider allows three requests per second: a request
74
+ starts at least 400 ms after the previous one. Selecting several items
75
+ quickly sends one request, for the latest; a late answer for an earlier
76
+ selection is dropped. The catalog and the orders run one after the other:
77
+ their bounds (3 and 2 MiB) do not fit the widget's 4 MiB network budget
78
+ together.
79
+ - **Search.** In memory, at each keystroke; the text is saved a second
80
+ after the last one.
81
+
82
+ ## Differences from the Web widget
83
+
84
+ - The catalog lived in IndexedDB; it is now in host storage, compacted.
85
+ - Its layout adapted to the panel width with CSS media queries; the style
86
+ subset has none, so the offer rows keep one grid and the panel scrolls.
87
+ - After "Clear", the Web widget put the focus back in the search field.
88
+ The SDK has no focus API; a future SDK version could add one.
89
+ - A "Back to results" button returns from an item to the search results.
90
+
91
+ ## Tests
92
+
93
+ - `tests/logic.test.mjs`: the logic on `@overcrow/sdk/testing`: start,
94
+ pacing, storage writes, search, selection, copy and its failure, refresh
95
+ (offers kept while they reload, a failed refresh), auto refresh (off by
96
+ default, every 30 s or minute, slower after errors, never two at once,
97
+ none without an item), tabs, the catalog and the orders one after the
98
+ other, the incremental readers (strings, nesting, slices, malformed or
99
+ oversized answers), the catalog, orders and whisper rules, the 150-offer
100
+ cap, and a catalog of today's size that fits two storage values.
101
+ - Scenarios, played by `overcrow-widget test` in OverCrow's headless
102
+ runtime, with synthetic `http.fetch` fixtures (no request reaches
103
+ warframe.market) and their reference images: `render` (both themes and
104
+ languages at 100 and 150 %), `detail` (both tabs, copies, back, clicks at
105
+ 100 and 150 %), `tabs` (161 sellers: the 150 cap and "+11 more", at the
106
+ minimum and default widths, both themes and languages), `auto-refresh`
107
+ (every 30 s, nothing while hidden, the due reload when shown again, the
108
+ refresh button), `search`, `passive`, `cached`, `refresh`, `bounds` (a
109
+ version answer beyond its 4 KiB bound), `errors`, `unavailable`,
110
+ `refused` (without `network`) and `no-clipboard`.
111
+
112
+ ```sh
113
+ node ../../scripts/prepare-widgets.mjs
114
+ overcrow-widget check && overcrow-widget package
115
+ node --test tests/*.test.mjs
116
+ overcrow-widget test --runtime <overcrow-widget-headless>
117
+ ```
118
+
119
+ ## Cost
120
+
121
+ Measured on 2026-09-30 with OverCrow's headless runtime (release build),
122
+ on an AMD Ryzen 7 5800X3D Linux workstation (the VM in its Bubblewrap and
123
+ seccomp sandbox, without the per-widget cgroup) and in a Windows 11 virtual
124
+ machine (2 vCPU, cross-built runtime, full containment: Less Privileged
125
+ AppContainer, Job, mitigations). The catalog is synthetic, 3,892 items
126
+ shaped and sized like the provider's (1.63 MB). Figures of the VM process:
127
+ `RssAnon`, `VmHWM` and `schedstat` on Linux; private commit, private
128
+ working set and peak working set on Windows. Three runs each; Windows
129
+ samples every few milliseconds on 2 vCPU and can miss a short peak.
130
+
131
+ | | Linux | Windows (VM) |
132
+ | --- | --- | --- |
133
+ | VM private memory, catalog downloaded and stored (peak) | 5.0 MiB `RssAnon` | 5.7–5.8 MiB commit, 5.1–5.3 MiB private working set |
134
+ | VM private memory, at rest after searches | 3.7 MiB `RssAnon` | 3.4–5.1 MiB private working set |
135
+ | VM private memory, start from the stored catalog | 3.2 MiB `RssAnon` | 2.6–3.0 MiB commit |
136
+ | VM resident peak, shared pages included | 11.5–11.7 MiB `VmHWM` | 14.9–15.1 MiB peak working set |
137
+ | VM CPU, download, check and store the catalog | 126–137 ms in about 35 turns | 110–160 ms (15.6 ms clock) |
138
+ | VM CPU per keystroke of a search | about 0.3 ms | not resolved by the clock |
139
+ | VM CPU at rest | none: no timer runs once the catalog is loaded | the same |
140
+ | First load, catalog downloaded | searchable after about 16 turns (1.6 s after the answer), stored after about 35 turns at 100 ms (3.5 s) | the same turns |
141
+ | Searchable after a start from the stored catalog | 5 turns, about 0.5 s | the same turns |
142
+ | Network, a refresh | 1.64 MB (catalog) + 0.5 KB (version), plus about 0.6 KB of headers each | — |
143
+ | Network, a start with the current catalog stored | 0.5 KB (version) | — |
144
+
145
+ All within the 8 MB engineering goal per widget. The eleven scenarios of
146
+ 3.0.1 pass on Windows too; their 22 images are identical, pixel for pixel,
147
+ to the Linux references.
148
+
149
+ The offers of one item (3.1.0), measured on 2026-10-08 on the same Linux
150
+ workstation with the provider's real answers, the VM in its sandbox with
151
+ the production cgroup leaf (a quarter of one core, 64 MiB):
152
+
153
+ | | 876 KB answer (1,718 orders, about 115 online) | synthetic 2 MB answer (3,895 orders) |
154
+ | --- | --- | --- |
155
+ | VM resident peak (`VmHWM`) | 9.4 MiB | 11.5 MiB |
156
+ | VM CPU per slice of 300 orders | 2 to 3 ms | the same |
157
+ | Last turn (sort, scene) | 3.5 to 6 ms | the same |
158
+ | Offers shown after the answer | 6 slices, about 0.6 s | 13 slices, about 1.3 s |
159
+ | Turns killed by the turn budget, 25 runs | none | none |
160
+ | One turn for the whole answer (rejected design) | killed 5 times in 5 | killed 5 times in 5 |
161
+
162
+ Sixty refreshes in a row leave the heap at 1.0 MiB and the resident memory
163
+ flat. The most offers found on a side among twelve popular items was 112
164
+ (Primed Flow): 933 scene nodes, about 15 ms of host work once when the list
165
+ arrives; 150 offers, the cap, stay near 1,250 nodes, far below the 4,096
166
+ nodes of a scene. Network, a refresh of a popular item: 0.4 to 1 MB, about
167
+ 1.75 MB a minute every 30 s (the host's broker takes no compression).
168
+
169
+ At the declared ceiling (a synthetic 3.0 MB catalog of 7,200 items) the
170
+ first load takes about 60 turns, the VM peaks at 8.1 MiB private on Linux
171
+ and the default 16 MiB heap suffices. The catalog then needs four storage
172
+ values, beyond three: it is searchable but kept in memory only, and
173
+ downloaded again at the next start. A catalog beyond 3 MiB fails with
174
+ `response_body_limit`, and the widget shows "Catalog unavailable" (or keeps
175
+ its stored catalog). Not measured: the overlay's share and frame times
176
+ (the headless runtime renders on the CPU).
@@ -0,0 +1,19 @@
1
+ {
2
+ "author": "PlayerVox",
3
+ "spdxLicense": "MIT",
4
+ "sourceUrl": "https://github.com/Valhallab/playervox-overcrow-releases/tree/main/widgets/warframe-market",
5
+ "preview": "assets/preview.png",
6
+ "defaultLocale": "en",
7
+ "localizations": [
8
+ {
9
+ "locale": "en",
10
+ "name": "Warframe Market",
11
+ "description": "Searches public PC items from a cached catalog, shows an item’s online sellers and buyers in two tabs, and copies a trade whisper when you click."
12
+ },
13
+ {
14
+ "locale": "fr",
15
+ "name": "Marché Warframe",
16
+ "description": "Recherche les objets PC publics dans un catalogue en cache, affiche les vendeurs et acheteurs en ligne d’un objet dans deux onglets et copie un message d’échange sur un clic."
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "eyebrow": "Market",
3
+ "subtitle": "Trade assistant",
4
+ "platform": "PC market",
5
+ "search-label": "Search items",
6
+ "search-field": "Item name",
7
+ "placeholder": "Arcane Energize, Soma Prime…",
8
+ "clear": "Clear",
9
+ "hint-interactive": "Results update as you type",
10
+ "hint-passive": "Switch to interactive mode to search",
11
+ "status-loading": "Loading catalog…",
12
+ "status-catalog-unavailable": "Catalog unavailable",
13
+ "status-catalog-stale": "Catalog refresh unavailable · using cached items",
14
+ "status-storage_unavailable": "Storage unavailable · changes may not survive restart",
15
+ "status-orders_unavailable": "Orders unavailable · select an item to retry",
16
+ "status-loading-orders": "Loading offers…",
17
+ "status-refreshing": "Refreshing offers…",
18
+ "status-refresh-failed": "Refresh failed · showing the previous offers",
19
+ "status-ready": "{count} items cached · select an item to view offers",
20
+ "status-detail": "{count} items cached",
21
+ "empty-loading": "Loading the item catalog…",
22
+ "empty-unavailable": "The item catalog could not be loaded. Reopen the widget later to try again.",
23
+ "empty-start": "Find an item to compare offers and copy a trade whisper.",
24
+ "empty-no-match": "No matching items. Try a different name.",
25
+ "selected": "Selected item",
26
+ "back": "Back to results",
27
+ "refresh": "Refresh",
28
+ "min-sell": "Min sell / item",
29
+ "max-buy": "Max buy / item",
30
+ "sellers": "Sellers",
31
+ "buyers": "Buyers",
32
+ "no-sell-offers": "No sell offers available.",
33
+ "no-buy-offers": "No buy offers available.",
34
+ "more": "+{count} more",
35
+ "presence-ingame": "In game",
36
+ "presence-online": "Online",
37
+ "one-item": "1 item",
38
+ "per-trade": "{count} items · total price",
39
+ "copy": "Whisper",
40
+ "copy-pending": "Copying…",
41
+ "copy-copied": "Copied",
42
+ "copy-failed": "Retry",
43
+ "copy-to": "Copy whisper to {name}"
44
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "eyebrow": "Marché",
3
+ "subtitle": "Assistant d’échange",
4
+ "platform": "Marché PC",
5
+ "search-label": "Rechercher un objet",
6
+ "search-field": "Nom de l’objet",
7
+ "placeholder": "Arcane Energize, Soma Prime…",
8
+ "clear": "Effacer",
9
+ "hint-interactive": "Les résultats suivent votre saisie",
10
+ "hint-passive": "Passez en mode interactif pour chercher",
11
+ "status-loading": "Chargement du catalogue…",
12
+ "status-catalog-unavailable": "Catalogue indisponible",
13
+ "status-catalog-stale": "Actualisation impossible · objets en cache utilisés",
14
+ "status-storage_unavailable": "Stockage indisponible · les changements peuvent être perdus au redémarrage",
15
+ "status-orders_unavailable": "Offres indisponibles · sélectionnez un objet pour réessayer",
16
+ "status-loading-orders": "Chargement des offres…",
17
+ "status-refreshing": "Actualisation des offres…",
18
+ "status-refresh-failed": "Actualisation impossible · offres précédentes affichées",
19
+ "status-ready": "{count} objets en cache · sélectionnez un objet pour voir les offres",
20
+ "status-detail": "{count} objets en cache",
21
+ "empty-loading": "Chargement du catalogue d’objets…",
22
+ "empty-unavailable": "Le catalogue d’objets n’a pas pu être chargé. Rouvrez le widget plus tard pour réessayer.",
23
+ "empty-start": "Cherchez un objet pour comparer les offres et copier un message d’échange.",
24
+ "empty-no-match": "Aucun objet ne correspond. Essayez un autre nom.",
25
+ "selected": "Objet sélectionné",
26
+ "back": "Retour aux résultats",
27
+ "refresh": "Actualiser",
28
+ "min-sell": "Vente min. / objet",
29
+ "max-buy": "Achat max. / objet",
30
+ "sellers": "Vendeurs",
31
+ "buyers": "Acheteurs",
32
+ "no-sell-offers": "Aucune offre de vente.",
33
+ "no-buy-offers": "Aucune offre d’achat.",
34
+ "more": "+{count} autres",
35
+ "presence-ingame": "En jeu",
36
+ "presence-online": "En ligne",
37
+ "one-item": "1 objet",
38
+ "per-trade": "{count} objets · prix total",
39
+ "copy": "Chuchoter",
40
+ "copy-pending": "Copie…",
41
+ "copy-copied": "Copié",
42
+ "copy-failed": "Réessayer",
43
+ "copy-to": "Copier le message pour {name}"
44
+ }