mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-07 16:19:05 +08:00
Mirrors the dev:automation backend stack (agent-server + automation + ingress) but serves a production frontend build through a small static server instead of Vite. Designed for use over flaky / high-RTT links where Vite's ~1000 ESM module fetches make full reloads painfully slow: hashed assets are now sent with public/immutable cache headers, so an SPA reload is ~1 round-trip (304 on index.html) and zero asset fetches. scripts/static-server.mjs: combined static-file server + reverse proxy. A drop-in for sirv-cli that additionally proxies the same prefixes Vite proxies in dev (/api, /api/automation, /sockets, /server_info, /alive, /health, /ready) so hitting :3001 directly behaves like Vite's dev server — without it, sirv-cli's --single fallback turns /server_info into the SPA shell whenever a tunnel exposes the static port instead of the ingress port. Caches /assets/* immutable, index.html no-cache, weak ETags. scripts/dev-static.mjs: orchestrator that builds the frontend, then spawns agent-server, automation, static-server, and the existing ingress with the same route table as dev-with-automation. scripts/dev-safe.mjs: add isPortBusy() and releaseStaleConversationLeases() helpers. The agent-server tags each conversation directory with an owner_lease.json keyed to a per-process owner_instance_id (45 s TTL, heartbeat-renewed) and skip-loads any conversation whose lease is held by a different instance. If the previous agent-server died ungracefully — or you restart inside the TTL window — every existing conversation becomes invisible to the new instance until the leases age out. dev:static now port-checks for a live agent-server (aborts on conflict), then unlinks stale leases so conversations created by npm run dev are immediately visible. Co-authored-by: openhands <openhands@all-hands.dev>
205 lines
6.9 KiB
JSON
205 lines
6.9 KiB
JSON
{
|
|
"name": "@openhands/agent-canvas",
|
|
"version": "1.6.0",
|
|
"license": "MIT",
|
|
"private": false,
|
|
"type": "module",
|
|
"engines": {
|
|
"node": ">=22.12.0"
|
|
},
|
|
"dependencies": {
|
|
"@heroui/react": "2.8.10",
|
|
"@microlink/react-json-view": "1.31.19",
|
|
"@monaco-editor/react": "4.7.0",
|
|
"@openhands/typescript-client": "github:OpenHands/typescript-client#6b9603f06ea0ecc9bc715bf2192e274c23cd3be6",
|
|
"@react-router/node": "7.14.2",
|
|
"@react-router/serve": "7.14.2",
|
|
"@tailwindcss/vite": "4.2.4",
|
|
"@tanstack/react-query": "5.100.6",
|
|
"@uidotdev/usehooks": "2.4.1",
|
|
"@xterm/addon-fit": "0.11.0",
|
|
"@xterm/xterm": "6.0.0",
|
|
"axios": "1.15.2",
|
|
"class-variance-authority": "0.7.1",
|
|
"clsx": "2.1.1",
|
|
"downshift": "9.3.2",
|
|
"eslint-config-airbnb-typescript": "18.0.0",
|
|
"framer-motion": "12.38.0",
|
|
"i18next": "26.0.8",
|
|
"i18next-browser-languagedetector": "8.2.1",
|
|
"i18next-http-backend": "3.0.6",
|
|
"isbot": "5.1.39",
|
|
"lucide-react": "1.14.0",
|
|
"monaco-editor": "0.55.1",
|
|
"posthog-js": "1.372.5",
|
|
"react": "19.2.5",
|
|
"react-dom": "19.2.5",
|
|
"react-hot-toast": "2.6.0",
|
|
"react-i18next": "17.0.6",
|
|
"react-icons": "5.6.0",
|
|
"react-markdown": "10.1.0",
|
|
"react-router": "7.14.2",
|
|
"react-syntax-highlighter": "16.1.1",
|
|
"remark-breaks": "4.0.0",
|
|
"remark-gfm": "4.0.1",
|
|
"sirv-cli": "3.0.1",
|
|
"socket.io-client": "4.8.3",
|
|
"tailwind-merge": "3.5.0",
|
|
"tailwind-scrollbar": "4.0.2",
|
|
"uuid": "^14.0.0",
|
|
"vite": "8.0.10",
|
|
"zustand": "5.0.12"
|
|
},
|
|
"scripts": {
|
|
"dev": "npm run dev:automation",
|
|
"dev:safe": "node --env-file-if-exists=.env scripts/dev-safe.mjs",
|
|
"dev:extra-backend": "node --env-file-if-exists=.env scripts/dev-extra-backend.mjs",
|
|
"dev:automation": "node --env-file-if-exists=.env scripts/dev-with-automation.mjs",
|
|
"dev:static": "node --env-file-if-exists=.env scripts/dev-static.mjs",
|
|
"dev:minimal": "node --env-file-if-exists=.env scripts/dev-safe.mjs",
|
|
"dev:frontend": "npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev",
|
|
"dev:mock": "npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev",
|
|
"build": "npm run build:app",
|
|
"build:mock": "npm run make-i18n && cross-env VITE_MOCK_API=true react-router build",
|
|
"start": "npx sirv-cli build/ --single",
|
|
"test": "npm run make-i18n && vitest run",
|
|
"test:e2e": "playwright test",
|
|
"test:coverage": "npm run make-i18n && vitest run --coverage",
|
|
"dev_wsl": "VITE_WATCH_USE_POLLING=true vite",
|
|
"preview": "vite preview",
|
|
"make-i18n": "node scripts/make-i18n-translations.cjs",
|
|
"prelint": "npm run make-i18n",
|
|
"lint": "npm run typecheck && eslint src --ext .ts,.tsx,.js && prettier --check src/**/*.{ts,tsx}",
|
|
"lint:fix": "eslint src --ext .ts,.tsx,.js --fix && prettier --write src/**/*.{ts,tsx}",
|
|
"prepare": "cd .. && husky frontend/.husky",
|
|
"typecheck": "react-router typegen && tsc",
|
|
"typecheck:staged": "react-router typegen && npx tsc --noEmit --skipLibCheck",
|
|
"check-translation-completeness": "node scripts/check-translation-completeness.cjs",
|
|
"build:app": "npm run make-i18n && react-router build",
|
|
"build:lib": "npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json"
|
|
},
|
|
"lint-staged": {
|
|
"src/**/*.{ts,tsx,js}": [
|
|
"eslint --fix",
|
|
"prettier --write"
|
|
],
|
|
"src/**/*.{ts,tsx}": [
|
|
"bash -c 'npm run typecheck:staged'"
|
|
],
|
|
"src/**/*": [
|
|
"npm run check-translation-completeness"
|
|
]
|
|
},
|
|
"devDependencies": {
|
|
"@mswjs/socket.io-binding": "0.2.0",
|
|
"@playwright/test": "1.59.1",
|
|
"@react-router/dev": "7.14.2",
|
|
"@tailwindcss/typography": "0.5.19",
|
|
"@tanstack/eslint-plugin-query": "5.100.6",
|
|
"@testing-library/dom": "10.4.1",
|
|
"@testing-library/jest-dom": "6.9.1",
|
|
"@testing-library/react": "16.3.2",
|
|
"@testing-library/user-event": "14.6.1",
|
|
"@types/node": "25.6.0",
|
|
"@types/react": "19.2.14",
|
|
"@types/react-dom": "19.2.3",
|
|
"@types/react-syntax-highlighter": "15.5.13",
|
|
"@typescript-eslint/eslint-plugin": "7.18.0",
|
|
"@typescript-eslint/parser": "7.18.0",
|
|
"@vercel/react-router": "1.2.6",
|
|
"@vitest/coverage-v8": "4.1.5",
|
|
"cross-env": "10.1.0",
|
|
"eslint": "8.57.1",
|
|
"eslint-config-airbnb": "19.0.4",
|
|
"eslint-config-airbnb-typescript": "18.0.0",
|
|
"eslint-config-prettier": "10.1.8",
|
|
"eslint-plugin-i18next": "6.1.4",
|
|
"eslint-plugin-import": "2.32.0",
|
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
"eslint-plugin-prettier": "5.5.5",
|
|
"eslint-plugin-react": "7.37.5",
|
|
"eslint-plugin-react-hooks": "7.1.1",
|
|
"eslint-plugin-unused-imports": "4.4.1",
|
|
"husky": "9.1.7",
|
|
"jsdom": "29.1.1",
|
|
"lint-staged": "16.4.0",
|
|
"msw": "2.14.2",
|
|
"postcss-prefix-selector": "2.1.1",
|
|
"prettier": "3.8.3",
|
|
"tailwindcss": "4.2.4",
|
|
"typescript": "6.0.3",
|
|
"vite-plugin-svgr": "5.2.0",
|
|
"vite-tsconfig-paths": "6.1.1",
|
|
"vitest": "4.1.5"
|
|
},
|
|
"packageManager": "npm@10.5.0",
|
|
"volta": {
|
|
"node": "22.12.0"
|
|
},
|
|
"msw": {
|
|
"workerDirectory": [
|
|
"public"
|
|
]
|
|
},
|
|
"overrides": {
|
|
"dompurify": "3.3.2",
|
|
"eslint-config-airbnb": {
|
|
"eslint-plugin-react-hooks": "$eslint-plugin-react-hooks"
|
|
}
|
|
},
|
|
"main": "./dist/index.cjs",
|
|
"module": "./dist/index.js",
|
|
"types": "./dist/index.d.ts",
|
|
"files": [
|
|
"dist"
|
|
],
|
|
"exports": {
|
|
".": {
|
|
"types": "./dist/index.d.ts",
|
|
"import": "./dist/index.js",
|
|
"require": "./dist/index.cjs"
|
|
},
|
|
"./browser": {
|
|
"types": "./dist/components/browser/index.d.ts",
|
|
"import": "./dist/components/browser/index.js",
|
|
"require": "./dist/components/browser/index.cjs"
|
|
},
|
|
"./conversation": {
|
|
"types": "./dist/components/conversation/index.d.ts",
|
|
"import": "./dist/components/conversation/index.js",
|
|
"require": "./dist/components/conversation/index.cjs"
|
|
},
|
|
"./files": {
|
|
"types": "./dist/components/files/index.d.ts",
|
|
"import": "./dist/components/files/index.js",
|
|
"require": "./dist/components/files/index.cjs"
|
|
},
|
|
"./settings": {
|
|
"types": "./dist/components/settings/index.d.ts",
|
|
"import": "./dist/components/settings/index.js",
|
|
"require": "./dist/components/settings/index.cjs"
|
|
},
|
|
"./sidebar": {
|
|
"types": "./dist/components/sidebar/index.d.ts",
|
|
"import": "./dist/components/sidebar/index.js",
|
|
"require": "./dist/components/sidebar/index.cjs"
|
|
},
|
|
"./terminal": {
|
|
"types": "./dist/components/terminal/index.d.ts",
|
|
"import": "./dist/components/terminal/index.js",
|
|
"require": "./dist/components/terminal/index.cjs"
|
|
},
|
|
"./i18n": {
|
|
"types": "./dist/i18n/index.d.ts",
|
|
"import": "./dist/i18n/index.js",
|
|
"require": "./dist/i18n/index.cjs"
|
|
},
|
|
"./package.json": "./package.json"
|
|
},
|
|
"peerDependencies": {
|
|
"react": "19.2.5",
|
|
"react-dom": "19.2.5",
|
|
"react-router": "7.14.2"
|
|
}
|
|
}
|