@agentdeck/bridge 0.2.2 → 1.0.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/assets/fm-helper/agentdeck-fm-helper +0 -0
- package/assets/fonts/IBMPlexSans-Bold.ttf +0 -0
- package/assets/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Bold.ttf +0 -0
- package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
- package/assets/fonts/LICENSES.md +22 -0
- package/dist/adapters/claude-code.d.ts +6 -0
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +8 -0
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/openclaw.d.ts +24 -0
- package/dist/adapters/openclaw.d.ts.map +1 -1
- package/dist/adapters/openclaw.js +291 -35
- package/dist/adapters/openclaw.js.map +1 -1
- package/dist/adapters/opencode-adapter.d.ts +59 -0
- package/dist/adapters/opencode-adapter.d.ts.map +1 -1
- package/dist/adapters/opencode-adapter.js +297 -35
- package/dist/adapters/opencode-adapter.js.map +1 -1
- package/dist/adb-reverse.d.ts +1 -1
- package/dist/adb-reverse.js +1 -1
- package/dist/antigravity-local.d.ts +1 -0
- package/dist/antigravity-local.d.ts.map +1 -1
- package/dist/antigravity-local.js +33 -0
- package/dist/antigravity-local.js.map +1 -1
- package/dist/apme/adapters/claude-hook.d.ts.map +1 -1
- package/dist/apme/adapters/claude-hook.js +5 -0
- package/dist/apme/adapters/claude-hook.js.map +1 -1
- package/dist/apme/adapters/codex-hook.d.ts +17 -0
- package/dist/apme/adapters/codex-hook.d.ts.map +1 -0
- package/dist/apme/adapters/codex-hook.js +95 -0
- package/dist/apme/adapters/codex-hook.js.map +1 -0
- package/dist/apme/adapters/codex-turn-manager.d.ts +86 -0
- package/dist/apme/adapters/codex-turn-manager.d.ts.map +1 -0
- package/dist/apme/adapters/codex-turn-manager.js +496 -0
- package/dist/apme/adapters/codex-turn-manager.js.map +1 -0
- package/dist/apme/adapters/openclaw-hook.d.ts +99 -0
- package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -0
- package/dist/apme/adapters/openclaw-hook.js +234 -0
- package/dist/apme/adapters/openclaw-hook.js.map +1 -0
- package/dist/apme/adapters/opencode-hook.d.ts +56 -0
- package/dist/apme/adapters/opencode-hook.d.ts.map +1 -0
- package/dist/apme/adapters/opencode-hook.js +182 -0
- package/dist/apme/adapters/opencode-hook.js.map +1 -0
- package/dist/apme/adapters/timeline.d.ts.map +1 -1
- package/dist/apme/adapters/timeline.js +6 -1
- package/dist/apme/adapters/timeline.js.map +1 -1
- package/dist/apme/antigravity-transcript.d.ts +18 -0
- package/dist/apme/antigravity-transcript.d.ts.map +1 -0
- package/dist/apme/antigravity-transcript.js +94 -0
- package/dist/apme/antigravity-transcript.js.map +1 -0
- package/dist/apme/classify-turn.d.ts +13 -0
- package/dist/apme/classify-turn.d.ts.map +1 -0
- package/dist/apme/classify-turn.js +49 -0
- package/dist/apme/classify-turn.js.map +1 -0
- package/dist/apme/claude-transcript-reader.d.ts +10 -0
- package/dist/apme/claude-transcript-reader.d.ts.map +1 -1
- package/dist/apme/claude-transcript-reader.js +35 -0
- package/dist/apme/claude-transcript-reader.js.map +1 -1
- package/dist/apme/collector.d.ts +133 -6
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +471 -23
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/dashboard-html.d.ts.map +1 -1
- package/dist/apme/dashboard-html.js +117 -11
- package/dist/apme/dashboard-html.js.map +1 -1
- package/dist/apme/http.d.ts.map +1 -1
- package/dist/apme/http.js +52 -6
- package/dist/apme/http.js.map +1 -1
- package/dist/apme/index.d.ts +26 -5
- package/dist/apme/index.d.ts.map +1 -1
- package/dist/apme/index.js +146 -9
- package/dist/apme/index.js.map +1 -1
- package/dist/apme/judge-detect.d.ts +26 -0
- package/dist/apme/judge-detect.d.ts.map +1 -0
- package/dist/apme/judge-detect.js +69 -0
- package/dist/apme/judge-detect.js.map +1 -0
- package/dist/apme/pareto.d.ts +39 -0
- package/dist/apme/pareto.d.ts.map +1 -0
- package/dist/apme/pareto.js +59 -0
- package/dist/apme/pareto.js.map +1 -0
- package/dist/apme/recommend.d.ts +3 -0
- package/dist/apme/recommend.d.ts.map +1 -1
- package/dist/apme/recommend.js +43 -1
- package/dist/apme/recommend.js.map +1 -1
- package/dist/apme/runner.d.ts +99 -4
- package/dist/apme/runner.d.ts.map +1 -1
- package/dist/apme/runner.js +743 -72
- package/dist/apme/runner.js.map +1 -1
- package/dist/apme/sample-to-timeline.d.ts +26 -0
- package/dist/apme/sample-to-timeline.d.ts.map +1 -0
- package/dist/apme/sample-to-timeline.js +95 -0
- package/dist/apme/sample-to-timeline.js.map +1 -0
- package/dist/apme/scorers/index.d.ts +47 -0
- package/dist/apme/scorers/index.d.ts.map +1 -0
- package/dist/apme/scorers/index.js +96 -0
- package/dist/apme/scorers/index.js.map +1 -0
- package/dist/apme/settings.d.ts +17 -11
- package/dist/apme/settings.d.ts.map +1 -1
- package/dist/apme/settings.js +30 -9
- package/dist/apme/settings.js.map +1 -1
- package/dist/apme/store.d.ts +33 -1
- package/dist/apme/store.d.ts.map +1 -1
- package/dist/apme/store.js +334 -25
- package/dist/apme/store.js.map +1 -1
- package/dist/awaiting-overlay.d.ts +112 -0
- package/dist/awaiting-overlay.d.ts.map +1 -0
- package/dist/awaiting-overlay.js +179 -0
- package/dist/awaiting-overlay.js.map +1 -0
- package/dist/ble-sync-spawn.d.ts +63 -0
- package/dist/ble-sync-spawn.d.ts.map +1 -0
- package/dist/ble-sync-spawn.js +196 -0
- package/dist/ble-sync-spawn.js.map +1 -0
- package/dist/bridge-core.d.ts +34 -1
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +207 -24
- package/dist/bridge-core.js.map +1 -1
- package/dist/broadcast.d.ts +3 -0
- package/dist/broadcast.d.ts.map +1 -0
- package/dist/broadcast.js +122 -0
- package/dist/broadcast.js.map +1 -0
- package/dist/check-deps.d.ts.map +1 -1
- package/dist/check-deps.js +25 -9
- package/dist/check-deps.js.map +1 -1
- package/dist/claude-permission-rules.d.ts +55 -0
- package/dist/claude-permission-rules.d.ts.map +1 -0
- package/dist/claude-permission-rules.js +197 -0
- package/dist/claude-permission-rules.js.map +1 -0
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1030 -93
- package/dist/cli.js.map +1 -1
- package/dist/codex-auth.d.ts +21 -0
- package/dist/codex-auth.d.ts.map +1 -1
- package/dist/codex-auth.js +52 -1
- package/dist/codex-auth.js.map +1 -1
- package/dist/codex-output-parser.d.ts +8 -0
- package/dist/codex-output-parser.d.ts.map +1 -1
- package/dist/codex-output-parser.js +110 -25
- package/dist/codex-output-parser.js.map +1 -1
- package/dist/codex-rate-limits.d.ts +16 -0
- package/dist/codex-rate-limits.d.ts.map +1 -0
- package/dist/codex-rate-limits.js +197 -0
- package/dist/codex-rate-limits.js.map +1 -0
- package/dist/codex-rollout-response.d.ts +31 -0
- package/dist/codex-rollout-response.d.ts.map +1 -0
- package/dist/codex-rollout-response.js +135 -0
- package/dist/codex-rollout-response.js.map +1 -0
- package/dist/d200h/image-renderer.d.ts +4 -16
- package/dist/d200h/image-renderer.d.ts.map +1 -1
- package/dist/d200h/image-renderer.js +46 -212
- package/dist/d200h/image-renderer.js.map +1 -1
- package/dist/daemon-server.d.ts +85 -0
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +1975 -159
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon.js +15 -6
- package/dist/daemon.js.map +1 -1
- package/dist/display-dim.d.ts +9 -0
- package/dist/display-dim.d.ts.map +1 -0
- package/dist/display-dim.js +53 -0
- package/dist/display-dim.js.map +1 -0
- package/dist/display-monitor.d.ts +15 -2
- package/dist/display-monitor.d.ts.map +1 -1
- package/dist/display-monitor.js +104 -26
- package/dist/display-monitor.js.map +1 -1
- package/dist/esp32-serial.d.ts +190 -1
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +1090 -156
- package/dist/esp32-serial.js.map +1 -1
- package/dist/fallback-task-timeline.d.ts +42 -0
- package/dist/fallback-task-timeline.d.ts.map +1 -0
- package/dist/fallback-task-timeline.js +119 -0
- package/dist/fallback-task-timeline.js.map +1 -0
- package/dist/foundation-models-helper.d.ts +11 -0
- package/dist/foundation-models-helper.d.ts.map +1 -0
- package/dist/foundation-models-helper.js +241 -0
- package/dist/foundation-models-helper.js.map +1 -0
- package/dist/hook-migration.js +1 -1
- package/dist/hook-migration.js.map +1 -1
- package/dist/hook-server.d.ts +2 -3
- package/dist/hook-server.d.ts.map +1 -1
- package/dist/hook-server.js +23 -10
- package/dist/hook-server.js.map +1 -1
- package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts +33 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.js +164 -0
- package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -0
- package/dist/idotmatrix/idotmatrix-discover.d.ts +18 -0
- package/dist/idotmatrix/idotmatrix-discover.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-discover.js +85 -0
- package/dist/idotmatrix/idotmatrix-discover.js.map +1 -0
- package/dist/idotmatrix/idotmatrix-settings.d.ts +20 -0
- package/dist/idotmatrix/idotmatrix-settings.d.ts.map +1 -0
- package/dist/idotmatrix/idotmatrix-settings.js +57 -0
- package/dist/idotmatrix/idotmatrix-settings.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +217 -179
- package/dist/index.js.map +1 -1
- package/dist/log-stream.d.ts +15 -16
- package/dist/log-stream.d.ts.map +1 -1
- package/dist/log-stream.js +18 -96
- package/dist/log-stream.js.map +1 -1
- package/dist/logger.d.ts +3 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +18 -5
- package/dist/logger.js.map +1 -1
- package/dist/mdns.d.ts +17 -0
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +52 -18
- package/dist/mdns.js.map +1 -1
- package/dist/model-catalog.d.ts +1 -1
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +2 -4
- package/dist/model-catalog.js.map +1 -1
- package/dist/modules/adb-module.d.ts +1 -1
- package/dist/modules/adb-module.d.ts.map +1 -1
- package/dist/modules/adb-module.js +4 -3
- package/dist/modules/adb-module.js.map +1 -1
- package/dist/modules/broadcast-module.d.ts +17 -0
- package/dist/modules/broadcast-module.d.ts.map +1 -0
- package/dist/modules/broadcast-module.js +26 -0
- package/dist/modules/broadcast-module.js.map +1 -0
- package/dist/modules/d200h-module.d.ts +22 -0
- package/dist/modules/d200h-module.d.ts.map +1 -1
- package/dist/modules/d200h-module.js +200 -65
- package/dist/modules/d200h-module.js.map +1 -1
- package/dist/modules/idotmatrix-module.d.ts +9 -0
- package/dist/modules/idotmatrix-module.d.ts.map +1 -0
- package/dist/modules/idotmatrix-module.js +46 -0
- package/dist/modules/idotmatrix-module.js.map +1 -0
- package/dist/modules/index.d.ts +3 -1
- package/dist/modules/index.d.ts.map +1 -1
- package/dist/modules/index.js +9 -3
- package/dist/modules/index.js.map +1 -1
- package/dist/modules/pixoo-module.d.ts.map +1 -1
- package/dist/modules/pixoo-module.js +14 -4
- package/dist/modules/pixoo-module.js.map +1 -1
- package/dist/modules/serial-module.d.ts +4 -0
- package/dist/modules/serial-module.d.ts.map +1 -1
- package/dist/modules/serial-module.js +14 -12
- package/dist/modules/serial-module.js.map +1 -1
- package/dist/modules/timebox-module.d.ts +9 -0
- package/dist/modules/timebox-module.d.ts.map +1 -0
- package/dist/modules/timebox-module.js +46 -0
- package/dist/modules/timebox-module.js.map +1 -0
- package/dist/modules/trmnl-module.d.ts +38 -0
- package/dist/modules/trmnl-module.d.ts.map +1 -0
- package/dist/modules/trmnl-module.js +111 -0
- package/dist/modules/trmnl-module.js.map +1 -0
- package/dist/modules/types.d.ts +4 -2
- package/dist/modules/types.d.ts.map +1 -1
- package/dist/observed-steering.d.ts +93 -0
- package/dist/observed-steering.d.ts.map +1 -0
- package/dist/observed-steering.js +247 -0
- package/dist/observed-steering.js.map +1 -0
- package/dist/openclaw-session.d.ts +18 -0
- package/dist/openclaw-session.d.ts.map +1 -0
- package/dist/openclaw-session.js +34 -0
- package/dist/openclaw-session.js.map +1 -0
- package/dist/opencode-steering.d.ts +36 -0
- package/dist/opencode-steering.d.ts.map +1 -0
- package/dist/opencode-steering.js +84 -0
- package/dist/opencode-steering.js.map +1 -0
- package/dist/output-parser.d.ts +30 -0
- package/dist/output-parser.d.ts.map +1 -1
- package/dist/output-parser.js +172 -18
- package/dist/output-parser.js.map +1 -1
- package/dist/passive-observer.d.ts +32 -0
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +288 -49
- package/dist/passive-observer.js.map +1 -1
- package/dist/permission-resolver.d.ts +55 -0
- package/dist/permission-resolver.d.ts.map +1 -0
- package/dist/permission-resolver.js +112 -0
- package/dist/permission-resolver.js.map +1 -0
- package/dist/pixoo/micro-glyphs.d.ts +18 -0
- package/dist/pixoo/micro-glyphs.d.ts.map +1 -0
- package/dist/pixoo/micro-glyphs.js +143 -0
- package/dist/pixoo/micro-glyphs.js.map +1 -0
- package/dist/pixoo/official-dot-glyphs.generated.d.ts +8 -0
- package/dist/pixoo/official-dot-glyphs.generated.d.ts.map +1 -0
- package/dist/pixoo/official-dot-glyphs.generated.js +247 -0
- package/dist/pixoo/official-dot-glyphs.generated.js.map +1 -0
- package/dist/pixoo/pixoo-bridge.d.ts +16 -8
- package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
- package/dist/pixoo/pixoo-bridge.js +127 -35
- package/dist/pixoo/pixoo-bridge.js.map +1 -1
- package/dist/pixoo/pixoo-camera.d.ts +19 -3
- package/dist/pixoo/pixoo-camera.d.ts.map +1 -1
- package/dist/pixoo/pixoo-camera.js +62 -27
- package/dist/pixoo/pixoo-camera.js.map +1 -1
- package/dist/pixoo/pixoo-client.d.ts +13 -3
- package/dist/pixoo/pixoo-client.d.ts.map +1 -1
- package/dist/pixoo/pixoo-client.js +51 -22
- package/dist/pixoo/pixoo-client.js.map +1 -1
- package/dist/pixoo/pixoo-discover.d.ts +37 -0
- package/dist/pixoo/pixoo-discover.d.ts.map +1 -0
- package/dist/pixoo/pixoo-discover.js +105 -0
- package/dist/pixoo/pixoo-discover.js.map +1 -0
- package/dist/pixoo/pixoo-renderer.d.ts +27 -3
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
- package/dist/pixoo/pixoo-renderer.js +533 -135
- package/dist/pixoo/pixoo-renderer.js.map +1 -1
- package/dist/pixoo/pixoo-settings.d.ts +6 -0
- package/dist/pixoo/pixoo-settings.d.ts.map +1 -1
- package/dist/pixoo/pixoo-settings.js +9 -0
- package/dist/pixoo/pixoo-settings.js.map +1 -1
- package/dist/pixoo/pixoo-sprites.d.ts +84 -11
- package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
- package/dist/pixoo/pixoo-sprites.js +620 -209
- package/dist/pixoo/pixoo-sprites.js.map +1 -1
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +8 -2
- package/dist/pty-manager.js.map +1 -1
- package/dist/review-runner.d.ts +113 -0
- package/dist/review-runner.d.ts.map +1 -0
- package/dist/review-runner.js +428 -0
- package/dist/review-runner.js.map +1 -0
- package/dist/session-activity.d.ts +14 -0
- package/dist/session-activity.d.ts.map +1 -0
- package/dist/session-activity.js +160 -0
- package/dist/session-activity.js.map +1 -0
- package/dist/session-aggregator.d.ts +25 -0
- package/dist/session-aggregator.d.ts.map +1 -1
- package/dist/session-aggregator.js +48 -9
- package/dist/session-aggregator.js.map +1 -1
- package/dist/session-focus-relay.d.ts.map +1 -1
- package/dist/session-focus-relay.js +7 -1
- package/dist/session-focus-relay.js.map +1 -1
- package/dist/session-registry.d.ts +74 -3
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +140 -8
- package/dist/session-registry.js.map +1 -1
- package/dist/session-timeline-relay.d.ts.map +1 -1
- package/dist/session-timeline-relay.js +13 -4
- package/dist/session-timeline-relay.js.map +1 -1
- package/dist/session-transcript-timeline.d.ts +49 -0
- package/dist/session-transcript-timeline.d.ts.map +1 -0
- package/dist/session-transcript-timeline.js +276 -0
- package/dist/session-transcript-timeline.js.map +1 -0
- package/dist/state-machine.d.ts +6 -1
- package/dist/state-machine.d.ts.map +1 -1
- package/dist/state-machine.js +86 -28
- package/dist/state-machine.js.map +1 -1
- package/dist/timebox/timebox-daemon-sync.d.ts +19 -0
- package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -0
- package/dist/timebox/timebox-daemon-sync.js +135 -0
- package/dist/timebox/timebox-daemon-sync.js.map +1 -0
- package/dist/timebox/timebox-discover.d.ts +19 -0
- package/dist/timebox/timebox-discover.d.ts.map +1 -0
- package/dist/timebox/timebox-discover.js +87 -0
- package/dist/timebox/timebox-discover.js.map +1 -0
- package/dist/timebox/timebox-settings.d.ts +32 -0
- package/dist/timebox/timebox-settings.d.ts.map +1 -0
- package/dist/timebox/timebox-settings.js +80 -0
- package/dist/timebox/timebox-settings.js.map +1 -0
- package/dist/timeline-store.d.ts +112 -3
- package/dist/timeline-store.d.ts.map +1 -1
- package/dist/timeline-store.js +460 -14
- package/dist/timeline-store.js.map +1 -1
- package/dist/timeline-summarizer.d.ts.map +1 -1
- package/dist/timeline-summarizer.js +29 -5
- package/dist/timeline-summarizer.js.map +1 -1
- package/dist/trmnl/byos-server.d.ts +39 -0
- package/dist/trmnl/byos-server.d.ts.map +1 -0
- package/dist/trmnl/byos-server.js +301 -0
- package/dist/trmnl/byos-server.js.map +1 -0
- package/dist/trmnl/frame-cache.d.ts +37 -0
- package/dist/trmnl/frame-cache.d.ts.map +1 -0
- package/dist/trmnl/frame-cache.js +157 -0
- package/dist/trmnl/frame-cache.js.map +1 -0
- package/dist/trmnl/image-renderer.d.ts +27 -0
- package/dist/trmnl/image-renderer.d.ts.map +1 -0
- package/dist/trmnl/image-renderer.js +235 -0
- package/dist/trmnl/image-renderer.js.map +1 -0
- package/dist/trmnl/trmnl-settings.d.ts +96 -0
- package/dist/trmnl/trmnl-settings.d.ts.map +1 -0
- package/dist/trmnl/trmnl-settings.js +177 -0
- package/dist/trmnl/trmnl-settings.js.map +1 -0
- package/dist/trmnl/trmnl-telemetry.d.ts +47 -0
- package/dist/trmnl/trmnl-telemetry.d.ts.map +1 -0
- package/dist/trmnl/trmnl-telemetry.js +56 -0
- package/dist/trmnl/trmnl-telemetry.js.map +1 -0
- package/dist/tui/ansi.d.ts +0 -4
- package/dist/tui/ansi.d.ts.map +1 -1
- package/dist/tui/ansi.js +14 -7
- package/dist/tui/ansi.js.map +1 -1
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.d.ts.map +1 -1
- package/dist/tui/dashboard.js +38 -11
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/tui/renderer.d.ts +36 -0
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +355 -121
- package/dist/tui/renderer.js.map +1 -1
- package/dist/tui/terrarium.d.ts.map +1 -1
- package/dist/tui/terrarium.js +44 -51
- package/dist/tui/terrarium.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/dist/usage-api.d.ts.map +1 -1
- package/dist/usage-api.js +7 -1
- package/dist/usage-api.js.map +1 -1
- package/dist/usage-event.d.ts +10 -3
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +98 -13
- package/dist/usage-event.js.map +1 -1
- package/dist/utility-proxy.d.ts.map +1 -1
- package/dist/utility-proxy.js +8 -0
- package/dist/utility-proxy.js.map +1 -1
- package/dist/utils/project-name.d.ts +3 -0
- package/dist/utils/project-name.d.ts.map +1 -1
- package/dist/utils/project-name.js +44 -2
- package/dist/utils/project-name.js.map +1 -1
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +1 -17
- package/dist/version-check.js.map +1 -1
- package/dist/windows-service.d.ts +26 -0
- package/dist/windows-service.d.ts.map +1 -0
- package/dist/windows-service.js +145 -0
- package/dist/windows-service.js.map +1 -0
- package/dist/ws-server.d.ts +17 -3
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +78 -8
- package/dist/ws-server.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +112 -0
- package/package.json +10 -4
- package/scripts/build-fm-helper.mjs +26 -0
- package/LICENSE +0 -21
- package/dist/apme/tuner.d.ts +0 -64
- package/dist/apme/tuner.d.ts.map +0 -1
- package/dist/apme/tuner.js +0 -297
- package/dist/apme/tuner.js.map +0 -1
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
* zoom 2.0 → octopus ~14px wide, crayfish ~24px wide
|
|
24
24
|
*/
|
|
25
25
|
import { worldToScreen, isVisible } from './pixoo-camera.js';
|
|
26
|
+
import { State, STATE_COLORS } from '@agentdeck/shared';
|
|
27
|
+
import { OFFICIAL_DOT_GLYPHS, OFFICIAL_DOT_GLYPH_SIZE, } from './official-dot-glyphs.generated.js';
|
|
26
28
|
// ===== Cell Types (shared with ESP32/Android) =====
|
|
27
29
|
const EMPTY = 0;
|
|
28
30
|
const BODY = 1;
|
|
@@ -32,132 +34,324 @@ const RIGHT_ARM = 4;
|
|
|
32
34
|
const LEFT_LEG = 5;
|
|
33
35
|
const RIGHT_LEG = 6;
|
|
34
36
|
const ANTENNA = 7;
|
|
35
|
-
// ===== Octopus
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
43
|
-
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
|
|
44
|
-
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
|
|
45
|
-
[0, 1, 1, 1, 2, 1, 1, 1,
|
|
46
|
-
[0, 1, 1, 1, 2, 1, 1, 1,
|
|
47
|
-
[
|
|
48
|
-
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
49
|
-
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
50
|
-
[
|
|
51
|
-
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
52
|
-
[0, 0,
|
|
53
|
-
[0, 0,
|
|
54
|
-
[0, 0,
|
|
37
|
+
// ===== Octopus HD 24×24 — Claude Code mascot aligned with SVG viewBox =====
|
|
38
|
+
export const OCTOPUS_GRID_HD = [
|
|
39
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
40
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
41
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
42
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
43
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
44
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
45
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
46
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
47
|
+
[0, 0, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 0],
|
|
48
|
+
[0, 0, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 0],
|
|
49
|
+
[0, 0, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 0],
|
|
50
|
+
[3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4],
|
|
51
|
+
[3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4],
|
|
52
|
+
[3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4],
|
|
53
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
54
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
55
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
56
|
+
[0, 0, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 6, 6, 0, 0, 6, 6, 0, 0, 0, 0],
|
|
57
|
+
[0, 0, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 6, 6, 0, 0, 6, 6, 0, 0, 0, 0],
|
|
58
|
+
[0, 0, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 0, 0, 6, 6, 0, 0, 6, 6, 0, 0, 0, 0],
|
|
59
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
60
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
61
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
62
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
55
63
|
];
|
|
56
|
-
const
|
|
57
|
-
const
|
|
64
|
+
const OCTO_HD_COLS = 24;
|
|
65
|
+
const OCTO_HD_ROWS = 24;
|
|
66
|
+
// ===== Octopus MD 14×13 — Claude Code boxy mascot =====
|
|
67
|
+
export const OCTOPUS_GRID_MD = [
|
|
68
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], // Flat top (12)
|
|
69
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // (14)
|
|
70
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // (14)
|
|
71
|
+
[1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1], // Wide eye holes (2px)
|
|
72
|
+
[1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1], // Eye holes bottom
|
|
73
|
+
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4], // Arms + body (14)
|
|
74
|
+
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4], // Arms + body (14)
|
|
75
|
+
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4], // Arms + body (14)
|
|
76
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], // Slightly tapered waist (12)
|
|
77
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], // (12)
|
|
78
|
+
[0, 5, 5, 0, 5, 5, 0, 0, 6, 6, 0, 6, 6, 0], // Thick 2px legs for distortion-free downscaling
|
|
79
|
+
[0, 5, 5, 0, 5, 5, 0, 0, 6, 6, 0, 6, 6, 0],
|
|
80
|
+
[0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0]
|
|
81
|
+
];
|
|
82
|
+
const OCTO_GRID_MD_COLS = 14;
|
|
83
|
+
const OCTO_GRID_MD_ROWS = 13;
|
|
84
|
+
export const OCTOPUS_GRID = OCTOPUS_GRID_HD; // alias for compatibility
|
|
85
|
+
const OCTO_COLS = OCTO_HD_COLS;
|
|
86
|
+
const OCTO_ROWS = OCTO_HD_ROWS;
|
|
58
87
|
/** World width of octopus in normalized coords. */
|
|
59
88
|
export const OCTO_WORLD_W = 7 / 64;
|
|
60
89
|
// ===== Octopus LOD 7×7 — chunky grid for zoom < 1.3 =====
|
|
61
|
-
const OCTOPUS_LOD = [
|
|
62
|
-
[0, 1, 1, 1, 1, 1, 0],
|
|
63
|
-
[1, 1, 1, 1, 1, 1, 1],
|
|
64
|
-
[1,
|
|
65
|
-
[
|
|
66
|
-
[0, 1, 1, 1, 1, 1, 0],
|
|
67
|
-
[0,
|
|
68
|
-
[0, 0,
|
|
90
|
+
export const OCTOPUS_LOD = [
|
|
91
|
+
[0, 1, 1, 1, 1, 1, 0],
|
|
92
|
+
[1, 1, 1, 1, 1, 1, 1],
|
|
93
|
+
[1, 2, 2, 1, 2, 2, 1], // Bold eye holes
|
|
94
|
+
[3, 1, 1, 1, 1, 1, 4], // Arms + body
|
|
95
|
+
[0, 1, 1, 1, 1, 1, 0],
|
|
96
|
+
[0, 5, 5, 1, 6, 6, 0], // Thick limbs
|
|
97
|
+
[0, 5, 0, 0, 0, 6, 0],
|
|
69
98
|
];
|
|
70
99
|
const OCTO_LOD_COLS = 7;
|
|
71
100
|
const OCTO_LOD_ROWS = 7;
|
|
72
|
-
// ===== Crayfish
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
[0, 0, 7, 0, 0, 0, 0, 0, 0,
|
|
80
|
-
[0, 0, 0,
|
|
81
|
-
[0, 0, 0, 1, 1, 1, 1, 1, 1,
|
|
82
|
-
[
|
|
83
|
-
[0,
|
|
84
|
-
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
|
|
85
|
-
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], //
|
|
86
|
-
[0,
|
|
101
|
+
// ===== Crayfish HD 24×24 — OpenClaw mascot, round full body matching design/brand/openclaw.svg =====
|
|
102
|
+
// Round body, antennae curving to the top corners, two separated side-claw blobs (3/4), two leg
|
|
103
|
+
// stubs (5/6). Eyes are NOT in the grid — drawn as a teal+black overlay at eyeRow/eyeCols below.
|
|
104
|
+
export const CRAYFISH_GRID_HD = [
|
|
105
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
106
|
+
[0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0],
|
|
107
|
+
[0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0],
|
|
108
|
+
[0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0],
|
|
109
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
110
|
+
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
|
|
111
|
+
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
|
|
112
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
113
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
114
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], // eyes overlaid at cols 8,14
|
|
115
|
+
[0, 3, 3, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 4, 4, 0],
|
|
116
|
+
[3, 3, 3, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 4, 4, 4],
|
|
117
|
+
[3, 3, 3, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 4, 4, 4],
|
|
118
|
+
[0, 3, 3, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 4, 4, 0],
|
|
119
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
120
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
121
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
122
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
123
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
124
|
+
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
|
|
125
|
+
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
|
|
126
|
+
[0, 0, 0, 0, 0, 0, 0, 1, 5, 5, 1, 1, 1, 1, 6, 6, 1, 0, 0, 0, 0, 0, 0, 0],
|
|
127
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 1, 1, 1, 1, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
128
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
129
|
+
];
|
|
130
|
+
const CF_HD_COLS = 24;
|
|
131
|
+
const CF_HD_ROWS = 24;
|
|
132
|
+
// ===== Crayfish MD 12×8 — OpenClaw mascot, round body (eyes overlaid at row 3, cols 4/7) =====
|
|
133
|
+
export const CRAYFISH_GRID_MD = [
|
|
134
|
+
[0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0], // Antennae tips at the corners
|
|
135
|
+
[0, 0, 7, 0, 0, 1, 1, 0, 0, 7, 0, 0], // Antennae + head crown
|
|
136
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], // Rounded head dome
|
|
137
|
+
[0, 3, 3, 1, 1, 1, 1, 1, 1, 4, 4, 0], // Claws + body (eyes overlay row 3)
|
|
138
|
+
[3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4], // Wide claws + body
|
|
139
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], // Thorax
|
|
140
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], // Lower body
|
|
141
|
+
[0, 0, 0, 5, 5, 0, 0, 6, 6, 0, 0, 0] // Walking legs
|
|
87
142
|
];
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
143
|
+
const CF_GRID_MD_COLS = 12;
|
|
144
|
+
const CF_GRID_MD_ROWS = 8;
|
|
145
|
+
export const CRAYFISH_GRID = CRAYFISH_GRID_HD; // alias for compatibility
|
|
146
|
+
const CF_COLS = CF_HD_COLS;
|
|
147
|
+
const CF_ROWS = CF_HD_ROWS;
|
|
148
|
+
/** World width of crayfish in normalized coords. */
|
|
91
149
|
export const CF_WORLD_W = 12 / 64;
|
|
92
|
-
// ===== Crayfish LOD 8×6 — compact
|
|
93
|
-
const CRAYFISH_LOD = [
|
|
94
|
-
[0, 7, 0, 0, 0, 0, 7, 0], //
|
|
95
|
-
[0, 0, 1, 1, 1, 1, 0, 0], //
|
|
96
|
-
[3,
|
|
97
|
-
[0, 1,
|
|
98
|
-
[0,
|
|
99
|
-
[0,
|
|
150
|
+
// ===== Crayfish LOD 8×6 — compact round body (eyes overlaid at row 2, cols 2/5) =====
|
|
151
|
+
export const CRAYFISH_LOD = [
|
|
152
|
+
[0, 7, 0, 0, 0, 0, 7, 0], // Antennae at corners
|
|
153
|
+
[0, 0, 1, 1, 1, 1, 0, 0], // Head crown
|
|
154
|
+
[3, 3, 1, 1, 1, 1, 4, 4], // Claws + body (eyes overlay row 2)
|
|
155
|
+
[0, 1, 1, 1, 1, 1, 1, 0], // Body
|
|
156
|
+
[0, 1, 1, 1, 1, 1, 1, 0], // Body
|
|
157
|
+
[0, 0, 5, 0, 0, 6, 0, 0], // Legs
|
|
100
158
|
];
|
|
101
159
|
const CF_LOD_COLS = 8;
|
|
102
160
|
const CF_LOD_ROWS = 6;
|
|
103
|
-
// ===== Jellyfish
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
[0, 0, 1, 1,
|
|
110
|
-
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0
|
|
111
|
-
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
112
|
-
[
|
|
113
|
-
[
|
|
114
|
-
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
115
|
-
[0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
116
|
-
[0, 0, 1, 1,
|
|
161
|
+
// ===== Jellyfish HD 24×24 — Codex cloud mascot aligned with SVG viewBox =====
|
|
162
|
+
export const JELLYFISH_GRID_HD = [
|
|
163
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
164
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
165
|
+
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
|
|
166
|
+
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
|
|
167
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
168
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
169
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
170
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
171
|
+
[0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], // prompt `>`
|
|
172
|
+
[0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
173
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
174
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
175
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
176
|
+
[0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
177
|
+
[0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
|
178
|
+
[0, 0, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0], // prompt `_`
|
|
179
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0],
|
|
180
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
|
|
181
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
182
|
+
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
|
|
183
|
+
[0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0], // bottom lobes are BREATHE_EDGE
|
|
184
|
+
[0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0],
|
|
185
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
186
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
187
|
+
];
|
|
188
|
+
const JF_HD_COLS = 24;
|
|
189
|
+
const JF_HD_ROWS = 24;
|
|
190
|
+
// ===== Jellyfish MD 13×11 — Codex mascot =====
|
|
191
|
+
export const JELLYFISH_GRID_MD = [
|
|
192
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], // Rounded top lobe
|
|
193
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
194
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
195
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
196
|
+
[3, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3], // `>` top stroke (2px thick)
|
|
197
|
+
[3, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 3], // `>` point + long `_` prompt (4px)
|
|
198
|
+
[3, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3], // `>` bottom stroke
|
|
199
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
200
|
+
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
201
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
202
|
+
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0] // Bottom cloud lobe, not dangling legs
|
|
117
203
|
];
|
|
118
|
-
const
|
|
119
|
-
const
|
|
204
|
+
const JF_GRID_MD_COLS = 13;
|
|
205
|
+
const JF_GRID_MD_ROWS = 11;
|
|
206
|
+
export const JELLYFISH_GRID = JELLYFISH_GRID_HD; // alias for compatibility
|
|
207
|
+
const JF_COLS = JF_HD_COLS;
|
|
208
|
+
const JF_ROWS = JF_HD_ROWS;
|
|
120
209
|
/** World width of jellyfish in normalized coords. */
|
|
121
|
-
export const JF_WORLD_W =
|
|
122
|
-
// ===== Jellyfish LOD 7
|
|
123
|
-
const JELLYFISH_LOD = [
|
|
124
|
-
[0, 1, 1,
|
|
125
|
-
[1, 1, 1, 1, 1, 1, 1],
|
|
126
|
-
[1,
|
|
127
|
-
[1, 1,
|
|
128
|
-
[
|
|
210
|
+
export const JF_WORLD_W = 13 / 64;
|
|
211
|
+
// ===== Jellyfish LOD 9×7 — compact for zoom < 1.3 =====
|
|
212
|
+
export const JELLYFISH_LOD = [
|
|
213
|
+
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
|
214
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
215
|
+
[1, 2, 2, 1, 1, 1, 1, 1, 1], // `>` upper stroke (2px)
|
|
216
|
+
[1, 1, 2, 2, 1, 2, 2, 2, 1], // `>` point + `_` prompt (3px)
|
|
217
|
+
[1, 2, 2, 1, 1, 1, 1, 1, 1], // `>` lower stroke
|
|
218
|
+
[0, 1, 1, 1, 1, 1, 1, 1, 0],
|
|
219
|
+
[0, 0, 1, 1, 1, 1, 1, 0, 0],
|
|
129
220
|
];
|
|
130
|
-
const JF_LOD_COLS =
|
|
131
|
-
const JF_LOD_ROWS =
|
|
221
|
+
const JF_LOD_COLS = 9;
|
|
222
|
+
const JF_LOD_ROWS = 7;
|
|
132
223
|
// Cell type constants for jellyfish
|
|
133
224
|
const MARKING = 2;
|
|
134
225
|
const BREATHE_EDGE = 3;
|
|
135
|
-
// ===== OpenCode
|
|
226
|
+
// ===== OpenCode HD 24×24 — OpenCode mascot aligned with SVG viewBox =====
|
|
227
|
+
export const OPENCODE_GRID_HD = [
|
|
228
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
229
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
230
|
+
[0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
231
|
+
[0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
232
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
233
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
234
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
235
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0],
|
|
236
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
237
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
238
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
239
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
240
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
241
|
+
[0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
242
|
+
[0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
243
|
+
[0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9],
|
|
244
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
245
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
246
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
247
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
248
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
249
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
250
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
251
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
252
|
+
];
|
|
253
|
+
const OC_HD_COLS = 24;
|
|
254
|
+
const OC_HD_ROWS = 24;
|
|
255
|
+
// ===== OpenCode MD 10×10 — nested-square logo =====
|
|
136
256
|
const OPENCODE_FRAME = 8;
|
|
137
257
|
const OPENCODE_CORE = 9;
|
|
138
|
-
const
|
|
139
|
-
[8, 8, 8, 8, 8, 8,
|
|
140
|
-
[8, 0, 0, 0, 0,
|
|
141
|
-
[8, 0,
|
|
142
|
-
[8, 0,
|
|
143
|
-
[8, 0,
|
|
144
|
-
[8,
|
|
145
|
-
[
|
|
146
|
-
[
|
|
147
|
-
[
|
|
258
|
+
export const OPENCODE_GRID_MD = [
|
|
259
|
+
[8, 8, 8, 8, 8, 8, 0, 0, 0, 0],
|
|
260
|
+
[8, 0, 0, 0, 0, 8, 0, 0, 0, 0],
|
|
261
|
+
[8, 0, 0, 0, 0, 8, 0, 0, 0, 0],
|
|
262
|
+
[8, 0, 0, 0, 0, 8, 0, 0, 0, 0],
|
|
263
|
+
[8, 0, 0, 0, 9, 8, 9, 9, 9, 9],
|
|
264
|
+
[8, 8, 8, 8, 8, 8, 9, 9, 9, 9],
|
|
265
|
+
[0, 0, 0, 0, 9, 9, 9, 9, 9, 9],
|
|
266
|
+
[0, 0, 0, 0, 9, 9, 9, 9, 9, 9],
|
|
267
|
+
[0, 0, 0, 0, 9, 9, 9, 9, 9, 9],
|
|
268
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
148
269
|
];
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
[8,
|
|
156
|
-
[8, 0, 0,
|
|
157
|
-
[8,
|
|
270
|
+
const OC_GRID_MD_COLS = 10;
|
|
271
|
+
const OC_GRID_MD_ROWS = 10;
|
|
272
|
+
export const OPENCODE_GRID = OPENCODE_GRID_HD; // alias for compatibility
|
|
273
|
+
const OC_COLS = OC_HD_COLS;
|
|
274
|
+
const OC_ROWS = OC_HD_ROWS;
|
|
275
|
+
export const OPENCODE_LOD = [
|
|
276
|
+
[8, 8, 8, 8, 0, 0],
|
|
277
|
+
[8, 0, 0, 8, 0, 0],
|
|
278
|
+
[8, 0, 9, 8, 9, 9],
|
|
279
|
+
[8, 8, 8, 8, 9, 9],
|
|
280
|
+
[0, 0, 9, 9, 9, 9],
|
|
281
|
+
[0, 0, 9, 9, 9, 9],
|
|
158
282
|
];
|
|
159
283
|
const OC_LOD_COLS = 6;
|
|
160
284
|
const OC_LOD_ROWS = 6;
|
|
285
|
+
// ===== Antigravity — rainbow peak/arc mark =====
|
|
286
|
+
const ANTIGRAVITY_GRID = [
|
|
287
|
+
'....YOO....',
|
|
288
|
+
'....YOO....',
|
|
289
|
+
'...LYOOR...',
|
|
290
|
+
'...LTORR...',
|
|
291
|
+
'..LLTVPP...',
|
|
292
|
+
'..TTKKVPP..',
|
|
293
|
+
'.TQQK.KVU..',
|
|
294
|
+
'.QQK...KUU.',
|
|
295
|
+
'NQK.....KUU',
|
|
296
|
+
'NN.......UU',
|
|
297
|
+
'...........',
|
|
298
|
+
];
|
|
299
|
+
const AG_COLS = 11;
|
|
300
|
+
const AG_ROWS = 11;
|
|
301
|
+
function selectGrid(zoom, canvasWidth, hd, hdCols, hdRows, md, mdCols, mdRows, lod, lodCols, lodRows) {
|
|
302
|
+
if (canvasWidth <= 32) {
|
|
303
|
+
if (zoom < 1.3) {
|
|
304
|
+
return { grid: lod, cols: lodCols, rows: lodRows };
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
// Zoomed-in on a 32px display (iDotMatrix): use the full HD grid, not MD. Now that cell size
|
|
308
|
+
// is resolution-aware (creatureCellSize), HD fits the 32px frame (~60% width) and keeps the
|
|
309
|
+
// creature's true silhouette instead of the coarser MD approximation. MD/LOD stay for the
|
|
310
|
+
// wide (zoom<1.3) shots where the creature is small and detail would just alias.
|
|
311
|
+
return { grid: hd, cols: hdCols, rows: hdRows };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
if (zoom < 1.3) {
|
|
316
|
+
return { grid: md, cols: mdCols, rows: mdRows };
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
return { grid: hd, cols: hdCols, rows: hdRows };
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* On-screen creature width as a fraction of (zoom × output width), independent of LOD grid.
|
|
325
|
+
*
|
|
326
|
+
* A sprite spans `SPRITE_W_FRAC × zoom × w` pixels regardless of which HD/MD/LOD grid is selected
|
|
327
|
+
* (cellSz = span / cols, so the `cols` term cancels). Multiplying by `w` (32 or 64) is what makes
|
|
328
|
+
* sizing resolution-aware — at 32px a creature is exactly half the pixels it is at 64px, so it stays
|
|
329
|
+
* inside the iDotMatrix frame instead of overflowing. 0.1875 reproduces the legacy 64px HD size
|
|
330
|
+
* (24 cols × zoom×0.5 = 12×zoom px = 0.1875 × zoom × 64). See drawOpenCode for the original pattern.
|
|
331
|
+
*/
|
|
332
|
+
const SPRITE_W_FRAC = 0.1875;
|
|
333
|
+
/** Resolution-aware square cell size for a creature sprite.
|
|
334
|
+
*
|
|
335
|
+
* Rounded to a whole pixel so every grid cell is a uniform integer block. A
|
|
336
|
+
* fractional cell size makes adjacent cells round to alternating 1/2px widths,
|
|
337
|
+
* and on the 2×2 eye holes that intermittently opens a 1px body-coloured seam
|
|
338
|
+
* between the two eye rows while the creature moves — the eyes appear to "break"
|
|
339
|
+
* into dots. Integer cells render the eye as a solid block every frame.
|
|
340
|
+
*
|
|
341
|
+
* The sizing zoom is itself quantized to a coarse 0.25 step first. The raw zoom
|
|
342
|
+
* lerps continuously during camera transitions, so a cell size sitting right on
|
|
343
|
+
* a rounding threshold (e.g. zoom where `…/cols` ≈ x.5) flickers 1↔2px frame to
|
|
344
|
+
* frame — and since the eye sits at a fixed column, a cellSz change jumps it by
|
|
345
|
+
* `eyeCol` pixels. Snapping the zoom to discrete steps holds cellSz stable
|
|
346
|
+
* through a transition so the eye only ever moves by whole-creature translation. */
|
|
347
|
+
export function creatureCellSize(zoom, canvasW, cols) {
|
|
348
|
+
const zq = Math.round(zoom * 4) / 4; // 0.25 steps — kills threshold-straddle flicker
|
|
349
|
+
return Math.max(1, Math.round((SPRITE_W_FRAC * zq * canvasW) / cols));
|
|
350
|
+
}
|
|
351
|
+
/** Canonical `#rrggbb` → RGB tuple (LED frame buffers take tuples, not hex). */
|
|
352
|
+
function hexRgb(hex) {
|
|
353
|
+
return [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)];
|
|
354
|
+
}
|
|
161
355
|
export const COLORS = {
|
|
162
356
|
// Octopus (terracotta — Android match)
|
|
163
357
|
octopusBody: [0xC0, 0x70, 0x58],
|
|
@@ -181,7 +375,7 @@ export const COLORS = {
|
|
|
181
375
|
// Jellyfish / Codex CLI (indigo — TUI/Android match)
|
|
182
376
|
jellyfishBody: [0x63, 0x66, 0xF1], // indigo #6366F1
|
|
183
377
|
jellyfishEdge: [0x4F, 0x46, 0xE5], // darker edge (breathe cells)
|
|
184
|
-
jellyfishMarking: [
|
|
378
|
+
jellyfishMarking: [0xF5, 0xF7, 0xFF], // near-white (>_ prompt)
|
|
185
379
|
jellyfishGlow: [0x31, 0x33, 0x78], // dim indigo glow halo
|
|
186
380
|
jellyfishPulse: [0xA5, 0xB4, 0xFC], // bioluminescent pulse
|
|
187
381
|
jellyfishSleeping: [0x3A, 0x3C, 0x90], // dimmed indigo
|
|
@@ -190,6 +384,17 @@ export const COLORS = {
|
|
|
190
384
|
opencodeInner: [0x4B, 0x46, 0x46], // dark core
|
|
191
385
|
opencodePulse: [0xCF, 0xCE, 0xCD], // pulse state
|
|
192
386
|
opencodeSleeping: [0x8A, 0x84, 0x84], // sleep dim
|
|
387
|
+
// Antigravity (reference rainbow peak/arc)
|
|
388
|
+
antigravityLime: [0x5C, 0xD6, 0x4D],
|
|
389
|
+
antigravityTeal: [0x1F, 0xC6, 0xB3],
|
|
390
|
+
antigravityCyan: [0x3A, 0xC7, 0xEB],
|
|
391
|
+
antigravityYellow: [0xF5, 0xCB, 0x24],
|
|
392
|
+
antigravityOrange: [0xFF, 0x84, 0x10],
|
|
393
|
+
antigravityRed: [0xFF, 0x52, 0x41],
|
|
394
|
+
antigravityPink: [0xB7, 0x5C, 0xB6],
|
|
395
|
+
antigravityViolet: [0x66, 0x6F, 0xE1],
|
|
396
|
+
antigravityBlue: [0x24, 0x7E, 0xFF],
|
|
397
|
+
antigravitySky: [0x29, 0xB8, 0xEE],
|
|
193
398
|
// Tetra (neon)
|
|
194
399
|
tetraNeon: [0x00, 0xE5, 0xFF],
|
|
195
400
|
tetraBody: [0x1E, 0x40, 0xAF],
|
|
@@ -235,11 +440,11 @@ export const COLORS = {
|
|
|
235
440
|
// Tank walls (above water)
|
|
236
441
|
tankWall: [0x06, 0x0A, 0x10],
|
|
237
442
|
tankWallEdge: [0x10, 0x14, 0x1C],
|
|
238
|
-
// State shimmer
|
|
239
|
-
stateIdle: [
|
|
240
|
-
stateProcessing: [
|
|
241
|
-
stateAwaiting: [
|
|
242
|
-
stateError: [0xEF, 0x44, 0x44],
|
|
443
|
+
// State shimmer — derived from the canonical shared palette
|
|
444
|
+
stateIdle: hexRgb(STATE_COLORS[State.IDLE]),
|
|
445
|
+
stateProcessing: hexRgb(STATE_COLORS[State.PROCESSING]),
|
|
446
|
+
stateAwaiting: hexRgb(STATE_COLORS[State.AWAITING_PERMISSION]),
|
|
447
|
+
stateError: [0xEF, 0x44, 0x44], // red — no canonical error state color exists
|
|
243
448
|
white: [0xFF, 0xFF, 0xFF],
|
|
244
449
|
black: [0x00, 0x00, 0x00],
|
|
245
450
|
};
|
|
@@ -288,27 +493,45 @@ export function getOpenCodePaletteForSession(sessionIndex = 0) {
|
|
|
288
493
|
pulse: scaleColor(COLORS.opencodePulse, tone),
|
|
289
494
|
};
|
|
290
495
|
}
|
|
496
|
+
export function getAntigravityPaletteForSession(sessionIndex = 0) {
|
|
497
|
+
const tone = SESSION_TONE_FACTORS[Math.max(0, Math.min(SESSION_TONE_FACTORS.length - 1, sessionIndex))];
|
|
498
|
+
return {
|
|
499
|
+
lime: scaleColor(COLORS.antigravityLime, tone),
|
|
500
|
+
teal: scaleColor(COLORS.antigravityTeal, tone),
|
|
501
|
+
cyan: scaleColor(COLORS.antigravityCyan, tone),
|
|
502
|
+
yellow: scaleColor(COLORS.antigravityYellow, tone),
|
|
503
|
+
orange: scaleColor(COLORS.antigravityOrange, tone),
|
|
504
|
+
red: scaleColor(COLORS.antigravityRed, tone),
|
|
505
|
+
pink: scaleColor(COLORS.antigravityPink, tone),
|
|
506
|
+
violet: scaleColor(COLORS.antigravityViolet, tone),
|
|
507
|
+
blue: scaleColor(COLORS.antigravityBlue, tone),
|
|
508
|
+
sky: scaleColor(COLORS.antigravitySky, tone),
|
|
509
|
+
cutout: COLORS.black,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
291
512
|
// ===== Pixel Operations =====
|
|
292
|
-
/** Set a pixel in the
|
|
513
|
+
/** Set a pixel in the dynamic RGB buffer. */
|
|
293
514
|
export function setPixel(buf, x, y, color) {
|
|
294
|
-
|
|
515
|
+
const w = Math.sqrt(buf.length / 3);
|
|
516
|
+
if (x < 0 || x >= w || y < 0 || y >= w)
|
|
295
517
|
return;
|
|
296
518
|
const ix = Math.round(x);
|
|
297
519
|
const iy = Math.round(y);
|
|
298
|
-
if (ix < 0 || ix >=
|
|
520
|
+
if (ix < 0 || ix >= w || iy < 0 || iy >= w)
|
|
299
521
|
return;
|
|
300
|
-
const idx = (iy *
|
|
522
|
+
const idx = (iy * w + ix) * 3;
|
|
301
523
|
buf[idx] = color[0];
|
|
302
524
|
buf[idx + 1] = color[1];
|
|
303
525
|
buf[idx + 2] = color[2];
|
|
304
526
|
}
|
|
305
527
|
/** Alpha-blend a pixel onto existing buffer content. */
|
|
306
528
|
export function blendPixel(buf, x, y, color, alpha) {
|
|
529
|
+
const w = Math.sqrt(buf.length / 3);
|
|
307
530
|
const ix = Math.round(x);
|
|
308
531
|
const iy = Math.round(y);
|
|
309
|
-
if (ix < 0 || ix >=
|
|
532
|
+
if (ix < 0 || ix >= w || iy < 0 || iy >= w || alpha <= 0)
|
|
310
533
|
return;
|
|
311
|
-
const idx = (iy *
|
|
534
|
+
const idx = (iy * w + ix) * 3;
|
|
312
535
|
const a = Math.min(1, alpha);
|
|
313
536
|
const inv = 1 - a;
|
|
314
537
|
buf[idx] = Math.min(255, Math.round(buf[idx] * inv + color[0] * a));
|
|
@@ -317,11 +540,12 @@ export function blendPixel(buf, x, y, color, alpha) {
|
|
|
317
540
|
}
|
|
318
541
|
/** Additive-blend (glow) a pixel. */
|
|
319
542
|
export function glowPixel(buf, x, y, color, intensity) {
|
|
543
|
+
const w = Math.sqrt(buf.length / 3);
|
|
320
544
|
const ix = Math.round(x);
|
|
321
545
|
const iy = Math.round(y);
|
|
322
|
-
if (ix < 0 || ix >=
|
|
546
|
+
if (ix < 0 || ix >= w || iy < 0 || iy >= w || intensity <= 0)
|
|
323
547
|
return;
|
|
324
|
-
const idx = (iy *
|
|
548
|
+
const idx = (iy * w + ix) * 3;
|
|
325
549
|
buf[idx] = Math.min(255, buf[idx] + Math.round(color[0] * intensity));
|
|
326
550
|
buf[idx + 1] = Math.min(255, buf[idx + 1] + Math.round(color[1] * intensity));
|
|
327
551
|
buf[idx + 2] = Math.min(255, buf[idx + 2] + Math.round(color[2] * intensity));
|
|
@@ -336,45 +560,52 @@ export function fillRect(buf, x, y, w, h, color) {
|
|
|
336
560
|
}
|
|
337
561
|
/** Fill a scaled cell (variable size rectangle) — edge rounding for correct PIXEL_ASPECT. */
|
|
338
562
|
function fillCell(buf, x, y, w, h, color) {
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
const
|
|
342
|
-
const
|
|
563
|
+
const ix1 = Math.round(x);
|
|
564
|
+
const iy1 = Math.round(y);
|
|
565
|
+
const ix2 = Math.round(x + w);
|
|
566
|
+
const iy2 = Math.round(y + h);
|
|
567
|
+
const iw = Math.max(1, ix2 - ix1);
|
|
568
|
+
const ih = Math.max(1, iy2 - iy1);
|
|
343
569
|
for (let dy = 0; dy < ih; dy++) {
|
|
344
570
|
for (let dx = 0; dx < iw; dx++) {
|
|
345
|
-
setPixel(buf,
|
|
571
|
+
setPixel(buf, ix1 + dx, iy1 + dy, color);
|
|
346
572
|
}
|
|
347
573
|
}
|
|
348
574
|
}
|
|
349
575
|
/** Fill a scaled cell and track drawn pixels for outline generation. */
|
|
350
576
|
function fillCellTracked(buf, x, y, w, h, color, pixels) {
|
|
351
|
-
const
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
577
|
+
const canvasW = Math.sqrt(buf.length / 3);
|
|
578
|
+
const ix1 = Math.round(x);
|
|
579
|
+
const iy1 = Math.round(y);
|
|
580
|
+
const ix2 = Math.round(x + w);
|
|
581
|
+
const iy2 = Math.round(y + h);
|
|
582
|
+
const iw = Math.max(1, ix2 - ix1);
|
|
583
|
+
const ih = Math.max(1, iy2 - iy1);
|
|
355
584
|
for (let dy = 0; dy < ih; dy++) {
|
|
356
585
|
for (let dx = 0; dx < iw; dx++) {
|
|
357
|
-
const px =
|
|
358
|
-
const py =
|
|
359
|
-
if (px >= 0 && px <
|
|
360
|
-
const idx = (py *
|
|
586
|
+
const px = ix1 + dx;
|
|
587
|
+
const py = iy1 + dy;
|
|
588
|
+
if (px >= 0 && px < canvasW && py >= 0 && py < canvasW) {
|
|
589
|
+
const idx = (py * canvasW + px) * 3;
|
|
361
590
|
buf[idx] = color[0];
|
|
362
591
|
buf[idx + 1] = color[1];
|
|
363
592
|
buf[idx + 2] = color[2];
|
|
364
|
-
pixels.add(py *
|
|
593
|
+
pixels.add(py * canvasW + px);
|
|
365
594
|
}
|
|
366
595
|
}
|
|
367
596
|
}
|
|
368
597
|
}
|
|
369
598
|
/** Glow-fill a scaled cell — edge rounding. */
|
|
370
599
|
function glowCell(buf, x, y, w, h, color, intensity) {
|
|
371
|
-
const
|
|
372
|
-
const
|
|
373
|
-
const
|
|
374
|
-
const
|
|
600
|
+
const ix1 = Math.round(x);
|
|
601
|
+
const iy1 = Math.round(y);
|
|
602
|
+
const ix2 = Math.round(x + w);
|
|
603
|
+
const iy2 = Math.round(y + h);
|
|
604
|
+
const iw = Math.max(1, ix2 - ix1);
|
|
605
|
+
const ih = Math.max(1, iy2 - iy1);
|
|
375
606
|
for (let dy = 0; dy < ih; dy++) {
|
|
376
607
|
for (let dx = 0; dx < iw; dx++) {
|
|
377
|
-
glowPixel(buf,
|
|
608
|
+
glowPixel(buf, ix1 + dx, iy1 + dy, color, intensity);
|
|
378
609
|
}
|
|
379
610
|
}
|
|
380
611
|
}
|
|
@@ -408,6 +639,7 @@ function drawCreatureGlow(buf, cx, cy, rx, ry, glowColor, intensity = 0.15, isLO
|
|
|
408
639
|
// ===== Creature Outline =====
|
|
409
640
|
/** 8-directional colored outline around tracked creature pixels. */
|
|
410
641
|
function drawCreatureOutline(buf, creaturePixels, bodyColor, alpha = 0.8) {
|
|
642
|
+
const w = Math.sqrt(buf.length / 3);
|
|
411
643
|
const outlineColor = [
|
|
412
644
|
Math.round(bodyColor[0] * 0.5),
|
|
413
645
|
Math.round(bodyColor[1] * 0.5),
|
|
@@ -415,17 +647,17 @@ function drawCreatureOutline(buf, creaturePixels, bodyColor, alpha = 0.8) {
|
|
|
415
647
|
];
|
|
416
648
|
const neighbors = [-1, 0, 1];
|
|
417
649
|
for (const key of creaturePixels) {
|
|
418
|
-
const cx = key %
|
|
419
|
-
const cy = Math.floor(key /
|
|
650
|
+
const cx = key % w;
|
|
651
|
+
const cy = Math.floor(key / w);
|
|
420
652
|
for (const ndx of neighbors) {
|
|
421
653
|
for (const ndy of neighbors) {
|
|
422
654
|
if (ndx === 0 && ndy === 0)
|
|
423
655
|
continue;
|
|
424
656
|
const nx = cx + ndx;
|
|
425
657
|
const ny = cy + ndy;
|
|
426
|
-
if (nx < 0 || nx >=
|
|
658
|
+
if (nx < 0 || nx >= w || ny < 0 || ny >= w)
|
|
427
659
|
continue;
|
|
428
|
-
if (!creaturePixels.has(ny *
|
|
660
|
+
if (!creaturePixels.has(ny * w + nx)) {
|
|
429
661
|
blendPixel(buf, nx, ny, outlineColor, alpha);
|
|
430
662
|
}
|
|
431
663
|
}
|
|
@@ -499,26 +731,37 @@ export function drawOctopus(buf, worldX, worldY, state, animFrame, cam, palette
|
|
|
499
731
|
if (!isVisible(worldX, worldY, cam, 0.15))
|
|
500
732
|
return;
|
|
501
733
|
const [scx, scy] = worldToScreen(worldX, worldY, cam);
|
|
734
|
+
const w = Math.sqrt(buf.length / 3);
|
|
502
735
|
// LOD selection
|
|
503
|
-
const
|
|
504
|
-
const grid =
|
|
505
|
-
const cols =
|
|
506
|
-
const rows =
|
|
507
|
-
//
|
|
508
|
-
|
|
509
|
-
const
|
|
510
|
-
const
|
|
736
|
+
const select = selectGrid(cam.zoom, w, OCTOPUS_GRID_HD, OCTO_HD_COLS, OCTO_HD_ROWS, OCTOPUS_GRID_MD, OCTO_GRID_MD_COLS, OCTO_GRID_MD_ROWS, OCTOPUS_LOD, OCTO_LOD_COLS, OCTO_LOD_ROWS);
|
|
737
|
+
const grid = select.grid;
|
|
738
|
+
const cols = select.cols;
|
|
739
|
+
const rows = select.rows;
|
|
740
|
+
// Resolution-aware cell size — sprite spans a fixed fraction of (zoom × output width),
|
|
741
|
+
// so it scales down on the 32px iDotMatrix instead of overflowing the frame.
|
|
742
|
+
const cellSz = creatureCellSize(cam.zoom, w, cols);
|
|
743
|
+
const spriteW = cols * cellSz;
|
|
744
|
+
const spriteH = rows * cellSz;
|
|
745
|
+
// Snap the sprite origin to whole pixels. The cells tile from this origin via
|
|
746
|
+
// round(base + col*cellSz); if `base` is fractional, a swimming creature's
|
|
747
|
+
// sub-pixel screen drift shifts the rounding phase every frame, so each cell
|
|
748
|
+
// oscillates ±1px (shimmer). On the small high-contrast eye holes that reads
|
|
749
|
+
// as the eyes "breaking up" while the octopus moves. Rounding the origin makes
|
|
750
|
+
// the cell pattern frame-stable (only an integer translation changes), so the
|
|
751
|
+
// creature moves in clean 1px steps with rock-steady eyes.
|
|
511
752
|
const baseX = Math.round(scx - spriteW / 2);
|
|
512
753
|
const baseY = Math.round(scy - spriteH / 2);
|
|
513
|
-
// Working: gentle vertical bob (
|
|
754
|
+
// Working: gentle vertical bob (scaled by cellSz)
|
|
514
755
|
const breathPx = state === 'working'
|
|
515
|
-
? Math.round(Math.sin(animFrame * 0.3) * 1.5)
|
|
756
|
+
? Math.round(Math.sin(animFrame * 0.3) * cellSz * 1.5)
|
|
516
757
|
: 0;
|
|
517
758
|
// Body color by state
|
|
518
759
|
const bodyColor = state === 'working' ? palette.starburst
|
|
519
760
|
: state === 'sleeping' ? palette.sleeping
|
|
520
761
|
: palette.body;
|
|
521
|
-
//
|
|
762
|
+
// Track drawn pixels for outline generation
|
|
763
|
+
const trackedPixels = new Set();
|
|
764
|
+
// Draw all cells
|
|
522
765
|
for (let row = 0; row < rows; row++) {
|
|
523
766
|
for (let col = 0; col < cols; col++) {
|
|
524
767
|
const cellType = grid[row][col];
|
|
@@ -541,16 +784,18 @@ export function drawOctopus(buf, worldX, worldY, state, animFrame, cam, palette
|
|
|
541
784
|
// Tentacle animation only — arms stay fixed (attached to body)
|
|
542
785
|
let dx = 0;
|
|
543
786
|
if (state !== 'sleeping' && (cellType === LEFT_LEG || cellType === RIGHT_LEG)) {
|
|
544
|
-
dx = Math.round(Math.sin(animFrame * 0.2 + col * 1.8) * 1.5);
|
|
787
|
+
dx = Math.round(Math.sin(animFrame * 0.2 + col * 1.8) * cellSz * 1.5);
|
|
545
788
|
}
|
|
546
|
-
|
|
789
|
+
fillCellTracked(buf, baseX + col * cellSz + dx, baseY + row * cellSz + breathPx, cellSz, cellSz, color, trackedPixels);
|
|
547
790
|
}
|
|
548
791
|
}
|
|
792
|
+
// Draw outline to separate octopus from blue water (matches crayfish style)
|
|
793
|
+
drawCreatureOutline(buf, trackedPixels, bodyColor, 0.8);
|
|
549
794
|
// "?" bubble when asking
|
|
550
795
|
if (state === 'asking') {
|
|
551
796
|
const bobY = Math.round(Math.sin(animFrame * 0.25));
|
|
552
797
|
const bx = scx;
|
|
553
|
-
const by = baseY - 3 + bobY;
|
|
798
|
+
const by = baseY - Math.round(cellSz * 3) + bobY;
|
|
554
799
|
const r = 3;
|
|
555
800
|
for (let dy = -r; dy <= r; dy++) {
|
|
556
801
|
for (let dx = -r; dx <= r; dx++) {
|
|
@@ -569,7 +814,7 @@ export function drawOctopus(buf, worldX, worldY, state, animFrame, cam, palette
|
|
|
569
814
|
// Starburst particles when working
|
|
570
815
|
if (state === 'working') {
|
|
571
816
|
const sparkPhase = animFrame * 0.35;
|
|
572
|
-
const dist = 5 + Math.sin(animFrame * 0.25) * 3;
|
|
817
|
+
const dist = (5 + Math.sin(animFrame * 0.25) * 3) * cellSz;
|
|
573
818
|
for (let i = 0; i < 6; i++) {
|
|
574
819
|
const angle = sparkPhase + (i * Math.PI * 2 / 6);
|
|
575
820
|
const sx = scx + Math.cos(angle) * dist;
|
|
@@ -589,28 +834,29 @@ export function drawJellyfish(buf, worldX, worldY, state, animFrame, cam, palett
|
|
|
589
834
|
if (!isVisible(worldX, worldY, cam, 0.15))
|
|
590
835
|
return;
|
|
591
836
|
const [scx, scy] = worldToScreen(worldX, worldY, cam);
|
|
837
|
+
const w = Math.sqrt(buf.length / 3);
|
|
592
838
|
// LOD selection
|
|
593
|
-
const
|
|
594
|
-
const grid =
|
|
595
|
-
const cols =
|
|
596
|
-
const rows =
|
|
597
|
-
//
|
|
598
|
-
const cellSz =
|
|
599
|
-
const spriteW = cols;
|
|
600
|
-
const spriteH = rows;
|
|
601
|
-
const baseX =
|
|
602
|
-
const baseY =
|
|
839
|
+
const select = selectGrid(cam.zoom, w, JELLYFISH_GRID_HD, JF_HD_COLS, JF_HD_ROWS, JELLYFISH_GRID_MD, JF_GRID_MD_COLS, JF_GRID_MD_ROWS, JELLYFISH_LOD, JF_LOD_COLS, JF_LOD_ROWS);
|
|
840
|
+
const grid = select.grid;
|
|
841
|
+
const cols = select.cols;
|
|
842
|
+
const rows = select.rows;
|
|
843
|
+
// Resolution-aware cell size (see creatureCellSize) — scales with output width.
|
|
844
|
+
const cellSz = creatureCellSize(cam.zoom, w, cols);
|
|
845
|
+
const spriteW = cols * cellSz;
|
|
846
|
+
const spriteH = rows * cellSz;
|
|
847
|
+
const baseX = scx - spriteW / 2;
|
|
848
|
+
const baseY = scy - spriteH / 2;
|
|
603
849
|
// Bell pulse: contraction/expansion
|
|
604
850
|
const pulseSpeed = state === 'working' ? 0.25 : 0.06;
|
|
605
851
|
const pulsePhase = Math.sin(animFrame * pulseSpeed);
|
|
606
852
|
const contracting = pulsePhase < 0;
|
|
607
|
-
// Vertical bob when working
|
|
853
|
+
// Vertical bob when working (scaled by cellSz)
|
|
608
854
|
const breathPx = state === 'working'
|
|
609
|
-
? Math.round(Math.sin(animFrame * 0.3) * 1.5)
|
|
855
|
+
? Math.round(Math.sin(animFrame * 0.3) * cellSz * 1.5)
|
|
610
856
|
: 0;
|
|
611
857
|
// Bioluminescent body color pulse when working
|
|
612
858
|
const bodyColor = state === 'working'
|
|
613
|
-
? lerpColor(palette.body, palette.pulse, (Math.sin(animFrame * 0.2) + 1) * 0.
|
|
859
|
+
? lerpColor(palette.body, palette.pulse, 0.18 + ((Math.sin(animFrame * 0.2) + 1) * 0.18))
|
|
614
860
|
: state === 'sleeping' ? palette.sleeping
|
|
615
861
|
: palette.body;
|
|
616
862
|
// >_ marking blink
|
|
@@ -646,7 +892,7 @@ export function drawJellyfish(buf, worldX, worldY, state, animFrame, cam, palett
|
|
|
646
892
|
if (state === 'asking') {
|
|
647
893
|
const bobY = Math.round(Math.sin(animFrame * 0.25));
|
|
648
894
|
const bx = scx;
|
|
649
|
-
const by = baseY - 3 + bobY;
|
|
895
|
+
const by = baseY - Math.round(cellSz * 3) + bobY;
|
|
650
896
|
const r = 3;
|
|
651
897
|
for (let dy = -r; dy <= r; dy++) {
|
|
652
898
|
for (let dx = -r; dx <= r; dx++) {
|
|
@@ -665,7 +911,7 @@ export function drawJellyfish(buf, worldX, worldY, state, animFrame, cam, palett
|
|
|
665
911
|
// Orbiting glow particles when working (bioluminescent)
|
|
666
912
|
if (state === 'working') {
|
|
667
913
|
const orbitPhase = animFrame * 0.2;
|
|
668
|
-
const dist = 5 + Math.sin(animFrame * 0.15) * 2;
|
|
914
|
+
const dist = (5 + Math.sin(animFrame * 0.15) * 2) * cellSz;
|
|
669
915
|
for (let i = 0; i < 4; i++) {
|
|
670
916
|
const angle = orbitPhase + (i * Math.PI * 2 / 4);
|
|
671
917
|
const sx = scx + Math.cos(angle) * dist;
|
|
@@ -676,48 +922,209 @@ export function drawJellyfish(buf, worldX, worldY, state, animFrame, cam, palett
|
|
|
676
922
|
}
|
|
677
923
|
// ===== OpenCode — nested-square logo (simulator SSOT) =====
|
|
678
924
|
export function drawOpenCode(buf, worldX, worldY, state, animFrame, camera, palette) {
|
|
679
|
-
const
|
|
680
|
-
const scy =
|
|
925
|
+
const w = Math.sqrt(buf.length / 3);
|
|
926
|
+
const [scx, scy] = worldToScreen(worldX, worldY, camera);
|
|
927
|
+
// Canonical opencode mark: a single-color vertical rectangular RING (16:20) with a
|
|
928
|
+
// HOLLOW center — drawn procedurally so it scales cleanly to any panel (64px, 32px,
|
|
929
|
+
// iDotMatrix) instead of grid sprites that overflowed 32px or drew a filled shadow.
|
|
681
930
|
const worldW = 10 / 64;
|
|
682
|
-
const
|
|
683
|
-
const
|
|
931
|
+
const unit = Math.max(1, Math.round((worldW * camera.zoom * w) / OC_GRID_MD_COLS));
|
|
932
|
+
const outerW = Math.max(5, 6 * unit);
|
|
933
|
+
const outerH = Math.max(6, Math.round(outerW * 1.25)); // slightly tall (16:20)
|
|
934
|
+
const thick = Math.max(1, Math.round(outerW * 0.28)); // frame thickness ~ brand 4/16
|
|
684
935
|
const breathPx = state === 'working'
|
|
685
936
|
? Math.round(Math.sin(animFrame * 0.3) * 1.5)
|
|
686
937
|
: state === 'idle' ? Math.round(Math.sin(animFrame * 0.08) * 0.7) : 0;
|
|
687
|
-
const
|
|
688
|
-
const grid = useLod ? OPENCODE_LOD : OPENCODE_GRID;
|
|
689
|
-
const gc = useLod ? OC_LOD_COLS : OC_COLS;
|
|
690
|
-
const gr = useLod ? OC_LOD_ROWS : OC_ROWS;
|
|
691
|
-
const baseX = scx - Math.round((gc * pixW) / 2);
|
|
692
|
-
const baseY = scy + breathPx - Math.round((gr * pixH) / 2);
|
|
693
|
-
const outerColor = state === 'working'
|
|
938
|
+
const color = state === 'working'
|
|
694
939
|
? lerpColor(palette.outer, palette.pulse, 0.5 + Math.sin(animFrame * 0.2) * 0.5)
|
|
695
940
|
: state === 'sleeping' ? palette.sleeping : palette.outer;
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
for (let
|
|
699
|
-
for (let
|
|
700
|
-
const
|
|
701
|
-
if (
|
|
702
|
-
continue;
|
|
703
|
-
|
|
704
|
-
for (let dy = 0; dy < pixH; dy++) {
|
|
705
|
-
for (let dx = 0; dx < pixW; dx++) {
|
|
706
|
-
setPixel(buf, baseX + c * pixW + dx, baseY + r * pixH + dy, color);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
941
|
+
const x0 = scx - Math.round(outerW / 2);
|
|
942
|
+
const y0 = scy + breathPx - Math.round(outerH / 2);
|
|
943
|
+
for (let dy = 0; dy < outerH; dy++) {
|
|
944
|
+
for (let dx = 0; dx < outerW; dx++) {
|
|
945
|
+
const onFrame = dx < thick || dx >= outerW - thick || dy < thick || dy >= outerH - thick;
|
|
946
|
+
if (!onFrame)
|
|
947
|
+
continue; // hollow center
|
|
948
|
+
setPixel(buf, x0 + dx, y0 + dy, color);
|
|
709
949
|
}
|
|
710
950
|
}
|
|
711
951
|
if (state === 'asking') {
|
|
712
|
-
// Amber three-dot asking indicator
|
|
713
|
-
const dotCx = scx + Math.round(
|
|
714
|
-
const dotCy =
|
|
952
|
+
// Amber three-dot asking indicator above the mark
|
|
953
|
+
const dotCx = scx + Math.round(outerW / 2) + 3;
|
|
954
|
+
const dotCy = y0 - 2 + Math.round(Math.sin(animFrame * 0.26) * 1.4);
|
|
715
955
|
for (let i = -1; i <= 1; i++) {
|
|
716
956
|
blendPixel(buf, dotCx + i * 3, dotCy, COLORS.stateAwaiting, 0.75);
|
|
717
957
|
blendPixel(buf, dotCx + i * 3 + 1, dotCy, COLORS.stateAwaiting, 0.45);
|
|
718
958
|
}
|
|
719
959
|
}
|
|
720
960
|
}
|
|
961
|
+
function antigravityCellColor(ch, palette) {
|
|
962
|
+
switch (ch) {
|
|
963
|
+
case 'L': return palette.lime;
|
|
964
|
+
case 'T': return palette.teal;
|
|
965
|
+
case 'Q': return palette.cyan;
|
|
966
|
+
case 'Y': return palette.yellow;
|
|
967
|
+
case 'O': return palette.orange;
|
|
968
|
+
case 'R': return palette.red;
|
|
969
|
+
case 'P': return palette.pink;
|
|
970
|
+
case 'V': return palette.violet;
|
|
971
|
+
case 'U': return palette.blue;
|
|
972
|
+
case 'N': return palette.sky;
|
|
973
|
+
case 'K': return palette.cutout;
|
|
974
|
+
default: return null;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function drawQuestionMark(buf, x, y, color) {
|
|
978
|
+
setPixel(buf, x, y, color);
|
|
979
|
+
setPixel(buf, x + 1, y, color);
|
|
980
|
+
setPixel(buf, x + 1, y + 1, color);
|
|
981
|
+
setPixel(buf, x, y + 2, color);
|
|
982
|
+
setPixel(buf, x, y + 4, color);
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Awaiting affordance: a soft white disc with an amber "?" on top.
|
|
986
|
+
*
|
|
987
|
+
* (centerX, centerY) is the CENTER of the disc. The disc is the backing that
|
|
988
|
+
* keeps the mark legible against mid-water blues; the glyph is the 5-pixel
|
|
989
|
+
* question mark above, which is the smallest form that still reads as "?"
|
|
990
|
+
* rather than as noise.
|
|
991
|
+
*
|
|
992
|
+
* Mirror of `drawQuestionBubble` in apple/AgentDeck/Daemon/Modules/PixooRenderer.swift —
|
|
993
|
+
* keep the radius, alpha, and glyph offsets identical.
|
|
994
|
+
*/
|
|
995
|
+
export function drawQuestionBubble(buf, centerX, centerY) {
|
|
996
|
+
const r = 3;
|
|
997
|
+
for (let dy = -r; dy <= r; dy++) {
|
|
998
|
+
for (let dx = -r; dx <= r; dx++) {
|
|
999
|
+
if (dx * dx + dy * dy <= r * r)
|
|
1000
|
+
blendPixel(buf, centerX + dx, centerY + dy, COLORS.white, 0.7);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
// 5-px "?" centered in the disc — every pixel stays inside radius 3.
|
|
1004
|
+
drawQuestionMark(buf, centerX, centerY - 2, COLORS.stateAwaiting);
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Draw a canonical agent mark rasterized from design/brand/*.svg.
|
|
1008
|
+
*
|
|
1009
|
+
* Pixoo64 and iDotMatrix used to maintain independent hand-drawn creature grids;
|
|
1010
|
+
* the Swift daemon carried another copy. That made the smallest panels look like
|
|
1011
|
+
* approximations of the agents while vector/e-ink surfaces showed their real marks.
|
|
1012
|
+
* This renderer consumes the generated 24×24 alpha masks so both daemon families
|
|
1013
|
+
* preserve the official silhouette and cutouts. State remains a motion/color layer
|
|
1014
|
+
* around the mark, never a geometry rewrite.
|
|
1015
|
+
*/
|
|
1016
|
+
export function drawOfficialDotGlyph(buf, glyph, worldX, worldY, state, animFrame, camera, sessionToneIndex = 0, sizeScale = 1.0, sick = false) {
|
|
1017
|
+
if (!isVisible(worldX, worldY, camera, 0.15))
|
|
1018
|
+
return;
|
|
1019
|
+
const [scx, scy] = worldToScreen(worldX, worldY, camera);
|
|
1020
|
+
const canvasW = Math.sqrt(buf.length / 3);
|
|
1021
|
+
// The 8px floor is the legibility limit of the official mask — a crowd shrink
|
|
1022
|
+
// is allowed to reach it but never to go under it and turn a brand mark into mush.
|
|
1023
|
+
const target = Math.max(8, Math.round(0.1875 * sizeScale * camera.zoom * canvasW));
|
|
1024
|
+
const bob = state === 'working' ? Math.round(Math.sin(animFrame * 0.28) * Math.max(1, target / 14)) : 0;
|
|
1025
|
+
const x0 = Math.round(scx - target / 2);
|
|
1026
|
+
const y0 = Math.round(scy - target / 2) + bob;
|
|
1027
|
+
const mask = OFFICIAL_DOT_GLYPHS[glyph];
|
|
1028
|
+
const octopus = getOctopusPaletteForSession(sessionToneIndex);
|
|
1029
|
+
const codex = getJellyfishPaletteForSession(sessionToneIndex);
|
|
1030
|
+
const openCode = getOpenCodePaletteForSession(sessionToneIndex);
|
|
1031
|
+
const processingPulse = 0.28 + 0.18 * ((Math.sin(animFrame * 0.2) + 1) / 2);
|
|
1032
|
+
const solidColor = () => {
|
|
1033
|
+
if (sick)
|
|
1034
|
+
return COLORS.crayfishSick;
|
|
1035
|
+
switch (glyph) {
|
|
1036
|
+
case 'claudeCode':
|
|
1037
|
+
return state === 'working' ? octopus.starburst : state === 'sleeping' ? octopus.sleeping : octopus.body;
|
|
1038
|
+
case 'codex':
|
|
1039
|
+
return state === 'working' ? lerpColor(codex.body, codex.pulse, processingPulse) : state === 'sleeping' ? codex.sleeping : codex.body;
|
|
1040
|
+
case 'openCode':
|
|
1041
|
+
return state === 'working' ? lerpColor(openCode.outer, openCode.pulse, processingPulse) : state === 'sleeping' ? openCode.sleeping : openCode.outer;
|
|
1042
|
+
case 'openClaw': {
|
|
1043
|
+
const base = state === 'working' ? COLORS.crayfishRouting : COLORS.crayfishBody;
|
|
1044
|
+
return sick ? COLORS.crayfishSick : base;
|
|
1045
|
+
}
|
|
1046
|
+
case 'antigravity':
|
|
1047
|
+
return COLORS.white;
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
const base = solidColor();
|
|
1051
|
+
for (let dy = 0; dy < target; dy++) {
|
|
1052
|
+
const sy = Math.min(OFFICIAL_DOT_GLYPH_SIZE - 1, Math.floor(dy * OFFICIAL_DOT_GLYPH_SIZE / target));
|
|
1053
|
+
for (let dx = 0; dx < target; dx++) {
|
|
1054
|
+
const sx = Math.min(OFFICIAL_DOT_GLYPH_SIZE - 1, Math.floor(dx * OFFICIAL_DOT_GLYPH_SIZE / target));
|
|
1055
|
+
const alpha = mask[sy * OFFICIAL_DOT_GLYPH_SIZE + sx] / 255;
|
|
1056
|
+
if (alpha <= 0.02)
|
|
1057
|
+
continue;
|
|
1058
|
+
let color = base;
|
|
1059
|
+
if (glyph === 'antigravity') {
|
|
1060
|
+
const t = sx / (OFFICIAL_DOT_GLYPH_SIZE - 1);
|
|
1061
|
+
color = t < 0.25 ? lerpColor([0x5c, 0xd6, 0x4d], [0xf5, 0xcb, 0x24], t * 4)
|
|
1062
|
+
: t < 0.55 ? lerpColor([0xf5, 0xcb, 0x24], [0xff, 0x52, 0x41], (t - 0.25) / 0.3)
|
|
1063
|
+
: t < 0.78 ? lerpColor([0xff, 0x52, 0x41], [0xb7, 0x5c, 0xb6], (t - 0.55) / 0.23)
|
|
1064
|
+
: lerpColor([0xb7, 0x5c, 0xb6], [0x24, 0x7e, 0xff], (t - 0.78) / 0.22);
|
|
1065
|
+
}
|
|
1066
|
+
blendPixel(buf, x0 + dx, y0 + dy, color, alpha);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
// OpenClaw's official mark has eye cutouts too small to survive every 32px
|
|
1070
|
+
// camera position. Re-light the canonical eye coordinates without changing
|
|
1071
|
+
// the silhouette so the hardware keeps its teal OpenClaw signature.
|
|
1072
|
+
if (glyph === 'openClaw' && !sick) {
|
|
1073
|
+
const eye = COLORS.crayfishEye;
|
|
1074
|
+
for (const [vx, vy] of [[9.05, 7.63], [15.38, 7.63]]) {
|
|
1075
|
+
setPixel(buf, x0 + Math.round(vx / 24 * target), y0 + Math.round(vy / 24 * target), eye);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (state === 'asking') {
|
|
1079
|
+
drawQuestionBubble(buf, x0 + target + 1, y0);
|
|
1080
|
+
}
|
|
1081
|
+
else if (state === 'working') {
|
|
1082
|
+
const sparkle = glyph === 'antigravity' ? [0xff, 0xd8, 0x50] : lerpColor(base, COLORS.white, 0.45);
|
|
1083
|
+
for (let i = 0; i < 4; i++) {
|
|
1084
|
+
const angle = animFrame * 0.22 + i * Math.PI / 2;
|
|
1085
|
+
const distance = target / 2 + 2;
|
|
1086
|
+
setPixel(buf, Math.round(scx + Math.cos(angle) * distance), Math.round(scy + bob + Math.sin(angle) * distance), sparkle);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
export function drawAntigravity(buf, worldX, worldY, state, animFrame, camera, palette) {
|
|
1091
|
+
if (!isVisible(worldX, worldY, camera, 0.15))
|
|
1092
|
+
return;
|
|
1093
|
+
const [scx, scy] = worldToScreen(worldX, worldY, camera);
|
|
1094
|
+
const w = Math.sqrt(buf.length / 3);
|
|
1095
|
+
const cellSz = creatureCellSize(camera.zoom, w, AG_COLS);
|
|
1096
|
+
const spriteW = AG_COLS * cellSz;
|
|
1097
|
+
const spriteH = AG_ROWS * cellSz;
|
|
1098
|
+
const breathPx = state === 'working'
|
|
1099
|
+
? Math.round(Math.sin(animFrame * 0.28) * cellSz)
|
|
1100
|
+
: state === 'idle' ? Math.round(Math.sin(animFrame * 0.08) * 0.5) : 0;
|
|
1101
|
+
const cameraNudgeX = state === 'working' && ((animFrame >> 3) & 1) ? cellSz : 0;
|
|
1102
|
+
const cameraNudgeY = state !== 'idle' && ((animFrame >> 2) & 1) ? -cellSz : 0;
|
|
1103
|
+
const baseX = Math.round(scx - spriteW / 2) + cameraNudgeX;
|
|
1104
|
+
const baseY = Math.round(scy - spriteH / 2) + breathPx + cameraNudgeY;
|
|
1105
|
+
const trackedPixels = new Set();
|
|
1106
|
+
for (let row = 0; row < AG_ROWS; row++) {
|
|
1107
|
+
const line = ANTIGRAVITY_GRID[row];
|
|
1108
|
+
for (let col = 0; col < AG_COLS; col++) {
|
|
1109
|
+
const color = antigravityCellColor(line[col], palette);
|
|
1110
|
+
if (!color)
|
|
1111
|
+
continue;
|
|
1112
|
+
fillCellTracked(buf, baseX + col * cellSz, baseY + row * cellSz, cellSz, cellSz, color, trackedPixels);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
drawCreatureOutline(buf, trackedPixels, palette.violet, 0.45);
|
|
1116
|
+
if (state === 'asking') {
|
|
1117
|
+
drawQuestionMark(buf, Math.round(scx + spriteW * 0.48), Math.round(baseY + spriteH * 0.18), COLORS.stateAwaiting);
|
|
1118
|
+
}
|
|
1119
|
+
if (state === 'working') {
|
|
1120
|
+
const sparkle = lerpColor(palette.yellow, COLORS.white, 0.35);
|
|
1121
|
+
const dist = Math.max(2, cellSz * 3);
|
|
1122
|
+
for (let i = 0; i < 4; i++) {
|
|
1123
|
+
const t = animFrame * 0.22 + i * Math.PI / 2;
|
|
1124
|
+
setPixel(buf, Math.round(scx + Math.cos(t) * dist), Math.round(baseY - 1 + Math.sin(t) * dist * 0.35), sparkle);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
721
1128
|
/**
|
|
722
1129
|
* Draw crayfish scaled by camera zoom.
|
|
723
1130
|
* @param worldX Crayfish center in normalized world X (0~1)
|
|
@@ -727,14 +1134,16 @@ export function drawCrayfish(buf, worldX, worldY, routing, animFrame, cam, sick
|
|
|
727
1134
|
if (!isVisible(worldX, worldY, cam, 0.15))
|
|
728
1135
|
return;
|
|
729
1136
|
const [scx, scy] = worldToScreen(worldX, worldY, cam);
|
|
1137
|
+
const w = Math.sqrt(buf.length / 3);
|
|
730
1138
|
// LOD selection — matches octopus threshold
|
|
731
|
-
const
|
|
732
|
-
const grid =
|
|
733
|
-
const cols =
|
|
734
|
-
const rows =
|
|
735
|
-
//
|
|
736
|
-
|
|
737
|
-
const
|
|
1139
|
+
const select = selectGrid(cam.zoom, w, CRAYFISH_GRID_HD, CF_HD_COLS, CF_HD_ROWS, CRAYFISH_GRID_MD, CF_GRID_MD_COLS, CF_GRID_MD_ROWS, CRAYFISH_LOD, CF_LOD_COLS, CF_LOD_ROWS);
|
|
1140
|
+
const grid = select.grid;
|
|
1141
|
+
const cols = select.cols;
|
|
1142
|
+
const rows = select.rows;
|
|
1143
|
+
// Resolution-aware square cells (see creatureCellSize). Square (cellH = cellW) — the old
|
|
1144
|
+
// cellH = cellW*1.5 stretched the round OpenClaw body into a tall pointed shape.
|
|
1145
|
+
const cellW = creatureCellSize(cam.zoom, w, cols);
|
|
1146
|
+
const cellH = cellW;
|
|
738
1147
|
const spriteW = cols * cellW;
|
|
739
1148
|
const spriteH = rows * cellH;
|
|
740
1149
|
const baseX = scx - spriteW / 2;
|
|
@@ -752,7 +1161,7 @@ export function drawCrayfish(buf, worldX, worldY, routing, animFrame, cam, sick
|
|
|
752
1161
|
// 1. Glow halo (before creature — stronger for LOD)
|
|
753
1162
|
const glowRx = spriteW / 2 + 2;
|
|
754
1163
|
const glowRy = spriteH / 2 + 2;
|
|
755
|
-
drawCreatureGlow(buf, scx, scy + breathPx, glowRx, glowRy, COLORS.crayfishGlow, 0.12,
|
|
1164
|
+
drawCreatureGlow(buf, scx, scy + breathPx, glowRx, glowRy, COLORS.crayfishGlow, 0.12, cols === 8);
|
|
756
1165
|
// 2. Draw cells with pixel tracking
|
|
757
1166
|
const trackedPixels = new Set();
|
|
758
1167
|
for (let row = 0; row < rows; row++) {
|
|
@@ -769,7 +1178,7 @@ export function drawCrayfish(buf, worldX, worldY, routing, animFrame, cam, sick
|
|
|
769
1178
|
const spd = routing ? 0.35 : 0.15;
|
|
770
1179
|
const wiggle = Math.sin(animFrame * spd + col * 3) * cellW * 1.5;
|
|
771
1180
|
// Random-ish twitch: sharp spike every ~30 frames
|
|
772
|
-
const twitch = ((animFrame + col * 17) % 60) < 4 ? cellW * 2 * (col <
|
|
1181
|
+
const twitch = ((animFrame + col * 17) % 60) < 4 ? cellW * 2 * (col < cols / 2 ? -1 : 1) : 0;
|
|
773
1182
|
dx = ensureMinAmplitude(wiggle + twitch, 1);
|
|
774
1183
|
}
|
|
775
1184
|
// Claw animation — routing: slower, wider clap; idle: gentle sway
|
|
@@ -800,11 +1209,11 @@ export function drawCrayfish(buf, worldX, worldY, routing, animFrame, cam, sick
|
|
|
800
1209
|
}
|
|
801
1210
|
// 3. Colored outline — moderate alpha for LOD
|
|
802
1211
|
const bodyColor = routing ? COLORS.crayfishRouting : COLORS.crayfishBody;
|
|
803
|
-
const outlineAlpha =
|
|
1212
|
+
const outlineAlpha = cols === 8 ? 0.6 : 0.8;
|
|
804
1213
|
drawCreatureOutline(buf, trackedPixels, bodyColor, outlineAlpha);
|
|
805
1214
|
// Fixed 3×3 eyes (teal center + black ring) — drawn at grid eye positions
|
|
806
|
-
const eyeRow =
|
|
807
|
-
const eyeCols =
|
|
1215
|
+
const eyeRow = cols === 24 ? 9 : (cols === 8 ? 2 : 3);
|
|
1216
|
+
const eyeCols = cols === 24 ? [8, 14] : (cols === 8 ? [2, 5] : [4, 7]);
|
|
808
1217
|
const sickEyeCenter = [0x44, 0x66, 0x60]; // dim teal for sick
|
|
809
1218
|
const eyeCenter = sick ? sickEyeCenter : COLORS.crayfishEye;
|
|
810
1219
|
const eyeRing = sick ? [0x44, 0x33, 0x33] : COLORS.crayfishEyeRing;
|
|
@@ -851,7 +1260,8 @@ export function drawTetra(buf, worldX, worldY, heading, cam) {
|
|
|
851
1260
|
if (!isVisible(worldX, worldY, cam, 0.08))
|
|
852
1261
|
return;
|
|
853
1262
|
const [sx, sy] = worldToScreen(worldX, worldY, cam);
|
|
854
|
-
const
|
|
1263
|
+
const w = Math.sqrt(buf.length / 3);
|
|
1264
|
+
const px = cam.zoom * (w / 64); // resolution-aware pixel scale (half-size on 32px iDotMatrix)
|
|
855
1265
|
// Body (2px-equivalent)
|
|
856
1266
|
const bw = Math.max(1, Math.round(px * 2));
|
|
857
1267
|
const bh = Math.max(1, Math.round(px));
|
|
@@ -887,6 +1297,7 @@ const PIXEL_FONT = {
|
|
|
887
1297
|
'8': [0b111, 0b101, 0b111, 0b101, 0b111],
|
|
888
1298
|
'9': [0b111, 0b101, 0b111, 0b001, 0b111],
|
|
889
1299
|
'%': [0b101, 0b001, 0b010, 0b100, 0b101],
|
|
1300
|
+
'/': [0b001, 0b001, 0b010, 0b100, 0b100],
|
|
890
1301
|
'h': [0b100, 0b100, 0b111, 0b101, 0b101],
|
|
891
1302
|
'm': [0b101, 0b111, 0b101, 0b101, 0b101], // two pillars joined — distinct from 'n'
|
|
892
1303
|
'd': [0b001, 0b001, 0b011, 0b101, 0b011], // lowercase d — for day units (e.g. "6d22h")
|