@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,651 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import { ProviderError } from "../error"
|
|
4
|
+
import { createClipboardProvider, type ClipboardProvider } from "../clipboard"
|
|
5
|
+
import { type CommandExecutor, withTimeout } from "../shared"
|
|
6
|
+
import { type KeyMacroProvider } from "../key-macro"
|
|
7
|
+
import { parseCombo } from "./parser"
|
|
8
|
+
|
|
9
|
+
export interface LinuxKeyMacroDeps {
|
|
10
|
+
readonly executor: CommandExecutor
|
|
11
|
+
readonly env: Readonly<Record<string, string>>
|
|
12
|
+
readonly logger: pino.Logger
|
|
13
|
+
readonly timeoutMs?: number
|
|
14
|
+
readonly extraFsProbe?: (tool: string) => boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const YDOTOOL_TOOL = "ydotool"
|
|
18
|
+
const WTYPE_TOOL = "wtype"
|
|
19
|
+
|
|
20
|
+
type Tool = "ydotool" | "wtype"
|
|
21
|
+
|
|
22
|
+
const YDOTOOL_CLIPBOARD_PRE_DELAY_MS = 50
|
|
23
|
+
|
|
24
|
+
// Linux input-event-codes.h — only the codes we need.
|
|
25
|
+
const SC_LEFTCTRL = 29
|
|
26
|
+
const SC_LEFTALT = 56
|
|
27
|
+
const SC_LEFTSHIFT = 42
|
|
28
|
+
const SC_LEFTMETA = 125 // also used for Super/Hyper
|
|
29
|
+
|
|
30
|
+
const SC_ESC = 1
|
|
31
|
+
const SC_1 = 2
|
|
32
|
+
const SC_2 = 3
|
|
33
|
+
const SC_3 = 4
|
|
34
|
+
const SC_4 = 5
|
|
35
|
+
const SC_5 = 6
|
|
36
|
+
const SC_6 = 7
|
|
37
|
+
const SC_7 = 8
|
|
38
|
+
const SC_8 = 9
|
|
39
|
+
const SC_9 = 10
|
|
40
|
+
const SC_0 = 11
|
|
41
|
+
const SC_MINUS = 12
|
|
42
|
+
const SC_EQUAL = 13
|
|
43
|
+
const SC_BACKSPACE = 14
|
|
44
|
+
const SC_TAB = 15
|
|
45
|
+
const SC_Q = 16
|
|
46
|
+
const SC_W = 17
|
|
47
|
+
const SC_E = 18
|
|
48
|
+
const SC_R = 19
|
|
49
|
+
const SC_T = 20
|
|
50
|
+
const SC_Y = 21
|
|
51
|
+
const SC_U = 22
|
|
52
|
+
const SC_I = 23
|
|
53
|
+
const SC_O = 24
|
|
54
|
+
const SC_P = 25
|
|
55
|
+
const SC_LEFTBRACE = 26
|
|
56
|
+
const SC_RIGHTBRACE = 27
|
|
57
|
+
const SC_ENTER = 28
|
|
58
|
+
const SC_A = 30
|
|
59
|
+
const SC_S = 31
|
|
60
|
+
const SC_D = 32
|
|
61
|
+
const SC_F = 33
|
|
62
|
+
const SC_G = 34
|
|
63
|
+
const SC_H = 35
|
|
64
|
+
const SC_J = 36
|
|
65
|
+
const SC_K = 37
|
|
66
|
+
const SC_L = 38
|
|
67
|
+
const SC_SEMICOLON = 39
|
|
68
|
+
const SC_APOSTROPHE = 40
|
|
69
|
+
const SC_GRAVE = 41
|
|
70
|
+
const SC_BACKSLASH = 43
|
|
71
|
+
const SC_Z = 44
|
|
72
|
+
const SC_X = 45
|
|
73
|
+
const SC_C = 46
|
|
74
|
+
const SC_V = 47
|
|
75
|
+
const SC_B = 48
|
|
76
|
+
const SC_N = 49
|
|
77
|
+
const SC_M = 50
|
|
78
|
+
const SC_COMMA = 51
|
|
79
|
+
const SC_DOT = 52
|
|
80
|
+
const SC_SLASH = 53
|
|
81
|
+
const SC_KPDOT = 83
|
|
82
|
+
const SC_KP0 = 82
|
|
83
|
+
const SC_KP1 = 79
|
|
84
|
+
const SC_KP2 = 80
|
|
85
|
+
const SC_KP3 = 81
|
|
86
|
+
const SC_KP4 = 75
|
|
87
|
+
const SC_KP5 = 76
|
|
88
|
+
const SC_KP6 = 77
|
|
89
|
+
const SC_KP7 = 71
|
|
90
|
+
const SC_KP8 = 72
|
|
91
|
+
const SC_KP9 = 73
|
|
92
|
+
const SC_CAPSLOCK = 58
|
|
93
|
+
const SC_SPACE = 57
|
|
94
|
+
const SC_F1 = 59
|
|
95
|
+
const SC_F2 = 60
|
|
96
|
+
const SC_F3 = 61
|
|
97
|
+
const SC_F4 = 62
|
|
98
|
+
const SC_F5 = 63
|
|
99
|
+
const SC_F6 = 64
|
|
100
|
+
const SC_F7 = 65
|
|
101
|
+
const SC_F8 = 66
|
|
102
|
+
const SC_F9 = 67
|
|
103
|
+
const SC_F10 = 68
|
|
104
|
+
const SC_F11 = 87
|
|
105
|
+
const SC_F12 = 88
|
|
106
|
+
const SC_NUMLOCK = 69
|
|
107
|
+
const SC_SCROLLLOCK = 70
|
|
108
|
+
const SC_KPENTER = 96
|
|
109
|
+
const SC_KPPLUS = 78
|
|
110
|
+
const SC_KPMINUS = 74
|
|
111
|
+
const SC_KPASTERISK = 55
|
|
112
|
+
const SC_KPSLASH = 98
|
|
113
|
+
const SC_HOME = 102
|
|
114
|
+
const SC_UP = 103
|
|
115
|
+
const SC_PAGEUP = 104
|
|
116
|
+
const SC_LEFT = 105
|
|
117
|
+
const SC_RIGHT = 106
|
|
118
|
+
const SC_END = 107
|
|
119
|
+
const SC_DOWN = 108
|
|
120
|
+
const SC_PAGEDOWN = 109
|
|
121
|
+
const SC_INSERT = 110
|
|
122
|
+
const SC_DELETE = 111
|
|
123
|
+
const SC_PAUSE = 119
|
|
124
|
+
const SC_PRINT = 99
|
|
125
|
+
const SC_MENU = 139
|
|
126
|
+
const SC_F13 = 183
|
|
127
|
+
const SC_F14 = 184
|
|
128
|
+
const SC_F15 = 185
|
|
129
|
+
const SC_F16 = 186
|
|
130
|
+
const SC_F17 = 187
|
|
131
|
+
const SC_F18 = 188
|
|
132
|
+
const SC_F19 = 189
|
|
133
|
+
const SC_F20 = 190
|
|
134
|
+
const SC_F21 = 191
|
|
135
|
+
const SC_F22 = 192
|
|
136
|
+
const SC_F23 = 193
|
|
137
|
+
const SC_F24 = 194
|
|
138
|
+
|
|
139
|
+
const MOD_SCANCODES: ReadonlyMap<string, number> = new Map<string, number>([
|
|
140
|
+
["ctrl", SC_LEFTCTRL],
|
|
141
|
+
["alt", SC_LEFTALT],
|
|
142
|
+
["shift", SC_LEFTSHIFT],
|
|
143
|
+
["meta", SC_LEFTMETA],
|
|
144
|
+
["super", SC_LEFTMETA],
|
|
145
|
+
["hyper", SC_LEFTMETA],
|
|
146
|
+
])
|
|
147
|
+
|
|
148
|
+
const MOD_ORDER: ReadonlyArray<string> = ["ctrl", "alt", "shift", "super"]
|
|
149
|
+
|
|
150
|
+
const modToScancode = (mod: string): number | null =>
|
|
151
|
+
MOD_SCANCODES.get(mod) ?? null
|
|
152
|
+
|
|
153
|
+
const namedKeyToScancode = (name: string): number | null => {
|
|
154
|
+
switch (name) {
|
|
155
|
+
case "Escape":
|
|
156
|
+
return SC_ESC
|
|
157
|
+
case "Tab":
|
|
158
|
+
return SC_TAB
|
|
159
|
+
case "Return":
|
|
160
|
+
return SC_ENTER
|
|
161
|
+
case "BackSpace":
|
|
162
|
+
return SC_BACKSPACE
|
|
163
|
+
case "Caps_Lock":
|
|
164
|
+
return SC_CAPSLOCK
|
|
165
|
+
case "Num_Lock":
|
|
166
|
+
return SC_NUMLOCK
|
|
167
|
+
case "Scroll_Lock":
|
|
168
|
+
return SC_SCROLLLOCK
|
|
169
|
+
case "space":
|
|
170
|
+
return SC_SPACE
|
|
171
|
+
case "Print":
|
|
172
|
+
return SC_PRINT
|
|
173
|
+
case "Pause":
|
|
174
|
+
return SC_PAUSE
|
|
175
|
+
case "Menu":
|
|
176
|
+
return SC_MENU
|
|
177
|
+
case "Insert":
|
|
178
|
+
return SC_INSERT
|
|
179
|
+
case "Delete":
|
|
180
|
+
return SC_DELETE
|
|
181
|
+
case "Home":
|
|
182
|
+
return SC_HOME
|
|
183
|
+
case "End":
|
|
184
|
+
return SC_END
|
|
185
|
+
case "Page_Up":
|
|
186
|
+
return SC_PAGEUP
|
|
187
|
+
case "Page_Down":
|
|
188
|
+
return SC_PAGEDOWN
|
|
189
|
+
case "Up":
|
|
190
|
+
return SC_UP
|
|
191
|
+
case "Down":
|
|
192
|
+
return SC_DOWN
|
|
193
|
+
case "Left":
|
|
194
|
+
return SC_LEFT
|
|
195
|
+
case "Right":
|
|
196
|
+
return SC_RIGHT
|
|
197
|
+
case "equal":
|
|
198
|
+
return SC_EQUAL
|
|
199
|
+
case "minus":
|
|
200
|
+
return SC_MINUS
|
|
201
|
+
case "comma":
|
|
202
|
+
return SC_COMMA
|
|
203
|
+
case "period":
|
|
204
|
+
return SC_DOT
|
|
205
|
+
case "F1":
|
|
206
|
+
return SC_F1
|
|
207
|
+
case "F2":
|
|
208
|
+
return SC_F2
|
|
209
|
+
case "F3":
|
|
210
|
+
return SC_F3
|
|
211
|
+
case "F4":
|
|
212
|
+
return SC_F4
|
|
213
|
+
case "F5":
|
|
214
|
+
return SC_F5
|
|
215
|
+
case "F6":
|
|
216
|
+
return SC_F6
|
|
217
|
+
case "F7":
|
|
218
|
+
return SC_F7
|
|
219
|
+
case "F8":
|
|
220
|
+
return SC_F8
|
|
221
|
+
case "F9":
|
|
222
|
+
return SC_F9
|
|
223
|
+
case "F10":
|
|
224
|
+
return SC_F10
|
|
225
|
+
case "F11":
|
|
226
|
+
return SC_F11
|
|
227
|
+
case "F12":
|
|
228
|
+
return SC_F12
|
|
229
|
+
case "F13":
|
|
230
|
+
return SC_F13
|
|
231
|
+
case "F14":
|
|
232
|
+
return SC_F14
|
|
233
|
+
case "F15":
|
|
234
|
+
return SC_F15
|
|
235
|
+
case "F16":
|
|
236
|
+
return SC_F16
|
|
237
|
+
case "F17":
|
|
238
|
+
return SC_F17
|
|
239
|
+
case "F18":
|
|
240
|
+
return SC_F18
|
|
241
|
+
case "F19":
|
|
242
|
+
return SC_F19
|
|
243
|
+
case "F20":
|
|
244
|
+
return SC_F20
|
|
245
|
+
case "F21":
|
|
246
|
+
return SC_F21
|
|
247
|
+
case "F22":
|
|
248
|
+
return SC_F22
|
|
249
|
+
case "F23":
|
|
250
|
+
return SC_F23
|
|
251
|
+
case "F24":
|
|
252
|
+
return SC_F24
|
|
253
|
+
default:
|
|
254
|
+
return null
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const LETTER_SC: ReadonlyMap<string, number> = new Map<string, number>([
|
|
259
|
+
["a", SC_A],
|
|
260
|
+
["b", SC_B],
|
|
261
|
+
["c", SC_C],
|
|
262
|
+
["d", SC_D],
|
|
263
|
+
["e", SC_E],
|
|
264
|
+
["f", SC_F],
|
|
265
|
+
["g", SC_G],
|
|
266
|
+
["h", SC_H],
|
|
267
|
+
["i", SC_I],
|
|
268
|
+
["j", SC_J],
|
|
269
|
+
["k", SC_K],
|
|
270
|
+
["l", SC_L],
|
|
271
|
+
["m", SC_M],
|
|
272
|
+
["n", SC_N],
|
|
273
|
+
["o", SC_O],
|
|
274
|
+
["p", SC_P],
|
|
275
|
+
["q", SC_Q],
|
|
276
|
+
["r", SC_R],
|
|
277
|
+
["s", SC_S],
|
|
278
|
+
["t", SC_T],
|
|
279
|
+
["u", SC_U],
|
|
280
|
+
["v", SC_V],
|
|
281
|
+
["w", SC_W],
|
|
282
|
+
["x", SC_X],
|
|
283
|
+
["y", SC_Y],
|
|
284
|
+
["z", SC_Z],
|
|
285
|
+
])
|
|
286
|
+
|
|
287
|
+
const DIGIT_SC: ReadonlyMap<string, number> = new Map<string, number>([
|
|
288
|
+
["0", SC_0],
|
|
289
|
+
["1", SC_1],
|
|
290
|
+
["2", SC_2],
|
|
291
|
+
["3", SC_3],
|
|
292
|
+
["4", SC_4],
|
|
293
|
+
["5", SC_5],
|
|
294
|
+
["6", SC_6],
|
|
295
|
+
["7", SC_7],
|
|
296
|
+
["8", SC_8],
|
|
297
|
+
["9", SC_9],
|
|
298
|
+
])
|
|
299
|
+
|
|
300
|
+
const KEY_ALIASES: ReadonlyMap<string, string> = new Map([
|
|
301
|
+
["plus", "equal"],
|
|
302
|
+
["minus", "minus"],
|
|
303
|
+
["equal", "equal"],
|
|
304
|
+
["comma", "comma"],
|
|
305
|
+
["period", "period"],
|
|
306
|
+
])
|
|
307
|
+
|
|
308
|
+
const keyToScancode = (key: string): number | null => {
|
|
309
|
+
const normalized = KEY_ALIASES.get(key) ?? key
|
|
310
|
+
const fromNamed = namedKeyToScancode(normalized)
|
|
311
|
+
if (fromNamed !== null) return fromNamed
|
|
312
|
+
const fromLetter = LETTER_SC.get(normalized)
|
|
313
|
+
if (fromLetter !== undefined) return fromLetter
|
|
314
|
+
const fromDigit = DIGIT_SC.get(normalized)
|
|
315
|
+
if (fromDigit !== undefined) return fromDigit
|
|
316
|
+
return null
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const probeTool = async (
|
|
320
|
+
executor: CommandExecutor,
|
|
321
|
+
tool: Tool,
|
|
322
|
+
extraFsProbe?: (tool: string) => boolean,
|
|
323
|
+
): Promise<boolean> => {
|
|
324
|
+
const result = await executor.run("which", [tool])
|
|
325
|
+
if (result.exitCode === 0 && result.stdout.trim().length > 0) return true
|
|
326
|
+
// ponytail: fallback when CLI is launched with a stripped PATH (systemd,
|
|
327
|
+
// launchd, IDE runners) and `which` returns nothing even though ydotool is
|
|
328
|
+
// installed at e.g. /usr/local/bin. Mirror of the requirements.ts probe.
|
|
329
|
+
return extraFsProbe?.(tool) === true
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const shellQuote = (value: string): string =>
|
|
333
|
+
`'${value.replace(/'/g, "'\\''")}'`
|
|
334
|
+
|
|
335
|
+
const YDOTOOL_CTRL_V_ARGS: string[] = [
|
|
336
|
+
"key",
|
|
337
|
+
`${SC_LEFTCTRL}:1`,
|
|
338
|
+
`${SC_V}:1`,
|
|
339
|
+
`${SC_V}:0`,
|
|
340
|
+
`${SC_LEFTCTRL}:0`,
|
|
341
|
+
]
|
|
342
|
+
|
|
343
|
+
const SHIFT_NEEDED_KEYS = new Set(["plus", "minus"])
|
|
344
|
+
|
|
345
|
+
const buildYdotoolComboArgs = (input: string): string[] | null => {
|
|
346
|
+
const parsed = parseCombo(input)
|
|
347
|
+
if (parsed === null) return null
|
|
348
|
+
|
|
349
|
+
const seenSc = new Set<number>()
|
|
350
|
+
const orderedMods: number[] = []
|
|
351
|
+
for (const mod of MOD_ORDER) {
|
|
352
|
+
if (!parsed.mods.includes(mod)) continue
|
|
353
|
+
const sc = modToScancode(mod)
|
|
354
|
+
if (sc === null) {
|
|
355
|
+
throw new ProviderError(
|
|
356
|
+
"EXEC_FAILED",
|
|
357
|
+
`ydotool: cannot map modifier '${mod}' to scancode`,
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
if (seenSc.has(sc)) continue
|
|
361
|
+
seenSc.add(sc)
|
|
362
|
+
orderedMods.push(sc)
|
|
363
|
+
}
|
|
364
|
+
for (const mod of parsed.mods) {
|
|
365
|
+
const sc = modToScancode(mod)
|
|
366
|
+
if (sc === null) {
|
|
367
|
+
throw new ProviderError(
|
|
368
|
+
"EXEC_FAILED",
|
|
369
|
+
`ydotool: cannot map modifier '${mod}' to scancode`,
|
|
370
|
+
)
|
|
371
|
+
}
|
|
372
|
+
if (seenSc.has(sc)) continue
|
|
373
|
+
seenSc.add(sc)
|
|
374
|
+
orderedMods.push(sc)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const keySc = keyToScancode(parsed.key)
|
|
378
|
+
if (keySc === null) {
|
|
379
|
+
throw new ProviderError(
|
|
380
|
+
"EXEC_FAILED",
|
|
381
|
+
`ydotool: cannot map key '${parsed.key}' to scancode (combo keys must be alphanumeric or a named key)`,
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const needsShift =
|
|
386
|
+
SHIFT_NEEDED_KEYS.has(parsed.key) && !parsed.mods.includes("shift")
|
|
387
|
+
if (needsShift && !seenSc.has(SC_LEFTSHIFT)) {
|
|
388
|
+
seenSc.add(SC_LEFTSHIFT)
|
|
389
|
+
orderedMods.push(SC_LEFTSHIFT)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const args: string[] = ["key"]
|
|
393
|
+
for (const sc of orderedMods) args.push(`${sc}:1`)
|
|
394
|
+
args.push(`${keySc}:1`)
|
|
395
|
+
args.push(`${keySc}:0`)
|
|
396
|
+
for (let i = orderedMods.length - 1; i >= 0; i -= 1) {
|
|
397
|
+
args.push(`${orderedMods[i]}:0`)
|
|
398
|
+
}
|
|
399
|
+
return args
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const buildYdotoolLiteralArgs = (text: string): string[] => {
|
|
403
|
+
return ["type", "--", text]
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const buildYdotoolArgs = (input: string): string[] => {
|
|
407
|
+
const combo = buildYdotoolComboArgs(input)
|
|
408
|
+
if (combo !== null) return combo
|
|
409
|
+
return buildYdotoolLiteralArgs(input)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const buildWtypeComboArgs = (input: string): string[] | null => {
|
|
413
|
+
const parsed = parseCombo(input)
|
|
414
|
+
if (parsed === null) return null
|
|
415
|
+
|
|
416
|
+
const seen = new Set<string>()
|
|
417
|
+
const orderedMods: string[] = []
|
|
418
|
+
for (const mod of MOD_ORDER) {
|
|
419
|
+
if (parsed.mods.includes(mod) && !seen.has(mod)) {
|
|
420
|
+
let wtype = mod
|
|
421
|
+
if (mod === "meta" || mod === "hyper") wtype = "super"
|
|
422
|
+
seen.add(mod)
|
|
423
|
+
orderedMods.push(wtype)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
for (const mod of parsed.mods) {
|
|
427
|
+
if (seen.has(mod)) continue
|
|
428
|
+
let wtype = mod
|
|
429
|
+
if (mod === "meta" || mod === "hyper") wtype = "super"
|
|
430
|
+
seen.add(mod)
|
|
431
|
+
orderedMods.push(wtype)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const args: string[] = []
|
|
435
|
+
for (const m of orderedMods) args.push("-M", m)
|
|
436
|
+
args.push("-k", parsed.key)
|
|
437
|
+
for (let i = orderedMods.length - 1; i >= 0; i -= 1) {
|
|
438
|
+
args.push("-m", orderedMods[i]!)
|
|
439
|
+
}
|
|
440
|
+
return args
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const buildWtypeLiteralArgs = (text: string): string[] => {
|
|
444
|
+
return [shellQuote(text)]
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const buildWtypeArgs = (input: string): string[] => {
|
|
448
|
+
const combo = buildWtypeComboArgs(input)
|
|
449
|
+
if (combo !== null) return combo
|
|
450
|
+
return buildWtypeLiteralArgs(input)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const isPureAscii = (text: string): boolean => /^[\x20-\x7E]*$/.test(text)
|
|
454
|
+
|
|
455
|
+
const sleep = (ms: number): Promise<void> =>
|
|
456
|
+
new Promise((resolve) => setTimeout(resolve, ms))
|
|
457
|
+
|
|
458
|
+
const runYdotool = async (
|
|
459
|
+
args: string[],
|
|
460
|
+
deps: LinuxKeyMacroDeps,
|
|
461
|
+
): Promise<void> => {
|
|
462
|
+
const baseTimeoutMs = deps.timeoutMs ?? 500
|
|
463
|
+
try {
|
|
464
|
+
const result = await withTimeout(
|
|
465
|
+
deps.executor.run(YDOTOOL_TOOL, args),
|
|
466
|
+
baseTimeoutMs + 2500,
|
|
467
|
+
)
|
|
468
|
+
if (result.exitCode !== 0) {
|
|
469
|
+
throw new ProviderError(
|
|
470
|
+
"EXEC_FAILED",
|
|
471
|
+
`${YDOTOOL_TOOL} ${args.join(" ")} exited with code ${result.exitCode}: ${result.stderr.trim()}`,
|
|
472
|
+
)
|
|
473
|
+
}
|
|
474
|
+
} catch (err) {
|
|
475
|
+
if (err instanceof ProviderError) throw err
|
|
476
|
+
throw new ProviderError(
|
|
477
|
+
"EXEC_FAILED",
|
|
478
|
+
`${YDOTOOL_TOOL} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
479
|
+
)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const runWtype = async (
|
|
484
|
+
args: string[],
|
|
485
|
+
deps: LinuxKeyMacroDeps,
|
|
486
|
+
): Promise<void> => {
|
|
487
|
+
const baseTimeoutMs = deps.timeoutMs ?? 500
|
|
488
|
+
try {
|
|
489
|
+
const result = await withTimeout(
|
|
490
|
+
deps.executor.run(WTYPE_TOOL, args),
|
|
491
|
+
baseTimeoutMs + 2500,
|
|
492
|
+
)
|
|
493
|
+
if (result.exitCode !== 0) {
|
|
494
|
+
throw new ProviderError(
|
|
495
|
+
"EXEC_FAILED",
|
|
496
|
+
`${WTYPE_TOOL} ${args.join(" ")} exited with code ${result.exitCode}: ${result.stderr.trim()}`,
|
|
497
|
+
)
|
|
498
|
+
}
|
|
499
|
+
} catch (err) {
|
|
500
|
+
if (err instanceof ProviderError) throw err
|
|
501
|
+
throw new ProviderError(
|
|
502
|
+
"EXEC_FAILED",
|
|
503
|
+
`${WTYPE_TOOL} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
504
|
+
)
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const sendKeyWtype = async (
|
|
509
|
+
input: string,
|
|
510
|
+
deps: LinuxKeyMacroDeps,
|
|
511
|
+
): Promise<void> => {
|
|
512
|
+
await runWtype(buildWtypeArgs(input), deps)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const sendKeyYdotool = async (
|
|
516
|
+
input: string,
|
|
517
|
+
deps: LinuxKeyMacroDeps,
|
|
518
|
+
clipboardProvider: ClipboardProvider | undefined,
|
|
519
|
+
): Promise<void> => {
|
|
520
|
+
const parsed = parseCombo(input)
|
|
521
|
+
if (parsed !== null) {
|
|
522
|
+
await runYdotool(buildYdotoolComboArgs(input)!, deps)
|
|
523
|
+
return
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (isPureAscii(input)) {
|
|
527
|
+
await runYdotool(buildYdotoolLiteralArgs(input), deps)
|
|
528
|
+
return
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (clipboardProvider === undefined) {
|
|
532
|
+
throw new ProviderError(
|
|
533
|
+
"NOT_AVAILABLE",
|
|
534
|
+
"non-ASCII text (e.g. emoji) on Linux needs wl-copy on PATH — install the wl-clipboard package",
|
|
535
|
+
)
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const totalStart = Date.now()
|
|
539
|
+
deps.logger.info(
|
|
540
|
+
{
|
|
541
|
+
step: "keyMacro.nonAscii.start",
|
|
542
|
+
textPreview: input.slice(0, 24),
|
|
543
|
+
},
|
|
544
|
+
"keyMacro: typing non-ASCII via clipboard+ctrl+v",
|
|
545
|
+
)
|
|
546
|
+
const writeStart = Date.now()
|
|
547
|
+
await clipboardProvider.writeText(input)
|
|
548
|
+
deps.logger.info(
|
|
549
|
+
{
|
|
550
|
+
step: "keyMacro.nonAscii.afterWrite",
|
|
551
|
+
writeElapsedMs: Date.now() - writeStart,
|
|
552
|
+
},
|
|
553
|
+
"keyMacro: clipboard writeText done",
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
deps.logger.info(
|
|
557
|
+
{ step: "keyMacro.nonAscii.preDelay", ms: YDOTOOL_CLIPBOARD_PRE_DELAY_MS },
|
|
558
|
+
"keyMacro: pre-keystroke delay",
|
|
559
|
+
)
|
|
560
|
+
await sleep(YDOTOOL_CLIPBOARD_PRE_DELAY_MS)
|
|
561
|
+
|
|
562
|
+
const keystrokeStart = Date.now()
|
|
563
|
+
await runYdotool(YDOTOOL_CTRL_V_ARGS, deps)
|
|
564
|
+
deps.logger.info(
|
|
565
|
+
{
|
|
566
|
+
step: "keyMacro.nonAscii.afterKeystroke",
|
|
567
|
+
keystrokeElapsedMs: Date.now() - keystrokeStart,
|
|
568
|
+
totalElapsedMs: Date.now() - totalStart,
|
|
569
|
+
},
|
|
570
|
+
"keyMacro: ctrl+v keystroke done",
|
|
571
|
+
)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export const createLinuxKeyMacroProvider = async (
|
|
575
|
+
deps: LinuxKeyMacroDeps,
|
|
576
|
+
): Promise<KeyMacroProvider> => {
|
|
577
|
+
const ydotoolOk = await probeTool(
|
|
578
|
+
deps.executor,
|
|
579
|
+
YDOTOOL_TOOL,
|
|
580
|
+
deps.extraFsProbe,
|
|
581
|
+
)
|
|
582
|
+
const wtypeOk =
|
|
583
|
+
!ydotoolOk &&
|
|
584
|
+
(await probeTool(deps.executor, WTYPE_TOOL, deps.extraFsProbe))
|
|
585
|
+
|
|
586
|
+
if (!ydotoolOk && !wtypeOk) {
|
|
587
|
+
deps.logger.warn(
|
|
588
|
+
{},
|
|
589
|
+
"no key-macro tool found (need ydotool or wtype on PATH); key-macro will throw ProviderError",
|
|
590
|
+
)
|
|
591
|
+
return {
|
|
592
|
+
async sendKey(_input: string) {
|
|
593
|
+
throw new ProviderError(
|
|
594
|
+
"NOT_AVAILABLE",
|
|
595
|
+
"no key-macro tool found on PATH (need ydotool or wtype)",
|
|
596
|
+
)
|
|
597
|
+
},
|
|
598
|
+
async stop() {
|
|
599
|
+
return
|
|
600
|
+
},
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const tool: Tool = ydotoolOk ? YDOTOOL_TOOL : WTYPE_TOOL
|
|
605
|
+
deps.logger.info({ tool }, "Linux key-macro tool selected")
|
|
606
|
+
|
|
607
|
+
let clipboardProvider: ClipboardProvider | undefined
|
|
608
|
+
if (tool === YDOTOOL_TOOL) {
|
|
609
|
+
try {
|
|
610
|
+
clipboardProvider = createClipboardProvider({
|
|
611
|
+
// ponytail: createClipboardProvider defaults to process.platform, so
|
|
612
|
+
// the LINUX key-macro provider was handing itself a darwin clipboard
|
|
613
|
+
// (pbcopy) whenever it ran on a Mac. The per-OS providers are chosen
|
|
614
|
+
// by the caller everywhere else; pin it here too rather than letting
|
|
615
|
+
// the host OS decide what a linux provider does.
|
|
616
|
+
platform: "linux",
|
|
617
|
+
executor: deps.executor,
|
|
618
|
+
env: deps.env,
|
|
619
|
+
logger: deps.logger,
|
|
620
|
+
...(deps.extraFsProbe !== undefined
|
|
621
|
+
? { extraFsProbe: deps.extraFsProbe }
|
|
622
|
+
: {}),
|
|
623
|
+
})
|
|
624
|
+
} catch (err) {
|
|
625
|
+
deps.logger.warn(
|
|
626
|
+
{ err },
|
|
627
|
+
"linux clipboard provider unavailable; non-ASCII typing will throw",
|
|
628
|
+
)
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (tool === YDOTOOL_TOOL) {
|
|
633
|
+
return {
|
|
634
|
+
async sendKey(input: string) {
|
|
635
|
+
await sendKeyYdotool(input, deps, clipboardProvider)
|
|
636
|
+
},
|
|
637
|
+
async stop() {
|
|
638
|
+
return
|
|
639
|
+
},
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return {
|
|
644
|
+
async sendKey(input: string) {
|
|
645
|
+
await sendKeyWtype(input, deps)
|
|
646
|
+
},
|
|
647
|
+
async stop() {
|
|
648
|
+
return
|
|
649
|
+
},
|
|
650
|
+
}
|
|
651
|
+
}
|