@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,97 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
logNull,
|
|
5
|
+
noopUnsubscribe,
|
|
6
|
+
type CommandExecutor,
|
|
7
|
+
type LinuxDbusBus,
|
|
8
|
+
} from "./shared"
|
|
9
|
+
|
|
10
|
+
export interface ActiveAppSnapshot {
|
|
11
|
+
name: string
|
|
12
|
+
windowTitle: string | null
|
|
13
|
+
processId: number | null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ActiveAppProvider {
|
|
17
|
+
getActive(): Promise<ActiveAppSnapshot | null>
|
|
18
|
+
subscribe(handler: (snapshot: ActiveAppSnapshot | null) => void): () => void
|
|
19
|
+
stop(): Promise<void>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const createNullActiveAppProvider = (
|
|
23
|
+
reason: string,
|
|
24
|
+
logger?: pino.Logger,
|
|
25
|
+
): ActiveAppProvider => {
|
|
26
|
+
logNull(logger, "active-app", reason)
|
|
27
|
+
return {
|
|
28
|
+
async getActive() {
|
|
29
|
+
return null
|
|
30
|
+
},
|
|
31
|
+
subscribe() {
|
|
32
|
+
return noopUnsubscribe
|
|
33
|
+
},
|
|
34
|
+
async stop() {
|
|
35
|
+
return
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface CreateActiveAppProviderOptions {
|
|
41
|
+
readonly platform?: NodeJS.Platform
|
|
42
|
+
readonly executor?: CommandExecutor
|
|
43
|
+
readonly dbus?: LinuxDbusBus
|
|
44
|
+
readonly logger: pino.Logger
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const createActiveAppProvider = async (
|
|
48
|
+
options: CreateActiveAppProviderOptions,
|
|
49
|
+
): Promise<ActiveAppProvider> => {
|
|
50
|
+
const platform = options.platform ?? process.platform
|
|
51
|
+
if (platform === "linux") {
|
|
52
|
+
if (options.executor === undefined) {
|
|
53
|
+
return createNullActiveAppProvider(
|
|
54
|
+
"executor-not-injected",
|
|
55
|
+
options.logger,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
const { createLinuxActiveAppProvider } = await import("./active-app/linux")
|
|
59
|
+
return createLinuxActiveAppProvider({
|
|
60
|
+
executor: options.executor,
|
|
61
|
+
...(options.dbus !== undefined ? { dbus: options.dbus } : {}),
|
|
62
|
+
logger: options.logger,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
if (platform === "darwin") {
|
|
66
|
+
if (options.executor === undefined) {
|
|
67
|
+
return createNullActiveAppProvider(
|
|
68
|
+
"executor-not-injected",
|
|
69
|
+
options.logger,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
const { createDarwinActiveAppProvider } =
|
|
73
|
+
await import("./active-app/darwin")
|
|
74
|
+
return createDarwinActiveAppProvider({
|
|
75
|
+
executor: options.executor,
|
|
76
|
+
logger: options.logger,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
if (platform === "win32") {
|
|
80
|
+
if (options.executor === undefined) {
|
|
81
|
+
return createNullActiveAppProvider(
|
|
82
|
+
"executor-not-injected",
|
|
83
|
+
options.logger,
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
const { createWindowsActiveAppProvider } =
|
|
87
|
+
await import("./active-app/windows")
|
|
88
|
+
return createWindowsActiveAppProvider({
|
|
89
|
+
executor: options.executor,
|
|
90
|
+
logger: options.logger,
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
return createNullActiveAppProvider(
|
|
94
|
+
`platform:${platform}-pending`,
|
|
95
|
+
options.logger,
|
|
96
|
+
)
|
|
97
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import type { ClipboardProvider } from "../clipboard"
|
|
4
|
+
import { ProviderError } from "../error"
|
|
5
|
+
import type { CommandExecutor } from "../shared"
|
|
6
|
+
import { withTimeout } from "../shared"
|
|
7
|
+
|
|
8
|
+
export interface CreateDarwinClipboardProviderOptions {
|
|
9
|
+
readonly executor: CommandExecutor
|
|
10
|
+
readonly logger: pino.Logger
|
|
11
|
+
readonly timeoutMs?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const createDarwinClipboardProvider = (
|
|
15
|
+
options: CreateDarwinClipboardProviderOptions,
|
|
16
|
+
): ClipboardProvider => {
|
|
17
|
+
const { executor, logger, timeoutMs: timeoutMsOption } = options
|
|
18
|
+
const timeoutMs = timeoutMsOption ?? 500
|
|
19
|
+
let disposed = false
|
|
20
|
+
const stop = async (): Promise<void> => {
|
|
21
|
+
disposed = true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const writeText = async (text: string): Promise<void> => {
|
|
25
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
26
|
+
const escaped = text.replace(/'/g, "'\\''")
|
|
27
|
+
try {
|
|
28
|
+
const result = await withTimeout(
|
|
29
|
+
executor.run("sh", ["-c", `printf '%s' '${escaped}' | pbcopy`], {
|
|
30
|
+
timeoutMs,
|
|
31
|
+
}),
|
|
32
|
+
timeoutMs + 500,
|
|
33
|
+
)
|
|
34
|
+
if (result.exitCode !== 0) {
|
|
35
|
+
logger.warn({ stderr: result.stderr }, "clipboard: pbcopy failed")
|
|
36
|
+
throw new ProviderError(
|
|
37
|
+
"EXEC_FAILED",
|
|
38
|
+
`clipboard write failed: ${result.stderr || "unknown error"}`,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof ProviderError) throw err
|
|
43
|
+
throw new ProviderError(
|
|
44
|
+
"EXEC_FAILED",
|
|
45
|
+
`clipboard write failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const readText = async (): Promise<string> => {
|
|
51
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
52
|
+
try {
|
|
53
|
+
const result = await withTimeout(
|
|
54
|
+
executor.run("pbpaste", [], { timeoutMs }),
|
|
55
|
+
timeoutMs + 500,
|
|
56
|
+
)
|
|
57
|
+
if (result.exitCode === 0) return result.stdout
|
|
58
|
+
} catch {
|
|
59
|
+
// ignore
|
|
60
|
+
}
|
|
61
|
+
return ""
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return { writeText, readText, stop }
|
|
65
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import type { ClipboardProvider } from "../clipboard"
|
|
4
|
+
import { ProviderError } from "../error"
|
|
5
|
+
import type { CommandExecutor } from "../shared"
|
|
6
|
+
import { withTimeout } from "../shared"
|
|
7
|
+
|
|
8
|
+
export interface CreateLinuxClipboardProviderOptions {
|
|
9
|
+
readonly executor: CommandExecutor
|
|
10
|
+
readonly env?: Readonly<Record<string, string>>
|
|
11
|
+
readonly logger: pino.Logger
|
|
12
|
+
readonly timeoutMs?: number
|
|
13
|
+
readonly extraFsProbe?: (tool: string) => boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const WL_COPY_TOOL = "wl-copy"
|
|
17
|
+
const WL_PASTE_TOOL = "wl-paste"
|
|
18
|
+
const XCLIP_TOOL = "xclip"
|
|
19
|
+
const XSEL_TOOL = "xsel"
|
|
20
|
+
|
|
21
|
+
const probeTool = async (
|
|
22
|
+
executor: CommandExecutor,
|
|
23
|
+
tool: string,
|
|
24
|
+
extraFsProbe?: (tool: string) => boolean,
|
|
25
|
+
): Promise<boolean> => {
|
|
26
|
+
const result = await executor.run("which", [tool])
|
|
27
|
+
if (result.exitCode === 0 && result.stdout.trim().length > 0) return true
|
|
28
|
+
// ponytail: fallback when CLI is launched with a stripped PATH (systemd,
|
|
29
|
+
// launchd, IDE runners) and `which` returns nothing even though wl-copy
|
|
30
|
+
// is installed at e.g. /usr/bin. Mirror of the requirements.ts probe and
|
|
31
|
+
// key-macro/linux.ts probeTool.
|
|
32
|
+
return extraFsProbe?.(tool) === true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const shellQuote = (value: string): string =>
|
|
36
|
+
`'${value.replace(/'/g, "'\\''")}'`
|
|
37
|
+
|
|
38
|
+
export const createLinuxClipboardProvider = (
|
|
39
|
+
options: CreateLinuxClipboardProviderOptions,
|
|
40
|
+
): ClipboardProvider => {
|
|
41
|
+
const { executor, logger, timeoutMs: timeoutMsOption } = options
|
|
42
|
+
const timeoutMs = timeoutMsOption ?? 500
|
|
43
|
+
const isX11 =
|
|
44
|
+
options.env?.["WAYLAND_DISPLAY"] === undefined &&
|
|
45
|
+
options.env?.["DISPLAY"] !== undefined
|
|
46
|
+
const tools = isX11 ? [XCLIP_TOOL, XSEL_TOOL] : [WL_COPY_TOOL]
|
|
47
|
+
let selectedTool = tools[0]!
|
|
48
|
+
let disposed = false
|
|
49
|
+
|
|
50
|
+
const stop = async (): Promise<void> => {
|
|
51
|
+
disposed = true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const writeText = async (text: string): Promise<void> => {
|
|
55
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
56
|
+
// ponytail: `-o` (paste-once) makes wl-copy exit after the next paste, so
|
|
57
|
+
// the surrounding `sh -c` pipeline does not wait on a long-lived wl-copy.
|
|
58
|
+
// The runtime's spawn() already drains stdio on 'exit', but the shell
|
|
59
|
+
// here waits for every child in the pipeline — without `-o`, wl-copy
|
|
60
|
+
// stays alive maintaining clipboard ownership and the pipe never closes.
|
|
61
|
+
const command = isX11
|
|
62
|
+
? selectedTool === XSEL_TOOL
|
|
63
|
+
? `printf '%s' ${shellQuote(text)} | ${XSEL_TOOL} --clipboard --input`
|
|
64
|
+
: `printf '%s' ${shellQuote(text)} | ${XCLIP_TOOL} -selection clipboard`
|
|
65
|
+
: `printf '%s' ${shellQuote(text)} | ${WL_COPY_TOOL} -o`
|
|
66
|
+
const startedAt = Date.now()
|
|
67
|
+
logger.info(
|
|
68
|
+
{ step: "clipboard.writeText", command, textPreview: text.slice(0, 24) },
|
|
69
|
+
"clipboard: invoking tool",
|
|
70
|
+
)
|
|
71
|
+
const result = await withTimeout(
|
|
72
|
+
executor.run("sh", ["-c", command]),
|
|
73
|
+
timeoutMs + 2500,
|
|
74
|
+
)
|
|
75
|
+
logger.info(
|
|
76
|
+
{
|
|
77
|
+
step: "clipboard.writeText",
|
|
78
|
+
exitCode: result.exitCode,
|
|
79
|
+
stderr: result.stderr.trim(),
|
|
80
|
+
elapsedMs: Date.now() - startedAt,
|
|
81
|
+
},
|
|
82
|
+
"clipboard: tool returned",
|
|
83
|
+
)
|
|
84
|
+
if (result.exitCode !== 0) {
|
|
85
|
+
logger.warn({ stderr: result.stderr.trim() }, "clipboard: write failed")
|
|
86
|
+
throw new ProviderError(
|
|
87
|
+
"EXEC_FAILED",
|
|
88
|
+
`clipboard write failed with ${tools.join(" or ")}: ${result.stderr.trim() || "unknown error"}`,
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const readText = async (): Promise<string> => {
|
|
94
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
95
|
+
try {
|
|
96
|
+
if (!(await ensureProbed())) return ""
|
|
97
|
+
const startedAt = Date.now()
|
|
98
|
+
const result = await withTimeout(
|
|
99
|
+
isX11
|
|
100
|
+
? selectedTool === XSEL_TOOL
|
|
101
|
+
? executor.run(XSEL_TOOL, ["--clipboard", "--output"])
|
|
102
|
+
: executor.run(XCLIP_TOOL, ["-selection", "clipboard", "-out"])
|
|
103
|
+
: executor.run(WL_PASTE_TOOL, []),
|
|
104
|
+
timeoutMs + 2500,
|
|
105
|
+
)
|
|
106
|
+
logger.info(
|
|
107
|
+
{
|
|
108
|
+
step: "clipboard.readText",
|
|
109
|
+
exitCode: result.exitCode,
|
|
110
|
+
stdoutPreview: result.stdout.slice(0, 32),
|
|
111
|
+
elapsedMs: Date.now() - startedAt,
|
|
112
|
+
},
|
|
113
|
+
"clipboard: wl-paste returned",
|
|
114
|
+
)
|
|
115
|
+
if (result.exitCode !== 0) return ""
|
|
116
|
+
return result.stdout
|
|
117
|
+
} catch {
|
|
118
|
+
return ""
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let _probeDone = false
|
|
123
|
+
let _probeOk = false
|
|
124
|
+
const ensureProbed = async (): Promise<boolean> => {
|
|
125
|
+
if (_probeDone) return _probeOk
|
|
126
|
+
_probeOk = false
|
|
127
|
+
for (const tool of tools) {
|
|
128
|
+
if (await probeTool(executor, tool, options.extraFsProbe)) {
|
|
129
|
+
selectedTool = tool
|
|
130
|
+
_probeOk = true
|
|
131
|
+
break
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
_probeDone = true
|
|
135
|
+
if (!_probeOk) {
|
|
136
|
+
logger.warn(
|
|
137
|
+
{ tools },
|
|
138
|
+
"clipboard tool not found on PATH; clipboard will throw ProviderError",
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
return _probeOk
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Eager probe so a missing tool surfaces at init time.
|
|
145
|
+
void ensureProbed()
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
writeText: async (text: string) => {
|
|
149
|
+
const ok = await ensureProbed()
|
|
150
|
+
if (!ok) {
|
|
151
|
+
throw new ProviderError(
|
|
152
|
+
"NOT_AVAILABLE",
|
|
153
|
+
isX11
|
|
154
|
+
? "none of xclip or xsel found on PATH"
|
|
155
|
+
: "wl-copy not found on PATH; install the wl-clipboard package",
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
await writeText(text)
|
|
159
|
+
},
|
|
160
|
+
readText,
|
|
161
|
+
stop,
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import type { ClipboardProvider } from "../clipboard"
|
|
4
|
+
import { ProviderError } from "../error"
|
|
5
|
+
import type { CommandExecutor } from "../shared"
|
|
6
|
+
import { withTimeout } from "../shared"
|
|
7
|
+
|
|
8
|
+
export interface CreateWindowsClipboardProviderOptions {
|
|
9
|
+
readonly executor: CommandExecutor
|
|
10
|
+
readonly logger: pino.Logger
|
|
11
|
+
readonly timeoutMs?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const encodePSCommand = (script: string): string => {
|
|
15
|
+
const buf = Buffer.from(script, "utf16le")
|
|
16
|
+
return buf.toString("base64")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const escapeForPowerShellSingleQuote = (s: string): string =>
|
|
20
|
+
s.replace(/'/g, "''")
|
|
21
|
+
|
|
22
|
+
const escapeForDoubleQuote = (s: string): string =>
|
|
23
|
+
s.replace(/[\\"$`]/g, "``$&")
|
|
24
|
+
|
|
25
|
+
export const createWindowsClipboardProvider = (
|
|
26
|
+
options: CreateWindowsClipboardProviderOptions,
|
|
27
|
+
): ClipboardProvider => {
|
|
28
|
+
const { executor, logger, timeoutMs: timeoutMsOption } = options
|
|
29
|
+
const timeoutMs = timeoutMsOption ?? 500
|
|
30
|
+
let disposed = false
|
|
31
|
+
const stop = async (): Promise<void> => {
|
|
32
|
+
disposed = true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const runPS = async (script: string): Promise<string> => {
|
|
36
|
+
const result = await withTimeout(
|
|
37
|
+
executor.run("powershell", ["-NoProfile", "-Command", script], {
|
|
38
|
+
timeoutMs,
|
|
39
|
+
}),
|
|
40
|
+
timeoutMs + 500,
|
|
41
|
+
)
|
|
42
|
+
if (result.exitCode !== 0) {
|
|
43
|
+
logger.warn({ stderr: result.stderr }, "clipboard: powershell failed")
|
|
44
|
+
throw new ProviderError(
|
|
45
|
+
"EXEC_FAILED",
|
|
46
|
+
`clipboard write failed: ${result.stderr.trim() || "unknown error"}`,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
return result.stdout
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const writeText = async (text: string): Promise<void> => {
|
|
53
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
54
|
+
// ponytail: -EncodedCommand avoids shell/interpolation entirely. The text
|
|
55
|
+
// is embedded inside a base64 UTF-16LE blob PowerShell parses as a script.
|
|
56
|
+
const escaped = escapeForDoubleQuote(text)
|
|
57
|
+
const psValue = `'${escapeForPowerShellSingleQuote(escaped)}'`
|
|
58
|
+
const script = `Set-Clipboard -Value ${psValue}`
|
|
59
|
+
const encoded = encodePSCommand(script)
|
|
60
|
+
const result = await withTimeout(
|
|
61
|
+
executor.run("powershell", ["-NoProfile", "-EncodedCommand", encoded], {
|
|
62
|
+
timeoutMs,
|
|
63
|
+
}),
|
|
64
|
+
timeoutMs + 500,
|
|
65
|
+
)
|
|
66
|
+
if (result.exitCode !== 0) {
|
|
67
|
+
logger.warn({ stderr: result.stderr }, "clipboard: powershell failed")
|
|
68
|
+
throw new ProviderError(
|
|
69
|
+
"EXEC_FAILED",
|
|
70
|
+
`clipboard write failed: ${result.stderr.trim() || "unknown error"}`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const readText = async (): Promise<string> => {
|
|
76
|
+
if (disposed) throw new Error("Clipboard provider is disposed")
|
|
77
|
+
try {
|
|
78
|
+
const result = await withTimeout(
|
|
79
|
+
executor.run(
|
|
80
|
+
"powershell",
|
|
81
|
+
["-NoProfile", "-Command", "Get-Clipboard"],
|
|
82
|
+
{ timeoutMs },
|
|
83
|
+
),
|
|
84
|
+
timeoutMs + 500,
|
|
85
|
+
)
|
|
86
|
+
if (result.exitCode === 0) return result.stdout
|
|
87
|
+
} catch {
|
|
88
|
+
// ignore
|
|
89
|
+
}
|
|
90
|
+
return ""
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { writeText, readText, stop }
|
|
94
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type pino from "pino"
|
|
2
|
+
|
|
3
|
+
import { ProviderError } from "./error"
|
|
4
|
+
|
|
5
|
+
import { createDarwinClipboardProvider } from "./clipboard/darwin"
|
|
6
|
+
import { createLinuxClipboardProvider } from "./clipboard/linux"
|
|
7
|
+
import { createWindowsClipboardProvider } from "./clipboard/windows"
|
|
8
|
+
import { type CommandExecutor } from "./shared"
|
|
9
|
+
|
|
10
|
+
export interface ClipboardProvider {
|
|
11
|
+
writeText(text: string): Promise<void>
|
|
12
|
+
readText(): Promise<string>
|
|
13
|
+
stop(): Promise<void>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const createNullClipboardProvider = (
|
|
17
|
+
logger?: pino.Logger,
|
|
18
|
+
): ClipboardProvider => {
|
|
19
|
+
if (logger) {
|
|
20
|
+
logger.warn(
|
|
21
|
+
{ provider: "clipboard" },
|
|
22
|
+
"OS clipboard provider unavailable, using null provider",
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
async writeText(_text: string): Promise<void> {
|
|
27
|
+
throw new ProviderError(
|
|
28
|
+
"NOT_AVAILABLE",
|
|
29
|
+
"Clipboard provider not available on this platform",
|
|
30
|
+
)
|
|
31
|
+
},
|
|
32
|
+
async readText(): Promise<string> {
|
|
33
|
+
throw new ProviderError(
|
|
34
|
+
"NOT_AVAILABLE",
|
|
35
|
+
"Clipboard provider not available on this platform",
|
|
36
|
+
)
|
|
37
|
+
},
|
|
38
|
+
async stop() {
|
|
39
|
+
return
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CreateClipboardProviderOptions {
|
|
45
|
+
readonly executor: CommandExecutor
|
|
46
|
+
readonly platform?: NodeJS.Platform
|
|
47
|
+
readonly env?: Readonly<Record<string, string>>
|
|
48
|
+
readonly logger: pino.Logger
|
|
49
|
+
readonly extraFsProbe?: (tool: string) => boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const createClipboardProvider = (
|
|
53
|
+
options: CreateClipboardProviderOptions,
|
|
54
|
+
): ClipboardProvider => {
|
|
55
|
+
const logger = options.logger.child({ component: "clipboard" })
|
|
56
|
+
const platform = options.platform ?? process.platform
|
|
57
|
+
if (platform === "linux") {
|
|
58
|
+
return createLinuxClipboardProvider({
|
|
59
|
+
executor: options.executor,
|
|
60
|
+
...(options.env !== undefined ? { env: options.env } : {}),
|
|
61
|
+
logger: options.logger,
|
|
62
|
+
...(options.extraFsProbe !== undefined
|
|
63
|
+
? { extraFsProbe: options.extraFsProbe }
|
|
64
|
+
: {}),
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
if (platform === "darwin") {
|
|
68
|
+
return createDarwinClipboardProvider({
|
|
69
|
+
executor: options.executor,
|
|
70
|
+
logger: options.logger,
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
if (platform === "win32") {
|
|
74
|
+
return createWindowsClipboardProvider({
|
|
75
|
+
executor: options.executor,
|
|
76
|
+
logger: options.logger,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
void createNullClipboardProvider(options.logger)
|
|
80
|
+
throw new ProviderError(
|
|
81
|
+
"UNSUPPORTED_PLATFORM",
|
|
82
|
+
`Clipboard provider not implemented for platform '${platform}' in this build`,
|
|
83
|
+
)
|
|
84
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ProviderErrorCode =
|
|
2
|
+
| "NOT_AVAILABLE"
|
|
3
|
+
| "TIMEOUT"
|
|
4
|
+
| "EXEC_FAILED"
|
|
5
|
+
| "PARSE_ERROR"
|
|
6
|
+
| "UNSUPPORTED_PLATFORM"
|
|
7
|
+
|
|
8
|
+
export class ProviderError extends Error {
|
|
9
|
+
readonly code: ProviderErrorCode
|
|
10
|
+
|
|
11
|
+
constructor(code: ProviderErrorCode, message: string) {
|
|
12
|
+
super(message)
|
|
13
|
+
this.name = "ProviderError"
|
|
14
|
+
this.code = code
|
|
15
|
+
}
|
|
16
|
+
}
|