release: bump version to 0.51.0
This commit is contained in:
@@ -8,6 +8,21 @@ This project follows the repository versioning rule:
|
||||
- `improvement` -> `+0.0.1`(bugfix + 小功能混合)
|
||||
- `bugfix` -> `+0.0.1`
|
||||
|
||||
## [0.51.0] — 2026-05-11
|
||||
|
||||
Released: 2026-05-11
|
||||
|
||||
### ✨ Highlights
|
||||
- 新增 AI Settings 控制台页面与 `backend/app/services/ai_tools/` 工具层,串通 Web Search Provider 与轻量 Agent orchestrator。
|
||||
- 重写 Earth 算力中心候选「预览 / 保存」交互:单一委托 click + 内存 candidate Map,新增空心呼吸圈预览,保存后即时生成正式图标,后台刷新失败不再误报为保存失败。
|
||||
- 重写动作捕捉 zoom 识别:mirror-safe 的 trend + pose hold 双通道,张开/合拢手势直接对应 zoom_in/out 并支持持续触发;单臂 rotate 仅在另一只手明确静止时才允许。
|
||||
|
||||
### Improvements
|
||||
- 同步中英文 `earth-frontend-context.md`、`frontend-admin-frontend-context.md`、`faq.md`、`manual.md`、`quickstart.md`。
|
||||
- Earth 模块多处优化:bgp-cruise-adapter、interactable、satellites、presentation-controller、controls 调整与回归测试补全。
|
||||
|
||||
---
|
||||
|
||||
## [0.50.0] — 2026-05-10
|
||||
|
||||
Released: 2026-05-10
|
||||
|
||||
@@ -179,6 +179,217 @@ Secret resolution should follow the existing settings pattern:
|
||||
2. provider-specific environment variable, for example `TAVILY_API_KEY`
|
||||
3. generic fallback `WEB_SEARCH_API_KEY`
|
||||
|
||||
### Common WebSearch Providers
|
||||
|
||||
The first implementation should model WebSearch as a provider-specific adapter
|
||||
behind one internal interface:
|
||||
|
||||
```text
|
||||
SearchEvidenceProvider.search(query, max_results, domains, freshness_days)
|
||||
-> list[SearchEvidence]
|
||||
```
|
||||
|
||||
Recommended provider ids and environment variables:
|
||||
|
||||
| Provider | Provider id | Env key | Default base URL | Primary use |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Tavily | `tavily` | `TAVILY_API_KEY` | `https://api.tavily.com` | Default hosted search for agent/RAG style results |
|
||||
| Brave Search API | `brave` | `BRAVE_SEARCH_API_KEY` | `https://api.search.brave.com` | Independent web index and low-level SERP results |
|
||||
| SerpAPI | `serpapi` | `SERPAPI_API_KEY` | `https://serpapi.com` | Search-engine-backed SERP data with engine options |
|
||||
| Exa | `exa` | `EXA_API_KEY` | `https://api.exa.ai` | Neural/semantic web search and result contents |
|
||||
| Firecrawl Search / Scrape | `firecrawl` | `FIRECRAWL_API_KEY` | `https://api.firecrawl.dev` | Search plus page scrape/markdown extraction |
|
||||
| SearXNG | `searxng` | optional `SEARXNG_API_KEY` | self-hosted instance URL | Self-hosted metasearch when external search APIs are undesirable |
|
||||
|
||||
The normalized configuration should support per-provider defaults while keeping
|
||||
one active provider:
|
||||
|
||||
```text
|
||||
external_integrations.web_search
|
||||
enabled: true
|
||||
default_provider: tavily
|
||||
providers:
|
||||
tavily:
|
||||
base_url: https://api.tavily.com
|
||||
api_key: <secret>
|
||||
max_results: 5
|
||||
search_depth: basic
|
||||
include_answer: false
|
||||
include_raw_content: false
|
||||
brave:
|
||||
base_url: https://api.search.brave.com
|
||||
api_key: <secret>
|
||||
endpoint_path: /res/v1/web/search
|
||||
max_results: 5
|
||||
serpapi:
|
||||
base_url: https://serpapi.com
|
||||
api_key: <secret>
|
||||
endpoint_path: /search.json
|
||||
engine: google
|
||||
max_results: 5
|
||||
exa:
|
||||
base_url: https://api.exa.ai
|
||||
api_key: <secret>
|
||||
endpoint_path: /search
|
||||
max_results: 5
|
||||
include_text: false
|
||||
firecrawl:
|
||||
base_url: https://api.firecrawl.dev
|
||||
api_key: <secret>
|
||||
search_path: /v2/search
|
||||
scrape_path: /v2/scrape
|
||||
max_results: 5
|
||||
scrape_formats: [markdown]
|
||||
searxng:
|
||||
base_url: http://localhost:8080
|
||||
api_key: <optional secret>
|
||||
endpoint_path: /
|
||||
max_results: 5
|
||||
categories: general
|
||||
engines: []
|
||||
```
|
||||
|
||||
Adapter notes:
|
||||
|
||||
- Tavily should call `/search` and normalize title, URL, snippet/content, score,
|
||||
and optional raw content.
|
||||
- Brave should call `/res/v1/web/search` and map web results into the same
|
||||
`SearchEvidence` shape.
|
||||
- SerpAPI should call `/search.json`, pass `engine`, and normalize organic
|
||||
results. Search-engine-specific fields should remain in provider metadata.
|
||||
- Exa should call `/search`; optional result text should be treated as fetched
|
||||
content only when enabled.
|
||||
- Firecrawl can be used both as `web_search` and `web_fetch`: `/v2/search`
|
||||
returns result URLs/descriptions and may include scrape options, while
|
||||
`/v2/scrape` can produce markdown for a selected URL.
|
||||
- SearXNG should query the configured instance with `q` and `format=json`.
|
||||
Public instances should not be assumed reliable for production; a controlled
|
||||
self-hosted instance is preferred.
|
||||
|
||||
The settings UI should expose only provider, base URL, key, max results, and a
|
||||
test button in the first version. Provider-specific advanced fields can stay
|
||||
collapsed or backend-only until a real workflow needs them.
|
||||
|
||||
### Frontend Configuration Window
|
||||
|
||||
Add a WebSearch configuration panel to the existing settings page, next to the
|
||||
LLM provider configuration. It should behave like the current AI provider secret
|
||||
controls: clear configured state, masked preview, explicit show/hide, test
|
||||
connection, and save feedback.
|
||||
|
||||
First-version visible fields:
|
||||
|
||||
```text
|
||||
WebSearch Provider
|
||||
API Base URL
|
||||
API Key
|
||||
Max Results
|
||||
Timeout Seconds
|
||||
Enable WebSearch
|
||||
Test Connection
|
||||
Save
|
||||
```
|
||||
|
||||
Provider dropdown options:
|
||||
|
||||
```text
|
||||
Tavily
|
||||
Brave Search API
|
||||
SerpAPI
|
||||
Exa
|
||||
Firecrawl Search / Scrape
|
||||
SearXNG
|
||||
```
|
||||
|
||||
Field behavior:
|
||||
|
||||
- Switching provider loads that provider's saved config and masked key preview.
|
||||
- Empty key input means keep the existing saved or environment key.
|
||||
- Typing a new key replaces only the selected provider's key.
|
||||
- Show key reveals the full current input value when the backend reveal endpoint
|
||||
allows it; hide key returns to the prefix-preserving masked preview.
|
||||
- The configured badge should only show `已配置` or `未配置`, not repeat the
|
||||
masked key text.
|
||||
- `Test Connection` sends the current unsaved draft to the backend and should
|
||||
not require a separate save first.
|
||||
- A successful test may save the draft as the new WebSearch default only if the
|
||||
API endpoint is explicitly designed to mirror the AI provider test behavior.
|
||||
Otherwise, test should be read-only and the Save button should persist.
|
||||
- Save success and test success must show visible feedback. Failures should show
|
||||
provider-specific but secret-safe error messages.
|
||||
|
||||
Provider-specific UI hints:
|
||||
|
||||
| Provider | UI hint |
|
||||
| --- | --- |
|
||||
| Tavily | Good default for agent/RAG style search. |
|
||||
| Brave Search API | Uses Brave's independent search index. |
|
||||
| SerpAPI | Supports search-engine-specific parameters such as `engine`. |
|
||||
| Exa | Good for semantic search and optional result text. |
|
||||
| Firecrawl | Can search and scrape pages into markdown. |
|
||||
| SearXNG | Requires a reachable self-hosted or trusted instance URL. |
|
||||
|
||||
Advanced fields can live in a collapsed section:
|
||||
|
||||
```text
|
||||
Endpoint Path
|
||||
Search Depth
|
||||
Engine
|
||||
Categories
|
||||
Engines
|
||||
Include Raw Content
|
||||
Scrape Formats
|
||||
Domain Allowlist
|
||||
```
|
||||
|
||||
The first version should keep the UI conservative. It should not expose every
|
||||
provider knob until backend workflows use those knobs.
|
||||
|
||||
### Web Fetch and Page Extraction
|
||||
|
||||
`web_fetch` is separate from `web_search`. Search finds candidate URLs; fetch
|
||||
turns selected pages into clean, citable evidence.
|
||||
|
||||
Recommended extraction chain:
|
||||
|
||||
```text
|
||||
1. plain httpx fetch
|
||||
2. trafilatura extraction for static HTML
|
||||
3. readability extraction as secondary cleanup
|
||||
4. Playwright fetch only for allowlisted JS-heavy pages
|
||||
5. Firecrawl scrape as hosted fallback when configured
|
||||
```
|
||||
|
||||
Implementation guidance:
|
||||
|
||||
- Use `trafilatura` as the first local extractor because it is Python-native and
|
||||
matches the backend stack.
|
||||
- Prefer a Python readability implementation for local cleanup. Do not introduce
|
||||
a Node-only readability dependency for backend fetch.
|
||||
- Use Playwright sparingly for JavaScript-rendered pages. It should have domain
|
||||
allowlists, low concurrency, strict timeouts, response size limits, and no
|
||||
automatic form submission or login behavior.
|
||||
- Store `content_hash`, `retrieved_at`, final URL, title, extracted text
|
||||
preview, and extractor name in `ai_evidence`.
|
||||
- Keep short quotes for UI review, but do not store huge page bodies directly in
|
||||
every task record. Large extracted content should be truncated or stored once
|
||||
by hash.
|
||||
|
||||
The local/self-hosted stack should look like this:
|
||||
|
||||
```text
|
||||
SearXNG
|
||||
-> SearchEvidence URLs
|
||||
-> httpx fetch
|
||||
-> trafilatura / readability
|
||||
-> Playwright only when static extraction fails and the domain is allowed
|
||||
-> normalized evidence
|
||||
-> LLM structured output through AIProviderClient
|
||||
```
|
||||
|
||||
This route gives Planet a lower-cost and more controllable search path, while
|
||||
hosted providers remain available when search quality or maintenance effort
|
||||
matters more than self-hosting.
|
||||
|
||||
|
||||
## Phase 3: Limited Agent Loop
|
||||
|
||||
|
||||
@@ -98,6 +98,18 @@ Gesture recognition may run locally in the browser or inside the local Agent, bu
|
||||
|
||||
[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"`.
|
||||
|
||||
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:
|
||||
|
||||
1. **`getZoomTrend` (trend zoom)** — derived from the per-frame change in `Math.abs(rightWrist.x - leftWrist.x)`. Both wrists must cross the noise floor (`ZOOM_TREND_MIN_WRIST_DELTA = 0.010`) and stay within `ZOOM_TREND_HEIGHT_TOLERANCE` of each other vertically. Growing span → `zoom_in`, shrinking span → `zoom_out`. Trend has highest priority so mid-motion frames cannot be hijacked by the layer/focus/rotate detectors.
|
||||
2. **`getZoomHoldPose` (sustained zoom)** — after motion stops, keeps emitting `zoom_in` while the wrists stay at chest level or above with span > `ZOOM_HOLD_SPREAD_FACTOR × shoulderWidth` (default 1.30), and `zoom_out` while elbows sit visibly outward and span < `ZOOM_HOLD_CLOSE_FACTOR × shoulderWidth` (default 0.85).
|
||||
3. **layer / focus** — left-wrist raise + vertical motion fires `layer_prev/next`; head tilt fires `focus_prev/next`.
|
||||
4. **`getRightArmPattern` (single-arm rotate)** — only considered when both `!isZoomCandidatePose(...)` and `isLeftArmAtRest(...)` hold. `isLeftArmAtRest` requires the left wrist to hang clearly below the shoulder line (≥ 0.13) and both left elbow and left wrist to stay near the body — any ambiguous left-arm posture (mid-spread, raised, held at chest) blocks single-arm rotate.
|
||||
|
||||
Two non-obvious decisions worth preserving:
|
||||
|
||||
- **Mirror-safe**: all zoom checks use `Math.abs(rightWrist.x - leftWrist.x)` and never rely on per-side x direction. `getUserMedia` returns the raw camera feed without horizontal flip, so a subject's anatomical left arm appears on the image right. A direction-based detector (e.g. "left wrist moves left, right wrist moves right") inverts on non-mirrored feeds — span-based detection is invariant.
|
||||
- **Continuous vs. discrete**: `rotate`, `layer`, `focus`, and `confirm` go through `applyPoseLatch`, which emits each gesture once until the pose returns to neutral (one wave = one rotation step). Zoom intentionally bypasses the latch and re-matches every frame; downstream `GESTURE_POLICIES.zoom_in/out.cooldownMs = 120` rate-limits to ~8 emits/sec, so holding a spread pose keeps zooming in until the user changes their pose. Do not reuse the latch for zoom — that semantic difference is the point.
|
||||
|
||||
[presentation-controller.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/presentation-controller.js) is the new Presentation layer. In the first stage only Motion uses it: `motion-cruise-adapter.js` uses a persistent presentation that reuses the cruise fixed-card placement and connector, but mouse movement does not auto-hide the card. The connector recalculates source and target anchors every frame so dragged cards, globe rotation, and moving targets stay connected. BGP/News still use the existing `CruiseSequencer` auto-advance path to preserve the old cruise experience.
|
||||
|
||||
### 6. Globe and Terrain
|
||||
@@ -134,6 +146,10 @@ The compute-center layer row has a notification badge for GeoJSON `unresolved` r
|
||||
|
||||
Location candidate state in the details card is cached in [info-card.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/info-card.js) by `entityType:entityId`. If the user closes the details card or unresolved queue and reopens the same compute center / BGP collector, previously collected candidates and status text are restored. Header-level `一键采用` prefers cached candidates, avoiding repeated online geocoding or LLM factcheck calls. After a location is saved, that entity's candidate list is cleared to a "refreshing layer" status so stale candidates do not keep misleading the user.
|
||||
|
||||
The `预览 / 保存` buttons on each candidate row use a single delegated `click` handler per candidate root (the `[data-collect-cache-key]` block in the details card, or `[data-unresolved-item]` in the unresolved queue), guarded by a `data-candidate-actions-bound` flag so it cannot be double-bound. Direct `pointerup` / `click` listeners on individual buttons and overlapping delegated handlers were removed. Candidate objects are no longer JSON-stringified into an HTML attribute and parsed back; buttons only carry `data-candidate-index`, and the handler resolves the candidate object from a module-level `Map` keyed by cache-key. This removes the entire class of failures caused by HTML entity escaping of `&` / `<` / `"` in candidate fields. Clicking `预览` dispatches `earth:preview-location-candidate`; `main.js`'s `previewLocationCandidate()` calls `showComputeCenterLocationPreview()`, which attaches a hollow breathing-ring sprite pair at the candidate coordinates (visually mirroring the BGP event ring) and focuses the camera on the candidate. Previewing another candidate replaces the ring; saving clears it and `spawnSavedComputeCenterLocation()` immediately spawns the formal compute-center interactable. Note that `main.js` has no module-level `earth` variable — every location-save / preview handler must call `const earth = getEarth();` first, otherwise the event handler throws a `ReferenceError` that the surrounding `.catch` swallows, producing the failure mode where the button "does nothing".
|
||||
|
||||
The `earth:compute-center-location-saved` reconciliation pipeline is deliberately silent on background-refresh failures. `spawnComputeCenterAfterLocationSave()` already presents the success toast and locked state; `refreshComputeCentersAfterLocationSave()` only reloads backend data when the scene is ready and no longer emits its own `已保存` toast. `handleComputeCenterLocationSaved()` runs refresh in the background after a successful spawn; only when spawn returns `null` (scene not ready) or throws does refresh take over the success toast. A refresh error is only `console.warn`'d — it must never surface as a `保存失败` message, because the save itself succeeded and the refresh is a follow-up sync.
|
||||
|
||||
### AIS Vessel Layer
|
||||
|
||||
The vessel layer fetches `/api/v1/visualization/geo/vessels` and renders the aggregated AIS GeoJSON through `createInteractableLayer()`. By default it does not send a `limit` parameter, and `VESSEL_CONFIG.maxRenderedMarkers = 0` means the frontend does not clip the result to 5000 vessels. A positive `options.limit` or positive `maxRenderedMarkers` can still be used as an explicit temporary cap.
|
||||
|
||||
@@ -102,7 +102,15 @@ If both localhost checks pass but a phone or another computer cannot connect, st
|
||||
./planet.sh start --allow-lan
|
||||
```
|
||||
|
||||
Then configure portproxy and firewall from Administrator PowerShell:
|
||||
The flag must be written as `--allow-lan`. `allowlan` or `--allowlan` is not recognized by the startup script. If Planet is already running and you only need to reopen the frontend on the LAN, restart the frontend explicitly:
|
||||
|
||||
```bash
|
||||
./planet.sh restart -f 3000 --allow-lan
|
||||
```
|
||||
|
||||
If `ss -ltnp` shows the frontend listening on `0.0.0.0:3000`, but `Test-NetConnection <Windows LAN IP> -Port 3000` still fails from Windows PowerShell, the problem is usually Windows-side forwarding or firewall policy rather than Vite or `.zshrc`.
|
||||
|
||||
For traditional WSL NAT networking, configure portproxy and firewall from Administrator PowerShell:
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3000 connectaddress=127.0.0.1 connectport=3000
|
||||
@@ -111,6 +119,20 @@ New-NetFirewallRule -DisplayName "WSL Planet 3000" -Direction Inbound -Action Al
|
||||
New-NetFirewallRule -DisplayName "WSL Planet 8000" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8000
|
||||
```
|
||||
|
||||
If `wslinfo --networking-mode` prints `mirrored`, also check Hyper-V firewall. Even when ordinary Windows Firewall rules exist, Hyper-V firewall can still block external devices from reaching WSL. From Administrator PowerShell, allow the required ports:
|
||||
|
||||
```powershell
|
||||
New-NetFirewallHyperVRule -Name "Planet-Frontend-3000" -DisplayName "Planet Frontend 3000" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 3000 -Action Allow
|
||||
New-NetFirewallHyperVRule -Name "Planet-Backend-8000" -DisplayName "Planet Backend 8000" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 8000 -Action Allow
|
||||
```
|
||||
|
||||
Use these commands to inspect the current Hyper-V firewall state:
|
||||
|
||||
```powershell
|
||||
Get-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}"
|
||||
Get-NetFirewallHyperVRule -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}"
|
||||
```
|
||||
|
||||
LAN devices should open the Windows LAN IP, for example `http://<Windows LAN IP>:3000/earth`, not the internal WSL IP.
|
||||
|
||||
### How do `--allow-lan` and the Motion Agent LAN URL fit together?
|
||||
|
||||
@@ -32,7 +32,7 @@ Current admin-related routes:
|
||||
- `/alerts/bgp`
|
||||
- `/alerts/situational`
|
||||
- `/bgp`
|
||||
- `/playground`
|
||||
- `/ai`
|
||||
- `/settings`
|
||||
|
||||
`/earth` is a standalone display page and is not part of the console shell.
|
||||
@@ -196,7 +196,24 @@ Responsibilities:
|
||||
|
||||
`App.tsx` uses it to decide whether to redirect to the login page. `/docs` remains a public route, but the backend decides the visible catalog and content from the token; anonymous visitors only receive public docs.
|
||||
|
||||
### 2. Business Data Gateway
|
||||
### 2. AI
|
||||
|
||||
File:
|
||||
|
||||
- [AISettings.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/AISettings/AISettings.tsx)
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- `/ai` now owns LLM Provider, AI Tool configuration, and the testbench instead of nesting them under `/settings`
|
||||
- The `模型供应商` tab manages default provider, model, base URL, provider key, local `aiprovider` proxy, and connection test
|
||||
- The `工具` tab manages WebSearch provider, search key, base URL, timeout, result count, and advanced provider options
|
||||
- The `测试台` tab embeds the former Playground real session, preset prompts, and AI Provider status debugging
|
||||
- The page reuses the Settings single-screen tabs, panel card, and internal scrolling style
|
||||
|
||||
Legacy `/settings?tab=ai` should redirect to `/ai?tab=providers`.
|
||||
Legacy `/playground` should redirect to `/ai?tab=playground`.
|
||||
|
||||
### 3. Business Data Gateway
|
||||
|
||||
AI / situational awareness related services are currently in:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ After a default startup, the common URLs are:
|
||||
| Docs | `http://localhost:3000/docs` | Partly | Usage docs are public; developer, backend, and operations docs require Gatekeeper groups |
|
||||
| FAQ | `http://localhost:3000/docs/faq` | No | Windows / WSL, ports, dependencies, motion capture, credentials, and permission troubleshooting |
|
||||
| Console | `http://localhost:3000/admin` | Yes | Data, config, alerts, logs, and situational observation |
|
||||
| AI Playground | `http://localhost:3000/playground` | Yes | AI Provider status and debugging |
|
||||
| AI | `http://localhost:3000/ai` | Yes | Model providers, AI tools, and testbench |
|
||||
| Backend API Docs | `http://localhost:8000/docs` | Depends on endpoint | FastAPI / OpenAPI documentation |
|
||||
|
||||
## planet.sh
|
||||
@@ -427,7 +427,7 @@ Common pages:
|
||||
| System Alerts | `/alerts/system` | System-level alerts |
|
||||
| BGP Alerts | `/alerts/bgp` | BGP-related alerts |
|
||||
| Situational Alerts | `/alerts/situational` | Situational assessment alerts |
|
||||
| AI Playground | `/playground` | AI Provider debugging |
|
||||
| AI | `/ai` | Model providers, WebSearch-style tools, and testbench |
|
||||
| System Logs | `/logs` | View system logs (typically super admin only) |
|
||||
| Users | `/users` | User management |
|
||||
| Settings | `/settings` | System config and TV live stream sources |
|
||||
@@ -487,7 +487,18 @@ Current common uses:
|
||||
- System settings
|
||||
- TV live stream source configuration
|
||||
- Collector settings
|
||||
- External integrations and AI Provider configuration
|
||||
|
||||
### AI
|
||||
|
||||
`/ai` manages the AI runtime chain and is now separate from system settings. Legacy `/playground` redirects to `/ai?tab=playground`.
|
||||
|
||||
It currently contains:
|
||||
|
||||
- `模型供应商`: default LLM provider, model, base URL, API key, local `aiprovider` proxy, and connection test
|
||||
- `工具`: WebSearch provider, search API key, base URL, max results, timeout, and advanced provider options
|
||||
- `测试台`: AI Provider status, preset prompts, and real analysis-chain debugging
|
||||
|
||||
Legacy `/settings?tab=ai` redirects to `/ai?tab=providers`.
|
||||
|
||||
Available configuration depends on the current user's role.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ After startup, the key URLs are:
|
||||
| Earth | `http://localhost:3000/earth` | Public 3D Earth visualization |
|
||||
| Console | `http://localhost:3000/admin` | Admin console (login required) |
|
||||
| Docs | `http://localhost:3000/docs` | Usage docs are public; developer and operations docs require Gatekeeper groups |
|
||||
| AI Playground | `http://localhost:3000/playground` | AI debugging (login required) |
|
||||
| AI | `http://localhost:3000/ai` | Model provider, tool, and testbench entry (login required) |
|
||||
| Backend API Docs | `http://localhost:8000/docs` | FastAPI / OpenAPI interface docs |
|
||||
|
||||
If the default ports are taken, specify custom ports:
|
||||
@@ -114,6 +114,7 @@ First-time inspection checklist:
|
||||
- `/datasources`: data source directory and collection triggers; endpoint, headers, and credentials are configured under `/settings` collector settings
|
||||
- `/data`: collected data
|
||||
- `/bgp`: BGP situational view
|
||||
- `/ai`: AI page for model providers, WebSearch-style tools, and the testbench
|
||||
- `/alerts/system`: system alerts
|
||||
- `/settings`: system configuration
|
||||
|
||||
|
||||
@@ -105,6 +105,18 @@ React 路由入口:
|
||||
|
||||
动捕调试面板由 [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"`。
|
||||
|
||||
Browser Camera provider 的手势识别管线在 [motion-browser-provider.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/motion-browser-provider.js) 的 `recognizeGesture()`,按以下顺序匹配,前者命中即返回:
|
||||
|
||||
1. **`getZoomTrend`(趋势 zoom)**:基于上一帧到当前帧两腕 x 间距的变化量(`Math.abs(rightWrist.x - leftWrist.x)` 的 delta)。两腕都越过噪声地板(`ZOOM_TREND_MIN_WRIST_DELTA = 0.010`)且高度差不超过 `ZOOM_TREND_HEIGHT_TOLERANCE`,spread 增加 → `zoom_in`,spread 减少 → `zoom_out`。趋势优先级最高,避免中间帧被 layer/focus/rotate 抢先误判。
|
||||
2. **`getZoomHoldPose`(姿态 zoom)**:动作停止后,只要两腕仍保持在胸口及以上、且 span > `ZOOM_HOLD_SPREAD_FACTOR × shoulderWidth`(默认 1.30)就持续派发 `zoom_in`;两肘明显外展且 span < `ZOOM_HOLD_CLOSE_FACTOR × shoulderWidth`(默认 0.85)就持续派发 `zoom_out`。
|
||||
3. **layer / focus**:左手抬起 + 上下移动派发 `layer_prev/next`;头部左右倾斜派发 `focus_prev/next`。
|
||||
4. **`getRightArmPattern`(单臂 rotate)**:仅当 `!isZoomCandidatePose(...) && isLeftArmAtRest(...)` 同时成立时才考虑。`isLeftArmAtRest` 要求左腕明显垂在肩下 13% 以下且左肘/左腕都不外伸,把「张臂中间帧」「单手举起」「左手扶在胸前」等所有模糊状态都判为非静止 —— 单臂 rotate 严格要求另一只手处于静止。
|
||||
|
||||
两个关键设计:
|
||||
|
||||
- **mirror-safe**:所有 zoom 检测都基于 `Math.abs(rightWrist.x - leftWrist.x)`,不依赖单侧 x 方向。无论摄像头是否做镜像翻转(浏览器默认不翻转,`getUserMedia` 返回的就是原始帧),张臂始终 → zoom_in,合手始终 → zoom_out。早期基于「左腕往左 + 右腕往右」的判定会在非镜像视图里把方向判反。
|
||||
- **连续 vs 离散**:rotate / layer / focus / confirm 都过 `applyPoseLatch`,同一手势只发一次,必须先回到中性位才能再发(挥一下转一格)。zoom 故意 bypass latch,每帧匹配都返回 → 下游 `GESTURE_POLICIES.zoom_in/out.cooldownMs = 120` 节流到 ~8 次/秒,张臂保持就一直放大直到姿势变化。这是 zoom 跟其它手势在交互语义上的本质区别,不要复用 latch 给 zoom。
|
||||
|
||||
[presentation-controller.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/presentation-controller.js) 是新的 Presentation 层。第一阶段只接入 Motion:`motion-cruise-adapter.js` 通过 persistent presentation 复用巡航固定卡片位置和 connector,但不会让鼠标移动触发自动隐藏;connector 每帧重算 source/target anchor,让卡片拖动、地球旋转和目标移动时端点继续跟随。BGP/News 仍保持原有 `CruiseSequencer` 自动轮播路径,避免改变既有巡航体验。
|
||||
|
||||
### 6. 地球与地形
|
||||
@@ -330,6 +342,10 @@ AISStream 的 `PositionReport` 常带实时位置和 `MetaData.ShipName`,但
|
||||
|
||||
详情卡里的坐标候选状态由 [info-card.js](/home/ray/dev/linkong/planet/frontend/public/earth/js/info-card.js) 按 `entityType:entityId` 缓存在模块内存中。用户关闭详情卡或待定位列表后再次打开同一个算力中心 / BGP 观测站,已经采集到的候选和状态文案会恢复;`一键采用` 会优先使用缓存候选,避免重复调用在线地理编码或 LLM factcheck。保存成功后该实体的候选列表会清空为“正在刷新图层”状态,避免旧候选在刷新后继续误导用户。
|
||||
|
||||
候选行的 `预览 / 保存` 按钮采用单一的事件委托模型:每个候选根(详情卡里的 `[data-collect-cache-key]` 块,或待定位列表里的 `[data-unresolved-item]`)只挂一个 `click` 监听,由 `data-candidate-actions-bound` 幂等标记,不再混用 `pointerup` / `click` 直绑或重复委托。候选对象不再以 JSON 字符串塞进 HTML 属性后再 `JSON.parse`,按钮只携带 `data-candidate-index`,handler 通过 cache-key 在模块内存的 `Map` 里取出原对象,避开 HTML 实体转义对 `&` / `<` / `"` 的破坏。点击 `预览` 会派发 `earth:preview-location-candidate`,由 `main.js` 的 `previewLocationCandidate()` 调用 `showComputeCenterLocationPreview()`:在候选经纬度上挂双层空心呼吸 sprite(视觉参考 BGP 事件 ring),并把视角聚焦到候选坐标;切换到另一个候选会替换为新呼吸圈,保存时立即清除并由 `spawnSavedComputeCenterLocation()` 即时生成正式算力中心交互图标。注意 `main.js` 没有模块级 `earth` 变量,所有 location-save / preview 处理函数必须先 `const earth = getEarth();`,否则会在事件 handler 里抛 `ReferenceError` 被 `.catch` 静默掉,外观上等同于按钮“没有反应”。
|
||||
|
||||
`earth:compute-center-location-saved` 之后的图层校准链路对后台刷新失败保持沉默:`spawnComputeCenterAfterLocationSave()` 已经把 toast 和 locked 状态都给了用户,`refreshComputeCentersAfterLocationSave()` 只在场景就绪时重新拉取后端数据,本身不再吐 `已保存` toast;`handleComputeCenterLocationSaved()` 在 spawn 成功路径让 refresh 静默后台运行,只在 spawn 返回 `null`(场景未就绪)或抛错时才让 refresh 接管成功 toast,refresh 自身报错只走 `console.warn`,绝不冒泡成 `保存失败` 文案——保存请求本身已经成功,刷新失败属于后续同步问题。
|
||||
|
||||
asset 图标大小由 `Interactable` 的 `icon.fitSize` 控制。SVG / 图片文件应尽量保持原始 viewBox 和路径,不要为了在地球上显示成 60x60 而手写 `transform`;`drawAssetIcon()` 会把资源等比 contain 到指定尺寸并居中绘制到 atlas canvas。
|
||||
|
||||
`Interactable` 默认使用固定屏幕像素尺寸,适合船只、BGP 事件、BGP 观测站、算力中心这类需要稳定识别的图标。如果某类图标需要跟随相机距离缩放,可以把 `sizeMode` 设为非 `"fixed"`,并用 `sizeScale.min / max / referenceFov` 控制缩放范围;单个 marker 的业务尺寸差异可以通过 `getPointSizeMultiplier()` 表达,例如 BGP 事件按严重级别调整点大小,BGP 观测站按活跃度调整点大小。
|
||||
|
||||
@@ -104,7 +104,15 @@ curl http://localhost:8000/health
|
||||
./planet.sh start --allow-lan
|
||||
```
|
||||
|
||||
管理员 PowerShell 中配置 portproxy 和防火墙:
|
||||
参数必须写成 `--allow-lan`。`allowlan` 或 `--allowlan` 不会被启动脚本识别。如果服务已经启动,只想重新开放前端,需要显式重启前端:
|
||||
|
||||
```bash
|
||||
./planet.sh restart -f 3000 --allow-lan
|
||||
```
|
||||
|
||||
如果 `ss -ltnp` 显示前端已经监听 `0.0.0.0:3000`,但 Windows PowerShell 中 `Test-NetConnection <Windows局域网IP> -Port 3000` 仍失败,问题通常不在 Vite 或 `.zshrc`,而是在 Windows 侧转发或防火墙。
|
||||
|
||||
传统 WSL NAT 场景下,管理员 PowerShell 中配置 portproxy 和防火墙:
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3000 connectaddress=127.0.0.1 connectport=3000
|
||||
@@ -113,6 +121,20 @@ New-NetFirewallRule -DisplayName "WSL Planet 3000" -Direction Inbound -Action Al
|
||||
New-NetFirewallRule -DisplayName "WSL Planet 8000" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8000
|
||||
```
|
||||
|
||||
如果 `wslinfo --networking-mode` 输出 `mirrored`,还需要检查 Hyper-V firewall。普通 Windows 防火墙规则存在时,Hyper-V firewall 仍可能拦截外部设备进入 WSL。管理员 PowerShell 中按端口放行:
|
||||
|
||||
```powershell
|
||||
New-NetFirewallHyperVRule -Name "Planet-Frontend-3000" -DisplayName "Planet Frontend 3000" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 3000 -Action Allow
|
||||
New-NetFirewallHyperVRule -Name "Planet-Backend-8000" -DisplayName "Planet Backend 8000" -Direction Inbound -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}" -Protocol TCP -LocalPorts 8000 -Action Allow
|
||||
```
|
||||
|
||||
也可以用下面命令确认当前 Hyper-V firewall 状态:
|
||||
|
||||
```powershell
|
||||
Get-NetFirewallHyperVVMSetting -Name "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}"
|
||||
Get-NetFirewallHyperVRule -VMCreatorId "{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}"
|
||||
```
|
||||
|
||||
局域网设备访问的是 Windows 的局域网 IP,例如 `http://<Windows局域网IP>:3000/earth`,不是 WSL 内部 IP。
|
||||
|
||||
### `--allow-lan` 和 Motion Agent 局域网地址怎么配?
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
- `/alerts/bgp`
|
||||
- `/alerts/situational`
|
||||
- `/bgp`
|
||||
- `/playground`
|
||||
- `/ai`
|
||||
- `/settings`
|
||||
|
||||
`/earth` 是独立展示页,不属于控制台骨架。
|
||||
@@ -196,7 +196,24 @@
|
||||
|
||||
`App.tsx` 用它判断是否进入登录页。`/docs` 仍是公开路由,但目录和正文由后端按 token 决定;未登录时只返回公开文档。
|
||||
|
||||
### 2. 业务数据网关
|
||||
### 2. AI
|
||||
|
||||
文件:
|
||||
|
||||
- [AISettings.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/AISettings/AISettings.tsx)
|
||||
|
||||
职责:
|
||||
|
||||
- `/ai` 独立承载 LLM Provider、AI Tool 配置和测试台,不再放在 `/settings` 的系统配置 tabs 中
|
||||
- `模型供应商` tab 管理默认 provider、模型、base URL、provider key、本地 `aiprovider` 代理和连接测试
|
||||
- `工具` tab 管理 WebSearch provider、搜索 key、base URL、超时、结果数和高级 provider 参数
|
||||
- `测试台` tab 嵌入原 Playground 的真实会话、预设请求和 AI Provider 状态调试
|
||||
- 页面复用 Settings 的单屏 tabs、panel card 和内部滚动样式
|
||||
|
||||
旧的 `/settings?tab=ai` 应跳转到 `/ai?tab=providers`。
|
||||
旧的 `/playground` 应跳转到 `/ai?tab=playground`。
|
||||
|
||||
### 3. 业务数据网关
|
||||
|
||||
目前 AI / 态势感知相关服务集中在:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
| Docs | `http://localhost:3000/docs` | 部分需要 | 使用手册公开;开发、后端、运维文档按 Gatekeeper 权限组开放 |
|
||||
| FAQ | `http://localhost:3000/docs/faq` | 否 | Windows / WSL、端口、依赖、动捕、凭证和权限排障 |
|
||||
| 控制台 | `http://localhost:3000/admin` | 是 | 数据、配置、告警、日志和专题观测 |
|
||||
| AI Playground | `http://localhost:3000/playground` | 是 | AI Provider 状态和调试 |
|
||||
| AI | `http://localhost:3000/ai` | 是 | 模型供应商、AI 工具和测试台 |
|
||||
| 后端 API 文档 | `http://localhost:8000/docs` | 视接口而定 | FastAPI / OpenAPI 文档 |
|
||||
|
||||
## planet.sh
|
||||
@@ -458,7 +458,7 @@ http://localhost:3000/admin
|
||||
| 系统告警 | `/alerts/system` | 系统级告警 |
|
||||
| BGP 告警 | `/alerts/bgp` | BGP 相关告警 |
|
||||
| 态势告警 | `/alerts/situational` | 态势研判告警 |
|
||||
| AI Playground | `/playground` | AI Provider 调试 |
|
||||
| AI | `/ai` | 模型供应商、WebSearch 等工具和测试台 |
|
||||
| 系统日志 | `/logs` | 查看系统日志,通常仅 super admin 可见 |
|
||||
| 用户管理 | `/users` | 管理用户 |
|
||||
| 系统配置 | `/settings` | 系统配置和电视直播源等设置 |
|
||||
@@ -518,7 +518,18 @@ http://localhost:3000/admin
|
||||
- 系统设置
|
||||
- 电视直播源配置
|
||||
- 采集器设置
|
||||
- 外部集成和 AI Provider 配置
|
||||
|
||||
### AI
|
||||
|
||||
`/ai` 用于管理 AI 运行链路,已经从系统配置中独立出来。旧链接 `/playground` 会跳转到 `/ai?tab=playground`。
|
||||
|
||||
当前包含:
|
||||
|
||||
- `模型供应商`:默认 LLM provider、模型、Base URL、API Key、本地 `aiprovider` 代理和连接测试
|
||||
- `工具`:WebSearch provider、搜索 API Key、Base URL、最大结果数、超时和高级 provider 参数
|
||||
- `测试台`:AI Provider 状态、预设请求和真实分析链路调试
|
||||
|
||||
旧链接 `/settings?tab=ai` 会跳转到 `/ai?tab=providers`。
|
||||
|
||||
具体可用配置取决于当前登录用户权限。
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export BARENTSWATCH_CLIENT_SECRET="..."
|
||||
| Earth | `http://localhost:3000/earth` | 公开 3D Earth 可视化页面 |
|
||||
| 控制台 | `http://localhost:3000/admin` | 登录后的管理后台 |
|
||||
| 文档站 | `http://localhost:3000/docs` | 使用手册公开;开发/运维文档按 Gatekeeper 权限组开放 |
|
||||
| AI Playground | `http://localhost:3000/playground` | 登录后的 AI 调试入口 |
|
||||
| AI | `http://localhost:3000/ai` | 登录后的模型供应商、工具和测试台入口 |
|
||||
| 后端 API 文档 | `http://localhost:8000/docs` | FastAPI / OpenAPI 接口文档 |
|
||||
|
||||
如果默认端口被占用,可以指定端口:
|
||||
@@ -114,6 +114,7 @@ http://localhost:3000/admin
|
||||
- `/datasources`:数据源目录和采集触发;接口、请求头和凭证配置在 `/settings` 的“采集器设置”
|
||||
- `/data`:已采集数据
|
||||
- `/bgp`:BGP 专题观测
|
||||
- `/ai`:AI,管理模型供应商、WebSearch 等工具和测试台
|
||||
- `/alerts/system`:系统告警
|
||||
- `/settings`:系统配置
|
||||
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
## Current Version
|
||||
|
||||
- `main` 当前主线历史推导到:`0.16.5`
|
||||
- `dev` 当前开发分支历史推导到:`0.50.0`
|
||||
- `dev` 当前开发分支历史推导到:`0.51.0`
|
||||
|
||||
## Timeline
|
||||
|
||||
| Version | Type | Branch | Commit | Summary |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `0.51.0` | feature | `dev` | `pending` | 新增 AI Settings 控制台与 ai_tools 工具层;重写算力中心候选预览/保存交互(呼吸圈 + 即时图标);动作捕捉 zoom 改为 mirror-safe trend + pose hold 双通道,支持持续触发 |
|
||||
| `0.50.0` | feature | `dev` | `pending` | 新增 Earth 动捕双通道控制、Motion Agent、Presentation 持久展示、AI Provider 多 provider 设置、位置候选 LLM 兜底与 FAQ |
|
||||
| `0.49.0` | feature | `dev` | `pending` | 新增位置解析 Pipeline、BGP/算力中心地理定位、Docs Gatekeeper、Earth 新闻栏与 Mobile 国家高亮 |
|
||||
| `0.48.0` | feature | `dev` | `pending` | 新增自定义源 REST/WebSocket 实时 mock 链路,完善 AIS 多源聚合/船舶 enrichment,并将 Earth 全球态势统计改为轻量 SQL 聚合 |
|
||||
|
||||
Reference in New Issue
Block a user