Spaces:
Running
Running
Update
Browse files- .dockerignore +45 -20
- .gitmodules +2 -0
- Dockerfile +50 -29
- bun.lock +0 -0
- docker-build.sh +30 -0
- package.json +2 -2
- packages/feetech.js/package.json +3 -3
- src/lib/components/3d/elements/compute/GPU.svelte +2 -2
- src/lib/components/3d/elements/compute/modal/VideoInputConnectionModal.svelte +5 -4
- src/lib/components/3d/elements/video/Video.svelte +2 -2
- src/lib/components/3d/elements/video/VideoGridItem.svelte +1 -1
- src/lib/components/3d/elements/video/Videos.svelte +2 -2
- src/lib/components/3d/elements/video/modal/VideoInputConnectionModal.svelte +2 -2
- src/lib/components/3d/elements/video/modal/VideoOutputConnectionModal.svelte +2 -2
- src/lib/components/3d/elements/video/status/InputVideoBoxUIKit.svelte +1 -1
- src/lib/components/3d/elements/video/status/OutputVideoBoxUIKit.svelte +1 -1
- src/lib/components/3d/elements/video/status/VideoBoxUIKit.svelte +1 -1
- src/lib/components/3d/elements/video/status/VideoConnectionFlowBoxUIKit.svelte +1 -1
- src/lib/components/3d/elements/video/status/VideoStatusBillboard.svelte +1 -1
- src/lib/components/interface/overlay/AddSensorButton.svelte +1 -1
- src/lib/elements/compute/RemoteComputeManager.svelte.ts +2 -2
- src/lib/elements/robot/RobotManager.svelte.ts +2 -2
- src/lib/elements/robot/calibration/CalibrationState.svelte.ts +1 -1
- src/lib/elements/robot/drivers/RemoteConsumer.ts +1 -1
- src/lib/elements/robot/drivers/RemoteProducer.ts +1 -1
- src/lib/elements/video/VideoManager.svelte.ts +2 -2
- src/lib/elements/video/videoConnection.svelte.ts +2 -2
- src/lib/elements/video/videoStreaming.svelte.ts +2 -2
- src/lib/sensors/consumers/RemoteServerConsumer.ts +1 -1
- static-server.js +106 -0
.dockerignore
CHANGED
@@ -1,56 +1,81 @@
|
|
1 |
-
#
|
2 |
node_modules/
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
-
# Build outputs
|
5 |
build/
|
6 |
.svelte-kit/
|
7 |
dist/
|
|
|
8 |
|
9 |
# Development files
|
10 |
-
.env
|
11 |
-
|
|
|
|
|
|
|
12 |
|
13 |
# IDE files
|
14 |
.vscode/
|
15 |
.idea/
|
16 |
*.swp
|
17 |
*.swo
|
|
|
18 |
|
19 |
# OS files
|
20 |
.DS_Store
|
|
|
|
|
|
|
|
|
|
|
21 |
Thumbs.db
|
22 |
|
23 |
# Git
|
24 |
.git/
|
25 |
.gitignore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
# Logs
|
28 |
*.log
|
29 |
-
|
30 |
-
|
31 |
-
bun-debug.log*
|
32 |
-
lerna-debug.log*
|
33 |
-
|
34 |
-
# Cache directories
|
35 |
-
.cache/
|
36 |
-
.temp/
|
37 |
-
.tmp/
|
38 |
|
39 |
-
#
|
40 |
coverage/
|
41 |
.nyc_output/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
# Other build artifacts
|
44 |
*.tgz
|
45 |
*.tar.gz
|
46 |
|
47 |
-
# Docker files
|
48 |
-
Dockerfile*
|
49 |
-
docker-compose*
|
50 |
-
.dockerignore
|
51 |
-
|
52 |
# Documentation that's not needed in container
|
53 |
README.md
|
54 |
CHANGELOG.md
|
55 |
-
*.md
|
56 |
!LICENSE
|
|
|
1 |
+
# Node.js
|
2 |
node_modules/
|
3 |
+
npm-debug.log*
|
4 |
+
yarn-debug.log*
|
5 |
+
yarn-error.log*
|
6 |
+
.npm
|
7 |
+
.yarn
|
8 |
|
9 |
+
# Build outputs
|
10 |
build/
|
11 |
.svelte-kit/
|
12 |
dist/
|
13 |
+
.output/
|
14 |
|
15 |
# Development files
|
16 |
+
.env
|
17 |
+
.env.local
|
18 |
+
.env.development.local
|
19 |
+
.env.test.local
|
20 |
+
.env.production.local
|
21 |
|
22 |
# IDE files
|
23 |
.vscode/
|
24 |
.idea/
|
25 |
*.swp
|
26 |
*.swo
|
27 |
+
*~
|
28 |
|
29 |
# OS files
|
30 |
.DS_Store
|
31 |
+
.DS_Store?
|
32 |
+
._*
|
33 |
+
.Spotlight-V100
|
34 |
+
.Trashes
|
35 |
+
ehthumbs.db
|
36 |
Thumbs.db
|
37 |
|
38 |
# Git
|
39 |
.git/
|
40 |
.gitignore
|
41 |
+
.gitattributes
|
42 |
+
.gitmodules
|
43 |
+
|
44 |
+
# Docker
|
45 |
+
Dockerfile*
|
46 |
+
docker-compose*
|
47 |
+
.dockerignore
|
48 |
|
49 |
# Logs
|
50 |
*.log
|
51 |
+
logs/
|
52 |
+
log.txt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
+
# Testing
|
55 |
coverage/
|
56 |
.nyc_output/
|
57 |
+
.pytest_cache/
|
58 |
+
|
59 |
+
# Temporary files
|
60 |
+
*.tmp
|
61 |
+
*.temp
|
62 |
+
.cache/
|
63 |
+
.parcel-cache/
|
64 |
+
|
65 |
+
# Documentation
|
66 |
+
*.md
|
67 |
+
docs/
|
68 |
+
README*
|
69 |
+
|
70 |
+
# Misc
|
71 |
+
.eslintcache
|
72 |
+
.prettierignore
|
73 |
|
74 |
# Other build artifacts
|
75 |
*.tgz
|
76 |
*.tar.gz
|
77 |
|
|
|
|
|
|
|
|
|
|
|
78 |
# Documentation that's not needed in container
|
79 |
README.md
|
80 |
CHANGELOG.md
|
|
|
81 |
!LICENSE
|
.gitmodules
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
[submodule "external/RobotHub-TransportServer"]
|
2 |
path = external/RobotHub-TransportServer
|
3 |
url = https://github.com/julien-blanchon/RobotHub-TransportServer
|
|
|
4 |
[submodule "external/RobotHub-InferenceServer"]
|
5 |
path = external/RobotHub-InferenceServer
|
6 |
url = https://github.com/julien-blanchon/RobotHub-InferenceServer
|
|
|
|
1 |
[submodule "external/RobotHub-TransportServer"]
|
2 |
path = external/RobotHub-TransportServer
|
3 |
url = https://github.com/julien-blanchon/RobotHub-TransportServer
|
4 |
+
branch = main
|
5 |
[submodule "external/RobotHub-InferenceServer"]
|
6 |
path = external/RobotHub-InferenceServer
|
7 |
url = https://github.com/julien-blanchon/RobotHub-InferenceServer
|
8 |
+
branch = main
|
Dockerfile
CHANGED
@@ -1,48 +1,69 @@
|
|
1 |
-
# Multi-stage
|
2 |
-
|
3 |
-
FROM oven/bun:1-alpine AS builder
|
4 |
|
|
|
|
|
|
|
|
|
5 |
WORKDIR /app
|
6 |
|
7 |
-
#
|
8 |
-
RUN
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
-
# Copy package files for dependency
|
11 |
COPY package.json bun.lock* ./
|
12 |
|
13 |
-
# Copy local packages
|
14 |
-
COPY packages/
|
|
|
15 |
|
16 |
-
# Install dependencies
|
17 |
RUN bun install --frozen-lockfile
|
18 |
|
19 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
COPY . .
|
21 |
|
22 |
-
# Build the static
|
23 |
RUN bun run build
|
24 |
|
25 |
-
#
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
RUN adduser -D -u 1000 user
|
30 |
|
31 |
-
#
|
32 |
-
|
|
|
33 |
|
34 |
-
#
|
35 |
-
|
36 |
-
|
37 |
|
38 |
-
#
|
39 |
-
|
40 |
|
41 |
-
#
|
42 |
-
|
43 |
|
44 |
-
#
|
45 |
-
|
|
|
46 |
|
47 |
-
# Start
|
48 |
-
CMD ["bun", "
|
|
|
1 |
+
# Multi-stage build for optimal image size and security
|
2 |
+
FROM oven/bun:1.2.17-alpine AS base
|
|
|
3 |
|
4 |
+
# Install curl for healthcheck
|
5 |
+
RUN apk --no-cache add curl
|
6 |
+
|
7 |
+
# Set working directory
|
8 |
WORKDIR /app
|
9 |
|
10 |
+
# Create non-root user for security
|
11 |
+
RUN addgroup -g 1001 -S svelte && \
|
12 |
+
adduser -S svelteuser -u 1001
|
13 |
+
|
14 |
+
# ===============================
|
15 |
+
# Dependencies stage
|
16 |
+
# ===============================
|
17 |
+
FROM base AS deps
|
18 |
|
19 |
+
# Copy package files for dependency installation
|
20 |
COPY package.json bun.lock* ./
|
21 |
|
22 |
+
# Copy local packages and external dependencies
|
23 |
+
COPY packages/ packages/
|
24 |
+
COPY external/ external/
|
25 |
|
26 |
+
# Install dependencies with frozen lockfile (including devDependencies)
|
27 |
RUN bun install --frozen-lockfile
|
28 |
|
29 |
+
# ===============================
|
30 |
+
# Build stage
|
31 |
+
# ===============================
|
32 |
+
FROM base AS builder
|
33 |
+
|
34 |
+
# Copy installed dependencies from deps stage
|
35 |
+
COPY --from=deps /app/node_modules ./node_modules
|
36 |
+
COPY --from=deps /app/packages ./packages
|
37 |
+
COPY --from=deps /app/external ./external
|
38 |
+
|
39 |
+
# Copy source code and configuration files
|
40 |
COPY . .
|
41 |
|
42 |
+
# Build the static site
|
43 |
RUN bun run build
|
44 |
|
45 |
+
# ===============================
|
46 |
+
# Production stage
|
47 |
+
# ===============================
|
48 |
+
FROM base AS runner
|
|
|
49 |
|
50 |
+
# Set environment to production
|
51 |
+
ENV NODE_ENV=production
|
52 |
+
ENV PORT=3000
|
53 |
|
54 |
+
# Copy built application and static server
|
55 |
+
COPY --from=builder --chown=svelteuser:svelte /app/build ./build
|
56 |
+
COPY --chown=svelteuser:svelte static-server.js ./
|
57 |
|
58 |
+
# Switch to non-root user
|
59 |
+
USER svelteuser
|
60 |
|
61 |
+
# Expose port
|
62 |
+
EXPOSE 3000
|
63 |
|
64 |
+
# Health check
|
65 |
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
66 |
+
CMD curl -f http://localhost:3000/ || exit 1
|
67 |
|
68 |
+
# Start custom static file server
|
69 |
+
CMD ["bun", "static-server.js"]
|
bun.lock
DELETED
The diff for this file is too large to render.
See raw diff
|
|
docker-build.sh
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Build and run the LeRobot Arena Frontend Docker container
|
4 |
+
|
5 |
+
set -e
|
6 |
+
|
7 |
+
echo "🏗️ Building LeRobot Arena Frontend Docker image..."
|
8 |
+
|
9 |
+
# Build the image
|
10 |
+
docker build -t lerobot-arena-svelte-frontend .
|
11 |
+
|
12 |
+
echo "✅ Build completed successfully!"
|
13 |
+
|
14 |
+
echo "🚀 Starting the container..."
|
15 |
+
|
16 |
+
# Run the container
|
17 |
+
docker run -d \
|
18 |
+
--name lerobot-arena-svelte-frontend \
|
19 |
+
-p 3000:3000 \
|
20 |
+
--restart unless-stopped \
|
21 |
+
lerobot-arena-svelte-frontend
|
22 |
+
|
23 |
+
echo "✅ Container started successfully!"
|
24 |
+
echo "🌐 Frontend is available at: http://localhost:3000"
|
25 |
+
echo ""
|
26 |
+
echo "📋 Useful commands:"
|
27 |
+
echo " • View logs: docker logs -f lerobot-arena-svelte-frontend"
|
28 |
+
echo " • Stop: docker stop lerobot-arena-svelte-frontend"
|
29 |
+
echo " • Remove: docker rm lerobot-arena-svelte-frontend"
|
30 |
+
echo " • Health check: docker inspect --format='{{.State.Health.Status}}' lerobot-arena-svelte-frontend"
|
package.json
CHANGED
@@ -53,8 +53,8 @@
|
|
53 |
"@types/three": "0.177.0",
|
54 |
"clsx": "^2.1.1",
|
55 |
"feetech.js": "file:./packages/feetech.js",
|
56 |
-
"@
|
57 |
-
"@
|
58 |
"tailwind-merge": "^3.3.0",
|
59 |
"three": "^0.177.0",
|
60 |
"threlte-uikit": "^1.1.0",
|
|
|
53 |
"@types/three": "0.177.0",
|
54 |
"clsx": "^2.1.1",
|
55 |
"feetech.js": "file:./packages/feetech.js",
|
56 |
+
"@robothub/transport-server-client": "file:./external/RobotHub-TransportServer/client/js",
|
57 |
+
"@robothub/inference-server-client": "file:./external/RobotHub-InferenceServer/client",
|
58 |
"tailwind-merge": "^3.3.0",
|
59 |
"three": "^0.177.0",
|
60 |
"threlte-uikit": "^1.1.0",
|
packages/feetech.js/package.json
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
},
|
17 |
"repository": {
|
18 |
"type": "git",
|
19 |
-
"url": "git+https://github.com/julien-blanchon/
|
20 |
},
|
21 |
"keywords": [
|
22 |
"feetech",
|
@@ -32,7 +32,7 @@
|
|
32 |
"author": "timqian",
|
33 |
"license": "MIT",
|
34 |
"bugs": {
|
35 |
-
"url": "https://github.com/julien-blanchon/
|
36 |
},
|
37 |
-
"homepage": "https://github.com/julien-blanchon/
|
38 |
}
|
|
|
16 |
},
|
17 |
"repository": {
|
18 |
"type": "git",
|
19 |
+
"url": "git+https://github.com/julien-blanchon/robothub.git#main:frontend/packages/feetech.js"
|
20 |
},
|
21 |
"keywords": [
|
22 |
"feetech",
|
|
|
32 |
"author": "timqian",
|
33 |
"license": "MIT",
|
34 |
"bugs": {
|
35 |
+
"url": "https://github.com/julien-blanchon/robothub.git#main:frontend/packages/feetech.js"
|
36 |
},
|
37 |
+
"homepage": "https://github.com/julien-blanchon/robothub.git#main:frontend/packages/feetech.js"
|
38 |
}
|
src/lib/components/3d/elements/compute/GPU.svelte
CHANGED
@@ -6,8 +6,8 @@
|
|
6 |
import Model from "./GPUModel.svelte";
|
7 |
import { Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
|
8 |
import { onMount } from "svelte";
|
9 |
-
import type { VideoInstance } from "$lib/elements/video
|
10 |
-
import { videoManager } from "$lib/elements/video
|
11 |
|
12 |
// Props interface
|
13 |
interface Props {
|
|
|
6 |
import Model from "./GPUModel.svelte";
|
7 |
import { Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
|
8 |
import { onMount } from "svelte";
|
9 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
10 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
11 |
|
12 |
// Props interface
|
13 |
interface Props {
|
src/lib/components/3d/elements/compute/modal/VideoInputConnectionModal.svelte
CHANGED
@@ -1,12 +1,14 @@
|
|
1 |
<script lang="ts">
|
2 |
import * as Dialog from "@/components/ui/dialog";
|
|
|
|
|
3 |
import { Button } from "@/components/ui/button";
|
4 |
import * as Card from "@/components/ui/card";
|
5 |
import { Badge } from "@/components/ui/badge";
|
6 |
import { toast } from "svelte-sonner";
|
7 |
import { settings } from "$lib/runes/settings.svelte";
|
8 |
-
import { videoManager } from "$lib/elements/video
|
9 |
-
import type { RemoteCompute } from "$lib/elements/compute
|
10 |
|
11 |
interface Props {
|
12 |
workspaceId: string;
|
@@ -50,8 +52,7 @@
|
|
50 |
}
|
51 |
|
52 |
// Create video producer and connect to the camera room
|
53 |
-
|
54 |
-
videoProducer = new VideoProducer(settings.transportServerUrl);
|
55 |
|
56 |
// Connect to the EXISTING camera room (don't create new one)
|
57 |
const participantId = `frontend-camera-${selectedCameraName}-${Date.now()}`;
|
|
|
1 |
<script lang="ts">
|
2 |
import * as Dialog from "@/components/ui/dialog";
|
3 |
+
import { video } from '@robothub/transport-server-client';
|
4 |
+
import type { video as videoTypes } from '@robothub/transport-server-client';
|
5 |
import { Button } from "@/components/ui/button";
|
6 |
import * as Card from "@/components/ui/card";
|
7 |
import { Badge } from "@/components/ui/badge";
|
8 |
import { toast } from "svelte-sonner";
|
9 |
import { settings } from "$lib/runes/settings.svelte";
|
10 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
11 |
+
import type { RemoteCompute } from "$lib/elements/compute/RemoteCompute.svelte";
|
12 |
|
13 |
interface Props {
|
14 |
workspaceId: string;
|
|
|
52 |
}
|
53 |
|
54 |
// Create video producer and connect to the camera room
|
55 |
+
videoProducer = new video.VideoProducer(settings.transportServerUrl);
|
|
|
56 |
|
57 |
// Connect to the EXISTING camera room (don't create new one)
|
58 |
const participantId = `frontend-camera-${selectedCameraName}-${Date.now()}`;
|
src/lib/components/3d/elements/video/Video.svelte
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
import { interactivity } from "@threlte/extras";
|
4 |
import { VideoTexture, CanvasTexture, LinearFilter, RGBAFormat, Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
|
5 |
import { onMount } from "svelte";
|
6 |
-
import type { VideoInstance } from "$lib/elements/video
|
7 |
-
import { videoManager } from "$lib/elements/video
|
8 |
|
9 |
// Props interface
|
10 |
interface Props {
|
|
|
3 |
import { interactivity } from "@threlte/extras";
|
4 |
import { VideoTexture, CanvasTexture, LinearFilter, RGBAFormat, Shape, Path, ExtrudeGeometry, BoxGeometry } from "three";
|
5 |
import { onMount } from "svelte";
|
6 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
7 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
8 |
|
9 |
// Props interface
|
10 |
interface Props {
|
src/lib/components/3d/elements/video/VideoGridItem.svelte
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
import { T } from "@threlte/core";
|
3 |
import Video from "./Video.svelte";
|
4 |
import VideoStatusBillboard from "./status/VideoStatusBillboard.svelte";
|
5 |
-
import type { VideoInstance, VideoStatus } from "$lib/elements/video
|
6 |
import { interactivity, type IntersectionEvent, useCursor } from "@threlte/extras";
|
7 |
|
8 |
interface Props {
|
|
|
2 |
import { T } from "@threlte/core";
|
3 |
import Video from "./Video.svelte";
|
4 |
import VideoStatusBillboard from "./status/VideoStatusBillboard.svelte";
|
5 |
+
import type { VideoInstance, VideoStatus } from "$lib/elements/video/VideoManager.svelte";
|
6 |
import { interactivity, type IntersectionEvent, useCursor } from "@threlte/extras";
|
7 |
|
8 |
interface Props {
|
src/lib/components/3d/elements/video/Videos.svelte
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
<script lang="ts">
|
2 |
import { useThrelte } from "@threlte/core";
|
3 |
-
import { videoManager } from "$lib/elements/video
|
4 |
import { onMount } from "svelte";
|
5 |
import VideoInputConnectionModal from "@/components/3d/elements/video/modal/VideoInputConnectionModal.svelte";
|
6 |
import VideoOutputConnectionModal from "@/components/3d/elements/video/modal/VideoOutputConnectionModal.svelte";
|
7 |
-
import type { VideoInstance } from "$lib/elements/video
|
8 |
import { generateName } from "$lib/utils/generateName";
|
9 |
import VideoGridItem from "@/components/3d/elements/video/VideoGridItem.svelte";
|
10 |
|
|
|
1 |
<script lang="ts">
|
2 |
import { useThrelte } from "@threlte/core";
|
3 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
4 |
import { onMount } from "svelte";
|
5 |
import VideoInputConnectionModal from "@/components/3d/elements/video/modal/VideoInputConnectionModal.svelte";
|
6 |
import VideoOutputConnectionModal from "@/components/3d/elements/video/modal/VideoOutputConnectionModal.svelte";
|
7 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
8 |
import { generateName } from "$lib/utils/generateName";
|
9 |
import VideoGridItem from "@/components/3d/elements/video/VideoGridItem.svelte";
|
10 |
|
src/lib/components/3d/elements/video/modal/VideoInputConnectionModal.svelte
CHANGED
@@ -5,8 +5,8 @@
|
|
5 |
import * as Alert from "@/components/ui/alert";
|
6 |
import { Badge } from "@/components/ui/badge";
|
7 |
import { toast } from "svelte-sonner";
|
8 |
-
import { videoManager } from "$lib/elements/video
|
9 |
-
import type { VideoInstance } from "$lib/elements/video
|
10 |
|
11 |
interface Props {
|
12 |
workspaceId: string;
|
|
|
5 |
import * as Alert from "@/components/ui/alert";
|
6 |
import { Badge } from "@/components/ui/badge";
|
7 |
import { toast } from "svelte-sonner";
|
8 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
9 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
10 |
|
11 |
interface Props {
|
12 |
workspaceId: string;
|
src/lib/components/3d/elements/video/modal/VideoOutputConnectionModal.svelte
CHANGED
@@ -5,8 +5,8 @@
|
|
5 |
import * as Alert from "@/components/ui/alert";
|
6 |
import { Badge } from "@/components/ui/badge";
|
7 |
import { toast } from "svelte-sonner";
|
8 |
-
import { videoManager } from "$lib/elements/video
|
9 |
-
import type { VideoInstance } from "$lib/elements/video
|
10 |
|
11 |
interface Props {
|
12 |
workspaceId: string;
|
|
|
5 |
import * as Alert from "@/components/ui/alert";
|
6 |
import { Badge } from "@/components/ui/badge";
|
7 |
import { toast } from "svelte-sonner";
|
8 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
9 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
10 |
|
11 |
interface Props {
|
12 |
workspaceId: string;
|
src/lib/components/3d/elements/video/status/InputVideoBoxUIKit.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
-
import type { VideoInstance } from "$lib/elements/video
|
4 |
import { BaseStatusBox, StatusHeader, StatusContent, StatusIndicator, StatusButton } from "$lib/components/3d/ui";
|
5 |
|
6 |
interface Props {
|
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
4 |
import { BaseStatusBox, StatusHeader, StatusContent, StatusIndicator, StatusButton } from "$lib/components/3d/ui";
|
5 |
|
6 |
interface Props {
|
src/lib/components/3d/elements/video/status/OutputVideoBoxUIKit.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
-
import type { VideoInstance } from "$lib/elements/video
|
4 |
import { BaseStatusBox, StatusHeader, StatusContent, StatusIndicator, StatusButton } from "$lib/components/3d/ui";
|
5 |
|
6 |
interface Props {
|
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
4 |
import { BaseStatusBox, StatusHeader, StatusContent, StatusIndicator, StatusButton } from "$lib/components/3d/ui";
|
5 |
|
6 |
interface Props {
|
src/lib/components/3d/elements/video/status/VideoBoxUIKit.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
-
import type { VideoInstance } from "$lib/elements/video
|
4 |
import {
|
5 |
BaseStatusBox,
|
6 |
StatusHeader,
|
|
|
1 |
<script lang="ts">
|
2 |
import { ICON } from "$lib/utils/icon";
|
3 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
4 |
import {
|
5 |
BaseStatusBox,
|
6 |
StatusHeader,
|
src/lib/components/3d/elements/video/status/VideoConnectionFlowBoxUIKit.svelte
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
import InputVideoBoxUIKit from "./InputVideoBoxUIKit.svelte";
|
3 |
import OutputVideoBoxUIKit from "./OutputVideoBoxUIKit.svelte";
|
4 |
import VideoBoxUIKit from "./VideoBoxUIKit.svelte";
|
5 |
-
import type { VideoInstance } from "$lib/elements/video
|
6 |
import { Container } from "threlte-uikit";
|
7 |
import { StatusArrow } from "$lib/components/3d/ui";
|
8 |
|
|
|
2 |
import InputVideoBoxUIKit from "./InputVideoBoxUIKit.svelte";
|
3 |
import OutputVideoBoxUIKit from "./OutputVideoBoxUIKit.svelte";
|
4 |
import VideoBoxUIKit from "./VideoBoxUIKit.svelte";
|
5 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
6 |
import { Container } from "threlte-uikit";
|
7 |
import { StatusArrow } from "$lib/components/3d/ui";
|
8 |
|
src/lib/components/3d/elements/video/status/VideoStatusBillboard.svelte
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
import { Billboard, interactivity } from "@threlte/extras";
|
4 |
import { Root, Container } from "threlte-uikit";
|
5 |
import VideoConnectionFlowBoxUIKit from "./VideoConnectionFlowBoxUIKit.svelte";
|
6 |
-
import type { VideoInstance } from "$lib/elements/video
|
7 |
|
8 |
interface Props {
|
9 |
video: VideoInstance;
|
|
|
3 |
import { Billboard, interactivity } from "@threlte/extras";
|
4 |
import { Root, Container } from "threlte-uikit";
|
5 |
import VideoConnectionFlowBoxUIKit from "./VideoConnectionFlowBoxUIKit.svelte";
|
6 |
+
import type { VideoInstance } from "$lib/elements/video/VideoManager.svelte";
|
7 |
|
8 |
interface Props {
|
9 |
video: VideoInstance;
|
src/lib/components/interface/overlay/AddSensorButton.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
import { toast } from "svelte-sonner";
|
6 |
import { cn } from "$lib/utils";
|
7 |
import { generateName } from "@/utils/generateName";
|
8 |
-
import { videoManager } from "$lib/elements/video
|
9 |
|
10 |
interface Props {
|
11 |
open: boolean;
|
|
|
5 |
import { toast } from "svelte-sonner";
|
6 |
import { cn } from "$lib/utils";
|
7 |
import { generateName } from "@/utils/generateName";
|
8 |
+
import { videoManager } from "$lib/elements/video/VideoManager.svelte";
|
9 |
|
10 |
interface Props {
|
11 |
open: boolean;
|
src/lib/elements/compute/RemoteComputeManager.svelte.ts
CHANGED
@@ -2,13 +2,13 @@ import { RemoteCompute } from './RemoteCompute.svelte';
|
|
2 |
import type { Position3D } from '$lib/types/positionable.js';
|
3 |
import { generateName } from '$lib/utils/generateName.js';
|
4 |
import { positionManager } from '$lib/utils/positionManager.js';
|
5 |
-
import { type LeRobotAIServerClient, createClient } from '@
|
6 |
import { settings } from '$lib/runes/settings.svelte';
|
7 |
import type {
|
8 |
CreateSessionRequest,
|
9 |
CreateSessionResponse,
|
10 |
SessionStatusResponse
|
11 |
-
} from '@
|
12 |
|
13 |
export interface AISessionConfig {
|
14 |
sessionId: string;
|
|
|
2 |
import type { Position3D } from '$lib/types/positionable.js';
|
3 |
import { generateName } from '$lib/utils/generateName.js';
|
4 |
import { positionManager } from '$lib/utils/positionManager.js';
|
5 |
+
import { type LeRobotAIServerClient, createClient } from '@robothub/inference-server-client';
|
6 |
import { settings } from '$lib/runes/settings.svelte';
|
7 |
import type {
|
8 |
CreateSessionRequest,
|
9 |
CreateSessionResponse,
|
10 |
SessionStatusResponse
|
11 |
+
} from '@robothub/inference-server-client';
|
12 |
|
13 |
export interface AISessionConfig {
|
14 |
sessionId: string;
|
src/lib/elements/robot/RobotManager.svelte.ts
CHANGED
@@ -6,8 +6,8 @@ import type { RobotUrdfConfig } from '$lib/types/urdf.js';
|
|
6 |
import { generateName } from '$lib/utils/generateName.js';
|
7 |
import { positionManager } from '$lib/utils/positionManager.js';
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
-
import { robotics } from '@
|
10 |
-
import type { robotics as roboticsTypes } from '@
|
11 |
|
12 |
export class RobotManager {
|
13 |
private _robots = $state<Robot[]>([]);
|
|
|
6 |
import { generateName } from '$lib/utils/generateName.js';
|
7 |
import { positionManager } from '$lib/utils/positionManager.js';
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
+
import { robotics } from '@robothub/transport-server-client';
|
10 |
+
import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
|
11 |
|
12 |
export class RobotManager {
|
13 |
private _robots = $state<Robot[]>([]);
|
src/lib/elements/robot/calibration/CalibrationState.svelte.ts
CHANGED
@@ -54,7 +54,7 @@ export class CalibrationState {
|
|
54 |
return Math.abs(calibration.maxServoValue - calibration.minServoValue);
|
55 |
}
|
56 |
|
57 |
-
private updateInterval:
|
58 |
private managerUnsubscribe: (() => void) | null = null;
|
59 |
|
60 |
private setupManagerSubscription(): void {
|
|
|
54 |
return Math.abs(calibration.maxServoValue - calibration.minServoValue);
|
55 |
}
|
56 |
|
57 |
+
private updateInterval: Timer | null = null;
|
58 |
private managerUnsubscribe: (() => void) | null = null;
|
59 |
|
60 |
private setupManagerSubscription(): void {
|
src/lib/elements/robot/drivers/RemoteConsumer.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import type { Consumer, ConnectionStatus, RobotCommand, RemoteDriverConfig } from '../models.js';
|
2 |
-
import { robotics } from "@
|
3 |
|
4 |
export class RemoteConsumer implements Consumer {
|
5 |
readonly id: string;
|
|
|
1 |
import type { Consumer, ConnectionStatus, RobotCommand, RemoteDriverConfig } from '../models.js';
|
2 |
+
import { robotics } from "@robothub/transport-server-client";
|
3 |
|
4 |
export class RemoteConsumer implements Consumer {
|
5 |
readonly id: string;
|
src/lib/elements/robot/drivers/RemoteProducer.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import type { Producer, ConnectionStatus, RobotCommand, RemoteDriverConfig } from '../models.js';
|
2 |
-
import { robotics } from "@
|
3 |
|
4 |
export class RemoteProducer implements Producer {
|
5 |
readonly id: string;
|
|
|
1 |
import type { Producer, ConnectionStatus, RobotCommand, RemoteDriverConfig } from '../models.js';
|
2 |
+
import { robotics } from "@robothub/transport-server-client";
|
3 |
|
4 |
export class RemoteProducer implements Producer {
|
5 |
readonly id: string;
|
src/lib/elements/video/VideoManager.svelte.ts
CHANGED
@@ -4,8 +4,8 @@
|
|
4 |
* Manages multiple video instances, each with their own streaming state
|
5 |
*/
|
6 |
|
7 |
-
import { video as videoClient } from '@
|
8 |
-
import type { video as videoTypes } from '@
|
9 |
import { generateName } from "$lib/utils/generateName";
|
10 |
import type { Positionable, Position3D } from '$lib/types/positionable';
|
11 |
import { positionManager } from '$lib/utils/positionManager';
|
|
|
4 |
* Manages multiple video instances, each with their own streaming state
|
5 |
*/
|
6 |
|
7 |
+
import { video as videoClient } from '@robothub/transport-server-client';
|
8 |
+
import type { video as videoTypes } from '@robothub/transport-server-client';
|
9 |
import { generateName } from "$lib/utils/generateName";
|
10 |
import type { Positionable, Position3D } from '$lib/types/positionable';
|
11 |
import { positionManager } from '$lib/utils/positionManager';
|
src/lib/elements/video/videoConnection.svelte.ts
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
* Clean and simple video producer/consumer management
|
4 |
*/
|
5 |
|
6 |
-
import { video } from '@
|
7 |
-
import type { video as videoTypes } from '@
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
|
10 |
// Simple connection state using runes
|
|
|
3 |
* Clean and simple video producer/consumer management
|
4 |
*/
|
5 |
|
6 |
+
import { video } from '@robothub/transport-server-client';
|
7 |
+
import type { video as videoTypes } from '@robothub/transport-server-client';
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
|
10 |
// Simple connection state using runes
|
src/lib/elements/video/videoStreaming.svelte.ts
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
* Clean separation between input sources and output destinations
|
4 |
*/
|
5 |
|
6 |
-
import { video } from '@
|
7 |
-
import type { video as videoTypes } from '@
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
|
10 |
// Input/Output state using runes
|
|
|
3 |
* Clean separation between input sources and output destinations
|
4 |
*/
|
5 |
|
6 |
+
import { video } from '@robothub/transport-server-client';
|
7 |
+
import type { video as videoTypes } from '@robothub/transport-server-client';
|
8 |
import { settings } from '$lib/runes/settings.svelte';
|
9 |
|
10 |
// Input/Output state using runes
|
src/lib/sensors/consumers/RemoteServerConsumer.ts
CHANGED
@@ -27,7 +27,7 @@ export class RemoteServerConsumer implements ConsumerSensorDriver {
|
|
27 |
// Connection management
|
28 |
private websocket: WebSocket | null = null;
|
29 |
private reconnectAttempts = 0;
|
30 |
-
private reconnectTimer?:
|
31 |
|
32 |
// Stream management
|
33 |
private activeOutputStreams = new Map<string, SensorStream>();
|
|
|
27 |
// Connection management
|
28 |
private websocket: WebSocket | null = null;
|
29 |
private reconnectAttempts = 0;
|
30 |
+
private reconnectTimer?: Timer;
|
31 |
|
32 |
// Stream management
|
33 |
private activeOutputStreams = new Map<string, SensorStream>();
|
static-server.js
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env bun
|
2 |
+
|
3 |
+
// Simple static file server for Svelte build output
|
4 |
+
import { resolve, join } from "path";
|
5 |
+
|
6 |
+
const PORT = process.env.PORT || 3000;
|
7 |
+
const BUILD_DIR = "./build";
|
8 |
+
|
9 |
+
// MIME types for common web assets
|
10 |
+
const MIME_TYPES = {
|
11 |
+
'.html': 'text/html',
|
12 |
+
'.css': 'text/css',
|
13 |
+
'.js': 'application/javascript',
|
14 |
+
'.json': 'application/json',
|
15 |
+
'.png': 'image/png',
|
16 |
+
'.jpg': 'image/jpeg',
|
17 |
+
'.jpeg': 'image/jpeg',
|
18 |
+
'.gif': 'image/gif',
|
19 |
+
'.svg': 'image/svg+xml',
|
20 |
+
'.ico': 'image/x-icon',
|
21 |
+
'.woff': 'font/woff',
|
22 |
+
'.woff2': 'font/woff2',
|
23 |
+
'.ttf': 'font/ttf',
|
24 |
+
'.eot': 'application/vnd.ms-fontobject',
|
25 |
+
'.webp': 'image/webp',
|
26 |
+
'.avif': 'image/avif',
|
27 |
+
'.mp4': 'video/mp4',
|
28 |
+
'.webm': 'video/webm'
|
29 |
+
};
|
30 |
+
|
31 |
+
function getMimeType(filename) {
|
32 |
+
const ext = filename.substring(filename.lastIndexOf('.'));
|
33 |
+
return MIME_TYPES[ext] || 'application/octet-stream';
|
34 |
+
}
|
35 |
+
|
36 |
+
const server = Bun.serve({
|
37 |
+
port: PORT,
|
38 |
+
hostname: "0.0.0.0",
|
39 |
+
|
40 |
+
async fetch(req) {
|
41 |
+
const url = new URL(req.url);
|
42 |
+
let pathname = url.pathname;
|
43 |
+
|
44 |
+
// Remove leading slash and default to index.html for root
|
45 |
+
if (pathname === '/') {
|
46 |
+
pathname = 'index.html';
|
47 |
+
} else {
|
48 |
+
pathname = pathname.substring(1); // Remove leading slash
|
49 |
+
}
|
50 |
+
|
51 |
+
try {
|
52 |
+
// Try to serve the requested file
|
53 |
+
const filePath = join(BUILD_DIR, pathname);
|
54 |
+
const file = Bun.file(filePath);
|
55 |
+
|
56 |
+
if (await file.exists()) {
|
57 |
+
const mimeType = getMimeType(pathname);
|
58 |
+
const headers = {
|
59 |
+
'Content-Type': mimeType,
|
60 |
+
};
|
61 |
+
|
62 |
+
// Set cache headers
|
63 |
+
if (pathname.includes('/_app/immutable/')) {
|
64 |
+
// Long-term cache for immutable assets
|
65 |
+
headers['Cache-Control'] = 'public, max-age=31536000, immutable';
|
66 |
+
} else if (pathname.endsWith('.html')) {
|
67 |
+
// No cache for HTML files
|
68 |
+
headers['Cache-Control'] = 'public, max-age=0, must-revalidate';
|
69 |
+
} else {
|
70 |
+
// Short cache for other assets
|
71 |
+
headers['Cache-Control'] = 'public, max-age=3600';
|
72 |
+
}
|
73 |
+
|
74 |
+
return new Response(file, { headers });
|
75 |
+
}
|
76 |
+
|
77 |
+
// If file not found and no extension, serve index.html for SPA routing
|
78 |
+
if (!pathname.includes('.')) {
|
79 |
+
const indexFile = Bun.file(join(BUILD_DIR, 'index.html'));
|
80 |
+
if (await indexFile.exists()) {
|
81 |
+
return new Response(indexFile, {
|
82 |
+
headers: {
|
83 |
+
'Content-Type': 'text/html',
|
84 |
+
'Cache-Control': 'public, max-age=0, must-revalidate'
|
85 |
+
}
|
86 |
+
});
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
return new Response('Not Found', {
|
91 |
+
status: 404,
|
92 |
+
headers: { 'Content-Type': 'text/plain' }
|
93 |
+
});
|
94 |
+
|
95 |
+
} catch (error) {
|
96 |
+
console.error('Server error:', error);
|
97 |
+
return new Response('Internal Server Error', {
|
98 |
+
status: 500,
|
99 |
+
headers: { 'Content-Type': 'text/plain' }
|
100 |
+
});
|
101 |
+
}
|
102 |
+
}
|
103 |
+
});
|
104 |
+
|
105 |
+
console.log(`🚀 Static server running on http://localhost:${server.port}`);
|
106 |
+
console.log(`📁 Serving files from: ${BUILD_DIR}`);
|