@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.
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/bin/_wrapper-shared.js +42 -0
- package/bin/dev.js +95 -0
- package/bin/sirenodeck.js +42 -0
- package/config/default-config.yml +117 -0
- package/config/starter-config.yml +54 -0
- package/dist/main.mjs +64702 -0
- package/package.json +140 -0
- package/src/action/executor.ts +156 -0
- package/src/action/index.ts +7 -0
- package/src/addon/api-types.ts +15 -0
- package/src/addon/api.ts +461 -0
- package/src/addon/check-runner.ts +84 -0
- package/src/addon/index.ts +5 -0
- package/src/addon/loader.ts +441 -0
- package/src/addon/registry.ts +230 -0
- package/src/addon/spec.ts +69 -0
- package/src/api/addon.ts +33 -0
- package/src/api/asset-url.ts +24 -0
- package/src/api/index.ts +50 -0
- package/src/api/protocol-internal.ts +656 -0
- package/src/api/protocol.ts +2 -0
- package/src/api/react/index.ts +11 -0
- package/src/api/react/registry.ts +91 -0
- package/src/api/react/use-addon-channel.ts +26 -0
- package/src/api/react/use-button-state.tsx +23 -0
- package/src/api/react/use-deck.ts +24 -0
- package/src/assets/logo.png +0 -0
- package/src/assets/logo72x72.png +0 -0
- package/src/assets/logoFull.png +0 -0
- package/src/builtin-addons/brightness/README.md +51 -0
- package/src/builtin-addons/brightness/buttons/brightness/backend.ts +13 -0
- package/src/builtin-addons/brightness/buttons/brightness/config.ts +10 -0
- package/src/builtin-addons/brightness/buttons/brightness/frontend.tsx +50 -0
- package/src/builtin-addons/brightness/domain/macos.ts +46 -0
- package/src/builtin-addons/brightness/index.d.ts +5 -0
- package/src/builtin-addons/brightness/index.ts +20 -0
- package/src/builtin-addons/brightness/poller.ts +27 -0
- package/src/builtin-addons/brightness/providers/darwin.ts +107 -0
- package/src/builtin-addons/brightness/providers/index.ts +81 -0
- package/src/builtin-addons/brightness/providers/linux.ts +108 -0
- package/src/builtin-addons/brightness/providers/windows.ts +77 -0
- package/src/builtin-addons/brightness/sirenodeck.json +6 -0
- package/src/builtin-addons/coding-agents/assets/claude-code.svg +1 -0
- package/src/builtin-addons/coding-agents/assets/opencode-dark-square.svg +1 -0
- package/src/builtin-addons/coding-agents/buttons/agent/backend.ts +82 -0
- package/src/builtin-addons/coding-agents/buttons/agent/config.ts +13 -0
- package/src/builtin-addons/coding-agents/buttons/agent/frontend.tsx +130 -0
- package/src/builtin-addons/coding-agents/buttons/agent/pages.tsx +150 -0
- package/src/builtin-addons/coding-agents/buttons/summary/backend.ts +48 -0
- package/src/builtin-addons/coding-agents/buttons/summary/config.ts +11 -0
- package/src/builtin-addons/coding-agents/buttons/summary/frontend.tsx +254 -0
- package/src/builtin-addons/coding-agents/decks/agents.ts +69 -0
- package/src/builtin-addons/coding-agents/global/backend.ts +402 -0
- package/src/builtin-addons/coding-agents/global-entry.ts +7 -0
- package/src/builtin-addons/coding-agents/hook/script.ts +123 -0
- package/src/builtin-addons/coding-agents/index.ts +15 -0
- package/src/builtin-addons/coding-agents/manifest.ts +115 -0
- package/src/builtin-addons/coding-agents/providers/claude-code.ts +470 -0
- package/src/builtin-addons/coding-agents/providers/claude-instances.ts +184 -0
- package/src/builtin-addons/coding-agents/providers/opencode-instances.ts +108 -0
- package/src/builtin-addons/coding-agents/providers/opencode.ts +636 -0
- package/src/builtin-addons/coding-agents/providers/registry.ts +120 -0
- package/src/builtin-addons/coding-agents/providers/spawn.ts +112 -0
- package/src/builtin-addons/coding-agents/shared/claude-hook-events.ts +55 -0
- package/src/builtin-addons/coding-agents/shared/claude-status.ts +236 -0
- package/src/builtin-addons/coding-agents/shared/live-count.ts +39 -0
- package/src/builtin-addons/coding-agents/shared/notifier.ts +58 -0
- package/src/builtin-addons/coding-agents/shared/opencode-status.ts +82 -0
- package/src/builtin-addons/coding-agents/shared/snapshot.ts +66 -0
- package/src/builtin-addons/coding-agents/shared/state.ts +72 -0
- package/src/builtin-addons/coding-agents/sirenodeck.json +6 -0
- package/src/builtin-addons/coding-agents/types/types.ts +33 -0
- package/src/builtin-addons/core/README.md +89 -0
- package/src/builtin-addons/core/buttons/action/backend.ts +7 -0
- package/src/builtin-addons/core/buttons/action/config.ts +13 -0
- package/src/builtin-addons/core/buttons/action/frontend.tsx +16 -0
- package/src/builtin-addons/core/buttons/change-deck/backend.ts +18 -0
- package/src/builtin-addons/core/buttons/change-deck/config.ts +15 -0
- package/src/builtin-addons/core/buttons/change-deck/frontend.tsx +18 -0
- package/src/builtin-addons/core/buttons/media-sample/backend.ts +8 -0
- package/src/builtin-addons/core/buttons/media-sample/config.ts +7 -0
- package/src/builtin-addons/core/buttons/media-sample/frontend.tsx +2 -0
- package/src/builtin-addons/core/buttons/page-nav/backend.ts +28 -0
- package/src/builtin-addons/core/buttons/page-nav/config.ts +9 -0
- package/src/builtin-addons/core/buttons/page-nav/frontend.tsx +68 -0
- package/src/builtin-addons/core/buttons/toggle/backend.ts +119 -0
- package/src/builtin-addons/core/buttons/toggle/config.ts +57 -0
- package/src/builtin-addons/core/buttons/toggle/frontend.tsx +57 -0
- package/src/builtin-addons/core/buttons/toggle/global-service.ts +174 -0
- package/src/builtin-addons/core/index.ts +120 -0
- package/src/builtin-addons/core/sirenodeck.json +6 -0
- package/src/builtin-addons/date-time/README.md +73 -0
- package/src/builtin-addons/date-time/buttons/analog-clock/backend.ts +10 -0
- package/src/builtin-addons/date-time/buttons/analog-clock/config.ts +4 -0
- package/src/builtin-addons/date-time/buttons/analog-clock/frontend.tsx +88 -0
- package/src/builtin-addons/date-time/buttons/custom/backend.ts +10 -0
- package/src/builtin-addons/date-time/buttons/custom/config.ts +9 -0
- package/src/builtin-addons/date-time/buttons/custom/frontend.tsx +26 -0
- package/src/builtin-addons/date-time/buttons/date/backend.ts +10 -0
- package/src/builtin-addons/date-time/buttons/date/config.ts +10 -0
- package/src/builtin-addons/date-time/buttons/date/frontend.tsx +42 -0
- package/src/builtin-addons/date-time/buttons/time/backend.ts +10 -0
- package/src/builtin-addons/date-time/buttons/time/config.ts +9 -0
- package/src/builtin-addons/date-time/buttons/time/frontend.tsx +29 -0
- package/src/builtin-addons/date-time/index.d.ts +5 -0
- package/src/builtin-addons/date-time/index.ts +30 -0
- package/src/builtin-addons/date-time/poller.ts +11 -0
- package/src/builtin-addons/date-time/shared/format-date.ts +36 -0
- package/src/builtin-addons/date-time/shared/format.ts +105 -0
- package/src/builtin-addons/date-time/shared/use-now.ts +10 -0
- package/src/builtin-addons/date-time/sirenodeck.json +6 -0
- package/src/builtin-addons/emoji-selector/README.md +45 -0
- package/src/builtin-addons/emoji-selector/assets/launcher.svg +10 -0
- package/src/builtin-addons/emoji-selector/assets/smileys.svg +8 -0
- package/src/builtin-addons/emoji-selector/buttons/category/backend.ts +14 -0
- package/src/builtin-addons/emoji-selector/buttons/category/config.ts +8 -0
- package/src/builtin-addons/emoji-selector/buttons/category/frontend.tsx +19 -0
- package/src/builtin-addons/emoji-selector/buttons/emoji/backend.ts +7 -0
- package/src/builtin-addons/emoji-selector/buttons/emoji/config.ts +9 -0
- package/src/builtin-addons/emoji-selector/buttons/emoji/frontend.tsx +11 -0
- package/src/builtin-addons/emoji-selector/buttons/launcher/backend.ts +13 -0
- package/src/builtin-addons/emoji-selector/buttons/launcher/config.ts +6 -0
- package/src/builtin-addons/emoji-selector/buttons/launcher/frontend.tsx +31 -0
- package/src/builtin-addons/emoji-selector/data/categories.ts +1084 -0
- package/src/builtin-addons/emoji-selector/decks/index.ts +137 -0
- package/src/builtin-addons/emoji-selector/index.d.ts +5 -0
- package/src/builtin-addons/emoji-selector/index.ts +29 -0
- package/src/builtin-addons/emoji-selector/sirenodeck.json +6 -0
- package/src/builtin-addons/emoji-selector/support.ts +49 -0
- package/src/builtin-addons/index.ts +13 -0
- package/src/builtin-addons/internal-settings/README.md +26 -0
- package/src/builtin-addons/internal-settings/backend.ts +58 -0
- package/src/builtin-addons/internal-settings/buttons/app-info/backend.ts +7 -0
- package/src/builtin-addons/internal-settings/buttons/app-info/config.ts +13 -0
- package/src/builtin-addons/internal-settings/buttons/app-info/frontend.tsx +18 -0
- package/src/builtin-addons/internal-settings/buttons/brightness/common/frontend.tsx +50 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-down/backend.ts +16 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-down/config.ts +6 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-down/frontend.tsx +8 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-up/backend.ts +16 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-up/config.ts +6 -0
- package/src/builtin-addons/internal-settings/buttons/brightness-up/frontend.tsx +8 -0
- package/src/builtin-addons/internal-settings/decks/settings.ts +25 -0
- package/src/builtin-addons/internal-settings/index.d.ts +4 -0
- package/src/builtin-addons/internal-settings/index.ts +53 -0
- package/src/builtin-addons/internal-settings/logo72x72.png +0 -0
- package/src/builtin-addons/internal-settings/sirenodeck.json +6 -0
- package/src/builtin-addons/media/README.md +45 -0
- package/src/builtin-addons/media/backend.ts +143 -0
- package/src/builtin-addons/media/buttons/media-player/backend.ts +19 -0
- package/src/builtin-addons/media/buttons/media-player/components/MediaStatus.tsx +25 -0
- package/src/builtin-addons/media/buttons/media-player/components/MediaSurface.tsx +52 -0
- package/src/builtin-addons/media/buttons/media-player/components/ProgressBar.tsx +21 -0
- package/src/builtin-addons/media/buttons/media-player/components/status-meta.ts +36 -0
- package/src/builtin-addons/media/buttons/media-player/config.ts +4 -0
- package/src/builtin-addons/media/buttons/media-player/frontend.tsx +29 -0
- package/src/builtin-addons/media/buttons/volume/common/frontend.tsx +52 -0
- package/src/builtin-addons/media/buttons/volume/mute/backend.ts +13 -0
- package/src/builtin-addons/media/buttons/volume/mute/config.ts +4 -0
- package/src/builtin-addons/media/buttons/volume/mute/frontend.tsx +26 -0
- package/src/builtin-addons/media/buttons/volume/volume-down/backend.ts +14 -0
- package/src/builtin-addons/media/buttons/volume/volume-down/config.ts +6 -0
- package/src/builtin-addons/media/buttons/volume/volume-down/frontend.tsx +10 -0
- package/src/builtin-addons/media/buttons/volume/volume-up/backend.ts +14 -0
- package/src/builtin-addons/media/buttons/volume/volume-up/config.ts +6 -0
- package/src/builtin-addons/media/buttons/volume/volume-up/frontend.tsx +8 -0
- package/src/builtin-addons/media/checks.ts +104 -0
- package/src/builtin-addons/media/executor.ts +36 -0
- package/src/builtin-addons/media/index.d.ts +5 -0
- package/src/builtin-addons/media/index.ts +53 -0
- package/src/builtin-addons/media/progress.ts +16 -0
- package/src/builtin-addons/media/providers/darwin.ts +391 -0
- package/src/builtin-addons/media/providers/index.ts +27 -0
- package/src/builtin-addons/media/providers/linux.ts +196 -0
- package/src/builtin-addons/media/providers/types.ts +48 -0
- package/src/builtin-addons/media/providers/windows.ts +121 -0
- package/src/builtin-addons/media/sirenodeck.json +6 -0
- package/src/builtin-addons/media/state.ts +19 -0
- package/src/builtin-addons/register-builtins.ts +65 -0
- package/src/builtin-addons/session/README.md +14 -0
- package/src/builtin-addons/session/buttons/session-info/backend.ts +8 -0
- package/src/builtin-addons/session/buttons/session-info/config.ts +4 -0
- package/src/builtin-addons/session/buttons/session-info/frontend.tsx +2 -0
- package/src/builtin-addons/session/buttons/time/backend.ts +7 -0
- package/src/builtin-addons/session/buttons/time/config.ts +6 -0
- package/src/builtin-addons/session/buttons/time/frontend.tsx +2 -0
- package/src/builtin-addons/session/index.d.ts +5 -0
- package/src/builtin-addons/session/index.ts +18 -0
- package/src/builtin-addons/session/sirenodeck.json +6 -0
- package/src/builtin-addons/system-status/README.md +169 -0
- package/src/builtin-addons/system-status/buttons/_shared.ts +131 -0
- package/src/builtin-addons/system-status/buttons/system-status/frontend.tsx +224 -0
- package/src/builtin-addons/system-status/buttons/system-status/schemas.ts +67 -0
- package/src/builtin-addons/system-status/domain/catalog.ts +53 -0
- package/src/builtin-addons/system-status/domain/chart-sampler.ts +58 -0
- package/src/builtin-addons/system-status/domain/display-metrics.ts +128 -0
- package/src/builtin-addons/system-status/domain/index.ts +10 -0
- package/src/builtin-addons/system-status/domain/live-metrics.ts +1021 -0
- package/src/builtin-addons/system-status/domain/metric-ids.ts +0 -0
- package/src/builtin-addons/system-status/index.ts +16 -0
- package/src/builtin-addons/system-status/manifest.ts +105 -0
- package/src/builtin-addons/system-status/shared/metrics-catalog.ts +316 -0
- package/src/builtin-addons/system-status/sirenodeck.json +6 -0
- package/src/builtin-addons/test-buildin/decks/action-buttons-test.ts +56 -0
- package/src/builtin-addons/test-buildin/index.d.ts +5 -0
- package/src/builtin-addons/test-buildin/index.ts +16 -0
- package/src/builtin-addons/value-display/README.md +59 -0
- package/src/builtin-addons/value-display/backend.ts +86 -0
- package/src/builtin-addons/value-display/buttons/value-display/backend.ts +17 -0
- package/src/builtin-addons/value-display/buttons/value-display/config.ts +36 -0
- package/src/builtin-addons/value-display/buttons/value-display/frontend.tsx +54 -0
- package/src/builtin-addons/value-display/index.d.ts +5 -0
- package/src/builtin-addons/value-display/index.ts +23 -0
- package/src/builtin-addons/value-display/sirenodeck.json +6 -0
- package/src/builtin-addons/weather/README.md +46 -0
- package/src/builtin-addons/weather/backend.ts +121 -0
- package/src/builtin-addons/weather/buttons/weather/backend.ts +27 -0
- package/src/builtin-addons/weather/buttons/weather/config.ts +29 -0
- package/src/builtin-addons/weather/buttons/weather/frontend.tsx +63 -0
- package/src/builtin-addons/weather/buttons/weather/icons.tsx +88 -0
- package/src/builtin-addons/weather/buttons/weather/pages.tsx +109 -0
- package/src/builtin-addons/weather/domain/codes.ts +35 -0
- package/src/builtin-addons/weather/domain/fetch.ts +47 -0
- package/src/builtin-addons/weather/index.d.ts +5 -0
- package/src/builtin-addons/weather/index.ts +23 -0
- package/src/builtin-addons/weather/poller.ts +70 -0
- package/src/builtin-addons/weather/provider/city-key.ts +9 -0
- package/src/builtin-addons/weather/provider/codes.ts +35 -0
- package/src/builtin-addons/weather/provider/fetch.ts +97 -0
- package/src/builtin-addons/weather/provider/geocode.ts +67 -0
- package/src/builtin-addons/weather/provider/types.ts +42 -0
- package/src/builtin-addons/weather/sirenodeck.json +6 -0
- package/src/cli/coding-agents-onboarding.ts +434 -0
- package/src/cli/commands/addon-decks.ts +441 -0
- package/src/cli/commands/addon-registry.ts +639 -0
- package/src/cli/commands/emulator-mode.ts +289 -0
- package/src/cli/commands/install.ts +128 -0
- package/src/cli/commands/logs.ts +74 -0
- package/src/cli/commands/network-bind.ts +111 -0
- package/src/cli/commands/pipeline/helpers.ts +75 -0
- package/src/cli/commands/pipeline/preflight.ts +20 -0
- package/src/cli/commands/port-identity.ts +152 -0
- package/src/cli/commands/reload.ts +37 -0
- package/src/cli/commands/restart.ts +139 -0
- package/src/cli/commands/run.ts +2270 -0
- package/src/cli/commands/service/install.ts +121 -0
- package/src/cli/commands/service/render-template.ts +158 -0
- package/src/cli/commands/service-manager.ts +184 -0
- package/src/cli/commands/spawn-daemon.ts +251 -0
- package/src/cli/commands/start.ts +1061 -0
- package/src/cli/commands/status.ts +110 -0
- package/src/cli/commands/stop.ts +121 -0
- package/src/cli/commands/subprocess-supervisor.ts +203 -0
- package/src/cli/commands/system-requirements.ts +699 -0
- package/src/cli/cwd.ts +28 -0
- package/src/cli/first-run.ts +149 -0
- package/src/cli/http-server.ts +244 -0
- package/src/cli/index.ts +355 -0
- package/src/cli/install-root.ts +26 -0
- package/src/cli/main.ts +194 -0
- package/src/cli/package-manager.ts +175 -0
- package/src/cli/probe-deps.ts +45 -0
- package/src/cli/prompt.ts +22 -0
- package/src/cli/startup-display.ts +452 -0
- package/src/config/builtin-icons.ts +57 -0
- package/src/config/config-diff.ts +54 -0
- package/src/config/discovery.ts +64 -0
- package/src/config/icon-resolver.ts +90 -0
- package/src/config/include-resolver.ts +202 -0
- package/src/config/index.ts +9 -0
- package/src/config/loader.ts +187 -0
- package/src/config/mutation.ts +514 -0
- package/src/config/reference-expander.ts +84 -0
- package/src/config/schemas.ts +223 -0
- package/src/config/validation.ts +254 -0
- package/src/core/asset-id.ts +21 -0
- package/src/core/gesture-state.ts +344 -0
- package/src/core/icon-asset-registry.ts +127 -0
- package/src/core/icon-source.ts +86 -0
- package/src/core/index.ts +30 -0
- package/src/core/mime.ts +16 -0
- package/src/core/pagination.ts +90 -0
- package/src/core/pub-sub.ts +126 -0
- package/src/core/settings.ts +153 -0
- package/src/core/store.ts +88 -0
- package/src/core/watcher.ts +73 -0
- package/src/deck/addon-handler-bridge.ts +516 -0
- package/src/deck/deck-config.ts +271 -0
- package/src/deck/editor-surfaces.ts +87 -0
- package/src/deck/host-context.ts +18 -0
- package/src/deck/index.ts +102 -0
- package/src/deck/macro-parse.ts +182 -0
- package/src/deck/methods.ts +348 -0
- package/src/deck/paginate-deck.ts +98 -0
- package/src/deck/position-buttons.ts +57 -0
- package/src/deck/runtime/index.ts +5 -0
- package/src/deck/runtime/runtime.ts +1060 -0
- package/src/deck/runtime-subscriptions.ts +45 -0
- package/src/deck/system-back-injection.ts +62 -0
- package/src/deck/system-buttons/registry.tsx +97 -0
- package/src/deck/system-buttons/types.ts +14 -0
- package/src/device/black-frame.ts +73 -0
- package/src/device/index.ts +13 -0
- package/src/device/linux-udev.ts +36 -0
- package/src/device/models.ts +89 -0
- package/src/device/reconnecting.ts +193 -0
- package/src/device/registry.ts +38 -0
- package/src/device/stream-deck.ts +155 -0
- package/src/index.ts +74 -0
- package/src/outputClient/emulator.ts +357 -0
- package/src/outputClient/index.ts +26 -0
- package/src/outputClient/open-browser.ts +26 -0
- package/src/outputClient/real.ts +393 -0
- package/src/outputClient/types.ts +83 -0
- package/src/render/browser-renderer.ts +240 -0
- package/src/render/buffer-hash.ts +20 -0
- package/src/render/editor-handler.ts +197 -0
- package/src/render/emulator-server.ts +128 -0
- package/src/render/icon-source-resolver.ts +69 -0
- package/src/render/index.ts +16 -0
- package/src/render/protocol.ts +61 -0
- package/src/render/push-raw-image.ts +100 -0
- package/src/render/screenshot-cadence.ts +87 -0
- package/src/render/state-publisher.ts +110 -0
- package/src/render/vite-server.ts +138 -0
- package/src/render/ws-bridge.ts +315 -0
- package/src/system/device-selection.ts +80 -0
- package/src/system/glob-match.ts +74 -0
- package/src/system/providers/active-app/darwin.ts +117 -0
- package/src/system/providers/active-app/linux.ts +245 -0
- package/src/system/providers/active-app/wayland-gnome.ts +303 -0
- package/src/system/providers/active-app/windows.ts +94 -0
- package/src/system/providers/active-app.ts +97 -0
- package/src/system/providers/clipboard/darwin.ts +65 -0
- package/src/system/providers/clipboard/linux.ts +163 -0
- package/src/system/providers/clipboard/windows.ts +94 -0
- package/src/system/providers/clipboard.ts +84 -0
- package/src/system/providers/error.ts +16 -0
- package/src/system/providers/key-macro/darwin.ts +221 -0
- package/src/system/providers/key-macro/linux.ts +651 -0
- package/src/system/providers/key-macro/parser.ts +215 -0
- package/src/system/providers/key-macro/windows.ts +476 -0
- package/src/system/providers/key-macro.ts +79 -0
- package/src/system/providers/notification/darwin.ts +36 -0
- package/src/system/providers/notification/linux.ts +115 -0
- package/src/system/providers/notification/windows.ts +72 -0
- package/src/system/providers/notification.ts +75 -0
- package/src/system/providers/session/darwin.ts +82 -0
- package/src/system/providers/session/linux.ts +175 -0
- package/src/system/providers/session/windows.ts +73 -0
- package/src/system/providers/session.ts +89 -0
- package/src/system/providers/shared.ts +65 -0
- package/src/system/requirements.ts +235 -0
- package/src/system/setup-wizard/config-seed.ts +30 -0
- package/src/system/setup-wizard/format.ts +275 -0
- package/src/system/setup-wizard/index.ts +45 -0
- package/src/system/setup-wizard/open-settings.ts +26 -0
- package/src/system/setup-wizard/plan.ts +230 -0
- package/src/system/setup-wizard/probe-cache.ts +34 -0
- package/src/system/setup-wizard/probe.ts +486 -0
- package/src/system/setup-wizard/runtime-features.ts +85 -0
- package/src/system/setup-wizard/sudo.ts +178 -0
- package/src/system/setup-wizard/types.ts +133 -0
- package/src/system/virtual-stream-deck.ts +67 -0
- package/src/themes/css.ts +210 -0
- package/src/themes/default/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- package/src/themes/default/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-BoldItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLight.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLightItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Italic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Light.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-LightItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-MediumItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBold.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBoldItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Thin.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ThinItalic.ttf +0 -0
- package/src/themes/default/assets/IBM_Plex_Mono/OFL.txt +93 -0
- package/src/themes/default/assets/OFL.txt +93 -0
- package/src/themes/default/assets/README.txt +106 -0
- package/src/themes/default/assets/static/IBMPlexSans-Bold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-BoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-ExtraLight.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-ExtraLightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-Italic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-Light.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-Medium.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-MediumItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-Regular.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-SemiBold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-SemiBoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-Thin.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans-ThinItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Bold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-BoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLight.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Italic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Light.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-LightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Medium.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-MediumItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Regular.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-Thin.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_Condensed-ThinItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Bold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-BoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLight.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Italic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Light.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-LightItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Medium.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-MediumItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Regular.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBold.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Thin.ttf +0 -0
- package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ThinItalic.ttf +0 -0
- package/src/themes/default/components.css +81 -0
- package/src/themes/default/sirenodeck.json +170 -0
- package/src/themes/index.ts +14 -0
- package/src/themes/light/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- package/src/themes/light/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
- package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
- package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
- package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
- package/src/themes/light/assets/IBM_Plex_Mono/OFL.txt +93 -0
- package/src/themes/light/assets/OFL.txt +93 -0
- package/src/themes/light/assets/README.txt +106 -0
- package/src/themes/light/assets/static/IBMPlexSans-Light.ttf +0 -0
- package/src/themes/light/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
- package/src/themes/light/assets/static/IBMPlexSans-Thin.ttf +0 -0
- package/src/themes/light/components.css +70 -0
- package/src/themes/light/sirenodeck.json +170 -0
- package/src/themes/loader.ts +343 -0
- package/src/themes/manifest.ts +164 -0
- package/src/themes/use-resolved-theme.tsx +32 -0
- package/src/ui/ButtonFrame.tsx +230 -0
- package/src/ui/contexts/AssetCacheContext.tsx +43 -0
- package/src/ui/index.ts +20 -0
- package/src/ui/primitives/Chip.tsx +53 -0
- package/src/ui/primitives/Icon.tsx +209 -0
- package/src/ui/primitives/Label.tsx +82 -0
- package/src/ui/primitives/ProgressBar.tsx +38 -0
- package/src/ui/primitives/TapIndicator.tsx +67 -0
- package/src/ui/primitives/Text.tsx +810 -0
- package/src/ui/primitives/index.ts +6 -0
- package/src/ui/surfaces/BarsSurface.tsx +211 -0
- package/src/ui/surfaces/IconLabelProgressSurface.tsx +133 -0
- package/src/ui/surfaces/IconLabelSurface.tsx +59 -0
- package/src/ui/surfaces/LabelValueListSurface.tsx +202 -0
- package/src/ui/surfaces/PaginatedSurface.tsx +164 -0
- package/src/ui/surfaces/SplitActionSurface.tsx +98 -0
- package/src/ui/surfaces/TemporaryErrorSurface.tsx +68 -0
- package/src/ui/surfaces/ValueChart.tsx +218 -0
- package/src/ui/surfaces/index.ts +32 -0
- package/src/ui/surfaces/paginated-schema.ts +22 -0
- package/src/ui/theme-presentation-builder.ts +184 -0
- package/src/ui/theme-presentation.tsx +146 -0
- package/src/ui/utils/cn.ts +12 -0
- package/src/util/cache-paths.ts +38 -0
- package/src/util/config-diff.ts +16 -0
- package/src/util/daemon-control.ts +85 -0
- package/src/util/daemon.ts +575 -0
- package/src/util/device-config.ts +56 -0
- package/src/util/errors.ts +13 -0
- package/src/util/log-reader.ts +114 -0
- package/src/util/log-tail.ts +103 -0
- package/src/util/logger.ts +417 -0
- package/src/util/process-title.ts +79 -0
- package/src/util/single-instance.ts +202 -0
- package/src/version.ts +10 -0
- package/src/vite/index.ts +6 -0
- package/src/vite/virtual-modules.ts +631 -0
- package/src/vite-env.d.ts +1 -0
package/src/addon/api.ts
ADDED
|
@@ -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())
|