dexterm-cli 0.0.0-stage → 0.1.2
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 +661 -0
- package/dist/packages/agents/src/audit.js +122 -0
- package/dist/packages/agents/src/bus.js +394 -0
- package/dist/packages/agents/src/executor.js +202 -0
- package/dist/packages/agents/src/gate.js +179 -0
- package/dist/packages/agents/src/identity.js +218 -0
- package/dist/packages/agents/src/index.js +15 -0
- package/dist/packages/agents/src/proposals.js +153 -0
- package/dist/packages/agents/src/schema.js +87 -0
- package/dist/packages/agents/src/sdk.js +140 -0
- package/dist/packages/agents/src/tiers.js +119 -0
- package/dist/packages/agents/src/tools.js +72 -0
- package/dist/packages/agents/src/ws.js +158 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +76 -0
- package/dist/packages/cli/assets/claude/plugin/.claude-plugin/plugin.json +5 -0
- package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +16 -0
- package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +75 -0
- package/dist/packages/cli/assets/claude/plugin/skills/rug-check/SKILL.md +74 -0
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +63 -0
- package/dist/packages/cli/assets/claude/plugin/skills/trench-scan/SKILL.md +44 -0
- package/dist/packages/cli/assets/claude/schemas/larp.schema.json +117 -0
- package/dist/packages/cli/assets/claude/schemas/trench-scan.schema.json +71 -0
- package/dist/packages/cli/assets/claude/schemas/verdict.schema.json +115 -0
- package/dist/packages/cli/bin/dexterm.mjs +11 -0
- package/dist/packages/cli/src/agent-cmd.js +336 -0
- package/dist/packages/cli/src/agent-roster.js +26 -0
- package/dist/packages/cli/src/alerts/adapters/desktop.js +40 -0
- package/dist/packages/cli/src/alerts/adapters/discord.js +36 -0
- package/dist/packages/cli/src/alerts/adapters/telegram.js +43 -0
- package/dist/packages/cli/src/alerts/adapters/toast.js +16 -0
- package/dist/packages/cli/src/alerts/creds.js +83 -0
- package/dist/packages/cli/src/alerts/format.js +41 -0
- package/dist/packages/cli/src/alerts/index.js +10 -0
- package/dist/packages/cli/src/alerts/notifier.js +53 -0
- package/dist/packages/cli/src/alerts/route.js +19 -0
- package/dist/packages/cli/src/alerts/types.js +1 -0
- package/dist/packages/cli/src/alerts-cmd.js +212 -0
- package/dist/packages/cli/src/analyst/backend.js +526 -0
- package/dist/packages/cli/src/analyst/results.js +38 -0
- package/dist/packages/cli/src/analyst/session.js +319 -0
- package/dist/packages/cli/src/audit.js +51 -0
- package/dist/packages/cli/src/backtest-cmd.js +208 -0
- package/dist/packages/cli/src/boot-state.js +62 -0
- package/dist/packages/cli/src/coin-target.js +2 -0
- package/dist/packages/cli/src/custom.js +261 -0
- package/dist/packages/cli/src/display.js +191 -0
- package/dist/packages/cli/src/doctor.js +375 -0
- package/dist/packages/cli/src/export.js +235 -0
- package/dist/packages/cli/src/feed.js +634 -0
- package/dist/packages/cli/src/fixtures.js +275 -0
- package/dist/packages/cli/src/follow-cmd.js +221 -0
- package/dist/packages/cli/src/images-config.js +59 -0
- package/dist/packages/cli/src/index.js +31 -0
- package/dist/packages/cli/src/kb-skill-cmd.js +240 -0
- package/dist/packages/cli/src/larp-record.js +21 -0
- package/dist/packages/cli/src/live/copy.js +80 -0
- package/dist/packages/cli/src/live/flow.js +233 -0
- package/dist/packages/cli/src/live/index.js +511 -0
- package/dist/packages/cli/src/live/intel.js +227 -0
- package/dist/packages/cli/src/live/newpairs.js +334 -0
- package/dist/packages/cli/src/live/screens/newpairs-live.js +219 -0
- package/dist/packages/cli/src/live/screens/token-live.js +459 -0
- package/dist/packages/cli/src/live/screens/watchlist-live.js +149 -0
- package/dist/packages/cli/src/live/token.js +585 -0
- package/dist/packages/cli/src/live/trade.js +929 -0
- package/dist/packages/cli/src/live/watchlist.js +178 -0
- package/dist/packages/cli/src/main.js +5785 -0
- package/dist/packages/cli/src/mcp-cmd.js +326 -0
- package/dist/packages/cli/src/narrative-cmd.js +76 -0
- package/dist/packages/cli/src/pack-cmd.js +323 -0
- package/dist/packages/cli/src/plan-cmd.js +278 -0
- package/dist/packages/cli/src/popup.js +810 -0
- package/dist/packages/cli/src/rules-cmd.js +131 -0
- package/dist/packages/cli/src/rules.js +358 -0
- package/dist/packages/cli/src/scan/command.js +57 -0
- package/dist/packages/cli/src/scan/engine.js +419 -0
- package/dist/packages/cli/src/scan/observe.js +64 -0
- package/dist/packages/cli/src/scan/ui.js +98 -0
- package/dist/packages/cli/src/screener/filter.js +241 -0
- package/dist/packages/cli/src/screener/presets.js +80 -0
- package/dist/packages/cli/src/screener/rows.js +146 -0
- package/dist/packages/cli/src/screener/rug.js +50 -0
- package/dist/packages/cli/src/screener/sort.js +52 -0
- package/dist/packages/cli/src/screener/view.js +183 -0
- package/dist/packages/cli/src/screens/analyst-session.js +343 -0
- package/dist/packages/cli/src/screens/analyst.js +326 -0
- package/dist/packages/cli/src/screens/boot.js +74 -0
- package/dist/packages/cli/src/screens/bubbles.js +255 -0
- package/dist/packages/cli/src/screens/coin.js +33 -0
- package/dist/packages/cli/src/screens/follows.js +201 -0
- package/dist/packages/cli/src/screens/kol.js +90 -0
- package/dist/packages/cli/src/screens/narrative.js +90 -0
- package/dist/packages/cli/src/screens/newpairs.js +150 -0
- package/dist/packages/cli/src/screens/overlay.js +257 -0
- package/dist/packages/cli/src/screens/plans.js +126 -0
- package/dist/packages/cli/src/screens/positions.js +176 -0
- package/dist/packages/cli/src/screens/rules.js +170 -0
- package/dist/packages/cli/src/screens/screener.js +459 -0
- package/dist/packages/cli/src/screens/social-panel.js +107 -0
- package/dist/packages/cli/src/screens/ticket.js +342 -0
- package/dist/packages/cli/src/screens/token.js +312 -0
- package/dist/packages/cli/src/screens/trending.js +181 -0
- package/dist/packages/cli/src/screens/watchlist.js +104 -0
- package/dist/packages/cli/src/skill-eval-build.js +109 -0
- package/dist/packages/cli/src/social/demo.js +96 -0
- package/dist/packages/cli/src/social/view.js +250 -0
- package/dist/packages/cli/src/state.js +463 -0
- package/dist/packages/cli/src/theme-cmd.js +126 -0
- package/dist/packages/cli/src/trade.js +319 -0
- package/dist/packages/cli/src/update.js +294 -0
- package/dist/packages/cli/src/version.js +3 -0
- package/dist/packages/cli/src/voice-cmd.js +119 -0
- package/dist/packages/cli/src/voice-hud.js +42 -0
- package/dist/packages/cli/src/wallet-cmd.js +440 -0
- package/dist/packages/cli/src/wallet-command.js +31 -0
- package/dist/packages/cli/src/watch-cmd.js +190 -0
- package/dist/packages/cli/src/widgets.js +208 -0
- package/dist/packages/cli/src/workspace-cmd.js +68 -0
- package/dist/packages/cli/src/x-cmd.js +154 -0
- package/dist/packages/custom/src/config.js +213 -0
- package/dist/packages/custom/src/index.js +10 -0
- package/dist/packages/custom/src/keymap.js +107 -0
- package/dist/packages/custom/src/layout.js +235 -0
- package/dist/packages/custom/src/packs.js +633 -0
- package/dist/packages/custom/src/rules.js +704 -0
- package/dist/packages/custom/src/schema.js +538 -0
- package/dist/packages/custom/src/themes.js +176 -0
- package/dist/packages/custom/src/widget-html.js +222 -0
- package/dist/packages/custom/src/workspace.js +141 -0
- package/dist/packages/data/src/analyst-actions.js +133 -0
- package/dist/packages/data/src/budget.js +88 -0
- package/dist/packages/data/src/cache.js +142 -0
- package/dist/packages/data/src/candles.js +168 -0
- package/dist/packages/data/src/clock.js +64 -0
- package/dist/packages/data/src/coin-target.js +82 -0
- package/dist/packages/data/src/credits.js +137 -0
- package/dist/packages/data/src/detail.js +97 -0
- package/dist/packages/data/src/fast-lane.js +321 -0
- package/dist/packages/data/src/fixtures.js +135 -0
- package/dist/packages/data/src/health.js +245 -0
- package/dist/packages/data/src/http.js +277 -0
- package/dist/packages/data/src/images/cache.js +141 -0
- package/dist/packages/data/src/images/decode-worker.js +28 -0
- package/dist/packages/data/src/images/decode.js +81 -0
- package/dist/packages/data/src/images/fetch.js +162 -0
- package/dist/packages/data/src/images/gif.js +214 -0
- package/dist/packages/data/src/images/index.js +10 -0
- package/dist/packages/data/src/images/jpeg.js +544 -0
- package/dist/packages/data/src/images/png.js +310 -0
- package/dist/packages/data/src/images/service.js +334 -0
- package/dist/packages/data/src/images/types.js +27 -0
- package/dist/packages/data/src/index.js +211 -0
- package/dist/packages/data/src/intel/helius-history.js +70 -0
- package/dist/packages/data/src/intel/holder-class.js +125 -0
- package/dist/packages/data/src/intel/rules.js +421 -0
- package/dist/packages/data/src/intel/scan.js +170 -0
- package/dist/packages/data/src/larp/evidence.js +288 -0
- package/dist/packages/data/src/larp/link-baseline.js +196 -0
- package/dist/packages/data/src/larp/links.js +137 -0
- package/dist/packages/data/src/larp/robots.js +90 -0
- package/dist/packages/data/src/larp/safe-fetch.js +389 -0
- package/dist/packages/data/src/limiter.js +341 -0
- package/dist/packages/data/src/model.js +12 -0
- package/dist/packages/data/src/paper.js +331 -0
- package/dist/packages/data/src/rpc-config.js +126 -0
- package/dist/packages/data/src/rpc-pool.js +166 -0
- package/dist/packages/data/src/social/chain.js +83 -0
- package/dist/packages/data/src/social/dedupe.js +205 -0
- package/dist/packages/data/src/social/feed.js +462 -0
- package/dist/packages/data/src/social/firewall.js +110 -0
- package/dist/packages/data/src/social/index.js +11 -0
- package/dist/packages/data/src/social/kol.js +269 -0
- package/dist/packages/data/src/social/model.js +11 -0
- package/dist/packages/data/src/social/rank.js +184 -0
- package/dist/packages/data/src/social/rss.js +113 -0
- package/dist/packages/data/src/social/summary.js +104 -0
- package/dist/packages/data/src/social/venues.js +186 -0
- package/dist/packages/data/src/sources/dexscreener.js +184 -0
- package/dist/packages/data/src/sources/geckoterminal.js +133 -0
- package/dist/packages/data/src/sources/goplus.js +161 -0
- package/dist/packages/data/src/sources/jupiter-swap.js +236 -0
- package/dist/packages/data/src/sources/jupiter.js +198 -0
- package/dist/packages/data/src/sources/pda.js +113 -0
- package/dist/packages/data/src/sources/pump-curve.js +58 -0
- package/dist/packages/data/src/sources/pumpportal.js +252 -0
- package/dist/packages/data/src/sources/rugcheck.js +71 -0
- package/dist/packages/data/src/sources/solana-rpc.js +299 -0
- package/dist/packages/data/src/sources/solana-ws.js +287 -0
- package/dist/packages/data/src/store.js +289 -0
- package/dist/packages/data/src/trade/bridge.js +464 -0
- package/dist/packages/data/src/trade/caps.js +323 -0
- package/dist/packages/data/src/trade/copy/auto.js +385 -0
- package/dist/packages/data/src/trade/copy/follows.js +103 -0
- package/dist/packages/data/src/trade/copy/index.js +9 -0
- package/dist/packages/data/src/trade/copy/mirror.js +91 -0
- package/dist/packages/data/src/trade/copy/stats.js +120 -0
- package/dist/packages/data/src/trade/copy/tracker.js +158 -0
- package/dist/packages/data/src/trade/copy/trades.js +87 -0
- package/dist/packages/data/src/trade/copy/types.js +6 -0
- package/dist/packages/data/src/trade/executor.js +933 -0
- package/dist/packages/data/src/trade/kill-switch.js +47 -0
- package/dist/packages/data/src/trade/link-store.js +52 -0
- package/dist/packages/data/src/trade/plans/confirm.js +157 -0
- package/dist/packages/data/src/trade/plans/engine.js +784 -0
- package/dist/packages/data/src/trade/plans/executor-live.js +220 -0
- package/dist/packages/data/src/trade/plans/executor-paper.js +44 -0
- package/dist/packages/data/src/trade/plans/executor.js +11 -0
- package/dist/packages/data/src/trade/plans/index.js +12 -0
- package/dist/packages/data/src/trade/plans/journal.js +77 -0
- package/dist/packages/data/src/trade/plans/mandate.js +129 -0
- package/dist/packages/data/src/trade/plans/plan.js +179 -0
- package/dist/packages/data/src/trade/plans/service.js +168 -0
- package/dist/packages/data/src/trade/plans/types.js +6 -0
- package/dist/packages/data/src/trade/rpc-exec.js +229 -0
- package/dist/packages/data/src/trade/signer/client.js +197 -0
- package/dist/packages/data/src/trade/signer/fast-wallet.js +154 -0
- package/dist/packages/data/src/trade/signer/host.js +97 -0
- package/dist/packages/data/src/trade/signer/main.js +121 -0
- package/dist/packages/data/src/trade/signer/probe-builder.js +85 -0
- package/dist/packages/data/src/trade/signer/protocol.js +92 -0
- package/dist/packages/data/src/trade/signer/service.js +400 -0
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +98 -0
- package/dist/packages/data/src/trade/sol-usd.js +86 -0
- package/dist/packages/data/src/trade/swap-build.js +108 -0
- package/dist/packages/data/src/trade/token-delta.js +201 -0
- package/dist/packages/data/src/trade/tx-decode.js +632 -0
- package/dist/packages/data/src/util.js +24 -0
- package/dist/packages/data/src/watchlist.js +176 -0
- package/dist/packages/data/src/x/api.js +256 -0
- package/dist/packages/data/src/x/budget.js +66 -0
- package/dist/packages/data/src/x/config.js +49 -0
- package/dist/packages/data/src/x/index.js +10 -0
- package/dist/packages/data/src/x/mock-server.js +217 -0
- package/dist/packages/data/src/x/oauth.js +242 -0
- package/dist/packages/data/src/x/pkce.js +21 -0
- package/dist/packages/data/src/x/source.js +285 -0
- package/dist/packages/data/src/x/token-store.js +134 -0
- package/dist/packages/data/src/x/transport.js +71 -0
- package/dist/packages/data/vendor/solana-web3/LICENSE +20 -0
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +13 -0
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +20 -0
- package/dist/packages/mcp/assets/cases.json +1194 -0
- package/dist/packages/mcp/assets/kb/entries/cabal-and-coordinated-launches.md +28 -0
- package/dist/packages/mcp/assets/kb/entries/common-rug-patterns.md +40 -0
- package/dist/packages/mcp/assets/kb/entries/dbc-mechanics.md +30 -0
- package/dist/packages/mcp/assets/kb/entries/dev-wallet-behaviour.md +33 -0
- package/dist/packages/mcp/assets/kb/entries/glossary.md +35 -0
- package/dist/packages/mcp/assets/kb/entries/holder-concentration.md +30 -0
- package/dist/packages/mcp/assets/kb/entries/jito-bundles.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/launchlab-curve.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/lp-burn-vs-lock.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/metadata-and-copycats.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/mint-freeze-authority.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/narrative-lifecycle.md +32 -0
- package/dist/packages/mcp/assets/kb/entries/pump-bonding-curve.md +33 -0
- package/dist/packages/mcp/assets/kb/entries/pumpswap-migration.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/sniping-and-snipers.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/token2022-extensions-risk.md +32 -0
- package/dist/packages/mcp/assets/kb/entries/wash-trading-fake-volume.md +33 -0
- package/dist/packages/mcp/assets/skills/rug-check.md +52 -0
- package/dist/packages/mcp/assets/skills/token-dossier.md +57 -0
- package/dist/packages/mcp/assets/skills/trench-scan.md +40 -0
- package/dist/packages/mcp/bin/dexterm-mcp.mjs +16 -0
- package/dist/packages/mcp/src/dossier.js +78 -0
- package/dist/packages/mcp/src/firewall.js +21 -0
- package/dist/packages/mcp/src/index.js +22 -0
- package/dist/packages/mcp/src/server.js +936 -0
- package/dist/packages/mcp/src/user-content.js +434 -0
- package/dist/packages/packs/src/backtest.js +183 -0
- package/dist/packages/packs/src/digest.js +95 -0
- package/dist/packages/packs/src/firewall.js +57 -0
- package/dist/packages/packs/src/index.js +20 -0
- package/dist/packages/packs/src/larp-eval.js +100 -0
- package/dist/packages/packs/src/narrative.js +309 -0
- package/dist/packages/packs/src/reason.js +135 -0
- package/dist/packages/packs/src/rug-model.js +137 -0
- package/dist/packages/packs/src/schema.js +54 -0
- package/dist/packages/packs/src/skill-backtest.js +300 -0
- package/dist/packages/packs/src/token-dossier.js +174 -0
- package/dist/packages/packs/src/verdicts.js +17 -0
- package/dist/packages/packs/src/wallet-dossier.js +105 -0
- package/dist/packages/popup/src/config.js +71 -0
- package/dist/packages/popup/src/dock.js +271 -0
- package/dist/packages/popup/src/host.js +210 -0
- package/dist/packages/popup/src/index.js +12 -0
- package/dist/packages/popup/src/loopback.js +53 -0
- package/dist/packages/popup/src/open.js +183 -0
- package/dist/packages/popup/src/pages/bubbles-lib.js +160 -0
- package/dist/packages/popup/src/pages/bubbles.css +23 -0
- package/dist/packages/popup/src/pages/bubbles.html +36 -0
- package/dist/packages/popup/src/pages/bubbles.js +214 -0
- package/dist/packages/popup/src/pages/chart-lib.js +262 -0
- package/dist/packages/popup/src/pages/chart.css +50 -0
- package/dist/packages/popup/src/pages/chart.html +56 -0
- package/dist/packages/popup/src/pages/chart.js +554 -0
- package/dist/packages/popup/src/pages/common.css +34 -0
- package/dist/packages/popup/src/pages/common.js +187 -0
- package/dist/packages/popup/src/pages/feeds.html +20 -0
- package/dist/packages/popup/src/pages/feeds.js +77 -0
- package/dist/packages/popup/src/pages/narrative.html +20 -0
- package/dist/packages/popup/src/pages/narrative.js +61 -0
- package/dist/packages/popup/src/pages/plans.css +30 -0
- package/dist/packages/popup/src/pages/plans.html +26 -0
- package/dist/packages/popup/src/pages/plans.js +82 -0
- package/dist/packages/popup/src/pages/roster.css +41 -0
- package/dist/packages/popup/src/pages/roster.html +25 -0
- package/dist/packages/popup/src/pages/roster.js +75 -0
- package/dist/packages/popup/src/pages/token.html +20 -0
- package/dist/packages/popup/src/pages/token.js +112 -0
- package/dist/packages/popup/src/pages/widget-sdk.js +224 -0
- package/dist/packages/popup/src/pages/widget.css +5 -0
- package/dist/packages/popup/src/pages/widget.html +21 -0
- package/dist/packages/popup/src/pages/widget.js +85 -0
- package/dist/packages/popup/src/protocol.js +31 -0
- package/dist/packages/popup/src/selftest.js +156 -0
- package/dist/packages/popup/src/server.js +582 -0
- package/dist/packages/popup/src/sinkproxy.js +167 -0
- package/dist/packages/popup/src/widget-html.js +231 -0
- package/dist/packages/popup/vendor/lightweight-charts/LICENSE +201 -0
- package/dist/packages/popup/vendor/lightweight-charts/NOTICE +2 -0
- package/dist/packages/popup/vendor/lightweight-charts/README.md +30 -0
- package/dist/packages/popup/vendor/lightweight-charts/VERSION +1 -0
- package/dist/packages/popup/vendor/lightweight-charts/lightweight-charts.standalone.production.js +7 -0
- package/dist/packages/recorder/bin/dexterm-recorder.mjs +11 -0
- package/dist/packages/recorder/src/cli.js +113 -0
- package/dist/packages/recorder/src/export.js +71 -0
- package/dist/packages/recorder/src/index.js +20 -0
- package/dist/packages/recorder/src/labels.js +151 -0
- package/dist/packages/recorder/src/open.js +29 -0
- package/dist/packages/recorder/src/recorder.js +553 -0
- package/dist/packages/recorder/src/schedule.js +43 -0
- package/dist/packages/recorder/src/schema.js +135 -0
- package/dist/packages/recorder/src/snapshot.js +191 -0
- package/dist/packages/recorder/src/sweep.js +52 -0
- package/dist/packages/recorder/src/verdicts.js +52 -0
- package/dist/packages/tui/src/bubbles.js +415 -0
- package/dist/packages/tui/src/canvas.js +370 -0
- package/dist/packages/tui/src/chrome.js +85 -0
- package/dist/packages/tui/src/color.js +133 -0
- package/dist/packages/tui/src/flush.js +62 -0
- package/dist/packages/tui/src/fmt.js +188 -0
- package/dist/packages/tui/src/fx-trade.js +278 -0
- package/dist/packages/tui/src/fx.js +527 -0
- package/dist/packages/tui/src/images/blocks.js +141 -0
- package/dist/packages/tui/src/images/coin.js +22 -0
- package/dist/packages/tui/src/images/detect.js +140 -0
- package/dist/packages/tui/src/images/index.js +7 -0
- package/dist/packages/tui/src/images/layer.js +146 -0
- package/dist/packages/tui/src/images/pixels.js +157 -0
- package/dist/packages/tui/src/images/protocols.js +87 -0
- package/dist/packages/tui/src/index.js +18 -0
- package/dist/packages/tui/src/keymap.js +357 -0
- package/dist/packages/tui/src/layout.js +11 -0
- package/dist/packages/tui/src/raster-font.js +195 -0
- package/dist/packages/tui/src/raster.js +213 -0
- package/dist/packages/tui/src/sound.js +177 -0
- package/dist/packages/tui/src/theme.js +182 -0
- package/dist/packages/tui/src/widgets.js +598 -0
- package/dist/packages/voice/src/controller.js +407 -0
- package/dist/packages/voice/src/doctor.js +131 -0
- package/dist/packages/voice/src/download.js +184 -0
- package/dist/packages/voice/src/engines.js +84 -0
- package/dist/packages/voice/src/index.js +20 -0
- package/dist/packages/voice/src/router.js +502 -0
- package/dist/packages/voice/src/stt/apple-helper.swift.js +103 -0
- package/dist/packages/voice/src/stt/apple.js +179 -0
- package/dist/packages/voice/src/stt/fake.js +34 -0
- package/dist/packages/voice/src/stt/whisper.js +112 -0
- package/dist/packages/voice/src/summary.js +44 -0
- package/dist/packages/voice/src/tts/espeak.js +131 -0
- package/dist/packages/voice/src/tts/fake.js +30 -0
- package/dist/packages/voice/src/tts/piper.js +206 -0
- package/dist/packages/voice/src/tts/say.js +132 -0
- package/dist/packages/voice/src/tts/voices.js +206 -0
- package/dist/packages/voice/src/types.js +3 -0
- package/package.json +38 -4
- package/README.md +0 -3
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { ATTR_BOLD, ATTR_DIM, ATTR_UNDERLINE } from "./canvas.js";
|
|
2
|
+
import { hexToRgb, mix } from "./color.js";
|
|
3
|
+
import { glyphBits, FONT_W, FONT_H } from "./raster-font.js";
|
|
4
|
+
class Px {
|
|
5
|
+
w;
|
|
6
|
+
h;
|
|
7
|
+
rgba;
|
|
8
|
+
constructor(w, h) { this.w = w; this.h = h; this.rgba = new Uint8Array(w * h * 4); }
|
|
9
|
+
rect(x, y, w, h, c, a = 1) {
|
|
10
|
+
const x0 = Math.max(0, Math.floor(x)), y0 = Math.max(0, Math.floor(y));
|
|
11
|
+
const x1 = Math.min(this.w, Math.floor(x + w)), y1 = Math.min(this.h, Math.floor(y + h));
|
|
12
|
+
for (let yy = y0; yy < y1; yy++)
|
|
13
|
+
for (let xx = x0; xx < x1; xx++) {
|
|
14
|
+
const i = (yy * this.w + xx) * 4;
|
|
15
|
+
if (a >= 1) {
|
|
16
|
+
this.rgba[i] = c[0];
|
|
17
|
+
this.rgba[i + 1] = c[1];
|
|
18
|
+
this.rgba[i + 2] = c[2];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.rgba[i] = Math.round(this.rgba[i] * (1 - a) + c[0] * a);
|
|
22
|
+
this.rgba[i + 1] = Math.round(this.rgba[i + 1] * (1 - a) + c[1] * a);
|
|
23
|
+
this.rgba[i + 2] = Math.round(this.rgba[i + 2] * (1 - a) + c[2] * a);
|
|
24
|
+
}
|
|
25
|
+
this.rgba[i + 3] = 255;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Box drawing: up, down, left, right weights (0 none, 1 light, 2 heavy/double) and a dashed flag.
|
|
30
|
+
const BOX = {
|
|
31
|
+
'─': '0011', '━': '0022', '│': '1100', '┃': '2200',
|
|
32
|
+
'┌': '0101', '╭': '0101', '┐': '0110', '╮': '0110', '└': '1001', '╰': '1001', '┘': '1010', '╯': '1010',
|
|
33
|
+
'┏': '0202', '┓': '0220', '┗': '2002', '┛': '2020',
|
|
34
|
+
'├': '1101', '┤': '1110', '┬': '0111', '┴': '1011', '┼': '1111',
|
|
35
|
+
'┣': '2202', '┫': '2220', '┳': '0222', '┻': '2022', '╋': '2222',
|
|
36
|
+
'═': '0022', '║': '2200', '╔': '0202', '╗': '0220', '╚': '2002', '╝': '2020', '╠': '2202', '╣': '2220', '╦': '0222', '╩': '2022', '╬': '2222',
|
|
37
|
+
'╴': '0010', '╵': '1000', '╶': '0001', '╷': '0100', '╸': '0020', '╹': '2000', '╺': '0002', '╻': '0200',
|
|
38
|
+
};
|
|
39
|
+
const DASH_H = new Set(['┄', '┅', '┈', '┉', '╌', '╍']);
|
|
40
|
+
const DASH_V = new Set(['┆', '┇', '┊', '┋', '╎', '╏']);
|
|
41
|
+
const EIGHTHS_LOW = '▁▂▃▄▅▆▇█';
|
|
42
|
+
const EIGHTHS_LEFT = '▏▎▍▌▋▊▉█';
|
|
43
|
+
const SHADES = { '░': 0.25, '▒': 0.5, '▓': 0.75 };
|
|
44
|
+
// Quadrants: TL, TR, BL, BR.
|
|
45
|
+
const QUAD = {
|
|
46
|
+
'▘': [1, 0, 0, 0], '▝': [0, 1, 0, 0], '▖': [0, 0, 1, 0], '▗': [0, 0, 0, 1], '▚': [1, 0, 0, 1], '▞': [0, 1, 1, 0],
|
|
47
|
+
'▛': [1, 1, 1, 0], '▜': [1, 1, 0, 1], '▙': [1, 0, 1, 1], '▟': [0, 1, 1, 1], '▀': [1, 1, 0, 0], '▄': [0, 0, 1, 1], '▌': [1, 0, 1, 0], '▐': [0, 1, 0, 1],
|
|
48
|
+
};
|
|
49
|
+
/** Draw one non-text glyph procedurally. Returns false when the glyph is not one of these families. */
|
|
50
|
+
function drawSpecial(p, ch, x, y, cw, chh, fg, bg, scale) {
|
|
51
|
+
const box = BOX[ch];
|
|
52
|
+
if (box) {
|
|
53
|
+
const t1 = Math.max(1, scale), t2 = Math.max(2, scale * 2);
|
|
54
|
+
const [u, d, l, r] = [...box].map(Number);
|
|
55
|
+
const cx = x + Math.floor(cw / 2), cy = y + Math.floor(chh / 2);
|
|
56
|
+
const th = (wgt) => (wgt === 2 ? t2 : t1);
|
|
57
|
+
const hT = Math.max(th(l), th(r)), vT = Math.max(th(u), th(d));
|
|
58
|
+
if (l)
|
|
59
|
+
p.rect(x, cy - Math.floor(th(l) / 2), cx - x + Math.ceil(vT / 2), th(l), fg);
|
|
60
|
+
if (r)
|
|
61
|
+
p.rect(cx - Math.floor(vT / 2), cy - Math.floor(th(r) / 2), x + cw - (cx - Math.floor(vT / 2)), th(r), fg);
|
|
62
|
+
if (u)
|
|
63
|
+
p.rect(cx - Math.floor(th(u) / 2), y, th(u), cy - y + Math.ceil(hT / 2), fg);
|
|
64
|
+
if (d)
|
|
65
|
+
p.rect(cx - Math.floor(th(d) / 2), cy - Math.floor(hT / 2), th(d), y + chh - (cy - Math.floor(hT / 2)), fg);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (DASH_H.has(ch)) {
|
|
69
|
+
const t = Math.max(1, scale);
|
|
70
|
+
const seg = Math.max(2, Math.floor(cw / 4));
|
|
71
|
+
for (let k = 0; k < cw; k += seg * 2)
|
|
72
|
+
p.rect(x + k, y + Math.floor(chh / 2) - Math.floor(t / 2), seg, t, fg);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (DASH_V.has(ch)) {
|
|
76
|
+
const t = Math.max(1, scale);
|
|
77
|
+
const seg = Math.max(2, Math.floor(chh / 6));
|
|
78
|
+
for (let k = 0; k < chh; k += seg * 2)
|
|
79
|
+
p.rect(x + Math.floor(cw / 2) - Math.floor(t / 2), y + k, t, seg, fg);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const low = EIGHTHS_LOW.indexOf(ch);
|
|
83
|
+
if (low >= 0) {
|
|
84
|
+
const hh = Math.round((chh * (low + 1)) / 8);
|
|
85
|
+
p.rect(x, y + chh - hh, cw, hh, fg);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const left = EIGHTHS_LEFT.indexOf(ch);
|
|
89
|
+
if (left >= 0) {
|
|
90
|
+
p.rect(x, y, Math.round((cw * (left + 1)) / 8), chh, fg);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (ch === '▔') {
|
|
94
|
+
p.rect(x, y, cw, Math.max(1, Math.round(chh / 8)), fg);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (ch === '▕') {
|
|
98
|
+
const ww = Math.max(1, Math.round(cw / 8));
|
|
99
|
+
p.rect(x + cw - ww, y, ww, chh, fg);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
const shade = SHADES[ch];
|
|
103
|
+
if (shade !== undefined) {
|
|
104
|
+
p.rect(x, y, cw, chh, [Math.round(bg[0] + (fg[0] - bg[0]) * shade), Math.round(bg[1] + (fg[1] - bg[1]) * shade), Math.round(bg[2] + (fg[2] - bg[2]) * shade)]);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
const q = QUAD[ch];
|
|
108
|
+
if (q) {
|
|
109
|
+
const hw = Math.floor(cw / 2), hh = Math.floor(chh / 2);
|
|
110
|
+
if (q[0])
|
|
111
|
+
p.rect(x, y, hw, hh, fg);
|
|
112
|
+
if (q[1])
|
|
113
|
+
p.rect(x + hw, y, cw - hw, hh, fg);
|
|
114
|
+
if (q[2])
|
|
115
|
+
p.rect(x, y + hh, hw, chh - hh, fg);
|
|
116
|
+
if (q[3])
|
|
117
|
+
p.rect(x + hw, y + hh, cw - hw, chh - hh, fg);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
121
|
+
if (code >= 0x2800 && code <= 0x28ff) {
|
|
122
|
+
const bits = code - 0x2800;
|
|
123
|
+
// dot n → (column, row): 1(0,0) 2(0,1) 3(0,2) 4(1,0) 5(1,1) 6(1,2) 7(0,3) 8(1,3)
|
|
124
|
+
const dots = [[0x01, 0, 0], [0x02, 0, 1], [0x04, 0, 2], [0x08, 1, 0], [0x10, 1, 1], [0x20, 1, 2], [0x40, 0, 3], [0x80, 1, 3]];
|
|
125
|
+
const dw = Math.max(1, Math.floor(cw / 4)), dh = Math.max(1, Math.floor(chh / 8));
|
|
126
|
+
for (const [bit, col, row] of dots)
|
|
127
|
+
if (bits & bit)
|
|
128
|
+
p.rect(x + Math.floor((cw * (col * 2 + 1)) / 4) - Math.floor(dw / 2), y + Math.floor((chh * (row * 2 + 1)) / 8) - Math.floor(dh / 2), dw, dh, fg);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
if (ch === '╱' || ch === '╲' || ch === '╳') {
|
|
132
|
+
const t = Math.max(1, scale);
|
|
133
|
+
for (let k = 0; k < chh; k++) {
|
|
134
|
+
const fx = Math.floor((k * cw) / chh);
|
|
135
|
+
if (ch !== '╲')
|
|
136
|
+
p.rect(x + cw - 1 - fx - Math.floor(t / 2), y + k, t, 1, fg);
|
|
137
|
+
if (ch !== '╱')
|
|
138
|
+
p.rect(x + fx - Math.floor(t / 2), y + k, t, 1, fg);
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
/** Rasterize every cell of a canvas: background, glyph (font or procedural), attributes, then image slots. */
|
|
145
|
+
export function rasterizeCanvas(c, opts = {}) {
|
|
146
|
+
const cw = opts.cellW ?? 12, chh = opts.cellH ?? 24, scale = opts.scale ?? 2;
|
|
147
|
+
const p = new Px(c.w * cw, c.h * chh);
|
|
148
|
+
const gx = Math.floor((cw - FONT_W * scale) / 2), gy = Math.floor((chh - FONT_H * scale) / 2);
|
|
149
|
+
const rgbCache = new Map();
|
|
150
|
+
const rgb = (h) => { let v = rgbCache.get(h); if (!v) {
|
|
151
|
+
v = hexToRgb(h);
|
|
152
|
+
rgbCache.set(h, v);
|
|
153
|
+
} return v; };
|
|
154
|
+
for (let row = 0; row < c.h; row++)
|
|
155
|
+
for (let col = 0; col < c.w; col++) {
|
|
156
|
+
const i = row * c.w + col;
|
|
157
|
+
const x = col * cw, y = row * chh;
|
|
158
|
+
const bgHex = c.bg[i];
|
|
159
|
+
const bg = rgb(bgHex);
|
|
160
|
+
p.rect(x, y, cw, chh, bg);
|
|
161
|
+
const ch = c.ch[i];
|
|
162
|
+
if (ch === ' ' || ch === '')
|
|
163
|
+
continue;
|
|
164
|
+
const at = c.at[i];
|
|
165
|
+
const fg = rgb(at & ATTR_DIM ? mix(c.fg[i], bgHex, 0.45) : c.fg[i]);
|
|
166
|
+
if (drawSpecial(p, ch, x, y, cw, chh, fg, bg, scale))
|
|
167
|
+
continue;
|
|
168
|
+
let bits = glyphBits(ch);
|
|
169
|
+
// an accented LETTER falls back to its base letter (é → e); never a digit or symbol, whose compatibility form
|
|
170
|
+
// can change meaning (a subscript ₅ is not a 5)
|
|
171
|
+
if (!bits && /^\p{L}$/u.test(ch)) {
|
|
172
|
+
const base = ch.normalize('NFD').replace(/\p{M}+/gu, '');
|
|
173
|
+
if (base && base !== ch)
|
|
174
|
+
bits = glyphBits(base[0]);
|
|
175
|
+
}
|
|
176
|
+
if (!bits) {
|
|
177
|
+
// tofu: a hollow box so an unsupported glyph is visible, never silently dropped
|
|
178
|
+
const t = Math.max(1, Math.floor(scale / 2));
|
|
179
|
+
const bx = x + gx + scale, by = y + gy + scale * 2, bw = (FONT_W - 2) * scale, bh = (FONT_H - 4) * scale;
|
|
180
|
+
p.rect(bx, by, bw, t, fg);
|
|
181
|
+
p.rect(bx, by + bh - t, bw, t, fg);
|
|
182
|
+
p.rect(bx, by, t, bh, fg);
|
|
183
|
+
p.rect(bx + bw - t, by, t, bh, fg);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const bold = (at & ATTR_BOLD) !== 0;
|
|
187
|
+
for (let yy = 0; yy < FONT_H; yy++)
|
|
188
|
+
for (let xx = 0; xx < FONT_W; xx++) {
|
|
189
|
+
if (!bits[yy * FONT_W + xx])
|
|
190
|
+
continue;
|
|
191
|
+
p.rect(x + gx + xx * scale, y + gy + yy * scale, scale + (bold ? 1 : 0), scale, fg);
|
|
192
|
+
}
|
|
193
|
+
if (at & ATTR_UNDERLINE)
|
|
194
|
+
p.rect(x, y + chh - Math.max(1, scale), cw, Math.max(1, Math.floor(scale / 2)), fg);
|
|
195
|
+
}
|
|
196
|
+
// Pixel image slots (coin images) recorded by the canvas in 'pixels' mode: nearest-neighbour into the cell rect.
|
|
197
|
+
for (const s of c.images) {
|
|
198
|
+
const rx = s.x * cw, ry = s.y * chh, rw = s.w * cw, rh = s.h * chh;
|
|
199
|
+
const { w: iw, h: ih, rgba } = s.img;
|
|
200
|
+
if (!iw || !ih)
|
|
201
|
+
continue;
|
|
202
|
+
for (let yy = 0; yy < rh; yy++)
|
|
203
|
+
for (let xx = 0; xx < rw; xx++) {
|
|
204
|
+
const sx = Math.min(iw - 1, Math.floor((xx * iw) / rw)), sy = Math.min(ih - 1, Math.floor((yy * ih) / rh));
|
|
205
|
+
const si = (sy * iw + sx) * 4;
|
|
206
|
+
const a = rgba[si + 3] / 255;
|
|
207
|
+
if (a <= 0)
|
|
208
|
+
continue;
|
|
209
|
+
p.rect(rx + xx, ry + yy, 1, 1, [rgba[si], rgba[si + 1], rgba[si + 2]], a);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return { w: p.w, h: p.h, rgba: p.rgba };
|
|
213
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// @dexterm/tui — sound cues (task-1340, ported from prototype-v2/src/sound.mjs, task-1291). Synthesized locally
|
|
2
|
+
// into tiny 16-bit mono WAV files on first use (~/.dexterm/sounds, DEXTERM_HOME overrides) and played with the
|
|
3
|
+
// OS player (`afplay` on macOS, `paplay`/`aplay` on Linux) in a DETACHED child: never blocks the render loop,
|
|
4
|
+
// never waits. MUTED by default; `--sound` (or DEXTERM_SOUND=1) turns the cues on. Cues only ever follow a
|
|
5
|
+
// SETTLED outcome (playMoment is called with the same moment fireMoment produced): nothing chirps on a quote.
|
|
6
|
+
//
|
|
7
|
+
// Cues (all short, all quiet, none mocking):
|
|
8
|
+
// buy up-chirp sine sweep 440→880 Hz, 140 ms
|
|
9
|
+
// sell down-sweep sine sweep 880→440 Hz, 160 ms
|
|
10
|
+
// profit chime E5 + B5 with a soft 2nd harmonic, 420 ms
|
|
11
|
+
// loss thud low sine 110→50 Hz + brief noise, 200 ms
|
|
12
|
+
// error buzz 120 Hz square-ish with 25 Hz amplitude modulation, 220 ms
|
|
13
|
+
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
14
|
+
import { spawn } from 'node:child_process';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
const RATE = 22050;
|
|
18
|
+
export const CUES = ['buy', 'sell', 'profit', 'loss', 'error'];
|
|
19
|
+
/** Where the cue files live: `$DEXTERM_HOME/sounds`, default `~/.dexterm/sounds`. */
|
|
20
|
+
export function soundDir(env = process.env) {
|
|
21
|
+
return join(env.DEXTERM_HOME && env.DEXTERM_HOME.trim() ? env.DEXTERM_HOME : join(homedir(), '.dexterm'), 'sounds');
|
|
22
|
+
}
|
|
23
|
+
/** `--sound` or DEXTERM_SOUND=1 turns cues on; everything else is muted. */
|
|
24
|
+
export function soundOn(flag, env = process.env) {
|
|
25
|
+
if (flag)
|
|
26
|
+
return true;
|
|
27
|
+
const e = (env.DEXTERM_SOUND ?? '').trim().toLowerCase();
|
|
28
|
+
return e === '1' || e === 'true' || e === 'on';
|
|
29
|
+
}
|
|
30
|
+
function env(i, n, attack = 0.01, release = 0.4) {
|
|
31
|
+
const t = i / n;
|
|
32
|
+
const a = Math.min(1, (i / RATE) / attack);
|
|
33
|
+
const r = t > 1 - release ? (1 - t) / release : 1;
|
|
34
|
+
return a * r;
|
|
35
|
+
}
|
|
36
|
+
/** Synthesize one cue as float samples in [-1, 1], peak-normalised to −6 dBFS. */
|
|
37
|
+
export function synth(name) {
|
|
38
|
+
const dur = { buy: 0.14, sell: 0.16, profit: 0.42, loss: 0.2, error: 0.22 }[name];
|
|
39
|
+
const n = Math.floor(RATE * dur);
|
|
40
|
+
const out = new Float32Array(n);
|
|
41
|
+
let ph = 0, ph2 = 0;
|
|
42
|
+
let seed = 12345;
|
|
43
|
+
const noise = () => { seed = (seed * 1664525 + 1013904223) >>> 0; return seed / 4294967296 * 2 - 1; };
|
|
44
|
+
for (let i = 0; i < n; i++) {
|
|
45
|
+
const t = i / RATE, u = i / n;
|
|
46
|
+
let s = 0;
|
|
47
|
+
if (name === 'buy') {
|
|
48
|
+
const f = 440 * Math.pow(2, u);
|
|
49
|
+
ph += 2 * Math.PI * f / RATE;
|
|
50
|
+
s = Math.sin(ph) * 0.8 + Math.sin(2 * ph) * 0.15;
|
|
51
|
+
s *= env(i, n, 0.005, 0.5);
|
|
52
|
+
}
|
|
53
|
+
else if (name === 'sell') {
|
|
54
|
+
const f = 880 * Math.pow(0.5, u);
|
|
55
|
+
ph += 2 * Math.PI * f / RATE;
|
|
56
|
+
s = Math.sin(ph) * 0.8 + Math.sin(2 * ph) * 0.1;
|
|
57
|
+
s *= env(i, n, 0.005, 0.5);
|
|
58
|
+
}
|
|
59
|
+
else if (name === 'profit') {
|
|
60
|
+
ph += 2 * Math.PI * 659.25 / RATE;
|
|
61
|
+
ph2 += 2 * Math.PI * 987.77 / RATE;
|
|
62
|
+
const second = t > 0.09 ? 1 : 0;
|
|
63
|
+
s = (Math.sin(ph) * 0.6 + Math.sin(2 * ph) * 0.12) * Math.exp(-t * 6) + second * (Math.sin(ph2) * 0.6 + Math.sin(2 * ph2) * 0.1) * Math.exp(-(t - 0.09) * 5);
|
|
64
|
+
s *= env(i, n, 0.004, 0.25);
|
|
65
|
+
}
|
|
66
|
+
else if (name === 'loss') {
|
|
67
|
+
const f = 110 * Math.pow(50 / 110, u);
|
|
68
|
+
ph += 2 * Math.PI * f / RATE;
|
|
69
|
+
s = Math.sin(ph) * 0.9 * Math.exp(-t * 9) + noise() * 0.12 * Math.exp(-t * 40);
|
|
70
|
+
s *= env(i, n, 0.003, 0.3);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
ph += 2 * Math.PI * 120 / RATE;
|
|
74
|
+
const sq = Math.tanh(Math.sin(ph) * 3) * 0.5;
|
|
75
|
+
const am = 0.55 + 0.45 * Math.sin(2 * Math.PI * 25 * t);
|
|
76
|
+
s = sq * am * env(i, n, 0.004, 0.2);
|
|
77
|
+
}
|
|
78
|
+
out[i] = s;
|
|
79
|
+
}
|
|
80
|
+
let peak = 0;
|
|
81
|
+
for (const x of out)
|
|
82
|
+
peak = Math.max(peak, Math.abs(x));
|
|
83
|
+
const g = peak > 0 ? 0.5 / peak : 1;
|
|
84
|
+
return out.map((x) => x * g);
|
|
85
|
+
}
|
|
86
|
+
/** 16-bit mono PCM WAV container. */
|
|
87
|
+
export function wav(samples) {
|
|
88
|
+
const n = samples.length;
|
|
89
|
+
const buf = Buffer.alloc(44 + n * 2);
|
|
90
|
+
buf.write('RIFF', 0);
|
|
91
|
+
buf.writeUInt32LE(36 + n * 2, 4);
|
|
92
|
+
buf.write('WAVE', 8);
|
|
93
|
+
buf.write('fmt ', 12);
|
|
94
|
+
buf.writeUInt32LE(16, 16);
|
|
95
|
+
buf.writeUInt16LE(1, 20);
|
|
96
|
+
buf.writeUInt16LE(1, 22);
|
|
97
|
+
buf.writeUInt32LE(RATE, 24);
|
|
98
|
+
buf.writeUInt32LE(RATE * 2, 28);
|
|
99
|
+
buf.writeUInt16LE(2, 32);
|
|
100
|
+
buf.writeUInt16LE(16, 34);
|
|
101
|
+
buf.write('data', 36);
|
|
102
|
+
buf.writeUInt32LE(n * 2, 40);
|
|
103
|
+
for (let i = 0; i < n; i++)
|
|
104
|
+
buf.writeInt16LE(Math.max(-32768, Math.min(32767, Math.round(samples[i] * 32767))), 44 + i * 2);
|
|
105
|
+
return buf;
|
|
106
|
+
}
|
|
107
|
+
/** Write every cue to `dir` (created). Idempotent; ~30 KB total. Returns the paths. */
|
|
108
|
+
export function writeCues(dir) {
|
|
109
|
+
mkdirSync(dir, { recursive: true });
|
|
110
|
+
const out = [];
|
|
111
|
+
for (const name of CUES) {
|
|
112
|
+
const p = join(dir, `${name}.wav`);
|
|
113
|
+
if (!existsSync(p))
|
|
114
|
+
writeFileSync(p, wav(synth(name)));
|
|
115
|
+
out.push(p);
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
/** The OS player for this platform (null = no known player → cues are silently skipped). */
|
|
120
|
+
export function defaultPlayer(platform = process.platform) {
|
|
121
|
+
if (platform === 'darwin')
|
|
122
|
+
return 'afplay';
|
|
123
|
+
if (platform === 'linux')
|
|
124
|
+
return 'paplay';
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
/** Non-blocking playback. Returns true when a cue was dispatched (false when muted / no player / no file). */
|
|
128
|
+
export function play(name, sound, opts = {}) {
|
|
129
|
+
if (!sound || !sound.on)
|
|
130
|
+
return false;
|
|
131
|
+
const dir = opts.dir ?? soundDir();
|
|
132
|
+
const player = opts.player === undefined ? defaultPlayer() : opts.player;
|
|
133
|
+
if (opts.log) {
|
|
134
|
+
opts.log.push({ name, at: Date.now() });
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
if (!player)
|
|
138
|
+
return false;
|
|
139
|
+
try {
|
|
140
|
+
writeCues(dir);
|
|
141
|
+
const file = join(dir, `${name}.wav`);
|
|
142
|
+
const child = (opts.spawnFn ?? spawn)(player, [file], { detached: true, stdio: 'ignore' });
|
|
143
|
+
child.on('error', () => { });
|
|
144
|
+
child.unref();
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Which cues a settled moment plays (sell sweep, then the verdict cue 150 ms later). Inflight plays nothing. */
|
|
152
|
+
export function cuesFor(kind, milestone = null) {
|
|
153
|
+
if (kind === 'buy')
|
|
154
|
+
return milestone === 'first' ? [['buy', 0], ['profit', 180]] : [['buy', 0]];
|
|
155
|
+
if (kind === 'profit')
|
|
156
|
+
return [['sell', 0], ['profit', 150]];
|
|
157
|
+
if (kind === 'loss')
|
|
158
|
+
return [['sell', 0], ['loss', 150]];
|
|
159
|
+
if (kind === 'failed')
|
|
160
|
+
return [['error', 0]];
|
|
161
|
+
if (kind === 'runner')
|
|
162
|
+
return [['profit', 0]];
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
export function playMoment(kind, milestone, sound, opts = {}) {
|
|
166
|
+
let n = 0;
|
|
167
|
+
for (const [name, delay] of cuesFor(kind, milestone)) {
|
|
168
|
+
n += 1;
|
|
169
|
+
if (delay) {
|
|
170
|
+
const tm = setTimeout(() => play(name, sound, opts), delay);
|
|
171
|
+
tm.unref?.();
|
|
172
|
+
}
|
|
173
|
+
else
|
|
174
|
+
play(name, sound, opts);
|
|
175
|
+
}
|
|
176
|
+
return n;
|
|
177
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/** Effect tokens for the non-cyberspace themes: effects still run, but their glyphs sit close to the theme's own dim/border. */
|
|
2
|
+
const BASE_FX = {
|
|
3
|
+
rain: ['#1a2230', '#243244', '#33465c', '#5b7893'],
|
|
4
|
+
rainPump: ['#2a2414', '#5a4a1a', '#a98a2a', '#ffe08a'],
|
|
5
|
+
rainDump: ['#2a1418', '#5a1f2a', '#a93145', '#ff9db0'],
|
|
6
|
+
magenta: '#f472b6',
|
|
7
|
+
cyan: '#22d3ee',
|
|
8
|
+
coral: '#d97757',
|
|
9
|
+
acid: '#fbbf24',
|
|
10
|
+
glow: '#1b3d2c',
|
|
11
|
+
scan: '#000000',
|
|
12
|
+
logo: ['#22d3ee', '#2dd4bf', '#34d399'],
|
|
13
|
+
};
|
|
14
|
+
export const THEMES = {
|
|
15
|
+
cyberspace: {
|
|
16
|
+
name: 'cyberspace',
|
|
17
|
+
bg: '#020507',
|
|
18
|
+
panel: '#03090c',
|
|
19
|
+
panelAlt: '#051017',
|
|
20
|
+
border: '#0c3a24',
|
|
21
|
+
borderFocus: '#39ff14',
|
|
22
|
+
text: '#eafff0', // numbers, tickers: near-white with a phosphor cast (≈ 19:1 on bg)
|
|
23
|
+
muted: '#62c98a', // secondary labels (≈ 9:1 on bg)
|
|
24
|
+
dim: '#3aa866', // tertiary: gridlines, hints (6.8:1 on bg, 4.9:1 on the selected row)
|
|
25
|
+
accent: '#00f0ff', // electric cyan: selection, sort, links
|
|
26
|
+
accentSoft: '#043a40',
|
|
27
|
+
up: '#5dff6e', // phosphor green (direction also carries a ▲ glyph)
|
|
28
|
+
upSoft: '#0a3a16',
|
|
29
|
+
down: '#ff3b6b', // hot red/pink (direction also carries a ▼ glyph)
|
|
30
|
+
downSoft: '#3d0a1a',
|
|
31
|
+
warn: '#f5ff2d', // acid yellow
|
|
32
|
+
warnSoft: '#35380a',
|
|
33
|
+
ai: '#d97757', // Claude coral/terracotta: the analyst's voice
|
|
34
|
+
aiSoft: '#3a1a10',
|
|
35
|
+
pump: '#ff2bd6', // hot magenta
|
|
36
|
+
dbc: '#ff8a3d',
|
|
37
|
+
raydium: '#00f0ff',
|
|
38
|
+
meteora: '#ffb02e',
|
|
39
|
+
bonk: '#f5ff2d',
|
|
40
|
+
selBg: '#082618', // was #0a2e1b; darkened after the calm audit so `down` digits on the selected row clear 4.5:1 (4.29 → 4.68)
|
|
41
|
+
headBg: '#020a08',
|
|
42
|
+
tabActiveBg: '#0b3b22',
|
|
43
|
+
sparkUp: '#5dff6e',
|
|
44
|
+
sparkDown: '#ff3b6b',
|
|
45
|
+
heat: ['#062013', '#0a4a2a', '#13a04a', '#39ff14'],
|
|
46
|
+
rain: ['#06301a', '#0b5a2c', '#16a848', '#b8ffc8'],
|
|
47
|
+
rainPump: ['#3a2a05', '#8a6410', '#f0b429', '#fff1b3'],
|
|
48
|
+
rainDump: ['#3a0a12', '#7a1226', '#d12a4a', '#ffb3c1'],
|
|
49
|
+
magenta: '#ff2bd6',
|
|
50
|
+
cyan: '#00f0ff',
|
|
51
|
+
coral: '#d97757',
|
|
52
|
+
acid: '#f5ff2d',
|
|
53
|
+
glow: '#0f4d2a',
|
|
54
|
+
scan: '#000000',
|
|
55
|
+
logo: ['#39ff14', '#00f0ff', '#ff2bd6'],
|
|
56
|
+
},
|
|
57
|
+
midnight: {
|
|
58
|
+
name: 'midnight',
|
|
59
|
+
bg: '#0b0e14',
|
|
60
|
+
panel: '#0f131b',
|
|
61
|
+
panelAlt: '#121823',
|
|
62
|
+
border: '#1f2733',
|
|
63
|
+
borderFocus: '#2dd4bf',
|
|
64
|
+
text: '#d6dde6',
|
|
65
|
+
muted: '#7c8794',
|
|
66
|
+
dim: '#4b5563',
|
|
67
|
+
accent: '#22d3ee',
|
|
68
|
+
accentSoft: '#164e63',
|
|
69
|
+
up: '#34d399',
|
|
70
|
+
upSoft: '#064e3b',
|
|
71
|
+
down: '#f87171',
|
|
72
|
+
downSoft: '#4c1d24',
|
|
73
|
+
warn: '#fbbf24',
|
|
74
|
+
warnSoft: '#3f2f05',
|
|
75
|
+
ai: '#a78bfa',
|
|
76
|
+
aiSoft: '#2e1065',
|
|
77
|
+
pump: '#f472b6',
|
|
78
|
+
dbc: '#fb923c',
|
|
79
|
+
raydium: '#60a5fa',
|
|
80
|
+
meteora: '#f59e0b',
|
|
81
|
+
bonk: '#fde047',
|
|
82
|
+
selBg: '#182233',
|
|
83
|
+
headBg: '#0d1118',
|
|
84
|
+
tabActiveBg: '#1b2a36',
|
|
85
|
+
sparkUp: '#34d399',
|
|
86
|
+
sparkDown: '#f87171',
|
|
87
|
+
heat: ['#1b2a36', '#164e63', '#0e7490', '#22d3ee'],
|
|
88
|
+
...BASE_FX,
|
|
89
|
+
},
|
|
90
|
+
ember: {
|
|
91
|
+
name: 'ember',
|
|
92
|
+
bg: '#120d0b',
|
|
93
|
+
panel: '#17110e',
|
|
94
|
+
panelAlt: '#1d1512',
|
|
95
|
+
border: '#3a2a22',
|
|
96
|
+
borderFocus: '#fb923c',
|
|
97
|
+
text: '#eadfd6',
|
|
98
|
+
muted: '#9a8578',
|
|
99
|
+
dim: '#5e4a3f',
|
|
100
|
+
accent: '#fb923c',
|
|
101
|
+
accentSoft: '#5a2e0f',
|
|
102
|
+
up: '#4ade80',
|
|
103
|
+
upSoft: '#113b26',
|
|
104
|
+
down: '#fb7185',
|
|
105
|
+
downSoft: '#4c1a27',
|
|
106
|
+
warn: '#facc15',
|
|
107
|
+
warnSoft: '#433a07',
|
|
108
|
+
ai: '#c4b5fd',
|
|
109
|
+
aiSoft: '#2d1b55',
|
|
110
|
+
pump: '#f472b6',
|
|
111
|
+
dbc: '#fdba74',
|
|
112
|
+
raydium: '#7dd3fc',
|
|
113
|
+
meteora: '#fcd34d',
|
|
114
|
+
bonk: '#fde68a',
|
|
115
|
+
selBg: '#2a1c15',
|
|
116
|
+
headBg: '#150f0c',
|
|
117
|
+
tabActiveBg: '#3a2416',
|
|
118
|
+
sparkUp: '#4ade80',
|
|
119
|
+
sparkDown: '#fb7185',
|
|
120
|
+
heat: ['#2a1c15', '#5a2e0f', '#b45309', '#fb923c'],
|
|
121
|
+
...BASE_FX,
|
|
122
|
+
rain: ['#2a1c15', '#3f2a1c', '#5e3f2a', '#9a6a45'],
|
|
123
|
+
logo: ['#fb923c', '#facc15', '#fb7185'],
|
|
124
|
+
},
|
|
125
|
+
paper: {
|
|
126
|
+
name: 'paper',
|
|
127
|
+
bg: '#f6f3ee',
|
|
128
|
+
panel: '#fbfaf7',
|
|
129
|
+
panelAlt: '#f0ece5',
|
|
130
|
+
border: '#d9d2c7',
|
|
131
|
+
borderFocus: '#0f766e',
|
|
132
|
+
text: '#1f2933',
|
|
133
|
+
muted: '#6b7280',
|
|
134
|
+
dim: '#a8a29e',
|
|
135
|
+
accent: '#0e7490',
|
|
136
|
+
accentSoft: '#cffafe',
|
|
137
|
+
up: '#15803d',
|
|
138
|
+
upSoft: '#dcfce7',
|
|
139
|
+
down: '#b91c1c',
|
|
140
|
+
downSoft: '#fee2e2',
|
|
141
|
+
warn: '#b45309',
|
|
142
|
+
warnSoft: '#fef3c7',
|
|
143
|
+
ai: '#6d28d9',
|
|
144
|
+
aiSoft: '#ede9fe',
|
|
145
|
+
pump: '#be185d',
|
|
146
|
+
dbc: '#c2410c',
|
|
147
|
+
raydium: '#1d4ed8',
|
|
148
|
+
meteora: '#b45309',
|
|
149
|
+
bonk: '#a16207',
|
|
150
|
+
selBg: '#e7e1d6',
|
|
151
|
+
headBg: '#ebe6dd',
|
|
152
|
+
tabActiveBg: '#dcd5c8',
|
|
153
|
+
sparkUp: '#15803d',
|
|
154
|
+
sparkDown: '#b91c1c',
|
|
155
|
+
heat: ['#e7e1d6', '#a5f3fc', '#22d3ee', '#0e7490'],
|
|
156
|
+
...BASE_FX,
|
|
157
|
+
rain: ['#ece7df', '#ddd6cb', '#c6bdb0', '#9c9184'],
|
|
158
|
+
glow: '#dcefe4',
|
|
159
|
+
scan: '#ffffff',
|
|
160
|
+
logo: ['#0e7490', '#0f766e', '#6d28d9'],
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
/** `t` cycles in this order: cyberspace → midnight → ember → paper. */
|
|
164
|
+
export const THEME_NAMES = ['cyberspace', 'midnight', 'ember', 'paper'];
|
|
165
|
+
export const DEFAULT_THEME = 'cyberspace';
|
|
166
|
+
export function isThemeName(s) {
|
|
167
|
+
return THEME_NAMES.includes(s);
|
|
168
|
+
}
|
|
169
|
+
export function nextTheme(current) {
|
|
170
|
+
const i = THEME_NAMES.indexOf(current.name);
|
|
171
|
+
return THEMES[THEME_NAMES[(i + 1) % THEME_NAMES.length]];
|
|
172
|
+
}
|
|
173
|
+
export function launchpadColor(theme, lp) {
|
|
174
|
+
switch (lp) {
|
|
175
|
+
case 'pump.fun': return theme.pump;
|
|
176
|
+
case 'dbc': return theme.dbc;
|
|
177
|
+
case 'raydium': return theme.raydium;
|
|
178
|
+
case 'meteora': return theme.meteora;
|
|
179
|
+
case 'bonk': return theme.bonk;
|
|
180
|
+
default: return theme.muted;
|
|
181
|
+
}
|
|
182
|
+
}
|