@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
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import type { CommandExecutor } from "../shared"
|
|
4
|
+
import { type SessionProvider, type SessionState } from "../session"
|
|
5
|
+
|
|
6
|
+
export interface WindowsSessionDeps {
|
|
7
|
+
readonly executor: CommandExecutor
|
|
8
|
+
readonly logger: pino.Logger
|
|
9
|
+
readonly pollIntervalMs?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const toState = (locked: boolean): SessionState =>
|
|
13
|
+
locked ? "locked" : "unlocked"
|
|
14
|
+
|
|
15
|
+
const PS_GET_LOGONUI = `if (Get-Process logonui -ErrorAction SilentlyContinue) { 'true' } else { 'false' }`
|
|
16
|
+
|
|
17
|
+
const parseLockResult = (raw: string): boolean =>
|
|
18
|
+
raw.trim().toLowerCase() === "true"
|
|
19
|
+
|
|
20
|
+
export const createWindowsSessionProvider = async (
|
|
21
|
+
deps: WindowsSessionDeps,
|
|
22
|
+
): Promise<SessionProvider> => {
|
|
23
|
+
const listeners = new Set<(s: SessionState) => void>()
|
|
24
|
+
let state: SessionState = "unknown"
|
|
25
|
+
let stopped = false
|
|
26
|
+
const pollMs = deps.pollIntervalMs ?? 5_000
|
|
27
|
+
|
|
28
|
+
const tick = async (): Promise<SessionState> => {
|
|
29
|
+
try {
|
|
30
|
+
const result = await deps.executor.run(
|
|
31
|
+
"powershell",
|
|
32
|
+
["-NoProfile", "-Command", PS_GET_LOGONUI],
|
|
33
|
+
{ timeoutMs: 2_000 },
|
|
34
|
+
)
|
|
35
|
+
if (result.exitCode !== 0) return state
|
|
36
|
+
return toState(parseLockResult(result.stdout))
|
|
37
|
+
} catch (err) {
|
|
38
|
+
deps.logger.debug({ err }, "session: powershell failed")
|
|
39
|
+
return state
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
state = await tick()
|
|
44
|
+
let interval: ReturnType<typeof setInterval> | null = setInterval(() => {
|
|
45
|
+
if (stopped) return
|
|
46
|
+
void tick().then((s) => {
|
|
47
|
+
if (stopped) return
|
|
48
|
+
if (s !== state) {
|
|
49
|
+
state = s
|
|
50
|
+
for (const l of listeners) l(state)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
}, pollMs)
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
getState() {
|
|
57
|
+
return state
|
|
58
|
+
},
|
|
59
|
+
subscribe(handler) {
|
|
60
|
+
listeners.add(handler)
|
|
61
|
+
return () => {
|
|
62
|
+
listeners.delete(handler)
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async stop() {
|
|
66
|
+
stopped = true
|
|
67
|
+
if (interval !== null) {
|
|
68
|
+
clearInterval(interval)
|
|
69
|
+
interval = null
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import { noopUnsubscribe } from "./shared"
|
|
4
|
+
|
|
5
|
+
export type SessionState = "locked" | "unlocked" | "unknown"
|
|
6
|
+
|
|
7
|
+
export interface SessionProvider {
|
|
8
|
+
getState(): SessionState
|
|
9
|
+
subscribe(handler: (state: SessionState) => void): () => void
|
|
10
|
+
stop(): Promise<void>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const createNullSessionProvider = (
|
|
14
|
+
logger?: pino.Logger,
|
|
15
|
+
): SessionProvider => {
|
|
16
|
+
if (logger) {
|
|
17
|
+
logger.warn(
|
|
18
|
+
{ provider: "session" },
|
|
19
|
+
"OS session provider unavailable, using null provider",
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
getState() {
|
|
24
|
+
return "unknown"
|
|
25
|
+
},
|
|
26
|
+
subscribe() {
|
|
27
|
+
return noopUnsubscribe
|
|
28
|
+
},
|
|
29
|
+
async stop() {
|
|
30
|
+
return
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CreateSessionProviderOptions {
|
|
36
|
+
readonly platform?: NodeJS.Platform
|
|
37
|
+
readonly dbus?: import("./shared").LinuxDbusBus
|
|
38
|
+
readonly executor?: import("./shared").CommandExecutor
|
|
39
|
+
readonly logger: pino.Logger
|
|
40
|
+
readonly idleMs?: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const createSessionProvider = async (
|
|
44
|
+
options: CreateSessionProviderOptions,
|
|
45
|
+
): Promise<SessionProvider> => {
|
|
46
|
+
// ponytail: capture mode — force unlocked so screenshots show the real
|
|
47
|
+
// decks instead of the lock screen. Set by capture-decks.mjs.
|
|
48
|
+
if (process.env["SIRENO_CAPTURE_UNLOCKED"] === "1") {
|
|
49
|
+
return {
|
|
50
|
+
getState: () => "unlocked" as const,
|
|
51
|
+
subscribe: () => noopUnsubscribe,
|
|
52
|
+
stop: async () => {},
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const platform = options.platform ?? process.platform
|
|
56
|
+
if (platform === "linux") {
|
|
57
|
+
// ponytail: let createLinuxSessionProvider self-own a dbus session bus when
|
|
58
|
+
// none is injected (mirrors active-app/wayland-gnome.ts:62-74). Returning a
|
|
59
|
+
// null provider here turned every Linux run into a silent no-op, which is
|
|
60
|
+
// why core:lock never fired.
|
|
61
|
+
const { createLinuxSessionProvider } = await import("./session/linux")
|
|
62
|
+
return createLinuxSessionProvider({
|
|
63
|
+
...(options.dbus !== undefined ? { dbus: options.dbus } : {}),
|
|
64
|
+
logger: options.logger,
|
|
65
|
+
...(options.idleMs !== undefined ? { idleMs: options.idleMs } : {}),
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
if (platform === "darwin") {
|
|
69
|
+
if (options.executor === undefined) {
|
|
70
|
+
return createNullSessionProvider(options.logger)
|
|
71
|
+
}
|
|
72
|
+
const { createDarwinSessionProvider } = await import("./session/darwin")
|
|
73
|
+
return createDarwinSessionProvider({
|
|
74
|
+
executor: options.executor,
|
|
75
|
+
logger: options.logger,
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
if (platform === "win32") {
|
|
79
|
+
if (options.executor === undefined) {
|
|
80
|
+
return createNullSessionProvider(options.logger)
|
|
81
|
+
}
|
|
82
|
+
const { createWindowsSessionProvider } = await import("./session/windows")
|
|
83
|
+
return createWindowsSessionProvider({
|
|
84
|
+
executor: options.executor,
|
|
85
|
+
logger: options.logger,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
return createNullSessionProvider(options.logger)
|
|
89
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import { ProviderError } from "./error"
|
|
4
|
+
|
|
5
|
+
export interface CommandExecutor {
|
|
6
|
+
run(
|
|
7
|
+
command: string,
|
|
8
|
+
args: ReadonlyArray<string>,
|
|
9
|
+
options?: { timeoutMs?: number },
|
|
10
|
+
): Promise<{ exitCode: number; stdout: string; stderr: string }>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface LinuxDbusBus {
|
|
14
|
+
getProxyObject(
|
|
15
|
+
serviceName: string,
|
|
16
|
+
objectPath: string,
|
|
17
|
+
): Promise<LinuxDbusProxyObject>
|
|
18
|
+
disconnect?(): void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface LinuxDbusProxyObject {
|
|
22
|
+
getInterface(name: string): LinuxDbusInterface
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LinuxDbusInterface {
|
|
26
|
+
Eval?(script: string): Promise<unknown>
|
|
27
|
+
GetActive?(): Promise<boolean>
|
|
28
|
+
GetIdletime?(): Promise<number>
|
|
29
|
+
FocusClass?(): Promise<string>
|
|
30
|
+
FocusTitle?(): Promise<string>
|
|
31
|
+
on?(event: string, handler: (...args: unknown[]) => void): void
|
|
32
|
+
off?(event: string, handler: (...args: unknown[]) => void): void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const withTimeout = async <T>(
|
|
36
|
+
promise: Promise<T>,
|
|
37
|
+
ms: number,
|
|
38
|
+
): Promise<T> => {
|
|
39
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
40
|
+
const timeout = new Promise<never>((_resolve, reject) => {
|
|
41
|
+
timer = setTimeout(() => {
|
|
42
|
+
reject(new ProviderError("TIMEOUT", `Operation timed out after ${ms}ms`))
|
|
43
|
+
}, ms)
|
|
44
|
+
})
|
|
45
|
+
try {
|
|
46
|
+
return await Promise.race([promise, timeout])
|
|
47
|
+
} finally {
|
|
48
|
+
if (timer !== null) clearTimeout(timer)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const noopUnsubscribe = (): void => undefined
|
|
53
|
+
|
|
54
|
+
export const logNull = (
|
|
55
|
+
logger: pino.Logger | undefined,
|
|
56
|
+
name: string,
|
|
57
|
+
reason: string,
|
|
58
|
+
): void => {
|
|
59
|
+
if (logger) {
|
|
60
|
+
logger.warn(
|
|
61
|
+
{ provider: name, reason },
|
|
62
|
+
"OS provider unavailable, using null provider",
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import type { CommandExecutor } from "./providers/shared"
|
|
2
|
+
import {
|
|
3
|
+
ACCESSIBILITY_HINT,
|
|
4
|
+
hasDarwinAccessibility,
|
|
5
|
+
} from "./setup-wizard/probe"
|
|
6
|
+
|
|
7
|
+
export type SystemCapability = "keyMacro" | "clipboard" | "notification"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Stand-in used in `missingCommands` when the capability is blocked by an OS
|
|
11
|
+
* permission rather than a missing binary — there is nothing to install.
|
|
12
|
+
*/
|
|
13
|
+
export const PERMISSION_SENTINEL = "accessibility-permission"
|
|
14
|
+
|
|
15
|
+
export interface CapabilityRequirement {
|
|
16
|
+
readonly name: SystemCapability
|
|
17
|
+
readonly commands: ReadonlyArray<string>
|
|
18
|
+
readonly reason: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CapabilityStatus {
|
|
22
|
+
readonly available: boolean
|
|
23
|
+
readonly commands: ReadonlyArray<string>
|
|
24
|
+
readonly missingCommands: ReadonlyArray<string>
|
|
25
|
+
readonly reason: string
|
|
26
|
+
readonly preferred: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type RequirementsCheckResult = Readonly<
|
|
30
|
+
Record<SystemCapability, CapabilityStatus>
|
|
31
|
+
>
|
|
32
|
+
|
|
33
|
+
export interface RequirementsCheckDeps {
|
|
34
|
+
readonly platform: string
|
|
35
|
+
readonly executor: CommandExecutor
|
|
36
|
+
readonly env?: NodeJS.ProcessEnv
|
|
37
|
+
// ponytail: fallback probe for stripped-PATH environments
|
|
38
|
+
// (systemd/launchd/IDE). `which` may return nothing even when the binary
|
|
39
|
+
// exists on disk at a non-default bin dir. The caller wires this with a
|
|
40
|
+
// statSync-based probe over `/usr/local/bin`, `~/.local/bin`, etc.
|
|
41
|
+
readonly extraFsProbe?: (command: string) => boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const capabilityConfig: Readonly<
|
|
45
|
+
Record<
|
|
46
|
+
SystemCapability,
|
|
47
|
+
{
|
|
48
|
+
readonly commands: ReadonlyArray<string>
|
|
49
|
+
readonly reason: string
|
|
50
|
+
readonly preferred: (platform: string, env: NodeJS.ProcessEnv) => string
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
> = {
|
|
54
|
+
keyMacro: {
|
|
55
|
+
commands: [
|
|
56
|
+
"ydotool",
|
|
57
|
+
"wtype",
|
|
58
|
+
"xdotool",
|
|
59
|
+
"dotool",
|
|
60
|
+
"osascript",
|
|
61
|
+
"powershell",
|
|
62
|
+
],
|
|
63
|
+
reason:
|
|
64
|
+
"type:// keystrokes need a key input tool. Install ydotool (works on most compositors via uinput) or wtype (wlroots compositors only). macOS uses osascript; Windows uses PowerShell with Win32 SendInput.",
|
|
65
|
+
preferred: (platform) => {
|
|
66
|
+
if (platform === "darwin") return "osascript"
|
|
67
|
+
if (platform === "win32") return "powershell"
|
|
68
|
+
return "ydotool"
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
clipboard: {
|
|
72
|
+
commands: ["wl-copy", "xclip", "xsel", "pbcopy"],
|
|
73
|
+
reason:
|
|
74
|
+
"non-ASCII literal text (emoji, accented letters, CJK) needs a clipboard tool because ydotool's `type` does not handle non-BMP characters. Install the wl-clipboard package (provides wl-copy) on Wayland; xclip / xsel work on X11; macOS ships pbcopy.",
|
|
75
|
+
preferred: (platform, env) => {
|
|
76
|
+
if (platform === "darwin") return "pbcopy"
|
|
77
|
+
return env["WAYLAND_DISPLAY"] === undefined &&
|
|
78
|
+
env["DISPLAY"] !== undefined
|
|
79
|
+
? "xclip"
|
|
80
|
+
: "wl-copy"
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
notification: {
|
|
84
|
+
commands: ["notify-send", "osascript", "powershell"],
|
|
85
|
+
reason:
|
|
86
|
+
"OS-level notifications (toast/notification-center) need a host tool. Linux uses notify-send (libnotify); macOS uses osascript; Windows uses PowerShell with System.Windows.Forms.NotifyIcon.",
|
|
87
|
+
preferred: (platform) => {
|
|
88
|
+
if (platform === "darwin") return "osascript"
|
|
89
|
+
if (platform === "win32") return "powershell"
|
|
90
|
+
return "notify-send"
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ponytail: `command` is a POSIX shell builtin, not a binary — execFile can't
|
|
96
|
+
// spawn it, so the old `executor.run("command", ["-v", x])` failed for EVERY
|
|
97
|
+
// candidate and the probe silently degraded to the `--version` fallback (which
|
|
98
|
+
// osascript, pbcopy and clip don't even support). Wrap in `sh -c`, matching
|
|
99
|
+
// setup-wizard/probe.ts, and shell-quote so the argument stays one token.
|
|
100
|
+
const probeCommandV = async (
|
|
101
|
+
executor: CommandExecutor,
|
|
102
|
+
command: string,
|
|
103
|
+
): Promise<boolean> => {
|
|
104
|
+
const quoted = `'${command.replaceAll(`'`, `'\\''`)}'`
|
|
105
|
+
const result = await executor.run("sh", ["-c", `command -v ${quoted}`])
|
|
106
|
+
return result.exitCode === 0 && result.stdout.trim().length > 0
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const probeVersion = async (
|
|
110
|
+
executor: CommandExecutor,
|
|
111
|
+
command: string,
|
|
112
|
+
): Promise<boolean> => {
|
|
113
|
+
try {
|
|
114
|
+
const result = await executor.run(command, ["--version"], {
|
|
115
|
+
timeoutMs: 1_000,
|
|
116
|
+
})
|
|
117
|
+
return result.exitCode === 0
|
|
118
|
+
} catch {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const probeCommand = async (
|
|
124
|
+
executor: CommandExecutor,
|
|
125
|
+
command: string,
|
|
126
|
+
extraFsProbe?: (command: string) => boolean,
|
|
127
|
+
): Promise<boolean> => {
|
|
128
|
+
if (await probeCommandV(executor, command)) return true
|
|
129
|
+
if (extraFsProbe?.(command) === true) return true
|
|
130
|
+
return await probeVersion(executor, command)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ponytail: the clipboard candidate list is session-dependent on Linux, so it
|
|
134
|
+
// can't just be `config.commands`. The old ternary keyed off `preferred ===
|
|
135
|
+
// "xclip"` and sent every other platform down the `["wl-copy"]` branch — so on
|
|
136
|
+
// macOS the probe looked for a Wayland tool, never for pbcopy, and every run
|
|
137
|
+
// logged "clipboard: none of wl-copy found" on a machine that ships pbcopy.
|
|
138
|
+
const clipboardCandidates = (
|
|
139
|
+
platform: string,
|
|
140
|
+
preferred: string,
|
|
141
|
+
): ReadonlyArray<string> => {
|
|
142
|
+
if (platform === "darwin") return ["pbcopy"]
|
|
143
|
+
if (platform === "win32") return ["clip"]
|
|
144
|
+
return preferred === "xclip" ? ["xclip", "xsel"] : ["wl-copy"]
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const checkRequirements = async ({
|
|
148
|
+
platform,
|
|
149
|
+
executor,
|
|
150
|
+
env = process.env,
|
|
151
|
+
extraFsProbe,
|
|
152
|
+
}: RequirementsCheckDeps): Promise<RequirementsCheckResult> => {
|
|
153
|
+
const result: Partial<Record<SystemCapability, CapabilityStatus>> = {}
|
|
154
|
+
|
|
155
|
+
for (const [name, config] of Object.entries(capabilityConfig)) {
|
|
156
|
+
const commands =
|
|
157
|
+
name === "clipboard"
|
|
158
|
+
? clipboardCandidates(platform, config.preferred(platform, env))
|
|
159
|
+
: config.commands
|
|
160
|
+
const availability = await Promise.all(
|
|
161
|
+
commands.map((command) => probeCommand(executor, command, extraFsProbe)),
|
|
162
|
+
)
|
|
163
|
+
const found = commands.filter((_, index) => availability[index])
|
|
164
|
+
const missing = commands.filter((_, index) => !availability[index])
|
|
165
|
+
result[name as SystemCapability] = {
|
|
166
|
+
available: found.length > 0,
|
|
167
|
+
commands: found,
|
|
168
|
+
missingCommands: missing,
|
|
169
|
+
reason: config.reason,
|
|
170
|
+
preferred: config.preferred(platform, env),
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ponytail: darwin-only. `osascript` ships with macOS, so probing for the
|
|
175
|
+
// binary always succeeds and the daemon started reporting keyMacro as
|
|
176
|
+
// available while every keystroke failed with -1719/1002. The setup wizard
|
|
177
|
+
// already checks the Accessibility grant; without the same check here the
|
|
178
|
+
// runtime never warned at boot, and a tapped macro button showed a generic
|
|
179
|
+
// "action-failed" tile instead of being pre-empted with the real reason.
|
|
180
|
+
// Linux and Windows are untouched — they return before this block.
|
|
181
|
+
if (platform === "darwin") {
|
|
182
|
+
const keyMacro = result.keyMacro
|
|
183
|
+
if (
|
|
184
|
+
keyMacro?.available === true &&
|
|
185
|
+
!(await hasDarwinAccessibility(executor))
|
|
186
|
+
) {
|
|
187
|
+
result.keyMacro = {
|
|
188
|
+
...keyMacro,
|
|
189
|
+
available: false,
|
|
190
|
+
missingCommands: [PERMISSION_SENTINEL],
|
|
191
|
+
reason: `osascript is installed but has no Accessibility permission — ${ACCESSIBILITY_HINT}`,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return result as RequirementsCheckResult
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const CAPABILITY_LABEL: Readonly<Record<SystemCapability, string>> = {
|
|
200
|
+
keyMacro: "Key macros",
|
|
201
|
+
clipboard: "Clipboard",
|
|
202
|
+
notification: "Notifications",
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const formatCapabilityWarning = (
|
|
206
|
+
name: SystemCapability,
|
|
207
|
+
status: CapabilityStatus,
|
|
208
|
+
): string => {
|
|
209
|
+
const label = CAPABILITY_LABEL[name]
|
|
210
|
+
if (status.available) {
|
|
211
|
+
const missingPreferred =
|
|
212
|
+
status.preferred.length > 0 &&
|
|
213
|
+
!status.commands.includes(status.preferred) &&
|
|
214
|
+
status.missingCommands.length > 0
|
|
215
|
+
if (missingPreferred) {
|
|
216
|
+
return `${label}: using ${status.commands.join(", ")} as fallback; preferred ${status.preferred} is missing — ${status.reason}`
|
|
217
|
+
}
|
|
218
|
+
return ""
|
|
219
|
+
}
|
|
220
|
+
// ponytail: "none of accessibility-permission found" reads like a missing
|
|
221
|
+
// binary. A denied OS permission is not something the user can install, so
|
|
222
|
+
// state it as a permission and let the reason carry the remedy.
|
|
223
|
+
if (status.missingCommands.includes(PERMISSION_SENTINEL)) {
|
|
224
|
+
return `${label}: ${status.reason}`
|
|
225
|
+
}
|
|
226
|
+
return `${label}: none of ${status.missingCommands.join(", ")} found — ${status.reason}`
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export const getRequiredCapability = (
|
|
230
|
+
action: string,
|
|
231
|
+
): SystemCapability | null => {
|
|
232
|
+
if (action.startsWith("type://")) return "keyMacro"
|
|
233
|
+
if (action.startsWith("macro://")) return "keyMacro"
|
|
234
|
+
return null
|
|
235
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { dirname, join } from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
export interface ConfigSeedResult {
|
|
6
|
+
readonly seeded: boolean
|
|
7
|
+
readonly targetPath: string
|
|
8
|
+
readonly sourcePath: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const here = (): string => dirname(fileURLToPath(import.meta.url))
|
|
12
|
+
|
|
13
|
+
// ponytail: seed `starter-config.yml`, NOT `default-config.yml`. The latter is
|
|
14
|
+
// the repo's own dev config — it carries `!include demos/*.yml` and
|
|
15
|
+
// `src: ./packages/addons/*`, both resolved relative to the config file. Copied
|
|
16
|
+
// to ~/.config/sirenodeck/ those paths point at directories that don't exist,
|
|
17
|
+
// so the very first `sirenodeck start` after the wizard died with
|
|
18
|
+
// "Included file not found". The starter config is self-contained by design.
|
|
19
|
+
export const defaultConfigSourcePath = (): string =>
|
|
20
|
+
join(here(), "..", "..", "..", "config", "starter-config.yml")
|
|
21
|
+
|
|
22
|
+
export const seedDefaultConfig = (targetPath: string): ConfigSeedResult => {
|
|
23
|
+
const sourcePath = defaultConfigSourcePath()
|
|
24
|
+
mkdirSync(dirname(targetPath), { recursive: true })
|
|
25
|
+
copyFileSync(sourcePath, targetPath)
|
|
26
|
+
writeFileSync(targetPath, readFileSync(targetPath, "utf8"), {
|
|
27
|
+
mode: 0o600,
|
|
28
|
+
})
|
|
29
|
+
return { seeded: true, targetPath, sourcePath }
|
|
30
|
+
}
|