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

View File

@@ -109,9 +109,9 @@ Earth 设置面板现在按 `data-settings-tab` 和 `data-settings-tab-panel`
-`rotate_left``rotate_right``rotate_up``rotate_down``zoom_in``zoom_out``focus_prev``focus_next``layer_prev``layer_next``confirm` 映射到 `main.js` 暴露的动作入口。
- 解析 `skeleton` 调试事件并派发 `earth:motion-debug-frame`
动作捕捉识别可以在浏览器本地执行,也可以在本地 Agent 中执行,但两者都不会把实时视频帧发给 SaaS 云端。`main.js` 暴露旋转、缩放、目标切换、图层切换和确认入口,并通过 `window.__planetEarth.motion` 提供调试入口。默认只有 URL 参数 `?motion=1`、本地存储 `planet-earth-motion-control-enabled=true`,或 Earth 设置中的“动捕调试模式”打开时才启动当前 provider。
动作捕捉识别可以在浏览器本地执行,也可以在本地 Agent 中执行,但两者都不会把实时视频帧发给 SaaS 云端。`main.js` 暴露旋转、缩放、目标切换、图层切换和确认入口,并通过 `window.__planetEarth.motion` 提供调试入口。默认只有 URL 参数 `?motion=1`、本地存储 `planet-earth-motion-control-enabled=true`,或 Earth 设置中的“动捕调试模式”打开时才启动当前 provider。`shared.motionEnabledGestures` 保存用户允许识别的动作浏览器端先过滤Motion Agent 模式还会通过 `set_enabled_gestures` 同步给服务端。
动捕调试面板由 [motion-debug-panel.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-debug-panel.js) 负责。它监听 `earth:motion-debug-frame`,用 canvas 绘制归一化骨架点和连线Browser Camera provider 会额外通过 `earth:motion-debug-video-source` 提供本机 `<video>` 作为调试预览底图,`shared.motionDebugSkeletonOnly` 可切换为只显示骨骼。`停止匹配动作` 通过 `earth:motion-recognition-pause` 暂停 gesture 执行,但继续显示视频和骨架。未匹配动作为红色,匹配后变绿并显示动作名。设置项持久化在 `planet.earth.settings.v2``shared.motionDebugEnabled``shared.motionProvider``shared.motionDebugSkeletonOnly`switch输入源控件都预留 `data-gatekeeper-permission="earth.motion_debug"`
动捕调试面板由 [motion-debug-panel.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-debug-panel.js) 负责。它监听 `earth:motion-debug-frame`,用 canvas 绘制归一化骨架点和连线Browser Camera provider 会额外通过 `earth:motion-debug-video-source` 提供本机 `<video>` 作为调试预览底图,`shared.motionDebugSkeletonOnly` 可切换为只显示骨骼。`停止匹配动作` 通过 `earth:motion-recognition-pause` 暂停 gesture 执行,但继续显示视频和骨架。未匹配动作为红色,匹配后变绿并显示动作名。设置项持久化在 `planet.earth.settings.v2``shared.motionDebugEnabled``shared.motionProvider``shared.motionDebugSkeletonOnly``shared.motionEnabledGestures`switch输入源和动作白名单控件都预留 `data-gatekeeper-permission="earth.motion_debug"`
Browser Camera provider 的手势识别管线在 [motion-browser-provider.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-browser-provider.js) 的 `recognizeGesture()`,按以下顺序匹配,前者命中即返回:

View File

@@ -86,6 +86,55 @@ Earth 态势新闻使用 `/api/v1/news/earth-feed` 输出给前端。新闻源
`GET /api/v1/earth/news-sources` 返回默认或已保存配置。`PUT /api/v1/earth/news-sources` 保存配置并递增 `cache_version`,同时清理进程内 region cache。`POST /api/v1/earth/news-sources/reset` 恢复默认源。`POST /api/v1/earth/news-sources/test` 只测试单个 RSS/Atom/Aggregated 源,不写入新闻表。
## 手动新闻内容
手动新闻是内容管理能力,不是 RSS 源配置。Admin 入口是 `智能星球内容 -> 新闻内容`,左栏按 RSS 来源和手动新闻组聚合;进入手动组详情后可以按条添加新闻或上传 JSON 数组批量导入。手动新闻写入 `earth_news_items`,并标记 `feed_type/source_type = manual`;前台展示文案是“手动添加”。它不参与 RSS 连通性测试,也不会进入 RSS 抓取流程。
手动新闻采用“先展示,再精修”的策略:
1. 保存后立即写入 `earth_news_items`
2. 没有人工坐标时使用所选区域锚点,`verified=false`
3. 有人工坐标时使用 `location_source=manual_location``verified=true`,后续 AI 精修不会覆盖该坐标。
4. 创建或重新处理后进入新闻增强队列后台补清洗、翻译、分类、重要度、Breaking 和目标位置推断。
5. 精修完成后更新同一条新闻,并通过 Earth news reload / patch 让前端无感替换。
后台接口挂在 `/api/v1/earth/news-items`
- `GET /earth/news-groups`:返回 RSS 虚拟来源组和手动新闻组。
- `POST /earth/news-groups`:新建手动新闻组。
- `PUT /earth/news-groups/{group_id}`:重命名手动新闻组,并同步组内新闻 meta。
- `GET /earth/news-items`:分页查询 RSS 与手动新闻,支持来源类型、区域、类型和状态过滤。
- `POST /earth/news-items`:新增一条手动新闻。
- `POST /earth/news-items/import`:上传 JSON 数组批量导入,`group_id` 指定当前手动新闻组。
- `PUT /earth/news-items/{id}`编辑手动新闻RSS 新闻只读。
- `DELETE /earth/news-items/{id}`:删除手动新闻,并触发 Earth 新闻重载。
- `POST /earth/news-items/{id}/reprocess`:重新进入清洗、翻译和定位队列。
JSON 导入首版只支持数组:
```json
[
{
"title": "必填标题",
"summary": "可选摘要",
"content": "可选正文",
"url": "https://example.com/story",
"source": "手动添加",
"region": "global",
"published_at": "2026-05-15T03:00:00Z",
"category": "business",
"tags": ["manual", "analysis"],
"location": {
"label": "北京市, 中国",
"latitude": 39.9057,
"longitude": 116.3913
}
}
]
```
重复导入使用稳定 ID 去重ID 由标题、发布时间、URL 和来源生成,格式为 `manual:{hash}`。同一条手动新闻再次导入会更新原记录,不会重复出现在 EarthFeed。
## Feed 查询与类型过滤
星球端和 UE 端统一使用 `GET /api/v1/news/earth-feed` 获取新闻。接口支持服务端过滤,不要求客户端拿全量列表后自行筛选。
@@ -107,6 +156,8 @@ GET /api/v1/news/earth-feed?region=global&categories=business,ecommerce&locale=z
Web 星球端的新闻类型按钮只保存当前浏览器的显示偏好偏好变化后会重新请求接口。UE 端应直接把类型选择拼到 `categories` 参数里,不需要再做主过滤。
未指定 `sources` 时,服务层会优先选择当前 `locale` 已有可展示标题和摘要的新闻,并从当前启用来源补齐候选后做来源轮转,避免一个来源的最新待处理条目占满默认 12 条。指定 `sources` 时保持精确来源过滤,不做跨来源补齐。数据库查询层只负责区域、类型、来源和排序条件,不包含语言展示策略。
源测试只证明当前 RSS/Atom/XML 能解析到条目,不等于这些条目已经入库展示。展示链路还会检查区域、类型过滤和数据库新鲜度。保存或重置新闻源会递增配置版本并清理缓存;如果当前启用的 Feed 子项在库里没有近期条目,下一次 `earth-feed` 请求会补抓,避免新启用的 36氪、亿邦被旧 Google News 缓存挡住。
## Breaking News 插队
@@ -163,9 +214,11 @@ Admin 入口是 `Earth 内容 -> 新闻源`。界面不是整包 JSON 编辑,
```mermaid
flowchart LR
Admin["Admin: Earth 内容 / 新闻源"] --> Source["Source 配置"]
ManualAdmin["Admin: Earth 内容 / 新闻内容"] --> ManualAPI["/api/v1/earth/news-items"]
Source --> Feed["Feed 子项"]
Feed --> ConfigAPI["/api/v1/earth/news-sources"]
ConfigAPI --> Config["SystemSetting: earth_news_sources"]
ManualAPI --> Store
Earth["Earth 新闻面板"] --> NewsAPI["/api/v1/news/earth-feed"]
NewsAPI --> Resolver["Source Resolver"]

View File

@@ -193,6 +193,7 @@ Base URL 输入框尾端的插头图标会触发连接测试。测试通过会
- **品牌资源**:维护智能星球 HUD 使用的 logo、标题图、标题文本、副标题和描述上传的图片会保存为智能星球品牌资产并立即供智能星球页面读取。
- **关于**:维护智能星球设置面板里的关于卡片,包括 logo、眉标、标题、版本、描述和元信息。
- **电视直播**:维护智能星球媒体面板里的直播源。
- **新闻内容**:按 RSS 来源和手动新闻组查看新闻。RSS 新闻保持只读;手动新闻组可以新增、批量导入 JSON、编辑、删除和重新处理。
- **国界精度**:查看当前国界 provider、低精 fallback、高精 PMTiles/manifest 状态,编辑本机源配置并手动构建。
- **地球底图**、**图层资源**、**三维素材**、**新闻锚点策略**:目前是待接入占位页,不展示假数据。
@@ -297,7 +298,7 @@ AIS 船只图例按船型显示颜色:货轮、油轮、客船、渔船、军
### 设置
设置面板按分类组织:运行、显示、面板、动捕、快捷键、系统。里面包含旋转模式 / 巡航模式 / 动捕模式、巡航模块BGP/新闻/算力中心/船只/海缆/卫星)、视图设置(卫星显示风格、悬停提示、卫星呼吸闪烁、真实卫星高度、轨迹显示、低缩放圆点、日夜模式、面板显示开关)、动捕调试模式 / 输入源 / 只显示骨骼、快捷键启用与改键、地球默认大小、地形透明度、重置设置。
设置面板按分类组织:运行、显示、面板、动捕、快捷键、系统。里面包含旋转模式 / 巡航模式 / 动捕模式、巡航模块BGP/新闻/算力中心/船只/海缆/卫星)、视图设置(卫星显示风格、悬停提示、卫星呼吸闪烁、真实卫星高度、轨迹显示、低缩放圆点、日夜模式、面板显示开关)、动捕调试模式 / 输入源 / 只显示骨骼 / 识别动作白名单、快捷键启用与改键、地球默认大小、地形透明度、重置设置。
新闻类型使用与巡航模块一致的标签选择器只筛选当前浏览器里的新闻面板和新闻巡航条目不影响图层、TV、数据点、底图、边界、采集任务或后台新闻源配置。
@@ -335,6 +336,8 @@ AIS 船只图例按船型显示颜色:货轮、油轮、客船、渔船、军
两种模式都不会把摄像头帧或实时手势发到云端,也不会复用新闻/RSS 聚合接口。
“识别动作”可以单独关闭旋转、缩放、焦点切换、图层切换或确认手势。浏览器端会忽略未勾选动作;使用 Motion Agent 时,同一白名单也会通过控制协议同步给 Agent。
手势语义:
| 手势事件 | 作用 |

View File

@@ -258,22 +258,27 @@ HTTP 健康检查统一使用 `curl -fsS --max-time`。因此 `/health` 返回 4
前端生产形态是 `vite build` 生成静态资源,再由 nginx/Caddy 等 HTTP 服务器托管。不要在生产中使用 `bun run dev``vite preview`。当前不维护 Webpack 双构建链;如果未来需要评估更企业化的构建生态,优先做 Rsbuild/Rspack spike。Electron 仅在正式目标变成离线桌面软件时再单独评估。
## Motion Agent 可选启动
## Motion Agent 默认启动
`planet.sh` 现在可以管理本地动作捕捉 Agent但默认不会启动它避免普通开发机因为没有摄像头、OpenCV 或 MediaPipe 而影响后端/前端启动
`planet.sh` 现在默认随 `start` 和全量 `restart` 启动本地 Motion Agent。这样星球端、UE 或调试客户端可以直接连接 `ws://127.0.0.1:8765/ws/gestures`。如果当前机器没有可用摄像头,默认隐式启动会降级为 dry-run 协议服务,不会阻断后端/前端启动;只有显式传入 `--motion-agent`、摄像头 index、摄像头 URL 或 WSL USB 参数时live 模式缺摄像头才会硬失败
启动方式
如果本次不需要 Motion Agent
```bash
./planet.sh start --motion-agent
./planet.sh start --non-motion-agent
./planet.sh restart --non-motion-agent
```
常用参数:
- `--motion-agent` / `-m`:随本次启动或重启拉起 Motion Agent。
- `--non-motion-agent`本次启动或全量重启拉起 Motion Agent。
- `--motion-agent` / `-m`:显式要求本次启动或重启拉起 Motion Agent此时 live 摄像头失败会作为错误反馈。
- `--motion-agent-port <端口>`:覆盖默认 WebSocket 端口 `8765`
- `--motion-agent-mode <模式>`:指定输入模式,可选 `auto``single``dual_redundant``single_fallback``calibrated_3d``dual` 作为兼容别名会进入双路冗余。
- `--motion-agent-camera-indexes <indexes>`:覆盖自动发现的摄像头 index例如 `0``0,1`。也可以用环境变量 `MOTION_AGENT_CAMERA_INDEXES=0,1`
- `--motion-agent-camera-urls <urls>`:使用 RTSP/HTTP 摄像头流,适合 WSL、手机摄像头或网络摄像头。也可以用环境变量 `MOTION_AGENT_CAMERA_URLS=...`
- `--motion-agent-wsl-usbipd`:在 WSL 中尝试通过 `usbipd-win` 自动把唯一的 Windows USB 摄像头透传到 Linux。
- `--motion-agent-wsl-usbipd-busid <BUSID>`:在 WSL 中指定 `usbipd list` 里的摄像头 BUSID 后透传,适合多摄像头设备。
- `--motion-agent-dry-run`:不打开摄像头、不加载 CV 依赖,只启动协议服务,适合调试 Web 端连接。
非 dry-run 的 live 模式会在启动前检查 `mediapipe``opencv-python`。如果当前 `.venv` 缺包,脚本会自动执行:
@@ -282,13 +287,17 @@ HTTP 健康检查统一使用 `curl -fsS --max-time`。因此 `/health` 返回 4
uv add mediapipe opencv-python
```
如需禁止启动时自动安装,可设置:
如需禁止启动时自动安装 Python CV 依赖,可设置:
```bash
PLANET_MOTION_AGENT_AUTO_INSTALL=0 ./planet.sh start --motion-agent
PLANET_MOTION_AGENT_AUTO_INSTALL=0 ./planet.sh start
```
live 模式会自动寻找 `/dev/video*`,优先取前两个 index 传给 Motion Agent。在 WSL 中Windows 摄像头通常不会自动出现在 `/dev/video*`。可先用下面命令看设备:
`./planet.sh init` 会在 WSL 中预检查 `usbipd-win`。如果没有 `usbipd.exe`,脚本会先尝试 `winget install -e --id dorssel.usbipd-win`,失败后复用仓库内置的 dorssel.usbipd-win MSI fallback如果缓存缺失或需要其他架构版本再下载 MSI 并请求管理员 PowerShell 安装。该步骤是 best-effort失败会提示后续处理方式但不会阻断普通初始化。可通过 `./planet.sh init --non-motion-agent` 跳过该预检。
live 模式会自动寻找 `/dev/video*`,并优先用 OpenCV 实测过滤出真正能打开并读帧的 index再传给 Motion Agent。在 WSL/USB 摄像头场景中,一个摄像头可能暴露多个 `/dev/video*` 节点,其中部分是 metadata 或非采集节点,脚本会跳过这类不可读 index。在 WSL 中Windows 摄像头通常不会自动出现在 `/dev/video*`。可先用下面命令看设备:
默认 live 采集使用低延迟参数:`640x360` 输入、约 `15Hz` 识别事件worker 内部用 latest-frame 读帧线程,只保留每路摄像头的最新帧,避免 MediaPipe 慢帧时继续排队识别旧画面。骨架调试流默认关闭,只在星球端打开动捕调试面板时按约 `8Hz` 推送,避免日常手势控制被调试数据拖慢。状态事件会同时上报采集 FPS 与识别 FPS方便区分摄像头掉帧和识别耗时。
```bash
ls /dev/video*
@@ -306,20 +315,42 @@ WSL 下更通用的方式是把手机摄像头或网络摄像头以 RTSP/HTTP
./planet.sh start --motion-agent --motion-agent-camera-urls http://192.168.1.20:8080/video
```
如果 WSL 中没有发现 `/dev/video*`,且没有提供 `--motion-agent-camera-urls`,脚本会停止 live 启动并提示处理方式,不会自动降级为 dry-run。可选处理
如果希望直接使用 Windows USB 摄像头,可以让脚本调用 `usbipd-win` 透传。该能力是显式开启的,因为摄像头附加到 WSL 期间通常会从 Windows 应用中暂时断开。
只有一个摄像头时:
```bash
./planet.sh start --motion-agent --motion-agent-wsl-usbipd
```
多个摄像头时,先查看 BUSID再指定设备
```bash
usbipd.exe list
./planet.sh start --motion-agent --motion-agent-wsl-usbipd-busid 3-2
```
如果 `usbipd attach` 提示设备未共享或未绑定,脚本会尝试弹出 Windows 管理员 PowerShell 自动执行 `usbipd bind`,然后重试 attach。若 UAC 被取消或自动 bind 失败,可在 Windows 管理员 PowerShell 中手动执行:
```powershell
usbipd bind --busid 3-2
usbipd attach --wsl --busid 3-2
```
如果 WSL 中没有发现 `/dev/video*`,且没有提供 `--motion-agent-camera-urls`,默认隐式启动会降级为 dry-run。显式 live 启动会停止并提示处理方式。可选处理:
```bash
./planet.sh start --motion-agent --motion-agent-camera-urls http://<手机IP>:8080/video
./planet.sh start --motion-agent --motion-agent-wsl-usbipd
./planet.sh start --motion-agent --motion-agent-dry-run
```
只有显式设置 `PLANET_MOTION_AGENT_WSL_ALLOW_DRY_RUN_FALLBACK=1`WSL 无摄像头才会自动降级。
显式 live 启动时,只有设置 `PLANET_MOTION_AGENT_WSL_ALLOW_DRY_RUN_FALLBACK=1`WSL 无摄像头才会自动降级。
也可以用环境变量启用
`--non-motion-agent` 是命令级跳过入口。环境变量仍可调整服务启动方式
```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
```
日志入口:

View File

@@ -39,7 +39,7 @@ flowchart TB
VesselRaw["AIS / BarentsWatch"] --> VesselDerived["vessel_static / vessel_position"]
VesselDerived --> VesselLayer["vessels 图层"]
Interactables["earth_interactables"] --> InteractableLayer["interactables 图层"]
NewsRaw["RSS / Live / News"] --> NewsItems["earth_news_items"]
NewsRaw["RSS / 手动新闻 / Live"] --> NewsItems["earth_news_items"]
NewsItems --> NewsLayer["news / media 图层"]
```
@@ -51,7 +51,7 @@ flowchart TB
| BGP 态势 | 展示观测站、异常事件、路由事件和区域态势 | `ris_live_bgp``bgpstream_bgp`、prefix geography sources | `bgp_observations``bgp_anomalies``bgp_incidents``bgp_collector_locations` | `bgp` | `clear_then_reload` |
| 船舶 | 展示 AIS 船只、位置、轨迹和源健康 | AIS sources、`barentswatch_vessels` | `vessel_static``vessel_position``ais_raw_observations``ais_source_health` | `vessels` | `clear_then_reload` |
| 可交互对象 | 支撑通用地表图标、人工点位和未来扩展对象 | `earth_interactables` | 无 | `interactables` | `delta` |
| 新闻与媒体 | 支撑 Earth 新闻、直播和巡航摘要 | news sources | `earth_news_items` | `news` / `media` | `reload` |
| 新闻与媒体 | 支撑 Earth 新闻、直播和巡航摘要 | RSS news sources、手动新闻、直播源 | `earth_news_items` | `news` / `media` | `reload` |
## 卫星链路
@@ -141,12 +141,12 @@ sequenceDiagram
新闻与媒体数据用于 Earth 顶部新闻条、直播面板、新闻巡航和态势摘要。它们的视觉状态比地理对象更偏内容刷新,因此默认使用 `reload`
- **采集入口**RSS、直播源、新闻 source
- **事实表**:新闻 source 的 `collected_data`
- **采集入口**RSS 新闻源、`智能星球内容 -> 新闻内容` 的手动新闻、直播源。
- **事实表**:新闻 source 的 `collected_data`;手动新闻直接写入 `earth_news_items`,并以 `feed_type/source_type=manual` 标记内容来源
- **派生表**`earth_news_items`
- **接口**新闻、直播和媒体 visualization / content API
- **接口**`/api/v1/news/earth-feed` 读取 `earth_news_items`;后台管理接口 `/api/v1/earth/news-items` 支持新增、JSON 导入、编辑、删除和重新处理手动新闻
- **删除语义**:删除新闻 source 或 `earth_news_items` 后广播 `news` / `media` reload前端重拉后列表为空即隐藏对应内容。
- **常见异常**:直播面板仍显示旧内容,通常是媒体组件本地状态没有响应 layer update或内容接口缓存未失效。
- **常见异常**手动新闻保存后只显示原文或大区锚点是正常的“先展示再精修”窗口;若长期不更新,应检查 `earth_news_enrichment` 队列、AI / Web Search 配置和 `enrichment_status`直播面板仍显示旧内容,通常是媒体组件本地状态没有响应 layer update或内容接口缓存未失效。
## 扩展新图层

View File

@@ -50,7 +50,7 @@
- 搜索可以查找海缆、卫星、算力中心、BGP 事件
- 算力中心和 BGP 观测站详情卡可以自动采集坐标候选,并能在智能星球上预览
- 鼠标拖动、滚轮缩放、缩放百分比提示工作正常
- 设置面板的旋转 / 巡航 / 动捕模式可以切换;视图设置里可以切换悬停提示,卫星相关设置里可以打开或关闭真实高度分层和轨迹显示
- 设置面板的旋转 / 巡航 / 动捕模式可以切换;动捕设置可以选择输入源和允许识别的动作;视图设置里可以切换悬停提示,卫星相关设置里可以打开或关闭真实高度分层和轨迹显示
## 5. 找回密码