@sirenodeck/sirenodeck 0.1.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/bin/_wrapper-shared.js +42 -0
  4. package/bin/dev.js +95 -0
  5. package/bin/sirenodeck.js +42 -0
  6. package/config/default-config.yml +117 -0
  7. package/config/starter-config.yml +54 -0
  8. package/dist/main.mjs +64702 -0
  9. package/package.json +140 -0
  10. package/src/action/executor.ts +156 -0
  11. package/src/action/index.ts +7 -0
  12. package/src/addon/api-types.ts +15 -0
  13. package/src/addon/api.ts +461 -0
  14. package/src/addon/check-runner.ts +84 -0
  15. package/src/addon/index.ts +5 -0
  16. package/src/addon/loader.ts +441 -0
  17. package/src/addon/registry.ts +230 -0
  18. package/src/addon/spec.ts +69 -0
  19. package/src/api/addon.ts +33 -0
  20. package/src/api/asset-url.ts +24 -0
  21. package/src/api/index.ts +50 -0
  22. package/src/api/protocol-internal.ts +656 -0
  23. package/src/api/protocol.ts +2 -0
  24. package/src/api/react/index.ts +11 -0
  25. package/src/api/react/registry.ts +91 -0
  26. package/src/api/react/use-addon-channel.ts +26 -0
  27. package/src/api/react/use-button-state.tsx +23 -0
  28. package/src/api/react/use-deck.ts +24 -0
  29. package/src/assets/logo.png +0 -0
  30. package/src/assets/logo72x72.png +0 -0
  31. package/src/assets/logoFull.png +0 -0
  32. package/src/builtin-addons/brightness/README.md +51 -0
  33. package/src/builtin-addons/brightness/buttons/brightness/backend.ts +13 -0
  34. package/src/builtin-addons/brightness/buttons/brightness/config.ts +10 -0
  35. package/src/builtin-addons/brightness/buttons/brightness/frontend.tsx +50 -0
  36. package/src/builtin-addons/brightness/domain/macos.ts +46 -0
  37. package/src/builtin-addons/brightness/index.d.ts +5 -0
  38. package/src/builtin-addons/brightness/index.ts +20 -0
  39. package/src/builtin-addons/brightness/poller.ts +27 -0
  40. package/src/builtin-addons/brightness/providers/darwin.ts +107 -0
  41. package/src/builtin-addons/brightness/providers/index.ts +81 -0
  42. package/src/builtin-addons/brightness/providers/linux.ts +108 -0
  43. package/src/builtin-addons/brightness/providers/windows.ts +77 -0
  44. package/src/builtin-addons/brightness/sirenodeck.json +6 -0
  45. package/src/builtin-addons/coding-agents/assets/claude-code.svg +1 -0
  46. package/src/builtin-addons/coding-agents/assets/opencode-dark-square.svg +1 -0
  47. package/src/builtin-addons/coding-agents/buttons/agent/backend.ts +82 -0
  48. package/src/builtin-addons/coding-agents/buttons/agent/config.ts +13 -0
  49. package/src/builtin-addons/coding-agents/buttons/agent/frontend.tsx +130 -0
  50. package/src/builtin-addons/coding-agents/buttons/agent/pages.tsx +150 -0
  51. package/src/builtin-addons/coding-agents/buttons/summary/backend.ts +48 -0
  52. package/src/builtin-addons/coding-agents/buttons/summary/config.ts +11 -0
  53. package/src/builtin-addons/coding-agents/buttons/summary/frontend.tsx +254 -0
  54. package/src/builtin-addons/coding-agents/decks/agents.ts +69 -0
  55. package/src/builtin-addons/coding-agents/global/backend.ts +402 -0
  56. package/src/builtin-addons/coding-agents/global-entry.ts +7 -0
  57. package/src/builtin-addons/coding-agents/hook/script.ts +123 -0
  58. package/src/builtin-addons/coding-agents/index.ts +15 -0
  59. package/src/builtin-addons/coding-agents/manifest.ts +115 -0
  60. package/src/builtin-addons/coding-agents/providers/claude-code.ts +470 -0
  61. package/src/builtin-addons/coding-agents/providers/claude-instances.ts +184 -0
  62. package/src/builtin-addons/coding-agents/providers/opencode-instances.ts +108 -0
  63. package/src/builtin-addons/coding-agents/providers/opencode.ts +636 -0
  64. package/src/builtin-addons/coding-agents/providers/registry.ts +120 -0
  65. package/src/builtin-addons/coding-agents/providers/spawn.ts +112 -0
  66. package/src/builtin-addons/coding-agents/shared/claude-hook-events.ts +55 -0
  67. package/src/builtin-addons/coding-agents/shared/claude-status.ts +236 -0
  68. package/src/builtin-addons/coding-agents/shared/live-count.ts +39 -0
  69. package/src/builtin-addons/coding-agents/shared/notifier.ts +58 -0
  70. package/src/builtin-addons/coding-agents/shared/opencode-status.ts +82 -0
  71. package/src/builtin-addons/coding-agents/shared/snapshot.ts +66 -0
  72. package/src/builtin-addons/coding-agents/shared/state.ts +72 -0
  73. package/src/builtin-addons/coding-agents/sirenodeck.json +6 -0
  74. package/src/builtin-addons/coding-agents/types/types.ts +33 -0
  75. package/src/builtin-addons/core/README.md +89 -0
  76. package/src/builtin-addons/core/buttons/action/backend.ts +7 -0
  77. package/src/builtin-addons/core/buttons/action/config.ts +13 -0
  78. package/src/builtin-addons/core/buttons/action/frontend.tsx +16 -0
  79. package/src/builtin-addons/core/buttons/change-deck/backend.ts +18 -0
  80. package/src/builtin-addons/core/buttons/change-deck/config.ts +15 -0
  81. package/src/builtin-addons/core/buttons/change-deck/frontend.tsx +18 -0
  82. package/src/builtin-addons/core/buttons/media-sample/backend.ts +8 -0
  83. package/src/builtin-addons/core/buttons/media-sample/config.ts +7 -0
  84. package/src/builtin-addons/core/buttons/media-sample/frontend.tsx +2 -0
  85. package/src/builtin-addons/core/buttons/page-nav/backend.ts +28 -0
  86. package/src/builtin-addons/core/buttons/page-nav/config.ts +9 -0
  87. package/src/builtin-addons/core/buttons/page-nav/frontend.tsx +68 -0
  88. package/src/builtin-addons/core/buttons/toggle/backend.ts +119 -0
  89. package/src/builtin-addons/core/buttons/toggle/config.ts +57 -0
  90. package/src/builtin-addons/core/buttons/toggle/frontend.tsx +57 -0
  91. package/src/builtin-addons/core/buttons/toggle/global-service.ts +174 -0
  92. package/src/builtin-addons/core/index.ts +120 -0
  93. package/src/builtin-addons/core/sirenodeck.json +6 -0
  94. package/src/builtin-addons/date-time/README.md +73 -0
  95. package/src/builtin-addons/date-time/buttons/analog-clock/backend.ts +10 -0
  96. package/src/builtin-addons/date-time/buttons/analog-clock/config.ts +4 -0
  97. package/src/builtin-addons/date-time/buttons/analog-clock/frontend.tsx +88 -0
  98. package/src/builtin-addons/date-time/buttons/custom/backend.ts +10 -0
  99. package/src/builtin-addons/date-time/buttons/custom/config.ts +9 -0
  100. package/src/builtin-addons/date-time/buttons/custom/frontend.tsx +26 -0
  101. package/src/builtin-addons/date-time/buttons/date/backend.ts +10 -0
  102. package/src/builtin-addons/date-time/buttons/date/config.ts +10 -0
  103. package/src/builtin-addons/date-time/buttons/date/frontend.tsx +42 -0
  104. package/src/builtin-addons/date-time/buttons/time/backend.ts +10 -0
  105. package/src/builtin-addons/date-time/buttons/time/config.ts +9 -0
  106. package/src/builtin-addons/date-time/buttons/time/frontend.tsx +29 -0
  107. package/src/builtin-addons/date-time/index.d.ts +5 -0
  108. package/src/builtin-addons/date-time/index.ts +30 -0
  109. package/src/builtin-addons/date-time/poller.ts +11 -0
  110. package/src/builtin-addons/date-time/shared/format-date.ts +36 -0
  111. package/src/builtin-addons/date-time/shared/format.ts +105 -0
  112. package/src/builtin-addons/date-time/shared/use-now.ts +10 -0
  113. package/src/builtin-addons/date-time/sirenodeck.json +6 -0
  114. package/src/builtin-addons/emoji-selector/README.md +45 -0
  115. package/src/builtin-addons/emoji-selector/assets/launcher.svg +10 -0
  116. package/src/builtin-addons/emoji-selector/assets/smileys.svg +8 -0
  117. package/src/builtin-addons/emoji-selector/buttons/category/backend.ts +14 -0
  118. package/src/builtin-addons/emoji-selector/buttons/category/config.ts +8 -0
  119. package/src/builtin-addons/emoji-selector/buttons/category/frontend.tsx +19 -0
  120. package/src/builtin-addons/emoji-selector/buttons/emoji/backend.ts +7 -0
  121. package/src/builtin-addons/emoji-selector/buttons/emoji/config.ts +9 -0
  122. package/src/builtin-addons/emoji-selector/buttons/emoji/frontend.tsx +11 -0
  123. package/src/builtin-addons/emoji-selector/buttons/launcher/backend.ts +13 -0
  124. package/src/builtin-addons/emoji-selector/buttons/launcher/config.ts +6 -0
  125. package/src/builtin-addons/emoji-selector/buttons/launcher/frontend.tsx +31 -0
  126. package/src/builtin-addons/emoji-selector/data/categories.ts +1084 -0
  127. package/src/builtin-addons/emoji-selector/decks/index.ts +137 -0
  128. package/src/builtin-addons/emoji-selector/index.d.ts +5 -0
  129. package/src/builtin-addons/emoji-selector/index.ts +29 -0
  130. package/src/builtin-addons/emoji-selector/sirenodeck.json +6 -0
  131. package/src/builtin-addons/emoji-selector/support.ts +49 -0
  132. package/src/builtin-addons/index.ts +13 -0
  133. package/src/builtin-addons/internal-settings/README.md +26 -0
  134. package/src/builtin-addons/internal-settings/backend.ts +58 -0
  135. package/src/builtin-addons/internal-settings/buttons/app-info/backend.ts +7 -0
  136. package/src/builtin-addons/internal-settings/buttons/app-info/config.ts +13 -0
  137. package/src/builtin-addons/internal-settings/buttons/app-info/frontend.tsx +18 -0
  138. package/src/builtin-addons/internal-settings/buttons/brightness/common/frontend.tsx +50 -0
  139. package/src/builtin-addons/internal-settings/buttons/brightness-down/backend.ts +16 -0
  140. package/src/builtin-addons/internal-settings/buttons/brightness-down/config.ts +6 -0
  141. package/src/builtin-addons/internal-settings/buttons/brightness-down/frontend.tsx +8 -0
  142. package/src/builtin-addons/internal-settings/buttons/brightness-up/backend.ts +16 -0
  143. package/src/builtin-addons/internal-settings/buttons/brightness-up/config.ts +6 -0
  144. package/src/builtin-addons/internal-settings/buttons/brightness-up/frontend.tsx +8 -0
  145. package/src/builtin-addons/internal-settings/decks/settings.ts +25 -0
  146. package/src/builtin-addons/internal-settings/index.d.ts +4 -0
  147. package/src/builtin-addons/internal-settings/index.ts +53 -0
  148. package/src/builtin-addons/internal-settings/logo72x72.png +0 -0
  149. package/src/builtin-addons/internal-settings/sirenodeck.json +6 -0
  150. package/src/builtin-addons/media/README.md +45 -0
  151. package/src/builtin-addons/media/backend.ts +143 -0
  152. package/src/builtin-addons/media/buttons/media-player/backend.ts +19 -0
  153. package/src/builtin-addons/media/buttons/media-player/components/MediaStatus.tsx +25 -0
  154. package/src/builtin-addons/media/buttons/media-player/components/MediaSurface.tsx +52 -0
  155. package/src/builtin-addons/media/buttons/media-player/components/ProgressBar.tsx +21 -0
  156. package/src/builtin-addons/media/buttons/media-player/components/status-meta.ts +36 -0
  157. package/src/builtin-addons/media/buttons/media-player/config.ts +4 -0
  158. package/src/builtin-addons/media/buttons/media-player/frontend.tsx +29 -0
  159. package/src/builtin-addons/media/buttons/volume/common/frontend.tsx +52 -0
  160. package/src/builtin-addons/media/buttons/volume/mute/backend.ts +13 -0
  161. package/src/builtin-addons/media/buttons/volume/mute/config.ts +4 -0
  162. package/src/builtin-addons/media/buttons/volume/mute/frontend.tsx +26 -0
  163. package/src/builtin-addons/media/buttons/volume/volume-down/backend.ts +14 -0
  164. package/src/builtin-addons/media/buttons/volume/volume-down/config.ts +6 -0
  165. package/src/builtin-addons/media/buttons/volume/volume-down/frontend.tsx +10 -0
  166. package/src/builtin-addons/media/buttons/volume/volume-up/backend.ts +14 -0
  167. package/src/builtin-addons/media/buttons/volume/volume-up/config.ts +6 -0
  168. package/src/builtin-addons/media/buttons/volume/volume-up/frontend.tsx +8 -0
  169. package/src/builtin-addons/media/checks.ts +104 -0
  170. package/src/builtin-addons/media/executor.ts +36 -0
  171. package/src/builtin-addons/media/index.d.ts +5 -0
  172. package/src/builtin-addons/media/index.ts +53 -0
  173. package/src/builtin-addons/media/progress.ts +16 -0
  174. package/src/builtin-addons/media/providers/darwin.ts +391 -0
  175. package/src/builtin-addons/media/providers/index.ts +27 -0
  176. package/src/builtin-addons/media/providers/linux.ts +196 -0
  177. package/src/builtin-addons/media/providers/types.ts +48 -0
  178. package/src/builtin-addons/media/providers/windows.ts +121 -0
  179. package/src/builtin-addons/media/sirenodeck.json +6 -0
  180. package/src/builtin-addons/media/state.ts +19 -0
  181. package/src/builtin-addons/register-builtins.ts +65 -0
  182. package/src/builtin-addons/session/README.md +14 -0
  183. package/src/builtin-addons/session/buttons/session-info/backend.ts +8 -0
  184. package/src/builtin-addons/session/buttons/session-info/config.ts +4 -0
  185. package/src/builtin-addons/session/buttons/session-info/frontend.tsx +2 -0
  186. package/src/builtin-addons/session/buttons/time/backend.ts +7 -0
  187. package/src/builtin-addons/session/buttons/time/config.ts +6 -0
  188. package/src/builtin-addons/session/buttons/time/frontend.tsx +2 -0
  189. package/src/builtin-addons/session/index.d.ts +5 -0
  190. package/src/builtin-addons/session/index.ts +18 -0
  191. package/src/builtin-addons/session/sirenodeck.json +6 -0
  192. package/src/builtin-addons/system-status/README.md +169 -0
  193. package/src/builtin-addons/system-status/buttons/_shared.ts +131 -0
  194. package/src/builtin-addons/system-status/buttons/system-status/frontend.tsx +224 -0
  195. package/src/builtin-addons/system-status/buttons/system-status/schemas.ts +67 -0
  196. package/src/builtin-addons/system-status/domain/catalog.ts +53 -0
  197. package/src/builtin-addons/system-status/domain/chart-sampler.ts +58 -0
  198. package/src/builtin-addons/system-status/domain/display-metrics.ts +128 -0
  199. package/src/builtin-addons/system-status/domain/index.ts +10 -0
  200. package/src/builtin-addons/system-status/domain/live-metrics.ts +1021 -0
  201. package/src/builtin-addons/system-status/domain/metric-ids.ts +0 -0
  202. package/src/builtin-addons/system-status/index.ts +16 -0
  203. package/src/builtin-addons/system-status/manifest.ts +105 -0
  204. package/src/builtin-addons/system-status/shared/metrics-catalog.ts +316 -0
  205. package/src/builtin-addons/system-status/sirenodeck.json +6 -0
  206. package/src/builtin-addons/test-buildin/decks/action-buttons-test.ts +56 -0
  207. package/src/builtin-addons/test-buildin/index.d.ts +5 -0
  208. package/src/builtin-addons/test-buildin/index.ts +16 -0
  209. package/src/builtin-addons/value-display/README.md +59 -0
  210. package/src/builtin-addons/value-display/backend.ts +86 -0
  211. package/src/builtin-addons/value-display/buttons/value-display/backend.ts +17 -0
  212. package/src/builtin-addons/value-display/buttons/value-display/config.ts +36 -0
  213. package/src/builtin-addons/value-display/buttons/value-display/frontend.tsx +54 -0
  214. package/src/builtin-addons/value-display/index.d.ts +5 -0
  215. package/src/builtin-addons/value-display/index.ts +23 -0
  216. package/src/builtin-addons/value-display/sirenodeck.json +6 -0
  217. package/src/builtin-addons/weather/README.md +46 -0
  218. package/src/builtin-addons/weather/backend.ts +121 -0
  219. package/src/builtin-addons/weather/buttons/weather/backend.ts +27 -0
  220. package/src/builtin-addons/weather/buttons/weather/config.ts +29 -0
  221. package/src/builtin-addons/weather/buttons/weather/frontend.tsx +63 -0
  222. package/src/builtin-addons/weather/buttons/weather/icons.tsx +88 -0
  223. package/src/builtin-addons/weather/buttons/weather/pages.tsx +109 -0
  224. package/src/builtin-addons/weather/domain/codes.ts +35 -0
  225. package/src/builtin-addons/weather/domain/fetch.ts +47 -0
  226. package/src/builtin-addons/weather/index.d.ts +5 -0
  227. package/src/builtin-addons/weather/index.ts +23 -0
  228. package/src/builtin-addons/weather/poller.ts +70 -0
  229. package/src/builtin-addons/weather/provider/city-key.ts +9 -0
  230. package/src/builtin-addons/weather/provider/codes.ts +35 -0
  231. package/src/builtin-addons/weather/provider/fetch.ts +97 -0
  232. package/src/builtin-addons/weather/provider/geocode.ts +67 -0
  233. package/src/builtin-addons/weather/provider/types.ts +42 -0
  234. package/src/builtin-addons/weather/sirenodeck.json +6 -0
  235. package/src/cli/coding-agents-onboarding.ts +434 -0
  236. package/src/cli/commands/addon-decks.ts +441 -0
  237. package/src/cli/commands/addon-registry.ts +639 -0
  238. package/src/cli/commands/emulator-mode.ts +289 -0
  239. package/src/cli/commands/install.ts +128 -0
  240. package/src/cli/commands/logs.ts +74 -0
  241. package/src/cli/commands/network-bind.ts +111 -0
  242. package/src/cli/commands/pipeline/helpers.ts +75 -0
  243. package/src/cli/commands/pipeline/preflight.ts +20 -0
  244. package/src/cli/commands/port-identity.ts +152 -0
  245. package/src/cli/commands/reload.ts +37 -0
  246. package/src/cli/commands/restart.ts +139 -0
  247. package/src/cli/commands/run.ts +2270 -0
  248. package/src/cli/commands/service/install.ts +121 -0
  249. package/src/cli/commands/service/render-template.ts +158 -0
  250. package/src/cli/commands/service-manager.ts +184 -0
  251. package/src/cli/commands/spawn-daemon.ts +251 -0
  252. package/src/cli/commands/start.ts +1061 -0
  253. package/src/cli/commands/status.ts +110 -0
  254. package/src/cli/commands/stop.ts +121 -0
  255. package/src/cli/commands/subprocess-supervisor.ts +203 -0
  256. package/src/cli/commands/system-requirements.ts +699 -0
  257. package/src/cli/cwd.ts +28 -0
  258. package/src/cli/first-run.ts +149 -0
  259. package/src/cli/http-server.ts +244 -0
  260. package/src/cli/index.ts +355 -0
  261. package/src/cli/install-root.ts +26 -0
  262. package/src/cli/main.ts +194 -0
  263. package/src/cli/package-manager.ts +175 -0
  264. package/src/cli/probe-deps.ts +45 -0
  265. package/src/cli/prompt.ts +22 -0
  266. package/src/cli/startup-display.ts +452 -0
  267. package/src/config/builtin-icons.ts +57 -0
  268. package/src/config/config-diff.ts +54 -0
  269. package/src/config/discovery.ts +64 -0
  270. package/src/config/icon-resolver.ts +90 -0
  271. package/src/config/include-resolver.ts +202 -0
  272. package/src/config/index.ts +9 -0
  273. package/src/config/loader.ts +187 -0
  274. package/src/config/mutation.ts +514 -0
  275. package/src/config/reference-expander.ts +84 -0
  276. package/src/config/schemas.ts +223 -0
  277. package/src/config/validation.ts +254 -0
  278. package/src/core/asset-id.ts +21 -0
  279. package/src/core/gesture-state.ts +344 -0
  280. package/src/core/icon-asset-registry.ts +127 -0
  281. package/src/core/icon-source.ts +86 -0
  282. package/src/core/index.ts +30 -0
  283. package/src/core/mime.ts +16 -0
  284. package/src/core/pagination.ts +90 -0
  285. package/src/core/pub-sub.ts +126 -0
  286. package/src/core/settings.ts +153 -0
  287. package/src/core/store.ts +88 -0
  288. package/src/core/watcher.ts +73 -0
  289. package/src/deck/addon-handler-bridge.ts +516 -0
  290. package/src/deck/deck-config.ts +271 -0
  291. package/src/deck/editor-surfaces.ts +87 -0
  292. package/src/deck/host-context.ts +18 -0
  293. package/src/deck/index.ts +102 -0
  294. package/src/deck/macro-parse.ts +182 -0
  295. package/src/deck/methods.ts +348 -0
  296. package/src/deck/paginate-deck.ts +98 -0
  297. package/src/deck/position-buttons.ts +57 -0
  298. package/src/deck/runtime/index.ts +5 -0
  299. package/src/deck/runtime/runtime.ts +1060 -0
  300. package/src/deck/runtime-subscriptions.ts +45 -0
  301. package/src/deck/system-back-injection.ts +62 -0
  302. package/src/deck/system-buttons/registry.tsx +97 -0
  303. package/src/deck/system-buttons/types.ts +14 -0
  304. package/src/device/black-frame.ts +73 -0
  305. package/src/device/index.ts +13 -0
  306. package/src/device/linux-udev.ts +36 -0
  307. package/src/device/models.ts +89 -0
  308. package/src/device/reconnecting.ts +193 -0
  309. package/src/device/registry.ts +38 -0
  310. package/src/device/stream-deck.ts +155 -0
  311. package/src/index.ts +74 -0
  312. package/src/outputClient/emulator.ts +357 -0
  313. package/src/outputClient/index.ts +26 -0
  314. package/src/outputClient/open-browser.ts +26 -0
  315. package/src/outputClient/real.ts +393 -0
  316. package/src/outputClient/types.ts +83 -0
  317. package/src/render/browser-renderer.ts +240 -0
  318. package/src/render/buffer-hash.ts +20 -0
  319. package/src/render/editor-handler.ts +197 -0
  320. package/src/render/emulator-server.ts +128 -0
  321. package/src/render/icon-source-resolver.ts +69 -0
  322. package/src/render/index.ts +16 -0
  323. package/src/render/protocol.ts +61 -0
  324. package/src/render/push-raw-image.ts +100 -0
  325. package/src/render/screenshot-cadence.ts +87 -0
  326. package/src/render/state-publisher.ts +110 -0
  327. package/src/render/vite-server.ts +138 -0
  328. package/src/render/ws-bridge.ts +315 -0
  329. package/src/system/device-selection.ts +80 -0
  330. package/src/system/glob-match.ts +74 -0
  331. package/src/system/providers/active-app/darwin.ts +117 -0
  332. package/src/system/providers/active-app/linux.ts +245 -0
  333. package/src/system/providers/active-app/wayland-gnome.ts +303 -0
  334. package/src/system/providers/active-app/windows.ts +94 -0
  335. package/src/system/providers/active-app.ts +97 -0
  336. package/src/system/providers/clipboard/darwin.ts +65 -0
  337. package/src/system/providers/clipboard/linux.ts +163 -0
  338. package/src/system/providers/clipboard/windows.ts +94 -0
  339. package/src/system/providers/clipboard.ts +84 -0
  340. package/src/system/providers/error.ts +16 -0
  341. package/src/system/providers/key-macro/darwin.ts +221 -0
  342. package/src/system/providers/key-macro/linux.ts +651 -0
  343. package/src/system/providers/key-macro/parser.ts +215 -0
  344. package/src/system/providers/key-macro/windows.ts +476 -0
  345. package/src/system/providers/key-macro.ts +79 -0
  346. package/src/system/providers/notification/darwin.ts +36 -0
  347. package/src/system/providers/notification/linux.ts +115 -0
  348. package/src/system/providers/notification/windows.ts +72 -0
  349. package/src/system/providers/notification.ts +75 -0
  350. package/src/system/providers/session/darwin.ts +82 -0
  351. package/src/system/providers/session/linux.ts +175 -0
  352. package/src/system/providers/session/windows.ts +73 -0
  353. package/src/system/providers/session.ts +89 -0
  354. package/src/system/providers/shared.ts +65 -0
  355. package/src/system/requirements.ts +235 -0
  356. package/src/system/setup-wizard/config-seed.ts +30 -0
  357. package/src/system/setup-wizard/format.ts +275 -0
  358. package/src/system/setup-wizard/index.ts +45 -0
  359. package/src/system/setup-wizard/open-settings.ts +26 -0
  360. package/src/system/setup-wizard/plan.ts +230 -0
  361. package/src/system/setup-wizard/probe-cache.ts +34 -0
  362. package/src/system/setup-wizard/probe.ts +486 -0
  363. package/src/system/setup-wizard/runtime-features.ts +85 -0
  364. package/src/system/setup-wizard/sudo.ts +178 -0
  365. package/src/system/setup-wizard/types.ts +133 -0
  366. package/src/system/virtual-stream-deck.ts +67 -0
  367. package/src/themes/css.ts +210 -0
  368. package/src/themes/default/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  369. package/src/themes/default/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  370. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
  371. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-BoldItalic.ttf +0 -0
  372. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLight.ttf +0 -0
  373. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLightItalic.ttf +0 -0
  374. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Italic.ttf +0 -0
  375. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Light.ttf +0 -0
  376. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-LightItalic.ttf +0 -0
  377. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
  378. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-MediumItalic.ttf +0 -0
  379. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
  380. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBold.ttf +0 -0
  381. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBoldItalic.ttf +0 -0
  382. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Thin.ttf +0 -0
  383. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ThinItalic.ttf +0 -0
  384. package/src/themes/default/assets/IBM_Plex_Mono/OFL.txt +93 -0
  385. package/src/themes/default/assets/OFL.txt +93 -0
  386. package/src/themes/default/assets/README.txt +106 -0
  387. package/src/themes/default/assets/static/IBMPlexSans-Bold.ttf +0 -0
  388. package/src/themes/default/assets/static/IBMPlexSans-BoldItalic.ttf +0 -0
  389. package/src/themes/default/assets/static/IBMPlexSans-ExtraLight.ttf +0 -0
  390. package/src/themes/default/assets/static/IBMPlexSans-ExtraLightItalic.ttf +0 -0
  391. package/src/themes/default/assets/static/IBMPlexSans-Italic.ttf +0 -0
  392. package/src/themes/default/assets/static/IBMPlexSans-Light.ttf +0 -0
  393. package/src/themes/default/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
  394. package/src/themes/default/assets/static/IBMPlexSans-Medium.ttf +0 -0
  395. package/src/themes/default/assets/static/IBMPlexSans-MediumItalic.ttf +0 -0
  396. package/src/themes/default/assets/static/IBMPlexSans-Regular.ttf +0 -0
  397. package/src/themes/default/assets/static/IBMPlexSans-SemiBold.ttf +0 -0
  398. package/src/themes/default/assets/static/IBMPlexSans-SemiBoldItalic.ttf +0 -0
  399. package/src/themes/default/assets/static/IBMPlexSans-Thin.ttf +0 -0
  400. package/src/themes/default/assets/static/IBMPlexSans-ThinItalic.ttf +0 -0
  401. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Bold.ttf +0 -0
  402. package/src/themes/default/assets/static/IBMPlexSans_Condensed-BoldItalic.ttf +0 -0
  403. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLight.ttf +0 -0
  404. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLightItalic.ttf +0 -0
  405. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Italic.ttf +0 -0
  406. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Light.ttf +0 -0
  407. package/src/themes/default/assets/static/IBMPlexSans_Condensed-LightItalic.ttf +0 -0
  408. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Medium.ttf +0 -0
  409. package/src/themes/default/assets/static/IBMPlexSans_Condensed-MediumItalic.ttf +0 -0
  410. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Regular.ttf +0 -0
  411. package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBold.ttf +0 -0
  412. package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBoldItalic.ttf +0 -0
  413. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Thin.ttf +0 -0
  414. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ThinItalic.ttf +0 -0
  415. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Bold.ttf +0 -0
  416. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-BoldItalic.ttf +0 -0
  417. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLight.ttf +0 -0
  418. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLightItalic.ttf +0 -0
  419. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Italic.ttf +0 -0
  420. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Light.ttf +0 -0
  421. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-LightItalic.ttf +0 -0
  422. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Medium.ttf +0 -0
  423. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-MediumItalic.ttf +0 -0
  424. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Regular.ttf +0 -0
  425. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBold.ttf +0 -0
  426. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
  427. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Thin.ttf +0 -0
  428. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ThinItalic.ttf +0 -0
  429. package/src/themes/default/components.css +81 -0
  430. package/src/themes/default/sirenodeck.json +170 -0
  431. package/src/themes/index.ts +14 -0
  432. package/src/themes/light/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  433. package/src/themes/light/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  434. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
  435. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
  436. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
  437. package/src/themes/light/assets/IBM_Plex_Mono/OFL.txt +93 -0
  438. package/src/themes/light/assets/OFL.txt +93 -0
  439. package/src/themes/light/assets/README.txt +106 -0
  440. package/src/themes/light/assets/static/IBMPlexSans-Light.ttf +0 -0
  441. package/src/themes/light/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
  442. package/src/themes/light/assets/static/IBMPlexSans-Thin.ttf +0 -0
  443. package/src/themes/light/components.css +70 -0
  444. package/src/themes/light/sirenodeck.json +170 -0
  445. package/src/themes/loader.ts +343 -0
  446. package/src/themes/manifest.ts +164 -0
  447. package/src/themes/use-resolved-theme.tsx +32 -0
  448. package/src/ui/ButtonFrame.tsx +230 -0
  449. package/src/ui/contexts/AssetCacheContext.tsx +43 -0
  450. package/src/ui/index.ts +20 -0
  451. package/src/ui/primitives/Chip.tsx +53 -0
  452. package/src/ui/primitives/Icon.tsx +209 -0
  453. package/src/ui/primitives/Label.tsx +82 -0
  454. package/src/ui/primitives/ProgressBar.tsx +38 -0
  455. package/src/ui/primitives/TapIndicator.tsx +67 -0
  456. package/src/ui/primitives/Text.tsx +810 -0
  457. package/src/ui/primitives/index.ts +6 -0
  458. package/src/ui/surfaces/BarsSurface.tsx +211 -0
  459. package/src/ui/surfaces/IconLabelProgressSurface.tsx +133 -0
  460. package/src/ui/surfaces/IconLabelSurface.tsx +59 -0
  461. package/src/ui/surfaces/LabelValueListSurface.tsx +202 -0
  462. package/src/ui/surfaces/PaginatedSurface.tsx +164 -0
  463. package/src/ui/surfaces/SplitActionSurface.tsx +98 -0
  464. package/src/ui/surfaces/TemporaryErrorSurface.tsx +68 -0
  465. package/src/ui/surfaces/ValueChart.tsx +218 -0
  466. package/src/ui/surfaces/index.ts +32 -0
  467. package/src/ui/surfaces/paginated-schema.ts +22 -0
  468. package/src/ui/theme-presentation-builder.ts +184 -0
  469. package/src/ui/theme-presentation.tsx +146 -0
  470. package/src/ui/utils/cn.ts +12 -0
  471. package/src/util/cache-paths.ts +38 -0
  472. package/src/util/config-diff.ts +16 -0
  473. package/src/util/daemon-control.ts +85 -0
  474. package/src/util/daemon.ts +575 -0
  475. package/src/util/device-config.ts +56 -0
  476. package/src/util/errors.ts +13 -0
  477. package/src/util/log-reader.ts +114 -0
  478. package/src/util/log-tail.ts +103 -0
  479. package/src/util/logger.ts +417 -0
  480. package/src/util/process-title.ts +79 -0
  481. package/src/util/single-instance.ts +202 -0
  482. package/src/version.ts +10 -0
  483. package/src/vite/index.ts +6 -0
  484. package/src/vite/virtual-modules.ts +631 -0
  485. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,461 @@
1
+ import type { ComponentType } from "react"
2
+
3
+ import type { z } from "zod"
4
+
5
+ import type { ActionExecutor } from "@/action/executor"
6
+ import type { Store } from "@/core/store"
7
+ import type { GestureKind } from "@/core/gesture-state"
8
+
9
+ export type { GestureKind }
10
+ import type { Methods } from "@/deck/methods"
11
+
12
+ /** The runtime manifest API version (`AddonManifestV1`). */
13
+ export const SIRENO_ADDON_API_VERSION = 1 as const
14
+
15
+ export type AddonKind = "runtime" | "theme"
16
+ export type AddonManifestKind = "addon" | "theme"
17
+
18
+ /**
19
+ * Per-button gesture stream delivered to addon renderers. `null` when no
20
+ * gesture has fired since the last handoff. See `AddonFrontendButtonProps.gesture`.
21
+ */
22
+ export interface AddonGestureEvent {
23
+ readonly gesture: GestureKind
24
+ readonly at: number
25
+ }
26
+
27
+ export interface AddonButtonTypeRenderContext {
28
+ config: unknown
29
+ pressed: boolean
30
+ addonName: string
31
+ frameState: unknown
32
+ }
33
+
34
+ export interface AddonButtonTypeActionContext {
35
+ config: unknown
36
+ pressed: boolean
37
+ addonName: string
38
+ hostContext: Record<string, unknown>
39
+ methods: Record<string, (...args: unknown[]) => unknown>
40
+ }
41
+
42
+ export interface AddonAssets {
43
+ styles?: string[]
44
+ }
45
+
46
+ export interface AddonFrontend {
47
+ main: string
48
+ styles?: string[]
49
+ }
50
+
51
+ export interface AddonManifest {
52
+ apiVersion: number
53
+ kind?: AddonKind
54
+ main?: string
55
+ frontend?: AddonFrontend
56
+ css?: string
57
+ name?: string
58
+ version?: string
59
+ description?: string
60
+ publishIntervalMs?: number
61
+ }
62
+
63
+ export interface LoadedTheme {
64
+ name: string
65
+ apiVersion: number
66
+ source: {
67
+ kind: "builtin" | "sibling" | "local" | "npm"
68
+ resolvedPath: string
69
+ }
70
+ manifestPath: string
71
+ uiOverridesPath: string | null
72
+ cssPath: string
73
+ }
74
+
75
+ export interface AddonLoadIssue {
76
+ level: "error" | "warning" | "info"
77
+ source: string
78
+ message: string
79
+ }
80
+
81
+ export interface AddonFrontendButtonProps<Config> {
82
+ readonly config: Config
83
+ readonly state: unknown
84
+ readonly addonName: string
85
+ readonly buttonType: string
86
+ readonly buttonId: string
87
+ /**
88
+ * Latest gesture delivered to this specific button since the previous
89
+ * commit. `null` when no gesture is pending. The renderer is expected to
90
+ * react in a `useEffect([gesture])` and the parent (Deck) will clear the
91
+ * value in a post-commit pass so unrelated re-renders do not re-fire it.
92
+ *
93
+ * Source: hardware + emulator only — never emitted for frontend-emulated
94
+ * clicks (those arrive via the WS `button-action` path which calls
95
+ * `runtime.invokeAction`, bypassing the gesture listener).
96
+ */
97
+ readonly gesture: AddonGestureEvent | null
98
+ }
99
+
100
+ export type AddonFrontendButton<Config> = ComponentType<
101
+ AddonFrontendButtonProps<Config>
102
+ >
103
+
104
+ export interface AddonButtonTypeService<Config = unknown> {
105
+ readonly configSchema?: unknown
106
+ readonly defaultRenderIntervalMs?: number
107
+ readonly internal?: boolean
108
+ readonly full?: boolean
109
+ /**
110
+ * Opt-in gesture allowlist. If the service declares onTap/onDblTap/onHold
111
+ * but this field is missing, the runtime logs a warning and strips the
112
+ * undeclared handlers (default-deny). If present, only listed gestures fire.
113
+ */
114
+ readonly gestureHandlers?: ReadonlyArray<GestureKind>
115
+ readonly onMount?: (
116
+ ctx: AddonButtonServiceContext<Config>,
117
+ ) => void | Promise<void>
118
+ readonly onTap?: (
119
+ ctx: AddonButtonServiceContext<Config>,
120
+ ) => void | Promise<void>
121
+ readonly onDblTap?: (
122
+ ctx: AddonButtonServiceContext<Config>,
123
+ ) => void | Promise<void>
124
+ readonly onHold?: (
125
+ ctx: AddonButtonServiceContext<Config>,
126
+ ) => void | Promise<void>
127
+ readonly dispose?: (
128
+ ctx: AddonButtonServiceContext<Config>,
129
+ ) => void | Promise<void>
130
+ }
131
+
132
+ export interface AddonButtonTypeDef<Config = unknown> {
133
+ readonly frontend: AddonFrontendButton<Config>
134
+ readonly service: AddonButtonTypeService<Config>
135
+ }
136
+
137
+ export interface AddonButtonTypeDefAny {
138
+ readonly frontend: AddonFrontendButton<any>
139
+ readonly service: AddonButtonTypeService<any>
140
+ readonly name?: string
141
+ readonly internal?: boolean
142
+ }
143
+
144
+ export type AddonDeckFactory = (page: number) => AddonGeneratedDeck
145
+
146
+ export interface AddonDeckDefinition {
147
+ type: string
148
+ configSchema?: unknown
149
+ createDecks: (ctx: {
150
+ config: unknown
151
+ deck: { id: string }
152
+ keyCount: number
153
+ }) => Record<string, AddonGeneratedDeck>
154
+ internal?: boolean
155
+ }
156
+
157
+ export interface AddonGeneratedDeck {
158
+ name?: string
159
+ icon?: string
160
+ background?: string
161
+ /**
162
+ * Variant token name. Themes declare which variants they support in
163
+ * their manifest; addon authors pick from the active theme's set.
164
+ * Unknown names fall back to "default" with a console.warn at render.
165
+ *
166
+ * `variant` is the *semantic* axis: highlighted / warning / success / error.
167
+ * Use it when the colour carries meaning (recording, paused, errored).
168
+ */
169
+ variant?: string
170
+ /**
171
+ * Per-button hue customisation — closed enum, distinct from `variant`.
172
+ * Themes declare a variant entry for each enum value they want to
173
+ * expose (e.g. `blue`, `cyan`); unknown names fall back to `default`
174
+ * with a console.warn at render. Use it to distinguish buttons
175
+ * inside a deck by colour (e.g. six app-shortcuts, each a different
176
+ * hue) without claiming semantic meaning.
177
+ */
178
+ buttonColor?:
179
+ | "blue"
180
+ | "green"
181
+ | "purple"
182
+ | "cyan"
183
+ | "magenta"
184
+ | "amber"
185
+ | "lime"
186
+ buttons?: unknown[]
187
+ paginated?: boolean
188
+ trigger?: unknown
189
+ autoShow?: boolean
190
+ isOverlay?: boolean
191
+ }
192
+
193
+ /**
194
+ * Phase 11: addon manifest deck entries. Three shapes, each an item in
195
+ * the manifest's `decks: ReadonlyArray<AddonDeckEntry>`:
196
+ *
197
+ * - Static: the entry itself IS the generated deck (id + AddonGeneratedDeck fields).
198
+ * - Single-dynamic: `createDeck(ctx)` returns ONE AddonGeneratedDeck under `id`.
199
+ * - Multi-dynamic: `createDecks(ctx)` returns a record keyed by `<addon>:<deck>`.
200
+ *
201
+ * The `type` field is gone — `id` (or the keys returned from createDecks) is the
202
+ * canonical deck-type key. Hard cutover from the legacy Record<key, AddonDeckDefinition>
203
+ * shape; AddonRegistry.load() rejects that at runtime.
204
+ */
205
+ export type AddonDeckEntryCtx = {
206
+ config: unknown
207
+ deck: { id: string }
208
+ keyCount: number
209
+ }
210
+
211
+ export type AddonDeckEntry =
212
+ | (AddonGeneratedDeck & {
213
+ id: string
214
+ createDeck?: never
215
+ createDecks?: never
216
+ internal?: boolean
217
+ })
218
+ | {
219
+ id: string
220
+ createDeck: (ctx: AddonDeckEntryCtx) => AddonGeneratedDeck
221
+ createDecks?: never
222
+ internal?: boolean
223
+ }
224
+ | {
225
+ id?: undefined
226
+ createDeck?: never
227
+ createDecks: (
228
+ ctx: AddonDeckEntryCtx,
229
+ ) => Record<string, AddonGeneratedDeck>
230
+ internal?: boolean
231
+ }
232
+
233
+ /**
234
+ * Runtime addon manifest. Both builtin and third-party addons export this from
235
+ * their entry file (`index.ts` in dev, `index.js` in prod).
236
+ *
237
+ * The `entry` field on `AddonJsonManifest` points at the file that exports this;
238
+ * the runtime loads it via dynamic `import()` and passes it to `AddonRegistry.load()`.
239
+ *
240
+ * `defaultButton` declares one of this addon's button types as the default. When
241
+ * set, users may write `type: <addonName>` in `config.yml` as a shorthand for
242
+ * `<defaultButton>` (e.g. `type: emoji-selector` resolves to
243
+ * `emoji-selector:launcher`). The value must be a key of `buttonTypes`.
244
+ */
245
+ /**
246
+ * Result of a single addon requirement check. Probes external dependencies
247
+ * (e.g. `playerctl` for media on Linux); failures are expected when the
248
+ * tool isn't installed and are surfaced as warnings, not exceptions.
249
+ */
250
+ export interface AddonCheckResult {
251
+ readonly available: boolean
252
+ readonly reason?: string
253
+ }
254
+
255
+ /**
256
+ * A named requirement check contributed by an addon. The check function
257
+ * probes external state and returns a structured result; it should not
258
+ * throw — unexpected errors are caught by the runner and reported as
259
+ * failures.
260
+ */
261
+ export interface AddonCheck {
262
+ readonly name: string
263
+ readonly check: () => Promise<AddonCheckResult>
264
+ }
265
+
266
+ export interface AddonManifestV1 {
267
+ readonly apiVersion: 1
268
+ readonly name: string
269
+ readonly kind?: AddonKind
270
+ readonly buttonTypes: Readonly<Record<string, AddonButtonTypeDefAny>>
271
+ readonly defaultButton?: string
272
+ readonly decks?: ReadonlyArray<AddonDeckEntry>
273
+ readonly frontend?: AddonFrontend
274
+ readonly poller?: {
275
+ readonly channels: ReadonlyArray<{
276
+ readonly channel: string
277
+ readonly intervalMs: number
278
+ readonly poll: () => unknown | Promise<unknown>
279
+ }>
280
+ }
281
+ readonly publishIntervalMs?: number
282
+ readonly globalService?: AddonGlobalService
283
+ /**
284
+ * Optional list of OS-specific requirement checks. Core runs these
285
+ * for enabled addons on start/restart and displays pass/fail in the
286
+ * startup banner. Checks never block startup — they only surface
287
+ * configuration gaps so the operator can act on them.
288
+ */
289
+ readonly checks?: ReadonlyArray<AddonCheck>
290
+ }
291
+
292
+ /**
293
+ * Addon-global service. Runs for the lifetime of the addon (while the addon
294
+ * is loaded). Multiple instances of the same button type share this state.
295
+ *
296
+ * - `pollers` are started when the addon activates and stopped when it
297
+ * deactivates; each publishes on a named channel that frontends consume
298
+ * via the bridge.
299
+ * - `subscriptions` are push-based sources (file watchers, sockets); they
300
+ * publish on the same channels.
301
+ * - `methods` is the namespaced API surface available to per-button
302
+ * services via `ctx.methods.<name>`.
303
+ * - `onLoad`/`onUnload` are the explicit lifecycle hooks; the runtime
304
+ * passes an `AbortSignal` so cleanup is automatic.
305
+ */
306
+ export interface AddonGlobalService {
307
+ readonly pollers?: ReadonlyArray<AddonGlobalPoller>
308
+ readonly subscriptions?: ReadonlyArray<AddonGlobalSubscription>
309
+ readonly methods?: Readonly<Record<string, AddonServiceMethod>>
310
+ // onLoad/onUnload accept an optional addon-specific config (typed as
311
+ // `unknown` since the runtime doesn't know the addon's config shape).
312
+ // Built-in addons ignore it; third-party / builtin addons that need
313
+ // hydrated state can read it. The runtime calls these once per process.
314
+ readonly onLoad?: (
315
+ ctx: AddonServiceContext,
316
+ config?: unknown,
317
+ ) => void | Promise<void>
318
+ readonly onUnload?: (
319
+ ctx: AddonServiceContext,
320
+ config?: unknown,
321
+ ) => void | Promise<void>
322
+ }
323
+
324
+ export type AddonServiceMethod = (
325
+ ...args: readonly unknown[]
326
+ ) => unknown | Promise<unknown>
327
+
328
+ export interface AddonGlobalPoller {
329
+ readonly id: string
330
+ readonly channel: string
331
+ readonly intervalMs: number
332
+ readonly poll: (ctx: AddonServiceContext) => unknown | Promise<unknown>
333
+ }
334
+
335
+ export interface AddonGlobalSubscription {
336
+ readonly channel: string
337
+ readonly subscribe: (ctx: AddonServiceContext) => { unsubscribe: () => void }
338
+ }
339
+
340
+ export interface AddonServiceContext {
341
+ /** Push data to the channel this poller/subscription is bound to. */
342
+ publish: (data: unknown) => void
343
+ /**
344
+ * Trigger the poller with the given id (within this addon) immediately and
345
+ * broadcast its result. Useful after a `methods` call to reflect the new
346
+ * state without waiting for the next polling tick. Unknown ids are no-ops;
347
+ * poller errors are logged and swallowed.
348
+ */
349
+ poll: (id: string) => Promise<void>
350
+ /** Aborted when the addon unloads. */
351
+ signal: AbortSignal
352
+ /** Run host commands (e.g. `brightness set 80`). */
353
+ executor: ActionExecutor
354
+ /** Fire an OS notification. */
355
+ notify(args: { title: string; body: string; sound?: boolean }): Promise<void>
356
+ /**
357
+ * Ask the host to re-materialize addon decks (dynamic deck shape). No-op
358
+ * when the host hasn't wired a rebuilder.
359
+ */
360
+ requestDeckRebuild?: () => void
361
+ }
362
+
363
+ /**
364
+ * Per-button service. One instance is created per rendered button of this
365
+ * type; the instance is disposed when the last instance unmounts.
366
+ *
367
+ * The runtime merges the addon-global service's `methods` into the action
368
+ * context so per-button services can call shared APIs without importing
369
+ * the addon's internals.
370
+ */
371
+ export interface AddonButtonService<Config = unknown> {
372
+ readonly onMount?: (
373
+ ctx: AddonButtonServiceContext<Config>,
374
+ ) => void | Promise<void>
375
+ readonly onUnmount?: (
376
+ ctx: AddonButtonServiceContext<Config>,
377
+ ) => void | Promise<void>
378
+ readonly onTap?: (
379
+ ctx: AddonButtonServiceContext<Config>,
380
+ ) => void | Promise<void>
381
+ readonly onDblTap?: (
382
+ ctx: AddonButtonServiceContext<Config>,
383
+ ) => void | Promise<void>
384
+ readonly onHold?: (
385
+ ctx: AddonButtonServiceContext<Config>,
386
+ ) => void | Promise<void>
387
+ readonly dispose?: (
388
+ ctx: AddonButtonServiceContext<Config>,
389
+ ) => void | Promise<void>
390
+ }
391
+
392
+ export interface AddonButtonServiceContext<Config = unknown> {
393
+ readonly config: Config
394
+ readonly buttonId: string
395
+ /** Declared button position within its deck, when the deck defines one. */
396
+ readonly position?: number
397
+ readonly addonName: string
398
+ /** Namespaced addon-global methods (`<addonName>:<methodName>` keys). */
399
+ readonly methods: Readonly<Record<string, AddonServiceMethod>>
400
+ /**
401
+ * Core runtime methods exposed to addons (e.g. `adjustBrightness`,
402
+ * `dispatch`, `runCommand`, `keyMacro`, `typeText`, `navigateToDeck`,
403
+ * `goBack`, `showTemporaryError`, `getActiveDeckId`). Setter functions
404
+ * like `setKeyMacroProvider` are intentionally not exposed — they belong
405
+ * to host setup, not addon backends.
406
+ */
407
+ readonly coreMethods: Methods
408
+ /** Publish on a channel. */
409
+ readonly publish: (channel: string, data: unknown) => void
410
+ /** Run host commands. */
411
+ readonly executor: ActionExecutor
412
+ /** Aborted when the button instance unmounts. */
413
+ readonly signal: AbortSignal
414
+ /**
415
+ * Per-addon persisted state. Use `store.buttonScope(addonName, key)` to
416
+ * scope reads/writes to this addon.
417
+ */
418
+ readonly store: Store
419
+ }
420
+
421
+ /**
422
+ * JSON metadata manifest. Both builtin and third-party addons ship this file
423
+ * for discovery. Runtime metadata (button types, decks, etc.) lives in the
424
+ * entry file (see `entry`) which exports an `AddonManifestV1` at runtime.
425
+ *
426
+ * Convention:
427
+ * - `name`: unique addon identifier (e.g. `date-time`).
428
+ * - `kind`: `"addon"` selects runtime registration; `"theme"` selects the theme loader.
429
+ * - `apiVersion`: the JSON manifest schema version (currently 1).
430
+ * - `entry`: path (relative to the JSON file) to the runtime entry that exports
431
+ * an `AddonManifestV1`. In dev this is `index.ts`; in prod this is `index.js`.
432
+ * The CLI dynamically imports it at startup.
433
+ */
434
+ export interface AddonJsonManifest {
435
+ readonly kind: AddonManifestKind
436
+ readonly apiVersion: 1
437
+ readonly name: string
438
+ readonly entry: string
439
+ /**
440
+ * Optional path (relative to the JSON file) to a SEPARATE browser bundle.
441
+ *
442
+ * ponytail: `entry` is imported by Node, which cannot resolve the host's
443
+ * `@sirenodeck/sirenodeck/ui/*` specifiers — they point at .tsx sources. A
444
+ * prebuilt addon therefore has to inline stubs for them at build time, and
445
+ * when that same bundle is also handed to the browser those stubs are what
446
+ * renders. The pomodoro addon shipped `Label = () => null` exactly this way,
447
+ * so its buttons drew no text at all.
448
+ *
449
+ * When set, the browser loads THIS file instead, built with the host UI
450
+ * specifiers left external so vite resolves them to the real components.
451
+ * Omitted, the loader falls back to `entry` and behaviour is unchanged, so
452
+ * existing addons keep working untouched.
453
+ */
454
+ readonly frontendEntry?: string
455
+ }
456
+
457
+ /** Validation schema for `AddonJsonManifest`; usable at scan time. */
458
+ export type AddonJsonManifestSchema = z.ZodType<AddonJsonManifest>
459
+
460
+ /** The current JSON manifest schema version. */
461
+ export const SIRENO_ADDON_JSON_API_VERSION = 1 as const
@@ -0,0 +1,84 @@
1
+ import type { AddonCheck, AddonCheckResult } from "./api"
2
+ import mediaAddonManifest from "@/builtin-addons/media/index"
3
+ import { buildMediaAddonChecks } from "@/builtin-addons/media/checks"
4
+ import { createChildProcessExecutor } from "@/builtin-addons/media/executor"
5
+
6
+ export interface AddonCheckInput {
7
+ readonly name: string
8
+ readonly checks?: ReadonlyArray<AddonCheck>
9
+ }
10
+
11
+ export interface AddonCheckOutcome {
12
+ readonly addonName: string
13
+ readonly checkName: string
14
+ readonly available: boolean
15
+ readonly reason?: string
16
+ }
17
+
18
+ // ponytail: probe errors are expected (tool not installed). Catching here
19
+ // keeps callers from having to wrap each check in try/catch and keeps the
20
+ // display layer uniform.
21
+ const runCheck = async (
22
+ addonName: string,
23
+ check: AddonCheck,
24
+ ): Promise<AddonCheckOutcome> => {
25
+ try {
26
+ const result: AddonCheckResult = await check.check()
27
+ return result.reason !== undefined
28
+ ? {
29
+ addonName,
30
+ checkName: check.name,
31
+ available: result.available,
32
+ reason: result.reason,
33
+ }
34
+ : {
35
+ addonName,
36
+ checkName: check.name,
37
+ available: result.available,
38
+ }
39
+ } catch (err) {
40
+ const message = err instanceof Error ? err.message : String(err)
41
+ return {
42
+ addonName,
43
+ checkName: check.name,
44
+ available: false,
45
+ reason: `check error: ${message}`,
46
+ }
47
+ }
48
+ }
49
+
50
+ export const runAddonChecks = async (
51
+ addons: ReadonlyArray<AddonCheckInput>,
52
+ ): Promise<ReadonlyArray<AddonCheckOutcome>> => {
53
+ const all = addons.flatMap((addon) =>
54
+ (addon.checks ?? []).map((check) => runCheck(addon.name, check)),
55
+ )
56
+ return Promise.all(all)
57
+ }
58
+
59
+ // ponytail: the CLI process doesn't share state with the daemon process,
60
+ // so it can't introspect a live `AddonRegistry`. Builtin addons ship as
61
+ // statically-known TS modules; importing their manifests here is enough
62
+ // to enumerate their `checks` for the start banner. External addons are
63
+ // out of scope — the registry is built inside the daemon process and the
64
+ // CLI doesn't have a way to safely re-resolve their entry files.
65
+ //
66
+ // We import the manifest only for the addon NAME (used in banner output),
67
+ // then build the checks at the Node edge here — the addon manifest itself
68
+ // is bundled into the frontend vite graph, so importing node-only modules
69
+ // (playerctl/wpctl probing) there would externalize them for the browser
70
+ // and break the SPA on load. Keeping the executor + check-builder import
71
+ // at the CLI edge keeps the manifest Node-pure.
72
+ export const collectBuiltinAddonChecks = (): ReadonlyArray<AddonCheckInput> => {
73
+ const checks = buildMediaAddonChecks({
74
+ platform: process.platform,
75
+ executor: createChildProcessExecutor(),
76
+ })
77
+ return checks.length > 0 ? [{ name: mediaAddonManifest.name, checks }] : []
78
+ }
79
+
80
+ // ponytail: probe errors are expected when external tools are missing —
81
+ // run checks in parallel so a slow `command -v` doesn't gate the banner.
82
+ export const runBuiltinAddonChecks = (): Promise<
83
+ ReadonlyArray<AddonCheckOutcome>
84
+ > => runAddonChecks(collectBuiltinAddonChecks())
@@ -0,0 +1,5 @@
1
+ export * from "./api"
2
+ export { SIRENO_ADDON_API_VERSION } from "./api-types"
3
+ export * from "./loader"
4
+ export * from "./registry"
5
+ export * from "./spec"