Skip to content

Add flight-map-canvas extension - #2482

Merged
aaronpowell merged 3 commits into
github:mainfrom
jhauga:extension-flight-map
Jul 30, 2026
Merged

Add flight-map-canvas extension#2482
aaronpowell merged 3 commits into
github:mainfrom
jhauga:extension-flight-map

Conversation

@jhauga

@jhauga jhauga commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Pull Request Checklist

  • I have read and followed the CONTRIBUTING.md guidelines.
  • I have read and followed the Guidance for submissions involving paid services.
  • My contribution adds a new instruction, prompt, agent, skill, workflow, or canvas extension file in the correct directory.
  • The file follows the required naming convention.
  • The content is clearly structured and follows the example format.
  • I have tested my instructions, prompt, agent, skill, workflow, or canvas extension with GitHub Copilot.
  • I have run npm start and verified that README.md is up to date.
  • I am targeting the main branch for this pull request.

Description

A canvas first-person flight-simulator using satellite terrain from
Google Maps. For session breaks while an agent works.

Test:

  • Agent: Interactive
  • Model: Claude Sonnet 4.6
  • Number of Prompts: 1
  • Post Edits: Screenshot

Prompt

create-canvas flight-map

Results

See screenshot below:

screenshot.png


Type of Contribution

  • New instruction file.
  • New prompt file.
  • New agent file.
  • New plugin.
  • New skill file.
  • New agentic workflow.
  • New canvas extension.
  • Update to existing instruction, prompt, agent, plugin, skill, workflow, or canvas extension.
  • Other (please specify):

By submitting this pull request, I confirm that my contribution abides by the Code of Conduct and will be licensed under the MIT License.

A canvas port of the Flight Map VSCode extension: a first-person
satellite terrain map flown with flight simulator controls, for
session breaks while an agent works.

The simulator under game/ is copied verbatim from the source
extension's media/ folder. That page already reached its host through
one seam - an acquireVsCodeApi() object and a placeholder in its head -
so extension.mjs fills that seam for the canvas: a loopback server that
injects a policy, the render configuration, and a shim translating
Server-Sent Events into the messages the page already handles.

Two agent actions: fly_to sends the flight to a capital, a geocoded
city, or a raw lat/lng, and picks a random capital when called with no
input; report_job shows the current job step under the HUD.

Adds the vendored three.min.js to the codespell skip list, matching the
existing entry for arcade-canvas's phaser.min.js.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 22:09
@jhauga
jhauga requested a review from aaronpowell as a code owner July 29, 2026 22:09
@github-actions github-actions Bot added canvas-extension PR touches canvas extensions new-submission PR adds at least one new contribution labels Jul 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an installable flight-simulator canvas using satellite imagery, Three.js, and agent-driven destination/status actions.

Changes:

  • Adds the loopback canvas host and simulator frontend.
  • Adds destination search, flight controls, rendering configuration, and assets.
  • Registers the extension in the GitHub Copilot marketplace.

Reviewed changes

Copilot reviewed 18 out of 22 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
.codespellrc Excludes vendored Three.js.
.github/plugin/marketplace.json Registers the extension.
extensions/flight-map-canvas/.github/plugin/plugin.json Defines marketplace metadata.
extensions/flight-map-canvas/README.md Documents installation and usage.
extensions/flight-map-canvas/assets/icon.png Provides the application icon.
extensions/flight-map-canvas/assets/preview.png Provides the gallery preview.
extensions/flight-map-canvas/copilot-extension.json Defines extension identity.
extensions/flight-map-canvas/extension.mjs Implements canvas hosting and actions.
extensions/flight-map-canvas/game/app.js Implements the map and simulation.
extensions/flight-map-canvas/game/capitals.js Supplies capital destinations.
extensions/flight-map-canvas/game/destinationInput.js Implements destination selection.
extensions/flight-map-canvas/game/flightControls.js Implements flight controls.
extensions/flight-map-canvas/game/geocoder.js Integrates Nominatim geocoding.
extensions/flight-map-canvas/game/hostBridge.js Bridges host messages.
extensions/flight-map-canvas/game/index.html Defines the simulator UI.
extensions/flight-map-canvas/game/renderConfig.js Manages rendering configuration.
extensions/flight-map-canvas/game/styles.css Styles the simulator interface.
extensions/flight-map-canvas/game/terrainFill.js Generates terrain and cloud fill.
extensions/flight-map-canvas/game/vendor/three.min.js Vendors Three.js r128.
extensions/flight-map-canvas/package-lock.json Locks dependencies.
extensions/flight-map-canvas/package.json Declares package metadata.
extensions/flight-map-canvas/renderMap.json Provides initial render settings.
Files not reviewed (1)
  • extensions/flight-map-canvas/package-lock.json: Generated file
Comments suppressed due to low confidence (1)

extensions/flight-map-canvas/game/app.js:908

  • The same falsy latitude check also disables zoom reloads for valid equatorial destinations. Check whether a destination has been loaded rather than treating latitude zero as absent.
    if (!originLat) return;

Comment thread extensions/flight-map-canvas/renderMap.json
Comment thread extensions/flight-map-canvas/game/app.js Outdated
Comment thread extensions/flight-map-canvas/game/terrainFill.js Outdated
Comment thread extensions/flight-map-canvas/game/flightControls.js
Comment thread extensions/flight-map-canvas/game/geocoder.js
Comment thread extensions/flight-map-canvas/game/app.js Outdated
Comment thread extensions/flight-map-canvas/game/destinationInput.js
Comment thread extensions/flight-map-canvas/game/index.html Outdated
Comment thread extensions/flight-map-canvas/extension.mjs Outdated
Comment thread extensions/flight-map-canvas/game/geocoder.js Outdated
@jhauga
jhauga marked this pull request as draft July 29, 2026 22:17
@jhauga
jhauga marked this pull request as ready for review July 30, 2026 01:48
Copilot AI review requested due to automatic review settings July 30, 2026 01:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 22 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • extensions/flight-map-canvas/package-lock.json: Generated file
Comments suppressed due to low confidence (5)

extensions/flight-map-canvas/game/app.js:268

  • Checking only that the key exists is unsafe after clearAllTiles(): selecting/reloading the same destination can recreate the same key while the old request is still pending. The old callback then writes to its disposed mesh, marks the replacement tile loaded, and leaks the returned texture. Capture the tile record and require loadedTiles[key] to be that exact record in every primary/fallback callback, disposing textures returned for stale records.
    textureLoader.load(url, function (texture) {
        if (!loadedTiles[key]) return; // Already unloaded

extensions/flight-map-canvas/extension.mjs:367

  • These SSE handlers dispatch updates without updating init. During startup, HostBridge has not registered the page command handlers yet, so an action arriving then is dropped; the later ready replay can also overwrite it with the stale opening destination/job. Save each parsed SSE payload into init before dispatching so the ready replay always carries the latest state.
      events.addEventListener('flyTo', function (event) {
        try { dispatch({ command: 'flyTo', destination: JSON.parse(event.data).destination }); } catch (e) {}
      });
      events.addEventListener('jobStatus', function (event) {
        try { dispatch({ command: 'jobStatus', job: JSON.parse(event.data).job }); } catch (e) {}

extensions/flight-map-canvas/extension.mjs:180

  • The server-side geocoder does not enforce the one-request-per-second limit described above. Concurrent fly_to/open calls (and requests from multiple canvas instances) call fetch in parallel, while the browser geocoder has a separate queue, so this can exceed Nominatim's limit and cause the shared client IP to be throttled. Route all Nominatim traffic through one shared, rate-limited queue (ideally via the loopback server).
        response = await fetch(`${NOMINATIM}?${params}`, {
            headers: { "user-agent": USER_AGENT, accept: "application/json" },
        });

extensions/flight-map-canvas/game/destinationInput.js:160

  • A search response is not tied to the dialog session or query that started it. If the user cancels, reopens, and starts another search before the first request returns, the first callback can replace the new search with stale results and re-enable the button while the newer request is pending. Add a monotonically increasing request/session token and ignore callbacks whose token is no longer current.
        }, function (error, found) {
            setSearching(false);

extensions/flight-map-canvas/game/app.js:265

  • tileY is sent to both providers without checking the valid Web Mercator row range [0, 2^zoom - 1]. Since the public input accepts latitude ±85.0511, opening at either limit immediately schedules roughly half of the load disk with negative or out-of-range rows (and flight can move farther beyond it), producing repeated primary and fallback failures. Filter invalid rows before scheduling requests and constrain flight at the projection boundary.

This issue also appears on line 267 of the same file.

    var urlX = wrapTileX(tileX, TILE_ZOOM);
    var url = getTileUrl(urlX, tileY, TILE_ZOOM);

@aaronpowell
aaronpowell merged commit c46b4a9 into github:main Jul 30, 2026
14 checks passed
@jhauga
jhauga deleted the extension-flight-map branch July 30, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

canvas-extension PR touches canvas extensions new-submission PR adds at least one new contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants