release: bump version to 0.71.0
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
release / images (push) Has been cancelled
ci / delivery (push) Has been cancelled

This commit is contained in:
linkong
2026-06-11 16:47:24 +08:00
parent 8c204717cd
commit 899e3bce43
56 changed files with 4618 additions and 260 deletions

View File

@@ -102,9 +102,9 @@ Responsibilities:
- Map `rotate_left`, `rotate_right`, `rotate_up`, `rotate_down`, `zoom_in`, `zoom_out`, `focus_prev`, `focus_next`, `layer_prev`, `layer_next`, and `confirm` to the action entry points exposed by `main.js`.
- Parse `skeleton` debug events and dispatch `earth:motion-debug-frame`.
Gesture recognition may run locally in the browser or inside the local Agent, but neither path sends realtime camera frames to the SaaS cloud. `main.js` exposes rotation, zoom, target focus, layer switching, and confirm entry points, plus a `window.__planetEarth.motion` debug entry. The adapter starts only when `?motion=1` is present, browser local storage contains `planet-earth-motion-control-enabled=true`, or Earth settings enable Motion Debug Mode.
Gesture recognition may run locally in the browser or inside the local Agent, but neither path sends realtime camera frames to the SaaS cloud. `main.js` exposes rotation, zoom, target focus, layer switching, and confirm entry points, plus a `window.__planetEarth.motion` debug entry. The adapter starts only when `?motion=1` is present, browser local storage contains `planet-earth-motion-control-enabled=true`, or Earth settings enable Motion Debug Mode. `shared.motionEnabledGestures` stores the user-approved gesture whitelist; the browser filters locally, and Motion Agent mode also synchronizes it through `set_enabled_gestures`.
[motion-debug-panel.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-debug-panel.js) owns the debug panel. It listens for `earth:motion-debug-frame` and draws normalized skeleton joints and bones on a canvas. The Browser Camera provider also emits `earth:motion-debug-video-source` with the local `<video>` element so the panel can show a local preview behind the skeleton; `shared.motionDebugSkeletonOnly` switches the panel back to skeleton-only rendering. `Stop Matching Gestures` dispatches `earth:motion-recognition-pause`, which suppresses gesture execution while video and skeleton drawing continue. Unmatched skeletons are red; matched gestures turn green and display the gesture name. Settings are persisted under `shared.motionDebugEnabled`, `shared.motionProvider`, and `shared.motionDebugSkeletonOnly` in `planet.earth.settings.v2`, and both the switch and provider selector reserve `data-gatekeeper-permission="earth.motion_debug"`.
[motion-debug-panel.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-debug-panel.js) owns the debug panel. It listens for `earth:motion-debug-frame` and draws normalized skeleton joints and bones on a canvas. The Browser Camera provider also emits `earth:motion-debug-video-source` with the local `<video>` element so the panel can show a local preview behind the skeleton; `shared.motionDebugSkeletonOnly` switches the panel back to skeleton-only rendering. `Stop Matching Gestures` dispatches `earth:motion-recognition-pause`, which suppresses gesture execution while video and skeleton drawing continue. Unmatched skeletons are red; matched gestures turn green and display the gesture name. Settings are persisted under `shared.motionDebugEnabled`, `shared.motionProvider`, `shared.motionDebugSkeletonOnly`, and `shared.motionEnabledGestures` in `planet.earth.settings.v2`; the switch, provider selector, and gesture whitelist reserve `data-gatekeeper-permission="earth.motion_debug"`.
The Browser Camera provider's gesture pipeline lives in `recognizeGesture()` inside [motion-browser-provider.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-browser-provider.js). Detectors are evaluated in this order, first match wins:

View File

@@ -86,6 +86,55 @@ Importance levels are fixed: `low` 034, `medium` 3559, `high` 6079, and
`GET /api/v1/earth/news-sources` returns the default or saved configuration. `PUT /api/v1/earth/news-sources` saves it, increments `cache_version`, and clears the process region cache. `POST /api/v1/earth/news-sources/reset` restores defaults. `POST /api/v1/earth/news-sources/test` tests one RSS/Atom/Aggregated source without writing news items.
## Manual News Content
Manual news is a content-management path, not an RSS source configuration. The Admin entry is `Earth Content -> News Content`; the left rail groups items by RSS source and manual news group. After opening a manual group, administrators can add one item or upload a JSON array. Manual items are written to `earth_news_items` with `feed_type/source_type = manual`; the display label is “手动添加” / “Manual”. They do not participate in RSS connectivity tests and are not routed through RSS fetching.
Manual news uses a publish-first, enrich-later flow:
1. Saving immediately writes the item to `earth_news_items`.
2. If no manual coordinates are provided, the selected region anchor is used and `verified=false`.
3. If manual coordinates are provided, the item uses `location_source=manual_location` and `verified=true`; later AI enrichment does not overwrite that location.
4. Create and reprocess actions enqueue the item for cleanup, translation, classification, importance, Breaking, and target-location inference.
5. When enrichment finishes, the same row is updated and Earth receives a news reload / patch so the frontend replaces the item without a manual refresh.
The Admin API is under `/api/v1/earth/news-items`:
- `GET /earth/news-groups`: return RSS virtual source groups and manual news groups.
- `POST /earth/news-groups`: create a manual news group.
- `PUT /earth/news-groups/{group_id}`: rename a manual news group and synchronize metadata for items in that group.
- `GET /earth/news-items`: paginated RSS and manual news list, with filters for source type, region, category, and status.
- `POST /earth/news-items`: create one manual news item.
- `POST /earth/news-items/import`: upload a JSON array; `group_id` selects the current manual news group.
- `PUT /earth/news-items/{id}`: edit a manual news item; RSS items are read-only.
- `DELETE /earth/news-items/{id}`: delete a manual news item and trigger an Earth news reload.
- `POST /earth/news-items/{id}/reprocess`: requeue cleanup, translation, and geolocation.
The first JSON import format supports arrays only:
```json
[
{
"title": "Required title",
"summary": "Optional summary",
"content": "Optional body",
"url": "https://example.com/story",
"source": "Manual",
"region": "global",
"published_at": "2026-05-15T03:00:00Z",
"category": "business",
"tags": ["manual", "analysis"],
"location": {
"label": "Beijing, China",
"latitude": 39.9057,
"longitude": 116.3913
}
}
]
```
Imports deduplicate through a stable `manual:{hash}` ID derived from title, published time, URL, and source. Importing the same manual item again updates the existing row instead of creating a duplicate EarthFeed entry.
## Feed Query and Category Filtering
The Web Earth client and UE client both consume `GET /api/v1/news/earth-feed`. The endpoint supports server-side filtering, so clients do not need to fetch the full list and apply the primary category filter locally.
@@ -107,6 +156,8 @@ Unknown category or locale values return `422` with the allowed values. The resp
The Web Earth category chips only store the current browser preference; changing them triggers a new API request. UE should pass its selected categories through the `categories` query parameter and does not need to perform the primary filtering itself.
When `sources` is omitted, the service layer prefers stories that already have displayable title and summary content for the requested `locale`, supplements candidates from enabled sources, and rotates sources so one source's newest pending items cannot occupy all 12 default slots. An explicit `sources` filter remains precise and does not supplement other sources. The database query layer owns region, category, source, and ordering constraints only; it does not own locale presentation policy.
Source testing only proves that a specific RSS/Atom/XML feed can be parsed. It does not mean those items have already been written to the news table or are visible in the current region/category view. Saving or resetting news sources increments the configuration version and clears cache; if an enabled feed has no recent stored items, the next `earth-feed` request supplements from RSS so newly enabled sources such as 36Kr and Ebrun are not masked by fresh Google News rows.
## Breaking News Insertion
@@ -163,9 +214,11 @@ Reference links show that they only record a homepage, report page, or future co
```mermaid
flowchart LR
Admin["Admin: Earth Content / News Sources"] --> Source["Source config"]
ManualAdmin["Admin: Earth Content / News Content"] --> ManualAPI["/api/v1/earth/news-items"]
Source --> Feed["Feed children"]
Feed --> ConfigAPI["/api/v1/earth/news-sources"]
ConfigAPI --> Config["SystemSetting: earth_news_sources"]
ManualAPI --> Store
Earth["Earth News Panel"] --> NewsAPI["/api/v1/news/earth-feed"]
NewsAPI --> Resolver["Source Resolver"]

View File

@@ -194,6 +194,7 @@ TV livestreams and boundary precision moved to `/earth-content`; collectors and
- **Brand Assets**: manages the logo, title image, title text, subtitle, and description used by the Earth HUD. Uploaded images are saved as Earth brand assets and read by the Earth page immediately.
- **About**: manages the About card shown in Earth settings, including logo, kicker, title, version, description, and metadata.
- **TV Livestream**: manages sources shown in the Earth media panel.
- **News Content**: browses news grouped by RSS source and manual group. RSS items remain read-only; manual groups support create, JSON import, edit, delete, and reprocess.
- **Boundary Precision**: shows the current provider, low-precision fallback, high-precision PMTiles/manifest status, local source JSON, and manual build action.
- **Base Map**, **Layer Resources**, **3D Assets**, and **News Anchor Strategy**: placeholder tabs for future configuration. They do not display fake data.
@@ -298,7 +299,7 @@ Adopt All is for batch processing the compute-center unresolved queue. It starts
### Settings
The settings panel is grouped into Runtime, Display, Panels, Motion, Shortcuts, and System. It covers rotate / cruise / motion mode, cruise modules (BGP/news/compute centers/vessels/cables/satellites), view (satellite display style, hover tooltip, satellite idle breathing, real satellite altitude, track display, compact dots, day-night mode, panel toggles), motion debug mode / input source / skeleton-only, shortcut enablement and remapping, default globe size, terrain opacity, reset.
The settings panel is grouped into Runtime, Display, Panels, Motion, Shortcuts, and System. It covers rotate / cruise / motion mode, cruise modules (BGP/news/compute centers/vessels/cables/satellites), view (satellite display style, hover tooltip, satellite idle breathing, real satellite altitude, track display, compact dots, day-night mode, panel toggles), motion debug mode / input source / skeleton-only / recognized-gesture whitelist, shortcut enablement and remapping, default globe size, terrain opacity, reset.
News categories use the same chip selector as Cruise Modules. They only filter the news panel and news cruise items in the current browser; they do not affect layers, TV, data points, basemap, boundaries, collector jobs, or admin news-source configuration.
@@ -336,6 +337,8 @@ Enable via the settings toggle "Motion Debug Mode", or with URL parameter `?moti
Neither mode uploads camera frames or live gestures; neither reuses the news/RSS aggregation API.
Recognized Gestures can disable rotation, zoom, focus switching, layer switching, or confirmation independently. The browser ignores unchecked actions; when Motion Agent is active, the same whitelist is synchronized through the control protocol.
Gesture semantics:
| Event | Effect |

View File

@@ -244,22 +244,27 @@ The recommended direction is a small platform compatibility layer for port liste
The production frontend shape is `vite build` static output served by nginx/Caddy or an equivalent HTTP server. Do not use `bun run dev` or `vite preview` in production. The project does not maintain a parallel Webpack build chain; if a future enterprise requirement needs closer Webpack-ecosystem compatibility, run an Rsbuild/Rspack spike first. Electron should only be evaluated when the official target becomes an offline desktop application.
## Optional Motion Agent Startup
## Default Motion Agent Startup
`planet.sh` can now manage the local Motion Capture Agent. It is disabled by default so ordinary development machines do not fail startup when cameras, OpenCV, or MediaPipe are unavailable.
`planet.sh` now starts the local Motion Agent by default during `start` and full `restart`. This makes the Earth page, UE clients, and debug clients able to connect to `ws://127.0.0.1:8765/ws/gestures` immediately. If the machine has no usable camera, implicit default startup falls back to dry-run protocol mode and does not block backend/frontend startup. Explicit Motion Agent startup through `--motion-agent`, camera indexes, camera URLs, or WSL USB options still treats live camera failures as real errors.
Start it with:
To skip Motion Agent for this run:
```bash
./planet.sh start --motion-agent
./planet.sh start --non-motion-agent
./planet.sh restart --non-motion-agent
```
Common options:
- `--motion-agent` / `-m`: start or restart the Motion Agent for this command.
- `--non-motion-agent`: do not start Motion Agent for this `start` or full `restart`.
- `--motion-agent` / `-m`: explicitly start or restart the Motion Agent for this command; live camera failures are reported as failures.
- `--motion-agent-port <port>`: override the default WebSocket port `8765`.
- `--motion-agent-mode <mode>`: choose `auto`, `single`, `dual_redundant`, `single_fallback`, or `calibrated_3d`; `dual` is kept as a compatibility alias for redundant dual-camera mode.
- `--motion-agent-camera-indexes <indexes>`: override auto-detected camera indexes, for example `0` or `0,1`. The same can be provided through `MOTION_AGENT_CAMERA_INDEXES=0,1`.
- `--motion-agent-camera-urls <urls>`: use RTSP/HTTP camera streams, useful for WSL, phone cameras, or network cameras. The same can be provided through `MOTION_AGENT_CAMERA_URLS=...`.
- `--motion-agent-wsl-usbipd`: in WSL, try to attach the single detected Windows USB camera through `usbipd-win`.
- `--motion-agent-wsl-usbipd-busid <BUSID>`: in WSL, attach the camera matching a `usbipd list` BUSID; use this when multiple cameras are present.
- `--motion-agent-dry-run`: start only the protocol service without opening cameras or loading CV dependencies; useful for Web client debugging.
Non-dry-run live mode checks `mediapipe` and `opencv-python` before startup. If the current `.venv` is missing them, the script automatically runs:
@@ -268,13 +273,17 @@ Non-dry-run live mode checks `mediapipe` and `opencv-python` before startup. If
uv add mediapipe opencv-python
```
To disable startup-time auto-install:
To disable startup-time Python CV dependency auto-install:
```bash
PLANET_MOTION_AGENT_AUTO_INSTALL=0 ./planet.sh start --motion-agent
PLANET_MOTION_AGENT_AUTO_INSTALL=0 ./planet.sh start
```
Live mode auto-detects `/dev/video*` and passes the first two indexes to the Motion Agent. In WSL, Windows cameras usually do not appear as `/dev/video*` automatically. Check available devices first:
`./planet.sh init` also performs a WSL host dependency preflight for `usbipd-win`. If `usbipd.exe` is missing, the script first tries `winget install -e --id dorssel.usbipd-win`, then reuses the repository-bundled dorssel.usbipd-win MSI fallback. If that cached MSI is missing or an architecture-specific MSI is needed, it downloads one and requests an Administrator PowerShell installation. This is best-effort: failure prints next steps but does not block normal initialization. Use `./planet.sh init --non-motion-agent` to skip this preflight.
Live mode auto-detects `/dev/video*`, then prefers an OpenCV probe to keep only indexes that can open and return frames before passing them to the Motion Agent. In WSL/USB camera setups, one camera can expose multiple `/dev/video*` nodes, and some of them are metadata or non-capture nodes; the script skips those unreadable indexes. In WSL, Windows cameras usually do not appear as `/dev/video*` automatically. Check available devices first:
Live capture defaults to low-latency settings: `640x360` input and roughly `15Hz` recognition events. The worker uses latest-frame reader threads and keeps only the newest frame from each camera, so a slow MediaPipe frame does not make the recognizer drain stale camera backlog. The skeleton debug stream is disabled by default and is only sent at roughly `8Hz` while the Earth motion debug panel is open, so normal gesture control is not slowed down by debug data. Status events report both capture FPS and recognition FPS to separate camera throughput issues from recognition cost.
```bash
ls /dev/video*
@@ -292,20 +301,42 @@ In WSL, the more general path is to connect a phone or network camera through an
./planet.sh start --motion-agent --motion-agent-camera-urls http://192.168.1.20:8080/video
```
If WSL has no `/dev/video*` and no `--motion-agent-camera-urls` is provided, live startup stops and prints guidance instead of silently falling back to dry-run. Choose one of:
To use a Windows USB camera directly from WSL, let the script call `usbipd-win`. This is opt-in because an attached camera is usually temporarily unavailable to Windows apps while WSL owns it.
When there is only one camera:
```bash
./planet.sh start --motion-agent --motion-agent-wsl-usbipd
```
When there are multiple cameras, inspect the BUSID first and pass it explicitly:
```bash
usbipd.exe list
./planet.sh start --motion-agent --motion-agent-wsl-usbipd-busid 3-2
```
If `usbipd attach` says the device is not shared or bound, the script tries to open an Administrator PowerShell to run `usbipd bind`, then retries attach. If UAC is canceled or automatic bind fails, run this manually from an Administrator PowerShell:
```powershell
usbipd bind --busid 3-2
usbipd attach --wsl --busid 3-2
```
If WSL has no `/dev/video*` and no `--motion-agent-camera-urls` is provided, implicit default startup falls back to dry-run. Explicit live startup stops and prints guidance. Choose one of:
```bash
./planet.sh start --motion-agent --motion-agent-camera-urls http://<phone-ip>:8080/video
./planet.sh start --motion-agent --motion-agent-wsl-usbipd
./planet.sh start --motion-agent --motion-agent-dry-run
```
Automatic dry-run fallback only happens when `PLANET_MOTION_AGENT_WSL_ALLOW_DRY_RUN_FALLBACK=1` is explicitly set.
For explicit live startup, automatic dry-run fallback only happens when `PLANET_MOTION_AGENT_WSL_ALLOW_DRY_RUN_FALLBACK=1` is set.
Environment-variable startup is also supported:
`--non-motion-agent` is the command-level opt-out. Environment variables can still tune how the service starts:
```bash
PLANET_START_MOTION_AGENT=1 ./planet.sh start
MOTION_AGENT_DRY_RUN=1 PLANET_START_MOTION_AGENT=1 ./planet.sh start
MOTION_AGENT_DRY_RUN=1 ./planet.sh start
```
Logs:

View File

@@ -39,7 +39,7 @@ flowchart TB
VesselRaw["AIS / BarentsWatch"] --> VesselDerived["vessel_static / vessel_position"]
VesselDerived --> VesselLayer["vessels layer"]
Interactables["earth_interactables"] --> InteractableLayer["interactables layer"]
NewsRaw["RSS / Live / News"] --> NewsItems["earth_news_items"]
NewsRaw["RSS / Manual News / Live"] --> NewsItems["earth_news_items"]
NewsItems --> NewsLayer["news / media layer"]
```
@@ -51,7 +51,7 @@ flowchart TB
| BGP context | Collectors, anomalies, incidents, route events, and regional context | `ris_live_bgp`, `bgpstream_bgp`, prefix geography sources | `bgp_observations`, `bgp_anomalies`, `bgp_incidents`, `bgp_collector_locations` | `bgp` | `clear_then_reload` |
| Vessels | AIS vessels, positions, tracks, legend, and source health | AIS sources, `barentswatch_vessels` | `vessel_static`, `vessel_position`, `ais_raw_observations`, `ais_source_health` | `vessels` | `clear_then_reload` |
| Interactables | Generic surface icons, manual objects, and future small layers | `earth_interactables` | None | `interactables` | `delta` |
| News and media | Earth news, live streams, cruise summaries, and situation content | news sources | `earth_news_items` | `news` / `media` | `reload` |
| News and media | Earth news, live streams, cruise summaries, and situation content | RSS news sources, manual news, live streams | `earth_news_items` | `news` / `media` | `reload` |
## Satellites
@@ -141,12 +141,12 @@ Vessel data shows AIS vessels, navigation state, vessel-type legend, and source
News and media support the Earth news ticker, live stream panel, news cruise, and situation summaries. They are content refresh paths rather than stable geographic object layers, so they default to `reload`.
- **Collection entry**: RSS, live streams, news sources.
- **Fact table**: news source rows in `collected_data`.
- **Collection entry**: RSS news sources, manual news from `Earth Content -> News Content`, and live streams.
- **Fact table**: news source rows in `collected_data`; manual news writes directly to `earth_news_items` and marks the content source with `feed_type/source_type=manual`.
- **Derived table**: `earth_news_items`.
- **API**: news, live stream, and media content APIs.
- **API**: `/api/v1/news/earth-feed` reads `earth_news_items`; the Admin API `/api/v1/earth/news-items` supports manual create, JSON import, edit, delete, and reprocess.
- **Delete semantics**: deleting news sources or `earth_news_items` broadcasts `news` / `media` reload; empty responses hide the corresponding content.
- **Common failure**: the live panel shows stale content. Usually the media component ignored the layer update or the content API cache was not invalidated.
- **Common failure**: a newly saved manual item may initially show source text or a region anchor; this is the normal publish-first enrichment window. If it never updates, check the `earth_news_enrichment` queue, AI / Web Search configuration, and `enrichment_status`. If the live panel shows stale content, the media component likely ignored the layer update or the content API cache was not invalidated.
## Adding a New Layer

View File

@@ -50,7 +50,7 @@ Once in, verify:
- Search finds cables, satellites, compute centers, BGP events
- Compute-center and BGP collector detail cards can collect coordinate candidates and preview them on Earth
- Mouse drag, wheel zoom, and the zoom percentage indicator work
- The settings panel can switch rotate / cruise / motion modes; view settings can switch hover tooltip content, and satellite settings can toggle real-altitude layering and track display
- The settings panel can switch rotate / cruise / motion modes; motion settings can select the input source and allowed gestures; view settings can switch hover tooltip content, and satellite settings can toggle real-altitude layering and track display
## 5. Recover a Lost Password