@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,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
agentKey,
|
|
3
|
+
type Agent,
|
|
4
|
+
type AgentStatus,
|
|
5
|
+
type AgentsSnapshot,
|
|
6
|
+
type ProviderId,
|
|
7
|
+
} from "./state.js"
|
|
8
|
+
|
|
9
|
+
export const mergeSnapshot = (
|
|
10
|
+
prev: AgentsSnapshot,
|
|
11
|
+
providers: Readonly<Record<ProviderId, readonly Agent[]>>,
|
|
12
|
+
): AgentsSnapshot => {
|
|
13
|
+
const merged: Record<ProviderId, Agent[]> = {
|
|
14
|
+
opencode: [...prev.byProvider["opencode"]],
|
|
15
|
+
"claude-code": [...prev.byProvider["claude-code"]],
|
|
16
|
+
}
|
|
17
|
+
const seen = new Map<string, Agent>()
|
|
18
|
+
const attention: string[] = []
|
|
19
|
+
|
|
20
|
+
for (const id of Object.keys(providers) as ProviderId[]) {
|
|
21
|
+
const list: Agent[] = []
|
|
22
|
+
for (const a of providers[id]) {
|
|
23
|
+
const k = agentKey(a)
|
|
24
|
+
seen.set(k, a)
|
|
25
|
+
list.push(a)
|
|
26
|
+
if (a.status === "waiting_for_human" || a.status === "error") {
|
|
27
|
+
attention.push(k)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
list.sort((x, y) => y.updatedAt - x.updatedAt)
|
|
31
|
+
merged[id] = list
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
byProvider: merged,
|
|
36
|
+
attention,
|
|
37
|
+
generatedAt: Date.now(),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const diffStatus = (
|
|
42
|
+
before: AgentStatus | undefined,
|
|
43
|
+
after: AgentStatus,
|
|
44
|
+
): boolean => before !== after
|
|
45
|
+
|
|
46
|
+
const byCreatedDesc = (a: Agent, b: Agent): number => {
|
|
47
|
+
const aCreated = a.createdAt ?? 0
|
|
48
|
+
const bCreated = b.createdAt ?? 0
|
|
49
|
+
if (aCreated !== bCreated) return bCreated - aCreated
|
|
50
|
+
return b.updatedAt - a.updatedAt
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ponytail: the agents deck is materialized once at startup with a fixed
|
|
54
|
+
// number of slot tiles, so which agent fills each tile is resolved per
|
|
55
|
+
// broadcast from the live snapshot. Ordered by creation date (newest first);
|
|
56
|
+
// state is conveyed by the tile's color instead of ordering.
|
|
57
|
+
export const listAgents = (snapshot: AgentsSnapshot): readonly Agent[] =>
|
|
58
|
+
[
|
|
59
|
+
...snapshot.byProvider["opencode"],
|
|
60
|
+
...snapshot.byProvider["claude-code"],
|
|
61
|
+
].sort(byCreatedDesc)
|
|
62
|
+
|
|
63
|
+
export const agentAtSlot = (
|
|
64
|
+
snapshot: AgentsSnapshot,
|
|
65
|
+
slot: number,
|
|
66
|
+
): Agent | undefined => listAgents(snapshot)[slot]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type AgentStatus =
|
|
2
|
+
| "idle"
|
|
3
|
+
| "running"
|
|
4
|
+
| "waiting"
|
|
5
|
+
| "waiting_for_human"
|
|
6
|
+
| "error"
|
|
7
|
+
| "compacting"
|
|
8
|
+
|
|
9
|
+
export type ProviderId = "opencode" | "claude-code"
|
|
10
|
+
|
|
11
|
+
export interface Agent {
|
|
12
|
+
readonly sessionId: string
|
|
13
|
+
readonly instanceId?: string
|
|
14
|
+
readonly pid?: number
|
|
15
|
+
readonly providerId: ProviderId
|
|
16
|
+
readonly title: string
|
|
17
|
+
readonly status: AgentStatus
|
|
18
|
+
readonly directory?: string
|
|
19
|
+
readonly cost?: number
|
|
20
|
+
readonly contextTokens?: number
|
|
21
|
+
readonly contextPercent?: number
|
|
22
|
+
readonly createdAt?: number
|
|
23
|
+
readonly updatedAt: number
|
|
24
|
+
readonly lastMessagePreview?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AgentsSnapshot {
|
|
28
|
+
readonly byProvider: Readonly<Record<ProviderId, readonly Agent[]>>
|
|
29
|
+
readonly attention: readonly string[]
|
|
30
|
+
readonly generatedAt: number
|
|
31
|
+
// ponytail: provider logo asset ids (asset://...) registered daemon-side so
|
|
32
|
+
// the frontend can render small `<Icon>` logos on tiles in dev AND real mode.
|
|
33
|
+
readonly icons?: Readonly<Partial<Record<ProviderId, string>>>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const CHANNEL = "coding-agents:agents" as const
|
|
37
|
+
|
|
38
|
+
export const KNOWN_PROVIDERS: readonly ProviderId[] = [
|
|
39
|
+
"opencode",
|
|
40
|
+
"claude-code",
|
|
41
|
+
] as const
|
|
42
|
+
|
|
43
|
+
export const notifiableStatus = (s: AgentStatus): boolean =>
|
|
44
|
+
s === "waiting_for_human" || s === "error"
|
|
45
|
+
|
|
46
|
+
export const agentKey = (
|
|
47
|
+
a: Pick<Agent, "providerId" | "sessionId" | "instanceId">,
|
|
48
|
+
): string => `${a.providerId}:${a.instanceId ?? a.sessionId}`
|
|
49
|
+
|
|
50
|
+
export const EMPTY_SNAPSHOT: AgentsSnapshot = {
|
|
51
|
+
byProvider: { opencode: [], "claude-code": [] },
|
|
52
|
+
attention: [],
|
|
53
|
+
generatedAt: 0,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface CoreMethods {
|
|
57
|
+
notify(args: { title: string; body: string; sound?: boolean }): Promise<void>
|
|
58
|
+
runCommand(
|
|
59
|
+
command: string,
|
|
60
|
+
options?: { timeoutMs?: number },
|
|
61
|
+
): Promise<unknown>
|
|
62
|
+
navigateToDeck(args: { id: string; addToHistory?: boolean }): void
|
|
63
|
+
goBack(): void
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface AgentProvider {
|
|
67
|
+
readonly id: ProviderId
|
|
68
|
+
readonly displayName: string
|
|
69
|
+
readonly logoPath: string
|
|
70
|
+
fetchSnapshot(signal: AbortSignal): Promise<readonly Agent[]>
|
|
71
|
+
subscribe(signal: AbortSignal, onChange: () => void): () => void
|
|
72
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// ponytail: as a builtin of the cli, this addon re-exports the runtime's
|
|
2
|
+
// type surface directly. The previous third-party addon shipped a
|
|
3
|
+
// minimal local mirror because third-party packages must not reach into
|
|
4
|
+
// the cli's @/ path aliases — builtins don't have that constraint.
|
|
5
|
+
export type {
|
|
6
|
+
AddonButtonService,
|
|
7
|
+
AddonButtonServiceContext,
|
|
8
|
+
AddonButtonTypeDef,
|
|
9
|
+
AddonButtonTypeDefAny,
|
|
10
|
+
AddonButtonTypeService,
|
|
11
|
+
AddonCheck,
|
|
12
|
+
AddonCheckResult,
|
|
13
|
+
AddonDeckDefinition,
|
|
14
|
+
AddonDeckEntry,
|
|
15
|
+
AddonDeckEntryCtx,
|
|
16
|
+
AddonDeckFactory,
|
|
17
|
+
AddonFrontend,
|
|
18
|
+
AddonFrontendButton,
|
|
19
|
+
AddonFrontendButtonProps,
|
|
20
|
+
AddonGeneratedDeck,
|
|
21
|
+
AddonGlobalPoller,
|
|
22
|
+
AddonGlobalService,
|
|
23
|
+
AddonGlobalSubscription,
|
|
24
|
+
AddonGestureEvent,
|
|
25
|
+
AddonLoadIssue,
|
|
26
|
+
AddonManifest,
|
|
27
|
+
AddonManifestKind,
|
|
28
|
+
AddonManifestV1,
|
|
29
|
+
AddonServiceContext,
|
|
30
|
+
AddonServiceMethod,
|
|
31
|
+
AddonKind,
|
|
32
|
+
GestureKind,
|
|
33
|
+
} from "@/addon/api"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# core
|
|
2
|
+
|
|
3
|
+
**Internal-only addon.** Provides the foundational button types every deck depends on. The runtime injects `core:change-deck` automatically (the reserved `n-1` slot); `core:action` and `core:toggle` are user-facing but the runtime also uses them internally for things like the settings back button.
|
|
4
|
+
|
|
5
|
+
If you're writing user-facing config, you only need `core:action` and `core:change-deck`. The other two are runtime-managed.
|
|
6
|
+
|
|
7
|
+
## Buttons
|
|
8
|
+
|
|
9
|
+
| Type | Description |
|
|
10
|
+
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `core:change-deck` | Navigate to another deck. Internal: the reserved `n-1` slot. |
|
|
12
|
+
| `core:action` | Run a shell command (xdg-open, google-chrome, etc.) |
|
|
13
|
+
| `core:toggle` | Toggle a stateful button. Two modes: legacy `{key,default}` boolean flip, or `statusCommand`/`states` polled status display with per-state tap action |
|
|
14
|
+
| `core:page-nav` | Internal: next/previous deck navigation |
|
|
15
|
+
| `core:media-sample` | Internal: a sample media-player button used in tests |
|
|
16
|
+
|
|
17
|
+
## Config
|
|
18
|
+
|
|
19
|
+
### `core:action`
|
|
20
|
+
|
|
21
|
+
Requires at least one of `icon` or `label`. Command goes in `actions.tap`
|
|
22
|
+
(also accepts `type://<combo-or-text>` URIs for keystroke shortcuts).
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
- position: 1
|
|
26
|
+
type: core:action
|
|
27
|
+
actions:
|
|
28
|
+
tap: "xdg-open https://example.com"
|
|
29
|
+
config:
|
|
30
|
+
label: Open
|
|
31
|
+
icon: icon://globe
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### `core:change-deck`
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
- position: 9
|
|
38
|
+
type: core:change-deck
|
|
39
|
+
config:
|
|
40
|
+
deck: emoji
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`deck` must reference a deck id defined in the same `config.yml` under `decks:`.
|
|
44
|
+
|
|
45
|
+
### `core:toggle`
|
|
46
|
+
|
|
47
|
+
Two shapes are supported.
|
|
48
|
+
|
|
49
|
+
**Status mode (recommended):** poll a command, match its trimmed stdout against
|
|
50
|
+
`states`, render the matched state's label/icon, and run the matched state's
|
|
51
|
+
`onTap` on user tap. Per-button `intervalMs` (default 2000) bounds how often
|
|
52
|
+
`statusCommand` runs.
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
- position: 1
|
|
56
|
+
type: core:toggle
|
|
57
|
+
config:
|
|
58
|
+
statusCommand: "playerctl status"
|
|
59
|
+
intervalMs: 2000
|
|
60
|
+
timeoutMs: 5000
|
|
61
|
+
states:
|
|
62
|
+
Playing:
|
|
63
|
+
label: "<xl>$(playerctl title)</xl>"
|
|
64
|
+
icon: "icon://play"
|
|
65
|
+
onTap: "playerctl pause"
|
|
66
|
+
Paused:
|
|
67
|
+
label: "Paused"
|
|
68
|
+
icon: "icon://pause"
|
|
69
|
+
onTap: "playerctl play"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Each state entry must declare at least one of `label` or `icon`. `onTap` is
|
|
73
|
+
optional — if omitted, tapping still triggers a republish so the deck reflects
|
|
74
|
+
the latest status without waiting for the next tick.
|
|
75
|
+
|
|
76
|
+
**Legacy mode:** keep the runtime boolean flip.
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
- position: 1
|
|
80
|
+
type: core:toggle
|
|
81
|
+
config:
|
|
82
|
+
key: my-flag
|
|
83
|
+
default: false
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## See also
|
|
87
|
+
|
|
88
|
+
- [Internal settings](../internal-settings/README.md) — overlay deck
|
|
89
|
+
- [Session](../session/README.md) — `session:locked` deck
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
import { IconSourceSchema } from "@/config/schemas"
|
|
4
|
+
|
|
5
|
+
export const configSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
icon: IconSourceSchema.optional(),
|
|
8
|
+
label: z.string().optional(),
|
|
9
|
+
})
|
|
10
|
+
.refine((c) => Boolean(c.icon) || Boolean(c.label), {
|
|
11
|
+
message: "core:action requires at least one of 'icon' or 'label'",
|
|
12
|
+
})
|
|
13
|
+
export type ConfigSchema = z.infer<typeof configSchema>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AddonFrontendButton } from "@/addon/api"
|
|
2
|
+
import { IconLabelSurface } from "@/ui/index"
|
|
3
|
+
|
|
4
|
+
type Config = { icon?: string; label?: string }
|
|
5
|
+
|
|
6
|
+
const CoreActionButtonFrontend: AddonFrontendButton<Config> = ({ config }) => {
|
|
7
|
+
const { icon, label } = config ?? {}
|
|
8
|
+
return (
|
|
9
|
+
<IconLabelSurface
|
|
10
|
+
{...(icon !== undefined ? { source: icon } : {})}
|
|
11
|
+
label={label ?? ""}
|
|
12
|
+
/>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default CoreActionButtonFrontend
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
import type { AddonButtonTypeService } from "@/addon/api"
|
|
3
|
+
|
|
4
|
+
import { configSchema } from "./config"
|
|
5
|
+
|
|
6
|
+
type Config = z.infer<typeof configSchema>
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
configSchema,
|
|
10
|
+
onTap: ({ config, publish, buttonId, position }) => {
|
|
11
|
+
publish("runtime:navigate-deck", {
|
|
12
|
+
deckId: config.deck,
|
|
13
|
+
addToHistory: config.addToHistory ?? true,
|
|
14
|
+
buttonId,
|
|
15
|
+
position,
|
|
16
|
+
})
|
|
17
|
+
},
|
|
18
|
+
} satisfies AddonButtonTypeService<Config>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
import { IconSourceSchema } from "@/config/schemas"
|
|
4
|
+
|
|
5
|
+
export const configSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
deck: z.string().min(1),
|
|
8
|
+
addToHistory: z.boolean().default(true).meta({ internal: true }),
|
|
9
|
+
icon: IconSourceSchema.optional(),
|
|
10
|
+
label: z.string().optional(),
|
|
11
|
+
})
|
|
12
|
+
.refine((c) => Boolean(c.icon) || Boolean(c.label), {
|
|
13
|
+
message: "core:change-deck requires at least one of 'icon' or 'label'",
|
|
14
|
+
})
|
|
15
|
+
export type ConfigSchema = z.infer<typeof configSchema>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AddonFrontendButton } from "@/addon/api"
|
|
2
|
+
import { IconLabelSurface } from "@/ui/index"
|
|
3
|
+
|
|
4
|
+
type Config = { icon?: string; label?: string }
|
|
5
|
+
|
|
6
|
+
const CoreChangeDeckButtonFrontend: AddonFrontendButton<Config> = ({
|
|
7
|
+
config,
|
|
8
|
+
}) => {
|
|
9
|
+
const { icon, label } = config ?? {}
|
|
10
|
+
return (
|
|
11
|
+
<IconLabelSurface
|
|
12
|
+
{...(icon !== undefined ? { source: icon } : {})}
|
|
13
|
+
label={label ?? ""}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default CoreChangeDeckButtonFrontend
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
import type { AddonButtonTypeService } from "@/addon/api"
|
|
3
|
+
|
|
4
|
+
import { configSchema } from "./config"
|
|
5
|
+
|
|
6
|
+
type Config = z.infer<typeof configSchema>
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
configSchema,
|
|
10
|
+
onTap: ({ config, publish, buttonId, position }) => {
|
|
11
|
+
const { nextDeckId } = config as Config
|
|
12
|
+
publish("runtime:navigate-deck", {
|
|
13
|
+
deckId: nextDeckId,
|
|
14
|
+
addToHistory: false,
|
|
15
|
+
buttonId,
|
|
16
|
+
position,
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
onHold: ({ config, publish, buttonId, position }) => {
|
|
20
|
+
const { prevDeckId } = config as Config
|
|
21
|
+
publish("runtime:navigate-deck", {
|
|
22
|
+
deckId: prevDeckId,
|
|
23
|
+
addToHistory: false,
|
|
24
|
+
buttonId,
|
|
25
|
+
position,
|
|
26
|
+
})
|
|
27
|
+
},
|
|
28
|
+
} satisfies AddonButtonTypeService<Config>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AddonFrontendButton } from "@/addon/api"
|
|
2
|
+
import { cn, Icon, TapIndicator, TapIndicatorType, Text } from "@/ui"
|
|
3
|
+
|
|
4
|
+
type Config = {
|
|
5
|
+
currentPage: number
|
|
6
|
+
totalPages: number
|
|
7
|
+
prevDeckId: string
|
|
8
|
+
nextDeckId: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type NavActionProps = {
|
|
12
|
+
dir: "next" | "prev"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const icons: Record<NavActionProps["dir"], string> = {
|
|
16
|
+
next: "chevron-right",
|
|
17
|
+
prev: "chevron-left",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const tapTypes: Record<NavActionProps["dir"], TapIndicatorType> = {
|
|
21
|
+
next: "tap",
|
|
22
|
+
prev: "hold",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const NavAction = ({ dir = "prev" }: NavActionProps) => {
|
|
26
|
+
const icon = icons[dir]
|
|
27
|
+
const tapType = tapTypes[dir]
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
className={cn(
|
|
32
|
+
"flex items-center gap-0",
|
|
33
|
+
dir === "prev" ? "flex-row" : "flex-row-reverse",
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
<Icon source={`icon://${icon}`} size={30} />
|
|
37
|
+
<TapIndicator type={tapType} size="xs" />
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const PageIndicator = ({
|
|
43
|
+
current,
|
|
44
|
+
total,
|
|
45
|
+
}: {
|
|
46
|
+
current: number
|
|
47
|
+
total: number
|
|
48
|
+
}) => <Text size="md" tone="muted" text={`*${current}* / ${total}`} />
|
|
49
|
+
|
|
50
|
+
const PageNavButtonFrontend: AddonFrontendButton<Config> = ({ config }) => {
|
|
51
|
+
const { currentPage, totalPages } = config
|
|
52
|
+
const isFirstPage = currentPage === 1
|
|
53
|
+
const isLastPage = currentPage === totalPages
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div className="size-full flex flex-col gap-0.5 justify-center items-center">
|
|
57
|
+
<div className={cn(isFirstPage ? "invisible" : "visible", "-ml-7")}>
|
|
58
|
+
<NavAction dir="prev" />
|
|
59
|
+
</div>
|
|
60
|
+
<PageIndicator current={currentPage} total={totalPages} />
|
|
61
|
+
<div className={cn(isLastPage ? "invisible" : "visible", "ml-7")}>
|
|
62
|
+
<NavAction dir="next" />
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default PageNavButtonFrontend
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Methods } from "@/deck/methods"
|
|
2
|
+
import type { Store } from "@/core/store"
|
|
3
|
+
import type {
|
|
4
|
+
AddonButtonServiceContext,
|
|
5
|
+
AddonButtonTypeService,
|
|
6
|
+
} from "@/addon/api"
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
configSchema,
|
|
10
|
+
isStatusToggleConfig,
|
|
11
|
+
type ConfigSchema,
|
|
12
|
+
type LegacyToggleConfig,
|
|
13
|
+
type StatusToggleConfig,
|
|
14
|
+
} from "./config"
|
|
15
|
+
|
|
16
|
+
// ponytail: bridge namespaces addon-global methods as `${addonName}:${methodName}`.
|
|
17
|
+
// core addon's method names are `register` / `unregister` / `republish` / `lookup`,
|
|
18
|
+
// so the namespaced keys are `core:register` etc.
|
|
19
|
+
const REG_METHOD = "core:register"
|
|
20
|
+
const UNREG_METHOD = "core:unregister"
|
|
21
|
+
const REPUBLISH_METHOD = "core:republish"
|
|
22
|
+
const LOOKUP_METHOD = "core:lookup"
|
|
23
|
+
|
|
24
|
+
interface ToggleStateLike {
|
|
25
|
+
readonly raw: string
|
|
26
|
+
readonly state: string | undefined
|
|
27
|
+
readonly error?: string
|
|
28
|
+
readonly at: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
configSchema,
|
|
33
|
+
onMount: (ctx: AddonButtonServiceContext<ConfigSchema>) => {
|
|
34
|
+
if (!isStatusToggleConfig(ctx.config)) return
|
|
35
|
+
const register = (
|
|
36
|
+
ctx.methods as unknown as Record<
|
|
37
|
+
string,
|
|
38
|
+
((...a: unknown[]) => unknown) | undefined
|
|
39
|
+
>
|
|
40
|
+
)[REG_METHOD]
|
|
41
|
+
register?.(ctx.buttonId, ctx.config)
|
|
42
|
+
},
|
|
43
|
+
dispose: (ctx: AddonButtonServiceContext<ConfigSchema>) => {
|
|
44
|
+
if (!isStatusToggleConfig(ctx.config)) return
|
|
45
|
+
const unregister = (
|
|
46
|
+
ctx.methods as unknown as Record<
|
|
47
|
+
string,
|
|
48
|
+
((...a: unknown[]) => unknown) | undefined
|
|
49
|
+
>
|
|
50
|
+
)[UNREG_METHOD]
|
|
51
|
+
unregister?.(ctx.buttonId)
|
|
52
|
+
},
|
|
53
|
+
onTap: async (ctx: AddonButtonServiceContext<ConfigSchema>) => {
|
|
54
|
+
const { config, methods, store, coreMethods, buttonId } =
|
|
55
|
+
ctx as unknown as {
|
|
56
|
+
config: ConfigSchema
|
|
57
|
+
methods: Methods
|
|
58
|
+
store: Store
|
|
59
|
+
coreMethods: Methods
|
|
60
|
+
buttonId: string
|
|
61
|
+
}
|
|
62
|
+
if (!isStatusToggleConfig(config)) {
|
|
63
|
+
await legacyTap({ config: config as LegacyToggleConfig, methods, store })
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
await statusTap({ config, methods, coreMethods, buttonId }, config)
|
|
67
|
+
},
|
|
68
|
+
} satisfies AddonButtonTypeService<ConfigSchema>
|
|
69
|
+
|
|
70
|
+
const legacyTap = async (ctx: {
|
|
71
|
+
config: LegacyToggleConfig
|
|
72
|
+
methods: Methods
|
|
73
|
+
store: Store
|
|
74
|
+
}): Promise<void> => {
|
|
75
|
+
const scope = ctx.store.buttonScope<boolean>("core", ctx.config.key)
|
|
76
|
+
const current = scope.get("value") ?? ctx.config.default
|
|
77
|
+
scope.set("value", !current)
|
|
78
|
+
ctx.methods.invalidate()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const statusTap = async (
|
|
82
|
+
ctx: {
|
|
83
|
+
config: StatusToggleConfig
|
|
84
|
+
methods: Methods
|
|
85
|
+
coreMethods: Methods
|
|
86
|
+
buttonId: string
|
|
87
|
+
},
|
|
88
|
+
config: StatusToggleConfig,
|
|
89
|
+
): Promise<void> => {
|
|
90
|
+
const lookup = (
|
|
91
|
+
ctx.methods as unknown as Record<
|
|
92
|
+
string,
|
|
93
|
+
((...a: unknown[]) => unknown) | undefined
|
|
94
|
+
>
|
|
95
|
+
)[LOOKUP_METHOD] as
|
|
96
|
+
| ((id: unknown) => Promise<ToggleStateLike | null>)
|
|
97
|
+
| undefined
|
|
98
|
+
let stateKey: string | undefined
|
|
99
|
+
if (lookup !== undefined) {
|
|
100
|
+
const current = await lookup(ctx.buttonId)
|
|
101
|
+
stateKey = current?.state
|
|
102
|
+
}
|
|
103
|
+
const entry = stateKey !== undefined ? config.states[stateKey] : undefined
|
|
104
|
+
const command = entry?.onTap
|
|
105
|
+
const republish = (
|
|
106
|
+
ctx.methods as unknown as Record<
|
|
107
|
+
string,
|
|
108
|
+
((...a: unknown[]) => unknown) | undefined
|
|
109
|
+
>
|
|
110
|
+
)[REPUBLISH_METHOD] as ((buttonId?: unknown) => void) | undefined
|
|
111
|
+
if (command === undefined || command.length === 0) {
|
|
112
|
+
republish?.(ctx.buttonId)
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
await ctx.coreMethods.runCommand(command, {
|
|
116
|
+
timeoutMs: config.timeoutMs,
|
|
117
|
+
} as Parameters<typeof ctx.coreMethods.runCommand>[1])
|
|
118
|
+
republish?.(ctx.buttonId)
|
|
119
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
|
|
3
|
+
export const TOGGLE_DEFAULT_INTERVAL_MS = 2000
|
|
4
|
+
export const TOGGLE_DEFAULT_TIMEOUT_MS = 5000
|
|
5
|
+
|
|
6
|
+
export const StatusToggleStateSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
label: z.string().min(1).optional(),
|
|
9
|
+
icon: z.string().min(1).optional(),
|
|
10
|
+
onTap: z.string().min(1).optional(),
|
|
11
|
+
})
|
|
12
|
+
.strict()
|
|
13
|
+
.refine((s) => s.label !== undefined || s.icon !== undefined, {
|
|
14
|
+
message: "each state requires at least one of `label` or `icon`",
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
export type StatusToggleState = z.infer<typeof StatusToggleStateSchema>
|
|
18
|
+
|
|
19
|
+
export const StatusToggleConfigSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
statusCommand: z.string().min(1),
|
|
22
|
+
intervalMs: z.number().int().positive().optional(),
|
|
23
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
24
|
+
states: z.record(z.string().min(1), StatusToggleStateSchema),
|
|
25
|
+
})
|
|
26
|
+
.strict()
|
|
27
|
+
.refine((c) => Object.keys(c.states).length > 0, {
|
|
28
|
+
message: "`states` must declare at least one entry",
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export type StatusToggleConfig = z.infer<typeof StatusToggleConfigSchema>
|
|
32
|
+
|
|
33
|
+
export const LegacyToggleConfigSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
key: z.string().min(1),
|
|
36
|
+
default: z.boolean().default(false),
|
|
37
|
+
})
|
|
38
|
+
.strict()
|
|
39
|
+
|
|
40
|
+
export type LegacyToggleConfig = z.infer<typeof LegacyToggleConfigSchema>
|
|
41
|
+
|
|
42
|
+
export const configSchema = z.union([
|
|
43
|
+
StatusToggleConfigSchema,
|
|
44
|
+
LegacyToggleConfigSchema,
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
export type ConfigSchema = z.infer<typeof configSchema>
|
|
48
|
+
|
|
49
|
+
export const isStatusToggleConfig = (
|
|
50
|
+
value: unknown,
|
|
51
|
+
): value is StatusToggleConfig =>
|
|
52
|
+
StatusToggleConfigSchema.safeParse(value).success
|
|
53
|
+
|
|
54
|
+
export const isLegacyToggleConfig = (
|
|
55
|
+
value: unknown,
|
|
56
|
+
): value is LegacyToggleConfig =>
|
|
57
|
+
LegacyToggleConfigSchema.safeParse(value).success
|