diff --git a/.env.example b/.env.example index eec52d87..bf0b0d47 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,9 @@ VITE_GATEWAY_TOKEN= # Mock 模式(设为 true 可不连接真实 Gateway 进行开发) # VITE_MOCK=true + +# --- 运营商引导配置(可选)--- +# 运营商引导包 URL(用于从框架层加载 projection bootstrap 数据) +# 支持 HTTP/HTTPS URL 或本地相对路径 +# VITE_PROJECTION_BOOTSTRAP_URL=https://example.com/projection-bootstrap.json +# VITE_PROJECTION_BOOTSTRAP_PATH=/bootstrap/projection-packet.json diff --git a/README.md b/README.md index 83cf87dd..4329e85b 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,36 @@ VITE_MOCK=true pnpm dev This uses simulated Agent data for UI development. +In the current bootstrap, mock mode also loads the framework-generated projection packet sample and seeds the office scene plus the first-batch projection panels from that packet. This is still a mock/dev path only; it does not change the live Gateway contract. + +### Operator-Facing Projection Bootstrap (Real Gateway + bootstrap feed) + +A controlled non-mock/operator path is also available when you want Office to connect to the **real Gateway** while still seeding the first projection panels from a framework-generated packet. + +1. Generate or copy a packet such as: + - `/home/ubuntu/projects/_department/work/openclaw-office-projection-feed-bootstrap-20260325/fixtures/openclaw_office_projection_packet_v0.json` +2. Serve it from the Office app origin, for example: + +```bash +mkdir -p public/bootstrap +cp /path/to/openclaw_office_projection_packet_v0.json public/bootstrap/projection-packet.json +``` + +3. Start Office against the real Gateway and point the operator bootstrap to that URL: + +```bash +VITE_GATEWAY_URL=ws://127.0.0.1:18789 \ +VITE_GATEWAY_TOKEN= \ +VITE_PROJECTION_BOOTSTRAP_URL=/bootstrap/projection-packet.json \ +pnpm dev +``` + +Behavior boundary: +- the real Gateway connection path remains intact +- bootstrap loading is optional and guarded by env vars +- this does **not** introduce a new live Gateway protocol message +- this supports operator-facing rollout progress, but does **not** by itself claim upstream merge + --- ## Project Structure diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 9ed61546..ae741ab0 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next"; import { AgentDetailPanel } from "@/components/panels/AgentDetailPanel"; import { EventTimeline } from "@/components/panels/EventTimeline"; import { MetricsPanel } from "@/components/panels/MetricsPanel"; +import { ProjectionBootstrapPanel } from "@/components/panels/ProjectionBootstrapPanel"; import { SubAgentPanel } from "@/components/panels/SubAgentPanel"; import { CollapsibleSection } from "@/components/shared/CollapsibleSection"; import { SvgAvatar } from "@/components/shared/SvgAvatar"; @@ -17,6 +18,7 @@ export function Sidebar() { const { t } = useTranslation("layout"); const agents = useOfficeStore((s) => s.agents); const selectedAgentId = useOfficeStore((s) => s.selectedAgentId); + const projectionPanels = useOfficeStore((s) => s.projectionPanels); const selectAgent = useOfficeStore((s) => s.selectAgent); const collapsed = useOfficeStore((s) => s.sidebarCollapsed); const setSidebarCollapsed = useOfficeStore((s) => s.setSidebarCollapsed); @@ -76,6 +78,7 @@ export function Sidebar() { const subAgentsSection = getSection("subAgents"); const detailSection = getSection("detail"); const timelineSection = getSection("timeline"); + const projectionSection = getSection("projectionBootstrap"); return (