blanchon commited on
Commit
c3f65a8
·
1 Parent(s): e510655
.env.example ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ PUBLIC_TRANSPORT_SERVER_URL=https://blanchon-robothub-transportserver.hf.space/api
2
+ PUBLIC_INFERENCE_SERVER_URL=https://blanchon-robothub-inference-server.hf.space/api
.github/workflows/sync-to-hf.yml CHANGED
@@ -18,4 +18,4 @@ jobs:
18
  - name: Push to hub
19
  env:
20
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
21
- run: git push https://blanchon:$HF_TOKEN@huggingface.co/spaces/blanchon/RobotHub-Frontend main
 
18
  - name: Push to hub
19
  env:
20
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
21
+ run: git push https://blanchon:$HF_TOKEN@huggingface.co/spaces/blanchon/RobotHub-Frontend main
Dockerfile CHANGED
@@ -8,8 +8,8 @@ RUN apk --no-cache add curl
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
@@ -52,14 +52,23 @@ 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 \
 
8
  WORKDIR /app
9
 
10
  # Create non-root user for security
11
+ RUN addgroup -g 1001 -S user && \
12
+ adduser -S user -u 1001
13
 
14
  # ===============================
15
  # Dependencies stage
 
52
  ENV PORT=3000
53
 
54
  # Copy built application and static server
55
+ COPY --from=builder --chown=user:user /app/build ./build
56
+ COPY --chown=user:user static-server.js ./
57
 
58
  # Switch to non-root user
59
+ USER user
60
+
61
+ ARG PUBLIC_TRANSPORT_SERVER_URL=https://blanchon-robothub-transportserver.hf.space/api
62
+ ENV PUBLIC_TRANSPORT_SERVER_URL=${PUBLIC_TRANSPORT_SERVER_URL}
63
+
64
+ ARG PUBLIC_INFERENCE_SERVER_URL=https://blanchon-robothub-inference-server.hf.space/api
65
+ ENV PUBLIC_INFERENCE_SERVER_URL=${PUBLIC_INFERENCE_SERVER_URL}
66
+
67
+ ARG PORT=8000
68
+ ENV PORT=${PORT}
69
 
70
  # Expose port
71
+ EXPOSE ${PORT}
72
 
73
  # Health check
74
  HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
external/RobotHub-InferenceServer CHANGED
@@ -1 +1 @@
1
- Subproject commit 287297c1eabcd6a1727e9453d9c48391ebd79659
 
1
+ Subproject commit 119f2e226ee9dd33a2ab59894e7c1be24cb5dbde
src/lib/elements/compute/RemoteComputeManager.svelte.ts CHANGED
@@ -2,7 +2,15 @@ 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 '@robothub/inference-server-client';
 
 
 
 
 
 
 
 
6
  import { settings } from '$lib/runes/settings.svelte';
7
  import type {
8
  CreateSessionRequest,
@@ -58,14 +66,9 @@ export interface AISessionStatus {
58
 
59
  export class RemoteComputeManager {
60
  private _computes = $state<RemoteCompute[]>([]);
61
-
62
- // Make the client reactive to URL changes
63
- private get inferenceServerClient() {
64
- return createClient(settings.inferenceServerUrl);
65
- }
66
 
67
  constructor() {
68
- // Remove the fixed client initialization
69
  }
70
 
71
  // Reactive getters
@@ -146,11 +149,20 @@ export class RemoteComputeManager {
146
  session_id: config.sessionId,
147
  policy_path: config.policyPath,
148
  camera_names: config.cameraNames,
149
- arena_server_url: config.transportServerUrl,
150
  workspace_id: config.workspaceId || undefined,
151
  };
152
 
153
- const data: CreateSessionResponse = await this.inferenceServerClient.createSession(request);
 
 
 
 
 
 
 
 
 
154
 
155
  // Update compute with session info
156
  compute.sessionId = config.sessionId;
@@ -183,7 +195,10 @@ export class RemoteComputeManager {
183
  }
184
 
185
  try {
186
- await this.inferenceServerClient.startInference(compute.sessionId);
 
 
 
187
  compute.status = 'running';
188
  return { success: true };
189
  } catch (error) {
@@ -205,7 +220,10 @@ export class RemoteComputeManager {
205
  }
206
 
207
  try {
208
- await this.inferenceServerClient.stopInference(compute.sessionId);
 
 
 
209
  compute.status = 'stopped';
210
  return { success: true };
211
  } catch (error) {
@@ -227,7 +245,10 @@ export class RemoteComputeManager {
227
  }
228
 
229
  try {
230
- await this.inferenceServerClient.deleteSession(compute.sessionId);
 
 
 
231
 
232
  // Reset compute session info
233
  compute.sessionId = null;
@@ -255,22 +276,34 @@ export class RemoteComputeManager {
255
  }
256
 
257
  try {
258
- const data: SessionStatusResponse = await this.inferenceServerClient.getSessionStatus(compute.sessionId);
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
  // Update compute status
261
- compute.status = data.status as 'initializing' | 'ready' | 'running' | 'stopped';
262
 
263
  // Convert to AISessionStatus format
264
  const sessionStatus: AISessionStatus = {
265
- session_id: data.session_id,
266
- status: data.status as 'initializing' | 'ready' | 'running' | 'stopped',
267
- policy_path: data.policy_path,
268
- camera_names: data.camera_names,
269
- workspace_id: data.workspace_id,
270
- rooms: data.rooms as any,
271
- stats: data.stats as any,
272
- inference_stats: data.inference_stats as any,
273
- error_message: data.error_message || undefined
274
  };
275
 
276
  return { success: true, data: sessionStatus };
@@ -288,13 +321,20 @@ export class RemoteComputeManager {
288
  */
289
  async checkServerHealth(): Promise<{ success: boolean; data?: any; error?: string }> {
290
  try {
291
- const isHealthy = await this.inferenceServerClient.isHealthy();
292
- if (!isHealthy) {
 
 
 
293
  return { success: false, error: 'Server is not healthy' };
294
  }
295
 
296
- const data = await this.inferenceServerClient.getHealth();
297
- return { success: true, data };
 
 
 
 
298
  } catch (error) {
299
  console.error('Failed to check AI server health:', error);
300
  return {
 
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 {
6
+ rootGet,
7
+ healthCheckHealthGet,
8
+ listSessionsSessionsGet,
9
+ createSessionSessionsPost,
10
+ startInferenceSessionsSessionIdStartPost,
11
+ stopInferenceSessionsSessionIdStopPost,
12
+ deleteSessionSessionsSessionIdDelete
13
+ } from '@robothub/inference-server-client';
14
  import { settings } from '$lib/runes/settings.svelte';
15
  import type {
16
  CreateSessionRequest,
 
66
 
67
  export class RemoteComputeManager {
68
  private _computes = $state<RemoteCompute[]>([]);
 
 
 
 
 
69
 
70
  constructor() {
71
+ // No client initialization needed anymore
72
  }
73
 
74
  // Reactive getters
 
149
  session_id: config.sessionId,
150
  policy_path: config.policyPath,
151
  camera_names: config.cameraNames,
152
+ transport_server_url: config.transportServerUrl,
153
  workspace_id: config.workspaceId || undefined,
154
  };
155
 
156
+ const response = await createSessionSessionsPost({
157
+ body: request,
158
+ baseUrl: settings.inferenceServerUrl
159
+ });
160
+
161
+ if (!response.data) {
162
+ throw new Error('Failed to create session - no data returned');
163
+ }
164
+
165
+ const data: CreateSessionResponse = response.data;
166
 
167
  // Update compute with session info
168
  compute.sessionId = config.sessionId;
 
195
  }
196
 
197
  try {
198
+ await startInferenceSessionsSessionIdStartPost({
199
+ path: { session_id: compute.sessionId },
200
+ baseUrl: settings.inferenceServerUrl
201
+ });
202
  compute.status = 'running';
203
  return { success: true };
204
  } catch (error) {
 
220
  }
221
 
222
  try {
223
+ await stopInferenceSessionsSessionIdStopPost({
224
+ path: { session_id: compute.sessionId },
225
+ baseUrl: settings.inferenceServerUrl
226
+ });
227
  compute.status = 'stopped';
228
  return { success: true };
229
  } catch (error) {
 
245
  }
246
 
247
  try {
248
+ await deleteSessionSessionsSessionIdDelete({
249
+ path: { session_id: compute.sessionId },
250
+ baseUrl: settings.inferenceServerUrl
251
+ });
252
 
253
  // Reset compute session info
254
  compute.sessionId = null;
 
276
  }
277
 
278
  try {
279
+ // Get all sessions and find the one we want
280
+ const response = await listSessionsSessionsGet({
281
+ baseUrl: settings.inferenceServerUrl
282
+ });
283
+
284
+ if (!response.data) {
285
+ throw new Error('Failed to get sessions list');
286
+ }
287
+
288
+ const session = response.data.find(s => s.session_id === compute.sessionId);
289
+ if (!session) {
290
+ throw new Error(`Session ${compute.sessionId} not found`);
291
+ }
292
 
293
  // Update compute status
294
+ compute.status = session.status as 'initializing' | 'ready' | 'running' | 'stopped';
295
 
296
  // Convert to AISessionStatus format
297
  const sessionStatus: AISessionStatus = {
298
+ session_id: session.session_id,
299
+ status: session.status as 'initializing' | 'ready' | 'running' | 'stopped',
300
+ policy_path: session.policy_path,
301
+ camera_names: session.camera_names,
302
+ workspace_id: session.workspace_id,
303
+ rooms: session.rooms as any,
304
+ stats: session.stats as any,
305
+ inference_stats: session.inference_stats as any,
306
+ error_message: session.error_message || undefined
307
  };
308
 
309
  return { success: true, data: sessionStatus };
 
321
  */
322
  async checkServerHealth(): Promise<{ success: boolean; data?: any; error?: string }> {
323
  try {
324
+ const healthResponse = await rootGet({
325
+ baseUrl: settings.inferenceServerUrl
326
+ });
327
+
328
+ if (!healthResponse.data) {
329
  return { success: false, error: 'Server is not healthy' };
330
  }
331
 
332
+ // Get detailed health info
333
+ const detailedHealthResponse = await healthCheckHealthGet({
334
+ baseUrl: settings.inferenceServerUrl
335
+ });
336
+
337
+ return { success: true, data: detailedHealthResponse.data };
338
  } catch (error) {
339
  console.error('Failed to check AI server health:', error);
340
  return {
src/lib/runes/settings.svelte.ts CHANGED
@@ -1,3 +1,4 @@
 
1
 
2
  interface Settings {
3
  inferenceServerUrl: string;
@@ -7,6 +8,8 @@ interface Settings {
7
  export const settings: Settings = $state({
8
  // inferenceServerUrl: 'http://localhost:8001',
9
  // transportServerUrl: 'http://localhost:8000'
10
- inferenceServerUrl: 'https://blanchon-robothub-inferenceserver.hf.space/api',
11
- transportServerUrl: 'https://blanchon-robothub-transportserver.hf.space/api'
 
 
12
  });
 
1
+ import { env } from '$env/dynamic/public';
2
 
3
  interface Settings {
4
  inferenceServerUrl: string;
 
8
  export const settings: Settings = $state({
9
  // inferenceServerUrl: 'http://localhost:8001',
10
  // transportServerUrl: 'http://localhost:8000'
11
+ // inferenceServerUrl: 'https://blanchon-robothub-inferenceserver.hf.space/api',
12
+ // transportServerUrl: 'https://blanchon-robothub-transportserver.hf.space/api'
13
+ inferenceServerUrl: env.PUBLIC_INFERENCE_SERVER_URL ?? 'http://localhost:8001',
14
+ transportServerUrl: env.PUBLIC_TRANSPORT_SERVER_URL ?? 'http://localhost:8000'
15
  });
static-server.js CHANGED
@@ -35,7 +35,7 @@ function getMimeType(filename) {
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);
 
35
 
36
  const server = Bun.serve({
37
  port: PORT,
38
+ hostname: "localhost",
39
 
40
  async fetch(req) {
41
  const url = new URL(req.url);
vite.config.ts CHANGED
@@ -4,5 +4,5 @@ import { defineConfig } from "vite";
4
 
5
  export default defineConfig({
6
  plugins: [tailwindcss(), sveltekit()],
7
- server: { fs: { allow: ["../backend/client/js", "packages/feetech.js"] } }
8
  });
 
4
 
5
  export default defineConfig({
6
  plugins: [tailwindcss(), sveltekit()],
7
+ // server: { fs: { allow: ["../backend/client/js", "packages/feetech.js"] } }
8
  });