Merge main into openhands/fix-saas-page-title to resolve conflicts

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
openhands 2025-12-19 21:08:17 +00:00
commit 0d9293fb6b
73 changed files with 321 additions and 413 deletions

12
.github/CODEOWNERS vendored
View File

@ -1,12 +1,8 @@
# CODEOWNERS file for OpenHands repository
# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Frontend code owners
/frontend/ @amanape
/openhands-ui/ @amanape
# Evaluation code owners
/frontend/ @amanape @hieptl
/openhands-ui/ @amanape @hieptl
/openhands/ @tofarr @malhotra5 @hieptl
/enterprise/ @chuckbutkus @tofarr @malhotra5
/evaluation/ @xingyaoww @neubig
# Documentation code owners
/docs/ @mamoodi

View File

@ -31,9 +31,8 @@ RUN pip install alembic psycopg2-binary cloud-sql-python-connector pg8000 gsprea
"pillow>=11.3.0"
WORKDIR /app
COPY enterprise .
COPY --chown=openhands:openhands --chmod=770 enterprise .
RUN chown -R openhands:openhands /app && chmod -R 770 /app
USER openhands
# Command will be overridden by Kubernetes deployment template

View File

@ -116,7 +116,7 @@ lines.append('POSTHOG_CLIENT_KEY=test')
lines.append('ENABLE_PROACTIVE_CONVERSATION_STARTERS=true')
lines.append('MAX_CONCURRENT_CONVERSATIONS=10')
lines.append('LITE_LLM_API_URL=https://llm-proxy.eval.all-hands.dev')
lines.append('LITELLM_DEFAULT_MODEL=litellm_proxy/claude-sonnet-4-20250514')
lines.append('LITELLM_DEFAULT_MODEL=litellm_proxy/claude-opus-4-5-20251101')
lines.append(f'LITE_LLM_API_KEY={lite_llm_api_key}')
lines.append('LOCAL_DEPLOYMENT=true')
lines.append('DB_HOST=localhost')

View File

@ -25,6 +25,7 @@ USER_SETTINGS_VERSION_TO_MODEL = {
2: 'claude-3-7-sonnet-20250219',
3: 'claude-sonnet-4-20250514',
4: 'claude-sonnet-4-20250514',
5: 'claude-opus-4-5-20251101',
}
LITELLM_DEFAULT_MODEL = os.getenv('LITELLM_DEFAULT_MODEL')

View File

@ -5,7 +5,7 @@ import { MemoryRouter } from "react-router";
import { AgentStatus } from "#/components/features/controls/agent-status";
import { AgentState } from "#/types/agent-state";
import { useAgentState } from "#/hooks/use-agent-state";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
vi.mock("#/hooks/use-agent-state");

View File

@ -12,7 +12,7 @@ import GitService from "#/api/git-service/git-service.api";
import { GitRepository } from "#/types/git";
import { RepositoryMicroagent } from "#/types/microagent-management";
import { Conversation } from "#/api/open-hands.types";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
// Mock hooks
const mockUseUserProviders = vi.fn();

View File

@ -6,7 +6,7 @@ import { InteractiveChatBox } from "#/components/features/chat/interactive-chat-
import { renderWithProviders } from "../../test-utils";
import { AgentState } from "#/types/agent-state";
import { useAgentState } from "#/hooks/use-agent-state";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
vi.mock("#/hooks/use-agent-state", () => ({
useAgentState: vi.fn(),

View File

@ -1,7 +1,7 @@
import { act, screen } from "@testing-library/react";
import { renderWithProviders } from "test-utils";
import { vi, describe, afterEach, it, expect } from "vitest";
import { Command, useCommandStore } from "#/state/command-store";
import { Command, useCommandStore } from "#/stores/command-store";
import Terminal from "#/components/features/terminal/terminal";
const renderTerminal = (commands: Command[] = []) => {

View File

@ -12,7 +12,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { http, HttpResponse } from "msw";
import { useOptimisticUserMessageStore } from "#/stores/optimistic-user-message-store";
import { useBrowserStore } from "#/stores/browser-store";
import { useCommandStore } from "#/state/command-store";
import { useCommandStore } from "#/stores/command-store";
import {
createMockMessageEvent,
createMockUserMessageEvent,
@ -453,18 +453,10 @@ describe("Conversation WebSocket Handler", () => {
// Set up MSW to mock both the HTTP API and WebSocket connection
mswServer.use(
http.get("/api/v1/events/count", ({ request }) => {
const url = new URL(request.url);
const conversationIdParam = url.searchParams.get(
"conversation_id__eq",
);
if (conversationIdParam === conversationId) {
return HttpResponse.json(expectedEventCount);
}
return HttpResponse.json(0);
}),
http.get(
`http://localhost:3000/api/conversations/${conversationId}/events/count`,
() => HttpResponse.json(expectedEventCount),
),
wsLink.addEventListener("connection", ({ client, server }) => {
server.connect();
// Send all history events
@ -520,18 +512,10 @@ describe("Conversation WebSocket Handler", () => {
// Set up MSW to mock both the HTTP API and WebSocket connection
mswServer.use(
http.get("/api/v1/events/count", ({ request }) => {
const url = new URL(request.url);
const conversationIdParam = url.searchParams.get(
"conversation_id__eq",
);
if (conversationIdParam === conversationId) {
return HttpResponse.json(0);
}
return HttpResponse.json(0);
}),
http.get(
`http://localhost:3000/api/conversations/${conversationId}/events/count`,
() => HttpResponse.json(0),
),
wsLink.addEventListener("connection", ({ server }) => {
server.connect();
// No events sent for empty history
@ -577,18 +561,10 @@ describe("Conversation WebSocket Handler", () => {
// Set up MSW to mock both the HTTP API and WebSocket connection
mswServer.use(
http.get("/api/v1/events/count", ({ request }) => {
const url = new URL(request.url);
const conversationIdParam = url.searchParams.get(
"conversation_id__eq",
);
if (conversationIdParam === conversationId) {
return HttpResponse.json(expectedEventCount);
}
return HttpResponse.json(0);
}),
http.get(
`http://localhost:3000/api/conversations/${conversationId}/events/count`,
() => HttpResponse.json(expectedEventCount),
),
wsLink.addEventListener("connection", ({ client, server }) => {
server.connect();
// Send all history events

View File

@ -1,7 +1,7 @@
/* eslint-disable max-classes-per-file */
import { beforeAll, describe, expect, it, vi, afterEach } from "vitest";
import { useTerminal } from "#/hooks/use-terminal";
import { Command, useCommandStore } from "#/state/command-store";
import { Command, useCommandStore } from "#/stores/command-store";
import { renderWithProviders } from "../../test-utils";
// Mock the WsClient context

View File

@ -72,7 +72,7 @@ describe("Content", () => {
await waitFor(() => {
expect(provider).toHaveValue("OpenHands");
expect(model).toHaveValue("claude-sonnet-4-20250514");
expect(model).toHaveValue("claude-opus-4-5-20251101");
expect(apiKey).toHaveValue("");
expect(apiKey).toHaveProperty("placeholder", "");
@ -190,7 +190,7 @@ describe("Content", () => {
const agent = screen.getByTestId("agent-input");
const condensor = screen.getByTestId("enable-memory-condenser-switch");
expect(model).toHaveValue("openhands/claude-sonnet-4-20250514");
expect(model).toHaveValue("openhands/claude-opus-4-5-20251101");
expect(baseUrl).toHaveValue("");
expect(apiKey).toHaveValue("");
expect(apiKey).toHaveProperty("placeholder", "");

View File

@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { handleStatusMessage } from "#/services/actions";
import { StatusMessage } from "#/types/message";
import { queryClient } from "#/query-client-config";
import { useStatusStore } from "#/state/status-store";
import { useStatusStore } from "#/stores/status-store";
import { trackError } from "#/utils/error-handler";
// Mock dependencies
@ -12,7 +12,7 @@ vi.mock("#/query-client-config", () => ({
},
}));
vi.mock("#/state/status-store", () => ({
vi.mock("#/stores/status-store", () => ({
useStatusStore: {
getState: vi.fn(() => ({
setCurStatusMessage: vi.fn(),

View File

@ -1,7 +1,7 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import ActionType from "#/types/action-type";
import { ActionMessage } from "#/types/message";
import { useCommandStore } from "#/state/command-store";
import { useCommandStore } from "#/stores/command-store";
const mockDispatch = vi.fn();
const mockAppendInput = vi.fn();

View File

@ -11,8 +11,8 @@
"@heroui/react": "2.8.6",
"@microlink/react-json-view": "^1.26.2",
"@monaco-editor/react": "^4.7.0-rc.0",
"@react-router/node": "^7.10.1",
"@react-router/serve": "^7.10.1",
"@react-router/node": "^7.11.0",
"@react-router/serve": "^7.11.0",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.12",
"@uidotdev/usehooks": "^2.4.1",
@ -28,16 +28,16 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"isbot": "^5.1.32",
"lucide-react": "^0.561.0",
"lucide-react": "^0.562.0",
"monaco-editor": "^0.55.1",
"posthog-js": "^1.309.0",
"posthog-js": "^1.309.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hot-toast": "^2.6.0",
"react-i18next": "^16.5.0",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router": "^7.10.1",
"react-router": "^7.11.0",
"react-syntax-highlighter": "^16.1.0",
"remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.1",
@ -51,7 +51,7 @@
"devDependencies": {
"@mswjs/socket.io-binding": "^0.2.0",
"@playwright/test": "^1.57.0",
"@react-router/dev": "^7.10.1",
"@react-router/dev": "^7.11.0",
"@tailwindcss/typography": "^0.5.19",
"@tanstack/eslint-plugin-query": "^5.91.0",
"@testing-library/dom": "^10.4.1",
@ -85,7 +85,7 @@
"tailwindcss": "^4.1.8",
"typescript": "^5.9.3",
"vite-plugin-svgr": "^4.5.0",
"vite-tsconfig-paths": "^6.0.2",
"vite-tsconfig-paths": "^6.0.3",
"vitest": "^4.0.14"
},
"engines": {
@ -93,9 +93,9 @@
}
},
"node_modules/@acemir/cssom": {
"version": "0.9.28",
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.28.tgz",
"integrity": "sha512-LuS6IVEivI75vKN8S04qRD+YySP0RmU/cV8UNukhQZvprxF+76Z43TNo/a08eCodaGhT1Us8etqS1ZRY9/Or0A==",
"version": "0.9.29",
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.29.tgz",
"integrity": "sha512-G90x0VW+9nW4dFajtjCoT+NM0scAfH9Mb08IcjgFHYbfiL/lU04dTF9JuVOi3/OH+DJCQdcIseSXkdCB9Ky6JA==",
"dev": true,
"license": "MIT"
},
@ -3195,7 +3195,6 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.8.1.tgz",
"integrity": "sha512-jfzBtQIk9auRi/biO+G/gumK5KxqsD5wOr7XpYMROE/I3pazjP4zIziinp21iQuIQJMXrDvwt9Af3njgOGwtew==",
"license": "MIT",
"dependencies": {
"cross-spawn": "^7.0.6"
}
@ -3873,11 +3872,10 @@
}
},
"node_modules/@react-router/dev": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.10.1.tgz",
"integrity": "sha512-kap9O8rTN6b3vxjd+0SGjhm5vqiAZHMmOX1Hc7Y4KXRVVdusn+0+hxs44cDSfbW6Z6fCLw6GXXe0Kr+DJIRezw==",
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.11.0.tgz",
"integrity": "sha512-g1ou5Zw3r4mCU0L+EXH4vRtAiyt8qz1JOvL1k+PW4rZ4+71h5nBy/fLgD7cg5BnzQZmjRO1PzCgpF5BIrlKYxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.27.7",
"@babel/generator": "^7.27.5",
@ -3886,7 +3884,7 @@
"@babel/preset-typescript": "^7.27.1",
"@babel/traverse": "^7.27.7",
"@babel/types": "^7.27.7",
"@react-router/node": "7.10.1",
"@react-router/node": "7.11.0",
"@remix-run/node-fetch-server": "^0.9.0",
"arg": "^5.0.1",
"babel-dead-code-elimination": "^1.0.6",
@ -3915,9 +3913,10 @@
"node": ">=20.0.0"
},
"peerDependencies": {
"@react-router/serve": "^7.10.1",
"@vitejs/plugin-rsc": "*",
"react-router": "^7.10.1",
"@react-router/serve": "^7.11.0",
"@vitejs/plugin-rsc": "~0.5.7",
"react-router": "^7.11.0",
"react-server-dom-webpack": "^19.2.3",
"typescript": "^5.1.0",
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0",
"wrangler": "^3.28.2 || ^4.0.0"
@ -3929,6 +3928,9 @@
"@vitejs/plugin-rsc": {
"optional": true
},
"react-server-dom-webpack": {
"optional": true
},
"typescript": {
"optional": true
},
@ -3937,33 +3939,10 @@
}
}
},
"node_modules/@react-router/express": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.10.1.tgz",
"integrity": "sha512-O7xjg6wWHfrsnPyVWgQG+tCamIE09SqLqtHwa1tAFzKPjcDpCw4S4+/OkJvNXLtBL60H3VhZ1r2OQgXBgGOMpw==",
"license": "MIT",
"dependencies": {
"@react-router/node": "7.10.1"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"express": "^4.17.1 || ^5",
"react-router": "7.10.1",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@react-router/node": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@react-router/node/-/node-7.10.1.tgz",
"integrity": "sha512-RLmjlR1zQu+ve8ibI0lu91pJrXGcmfkvsrQl7z/eTc5V5FZgl0OvQVWL5JDWBlBZyzdLMQQekUOX5WcPhCP1FQ==",
"license": "MIT",
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@react-router/node/-/node-7.11.0.tgz",
"integrity": "sha512-11ha8EW+F7wTMmPz2pdi11LJxz2irtuksiCpunpZjtpPmYU37S+GGihG8vFeTa2xFPNunEaHNlfzKyzeYm570Q==",
"dependencies": {
"@mjackson/node-fetch-server": "^0.2.0"
},
@ -3971,7 +3950,7 @@
"node": ">=20.0.0"
},
"peerDependencies": {
"react-router": "7.10.1",
"react-router": "7.11.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
@ -3981,18 +3960,17 @@
}
},
"node_modules/@react-router/serve": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.10.1.tgz",
"integrity": "sha512-qYco7sFpbRgoKJKsCgJmFBQwaLVsLv255K8vbPodnXe13YBEzV/ugIqRCYVz2hghvlPiEKgaHh2On0s/5npn6w==",
"license": "MIT",
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.11.0.tgz",
"integrity": "sha512-U5Ht9PmUYF4Ti1ssaWlddLY4ZCbXBtHDGFU/u1h3VsHqleSdHsFuGAFrr/ZEuqTuEWp1CLqn2npEDAmlV9IUKQ==",
"dependencies": {
"@mjackson/node-fetch-server": "^0.2.0",
"@react-router/express": "7.10.1",
"@react-router/node": "7.10.1",
"compression": "^1.7.4",
"@react-router/express": "7.11.0",
"@react-router/node": "7.11.0",
"compression": "^1.8.1",
"express": "^4.19.2",
"get-port": "5.1.1",
"morgan": "^1.10.0",
"morgan": "^1.10.1",
"source-map-support": "^0.5.21"
},
"bin": {
@ -4002,7 +3980,28 @@
"node": ">=20.0.0"
},
"peerDependencies": {
"react-router": "7.10.1"
"react-router": "7.11.0"
}
},
"node_modules/@react-router/serve/node_modules/@react-router/express": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.11.0.tgz",
"integrity": "sha512-o5DeO9tqUrZcUWAgmPGgK4I/S6iFpqnj/e20xMGA04trk+90b9KAx9eqmRMgHERubVKANTM9gTDPduobQjeH1A==",
"dependencies": {
"@react-router/node": "7.11.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"express": "^4.17.1 || ^5",
"react-router": "7.11.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@react-stately/calendar": {
@ -6401,7 +6400,6 @@
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
@ -6414,7 +6412,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -6555,8 +6552,7 @@
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
"license": "MIT"
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/array-includes": {
"version": "3.1.9",
@ -6846,9 +6842,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.9.5",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.5.tgz",
"integrity": "sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==",
"version": "2.9.6",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz",
"integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@ -6887,7 +6883,6 @@
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
"integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"content-type": "~1.0.5",
@ -6911,7 +6906,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -6919,8 +6913,7 @@
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/brace-expansion": {
"version": "2.0.2",
@ -7486,7 +7479,6 @@
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
@ -7498,7 +7490,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -7514,7 +7505,6 @@
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -7522,8 +7512,7 @@
"node_modules/cookie-signature": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
"license": "MIT"
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
},
"node_modules/core-js": {
"version": "3.47.0",
@ -7867,7 +7856,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@ -7985,9 +7973,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.266",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz",
"integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==",
"version": "1.5.267",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
"integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
"dev": true,
"license": "ISC"
},
@ -8002,7 +7990,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -8355,8 +8342,7 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
@ -9030,7 +9016,6 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -9069,7 +9054,6 @@
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
"integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@ -9115,7 +9099,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -9123,8 +9106,7 @@
"node_modules/express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/exsolve": {
"version": "1.0.8",
@ -9256,7 +9238,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
"integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
@ -9274,7 +9255,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -9282,8 +9262,7 @@
"node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/find-up": {
"version": "5.0.0",
@ -9396,7 +9375,6 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -9432,7 +9410,6 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -9997,7 +9974,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
@ -10075,7 +10051,6 @@
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4"
},
@ -10110,7 +10085,6 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@ -10228,7 +10202,6 @@
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
@ -11462,10 +11435,9 @@
}
},
"node_modules/lucide-react": {
"version": "0.561.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz",
"integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==",
"license": "ISC",
"version": "0.562.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz",
"integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@ -11855,7 +11827,6 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -11864,7 +11835,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@ -11883,7 +11853,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -12469,7 +12438,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
@ -13001,7 +12969,6 @@
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
@ -13206,7 +13173,6 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -13250,8 +13216,7 @@
"node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"license": "MIT"
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
},
"node_modules/path-type": {
"version": "4.0.0",
@ -13409,7 +13374,6 @@
"version": "1.309.1",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.309.1.tgz",
"integrity": "sha512-JUJcQhYzNNKO0cgnSbowCsVi2RTu75XGZ2EmnTQti4tMGRCTOv/HCnZasdFniBGZ0rLugQkaScYca/84Ta2u5Q==",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"@posthog/core": "1.8.1",
"core-js": "^3.38.1",
@ -13555,7 +13519,6 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
@ -13584,7 +13547,6 @@
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
@ -13620,7 +13582,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -13629,7 +13590,6 @@
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
"integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
@ -13720,7 +13680,6 @@
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.0.tgz",
"integrity": "sha512-IMpPTyCTKxEj8klCrLKUTIUa8uYTd851+jcu2fJuUB9Agkk9Qq8asw4omyeHVnOXHrLgQJGTm5zTvn8HpaPiqw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.27.6",
"html-parse-stringify": "^3.0.1",
@ -13802,10 +13761,9 @@
}
},
"node_modules/react-router": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.10.1.tgz",
"integrity": "sha512-gHL89dRa3kwlUYtRQ+m8NmxGI6CgqN+k4XyGjwcFoQwwCWF6xXpOCUlDovkXClS0d0XJN/5q7kc5W3kiFEd0Yw==",
"license": "MIT",
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.11.0.tgz",
"integrity": "sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ==",
"dependencies": {
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0"
@ -14370,10 +14328,9 @@
}
},
"node_modules/send": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz",
"integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==",
"license": "MIT",
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
"integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@ -14381,13 +14338,13 @@
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"fresh": "~0.5.2",
"http-errors": "~2.0.1",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"on-finished": "~2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
"statuses": "~2.0.2"
},
"engines": {
"node": ">= 0.8.0"
@ -14397,7 +14354,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -14405,122 +14361,22 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/send/node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/send/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/serve-static": {
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"license": "MIT",
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
"integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.19.0"
"send": "~0.19.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/serve-static/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/serve-static/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/serve-static/node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/serve-static/node_modules/send": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/serve-static/node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/serve-static/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
@ -14579,8 +14435,7 @@
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
@ -15445,7 +15300,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
@ -15601,7 +15455,6 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@ -15819,7 +15672,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -15940,7 +15792,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
@ -16001,7 +15852,6 @@
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
"license": "MIT",
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@ -16117,9 +15967,9 @@
}
},
"node_modules/vite-tsconfig-paths": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-6.0.2.tgz",
"integrity": "sha512-c06LOO8fWB5RuEPpEIHXU9t7Dt4DoiPIljnKws9UygIaQo6PoFKawTftz5/QVcO+6pOs/HHWycnq4UrZkWVYnQ==",
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-6.0.3.tgz",
"integrity": "sha512-7bL7FPX/DSviaZGYUKowWF1AiDVWjMjxNbE8lyaVGDezkedWqfGhlnQ4BZXre0ZN5P4kAgIJfAlgFDVyjrCIyg==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",

View File

@ -10,8 +10,8 @@
"@heroui/react": "2.8.6",
"@microlink/react-json-view": "^1.26.2",
"@monaco-editor/react": "^4.7.0-rc.0",
"@react-router/node": "^7.10.1",
"@react-router/serve": "^7.10.1",
"@react-router/node": "^7.11.0",
"@react-router/serve": "^7.11.0",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/react-query": "^5.90.12",
"@uidotdev/usehooks": "^2.4.1",
@ -27,16 +27,16 @@
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"isbot": "^5.1.32",
"lucide-react": "^0.561.0",
"lucide-react": "^0.562.0",
"monaco-editor": "^0.55.1",
"posthog-js": "^1.309.0",
"posthog-js": "^1.309.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hot-toast": "^2.6.0",
"react-i18next": "^16.5.0",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router": "^7.10.1",
"react-router": "^7.11.0",
"react-syntax-highlighter": "^16.1.0",
"remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.1",
@ -82,7 +82,7 @@
"devDependencies": {
"@mswjs/socket.io-binding": "^0.2.0",
"@playwright/test": "^1.57.0",
"@react-router/dev": "^7.10.1",
"@react-router/dev": "^7.11.0",
"@tailwindcss/typography": "^0.5.19",
"@tanstack/eslint-plugin-query": "^5.91.0",
"@testing-library/dom": "^10.4.1",
@ -116,7 +116,7 @@
"tailwindcss": "^4.1.8",
"typescript": "^5.9.3",
"vite-plugin-svgr": "^4.5.0",
"vite-tsconfig-paths": "^6.0.2",
"vite-tsconfig-paths": "^6.0.3",
"vitest": "^4.0.14"
},
"packageManager": "npm@10.5.0",

View File

@ -5,7 +5,7 @@ import { I18nKey } from "#/i18n/declaration";
import CodeTagIcon from "#/icons/code-tag.svg?react";
import ChevronDownSmallIcon from "#/icons/chevron-down-small.svg?react";
import LessonPlanIcon from "#/icons/lesson-plan.svg?react";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { ChangeAgentContextMenu } from "./change-agent-context-menu";
import { cn } from "#/utils/utils";
import { USE_PLANNING_AGENT } from "#/utils/feature-flags";

View File

@ -38,7 +38,7 @@ import {
import { useUnifiedUploadFiles } from "#/hooks/mutation/use-unified-upload-files";
import { useConfig } from "#/hooks/query/use-config";
import { validateFiles } from "#/utils/file-validation";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import ConfirmationModeEnabled from "./confirmation-mode-enabled";
import {
isV0Event,

View File

@ -4,7 +4,7 @@ import { Suggestions } from "#/components/features/suggestions/suggestions";
import { I18nKey } from "#/i18n/declaration";
import BuildIt from "#/icons/build-it.svg?react";
import { SUGGESTIONS } from "#/utils/suggestions";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
interface ChatSuggestionsProps {
onSuggestionsClick: (value: string) => void;

View File

@ -3,7 +3,7 @@ import { DragOver } from "../drag-over";
import { UploadedFiles } from "../uploaded-files";
import { ChatInputRow } from "./chat-input-row";
import { ChatInputActions } from "./chat-input-actions";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { cn } from "#/utils/utils";
interface ChatInputContainerProps {

View File

@ -1,7 +1,7 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
interface ChatInputFieldProps {
chatInputRef: React.RefObject<HTMLDivElement | null>;

View File

@ -8,7 +8,7 @@ import { useChatSubmission } from "#/hooks/chat/use-chat-submission";
import { ChatInputGrip } from "./components/chat-input-grip";
import { ChatInputContainer } from "./components/chat-input-container";
import { HiddenFileInput } from "./components/hidden-file-input";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
export interface CustomChatInputProps {
disabled?: boolean;

View File

@ -5,7 +5,7 @@ import { CustomChatInput } from "./custom-chat-input";
import { AgentState } from "#/types/agent-state";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import { GitControlBar } from "./git-control-bar";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { useAgentState } from "#/hooks/use-agent-state";
import { processFiles, processImages } from "#/utils/file-processing";
import { useSubConversationTaskPolling } from "#/hooks/query/use-sub-conversation-task-polling";

View File

@ -1,6 +1,6 @@
import { UploadedFile } from "./uploaded-file";
import { UploadedImage } from "./uploaded-image";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
export function UploadedFiles() {
const {

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { useEffect } from "react";
import { useStatusStore } from "#/state/status-store";
import { useStatusStore } from "#/stores/status-store";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import { getStatusCode } from "#/utils/status";
import { ChatStopButton } from "../chat/chat-stop-button";
@ -9,7 +9,7 @@ import ClockIcon from "#/icons/u-clock-three.svg?react";
import { ChatResumeAgentButton } from "../chat/chat-play-button";
import { cn, isTaskPolling } from "#/utils/utils";
import { AgentLoading } from "./agent-loading";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import CircleErrorIcon from "#/icons/circle-error.svg?react";
import { useAgentState } from "#/hooks/use-agent-state";
import { useUnifiedWebSocketStatus } from "#/hooks/use-unified-websocket-status";

View File

@ -10,7 +10,7 @@ import {
getCreatePRPrompt,
getCreateNewBranchPrompt,
} from "#/utils/utils";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import ArrowUpIcon from "#/icons/u-arrow-up.svg?react";
import ArrowDownIcon from "#/icons/u-arrow-down.svg?react";

View File

@ -8,7 +8,7 @@ import PrStatusIcon from "#/icons/pr-status.svg?react";
import DocumentIcon from "#/icons/document.svg?react";
import WaterIcon from "#/icons/u-water.svg?react";
import { I18nKey } from "#/i18n/declaration";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { REPO_SUGGESTIONS } from "#/utils/suggestions/repo-suggestions";
import { CONTEXT_MENU_ICON_TEXT_CLASSNAME } from "#/utils/constants";

View File

@ -1,7 +1,7 @@
import { useWindowSize } from "@uidotdev/usehooks";
import { MobileLayout } from "./mobile-layout";
import { DesktopLayout } from "./desktop-layout";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
export function ConversationMain() {
const { width } = useWindowSize();

View File

@ -7,7 +7,7 @@ import { TabContainer } from "./tab-container";
import { TabContentArea } from "./tab-content-area";
import { ConversationTabTitle } from "../conversation-tab-title";
import Terminal from "#/components/features/terminal/terminal";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { useConversationId } from "#/hooks/use-conversation-id";
// Lazy load all tab components

View File

@ -16,7 +16,7 @@ import { VSCodeTooltipContent } from "./vscode-tooltip-content";
import {
useConversationStore,
type ConversationTab,
} from "#/state/conversation-store";
} from "#/stores/conversation-store";
import { ConversationTabsContextMenu } from "./conversation-tabs-context-menu";
import { USE_PLANNING_AGENT } from "#/utils/feature-flags";
import { useConversationId } from "#/hooks/use-conversation-id";

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { GitRepository } from "#/types/git";
interface MicroagentManagementAddMicroagentButtonProps {

View File

@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
import { MicroagentManagementSidebar } from "./microagent-management-sidebar";
import { MicroagentManagementMain } from "./microagent-management-main";
import { MicroagentManagementUpsertMicroagentModal } from "./microagent-management-upsert-microagent-modal";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { useCreateConversationAndSubscribeMultiple } from "#/hooks/use-create-conversation-and-subscribe-multiple";
import {
LearnThisRepoFormData,

View File

@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { BrandButton } from "../settings/brand-button";
import { Loader } from "#/components/shared/loader";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
export function MicroagentManagementConversationStopped() {
const { t } = useTranslation();

View File

@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { BrandButton } from "../settings/brand-button";
import { Loader } from "#/components/shared/loader";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
export function MicroagentManagementError() {
const { t } = useTranslation();

View File

@ -5,7 +5,7 @@ import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop";
import { ModalBody } from "#/components/shared/modals/modal-body";
import { BrandButton } from "../settings/brand-button";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import XIcon from "#/icons/x.svg?react";
import { cn, getRepoMdCreatePrompt } from "#/utils/utils";
import { LearnThisRepoFormData } from "#/types/microagent-management";

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { GitRepository } from "#/types/git";
interface MicroagentManagementLearnThisRepoProps {

View File

@ -1,4 +1,4 @@
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { MicroagentManagementDefault } from "./microagent-management-default";
import { MicroagentManagementOpeningPr } from "./microagent-management-opening-pr";
import { MicroagentManagementReviewPr } from "./microagent-management-review-pr";

View File

@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { RepositoryMicroagent } from "#/types/microagent-management";
import { Conversation } from "#/api/open-hands.types";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { cn } from "#/utils/utils";
import { GitRepository } from "#/types/git";

View File

@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { BrandButton } from "../settings/brand-button";
import { Loader } from "#/components/shared/loader";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
export function MicroagentManagementOpeningPr() {
const { t } = useTranslation();

View File

@ -6,7 +6,7 @@ import { MicroagentManagementLearnThisRepo } from "./microagent-management-learn
import { useRepositoryMicroagents } from "#/hooks/query/use-repository-microagents";
import { useMicroagentManagementConversations } from "#/hooks/query/use-microagent-management-conversations";
import { GitRepository } from "#/types/git";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { cn } from "#/utils/utils";
import { I18nKey } from "#/i18n/declaration";

View File

@ -3,7 +3,7 @@ import { I18nKey } from "#/i18n/declaration";
import { BrandButton } from "../settings/brand-button";
import { getProviderName, constructPullRequestUrl } from "#/utils/utils";
import { Provider } from "#/types/settings";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
export function MicroagentManagementReviewPr() {
const { t } = useTranslation();

View File

@ -2,7 +2,7 @@ import { Tab, Tabs } from "@heroui/react";
import { useTranslation } from "react-i18next";
import { MicroagentManagementRepositories } from "./microagent-management-repositories";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
interface MicroagentManagementSidebarTabsProps {
isSearchLoading?: boolean;

View File

@ -6,7 +6,7 @@ import { MicroagentManagementSidebarTabs } from "./microagent-management-sidebar
import { useGitRepositories } from "#/hooks/query/use-git-repositories";
import { useSearchRepositories } from "#/hooks/query/use-search-repositories";
import { GitProviderDropdown } from "#/components/features/home/git-provider-dropdown";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { GitRepository } from "#/types/git";
import { Provider } from "#/types/settings";
import {

View File

@ -5,7 +5,7 @@ import { ModalBackdrop } from "#/components/shared/modals/modal-backdrop";
import { ModalBody } from "#/components/shared/modals/modal-body";
import { BrandButton } from "../settings/brand-button";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import XIcon from "#/icons/x.svg?react";
import { cn, extractRepositoryInfo } from "#/utils/utils";
import { BadgeInput } from "#/components/shared/inputs/badge-input";

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { Spinner } from "@heroui/react";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { useRepositoryMicroagentContent } from "#/hooks/query/use-repository-microagent-content";
import { I18nKey } from "#/i18n/declaration";
import { extractRepositoryInfo } from "#/utils/utils";

View File

@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
import { BrandButton } from "../settings/brand-button";
import { getProviderName, constructMicroagentUrl } from "#/utils/utils";
import { I18nKey } from "#/i18n/declaration";
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
export function MicroagentManagementViewMicroagentHeader() {
const { t } = useTranslation();

View File

@ -1,4 +1,4 @@
import { useMicroagentManagementStore } from "#/state/microagent-management-store";
import { useMicroagentManagementStore } from "#/stores/microagent-management-store";
import { MicroagentManagementViewMicroagentHeader } from "./microagent-management-view-microagent-header";
import { MicroagentManagementViewMicroagentContent } from "./microagent-management-view-microagent-content";

View File

@ -14,7 +14,7 @@ import { useEventStore } from "#/stores/use-event-store";
import { useErrorMessageStore } from "#/stores/error-message-store";
import { useOptimisticUserMessageStore } from "#/stores/optimistic-user-message-store";
import { useV1ConversationStateStore } from "#/stores/v1-conversation-state-store";
import { useCommandStore } from "#/state/command-store";
import { useCommandStore } from "#/stores/command-store";
import { useBrowserStore } from "#/stores/browser-store";
import {
isV1Event,
@ -40,7 +40,7 @@ import type {
V1SendMessageRequest,
} from "#/api/conversation-service/v1-conversation-service.types";
import EventService from "#/api/event-service/event-service.api";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { isBudgetOrCreditError } from "#/utils/error-handler";
import { useTracking } from "#/hooks/use-tracking";
import { useReadConversationFile } from "#/hooks/mutation/use-read-conversation-file";

View File

@ -4,7 +4,7 @@ import {
clearEmptyContent,
getTextContent,
} from "#/components/features/chat/utils/chat-input.utils";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
/**
* Hook for managing chat input content logic

View File

@ -4,7 +4,7 @@ import { CHAT_INPUT } from "#/utils/constants";
import {
IMessageToSend,
useConversationStore,
} from "#/state/conversation-store";
} from "#/stores/conversation-store";
/**
* Hook for managing grip resize functionality

View File

@ -1,5 +1,5 @@
import { useCallback, useEffect, RefObject, useRef } from "react";
import { IMessageToSend } from "#/state/conversation-store";
import { IMessageToSend } from "#/stores/conversation-store";
import { EPS } from "#/utils/constants";
import { getStyleHeightPx, setStyleHeightPx } from "#/utils/utils";
import { useDragResize } from "./use-drag-resize";

View File

@ -1,7 +1,7 @@
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import { useCreateConversation } from "#/hooks/mutation/use-create-conversation";
import { displaySuccessToast } from "#/utils/custom-toast-handlers";

View File

@ -1,7 +1,7 @@
import { FitAddon } from "@xterm/addon-fit";
import { Terminal } from "@xterm/xterm";
import React from "react";
import { Command, useCommandStore } from "#/state/command-store";
import { Command, useCommandStore } from "#/stores/command-store";
import { parseTerminalOutput } from "#/utils/parse-terminal-output";
/*

View File

@ -436,6 +436,8 @@ export enum I18nKey {
BUTTON$CREATE = "BUTTON$CREATE",
BUTTON$DELETE = "BUTTON$DELETE",
BUTTON$COPY_TO_CLIPBOARD = "BUTTON$COPY_TO_CLIPBOARD",
BUTTON$HOME = "BUTTON$HOME",
BUTTON$OPEN_IN_NEW_TAB = "BUTTON$OPEN_IN_NEW_TAB",
BUTTON$REFRESH = "BUTTON$REFRESH",
ERROR$REQUIRED_FIELD = "ERROR$REQUIRED_FIELD",
PLANNER$EMPTY_MESSAGE = "PLANNER$EMPTY_MESSAGE",

View File

@ -6975,6 +6975,38 @@
"es": "Copiar al portapapeles",
"tr": "Panoya Kopyala"
},
"BUTTON$HOME": {
"en": "Home",
"ja": "ホーム",
"zh-CN": "主页",
"zh-TW": "首頁",
"ko-KR": "홈",
"no": "Hjem",
"it": "Home",
"pt": "Início",
"es": "Inicio",
"ar": "الرئيسية",
"fr": "Accueil",
"tr": "Ana Sayfa",
"de": "Startseite",
"uk": "Головна"
},
"BUTTON$OPEN_IN_NEW_TAB": {
"en": "Open in New Tab",
"ja": "新しいタブで開く",
"zh-CN": "在新标签页中打开",
"zh-TW": "在新分頁中開啟",
"ko-KR": "새 탭에서 열기",
"no": "Åpne i ny fane",
"it": "Apri in una nuova scheda",
"pt": "Abrir em nova aba",
"es": "Abrir en nueva pestaña",
"ar": "فتح في علامة تبويب جديدة",
"fr": "Ouvrir dans un nouvel onglet",
"tr": "Yeni Sekmede Aç",
"de": "In neuem Tab öffnen",
"uk": "Відкрити в новій вкладці"
},
"BUTTON$REFRESH": {
"en": "Refresh",
"ja": "更新",

View File

@ -49,9 +49,11 @@ export const SETTINGS_HANDLERS = [
"anthropic/claude-sonnet-4-20250514",
"anthropic/claude-sonnet-4-5-20250929",
"anthropic/claude-haiku-4-5-20251001",
"anthropic/claude-opus-4-5-20251101",
"openhands/claude-sonnet-4-20250514",
"openhands/claude-sonnet-4-5-20250929",
"openhands/claude-haiku-4-5-20251001",
"openhands/claude-opus-4-5-20251101",
"sambanova/Meta-Llama-3.1-8B-Instruct",
]),
),

View File

@ -3,8 +3,8 @@ import { useNavigate } from "react-router";
import { useTranslation } from "react-i18next";
import { useConversationId } from "#/hooks/use-conversation-id";
import { useCommandStore } from "#/state/command-store";
import { useConversationStore } from "#/state/conversation-store";
import { useCommandStore } from "#/stores/command-store";
import { useConversationStore } from "#/stores/conversation-store";
import { useAgentStore } from "#/stores/agent-store";
import { AgentState } from "#/types/agent-state";

View File

@ -2,7 +2,7 @@ import React from "react";
import { useTranslation } from "react-i18next";
import { I18nKey } from "#/i18n/declaration";
import LessonPlanIcon from "#/icons/lesson-plan.svg?react";
import { useConversationStore } from "#/state/conversation-store";
import { useConversationStore } from "#/stores/conversation-store";
import { useScrollToBottom } from "#/hooks/use-scroll-to-bottom";
import { MarkdownRenderer } from "#/components/features/markdown/markdown-renderer";
import { useHandlePlanClick } from "#/hooks/use-handle-plan-click";

View File

@ -65,6 +65,7 @@ function ServedApp() {
type="button"
onClick={() => window.open(fullUrl, "_blank")}
className="text-sm"
aria-label={t(I18nKey.BUTTON$OPEN_IN_NEW_TAB)}
>
<FaExternalLinkAlt className="w-4 h-4" />
</button>
@ -72,11 +73,17 @@ function ServedApp() {
type="button"
onClick={() => setRefreshKey((prev) => prev + 1)}
className="text-sm"
aria-label={t(I18nKey.BUTTON$REFRESH)}
>
<FaArrowRotateRight className="w-4 h-4" />
</button>
<button type="button" onClick={() => resetUrl()} className="text-sm">
<button
type="button"
onClick={() => resetUrl()}
className="text-sm"
aria-label={t(I18nKey.BUTTON$HOME)}
>
<FaHome className="w-4 h-4" />
</button>
<div className="w-full flex">

View File

@ -1,6 +1,6 @@
import { trackError } from "#/utils/error-handler";
import useMetricsStore from "#/stores/metrics-store";
import { useStatusStore } from "#/state/status-store";
import { useStatusStore } from "#/stores/status-store";
import ActionType from "#/types/action-type";
import {
ActionMessage,
@ -8,7 +8,7 @@ import {
StatusMessage,
} from "#/types/message";
import { handleObservationMessage } from "./observations";
import { useCommandStore } from "#/state/command-store";
import { useCommandStore } from "#/stores/command-store";
import { queryClient } from "#/query-client-config";
import {
ActionSecurityRisk,

View File

@ -1,5 +1,5 @@
import { ObservationMessage } from "#/types/message";
import { useCommandStore } from "#/state/command-store";
import { useCommandStore } from "#/stores/command-store";
import ObservationType from "#/types/observation-type";
import { useBrowserStore } from "#/stores/browser-store";
import { useAgentStore } from "#/stores/agent-store";

View File

@ -3,7 +3,7 @@ import { Settings } from "#/types/settings";
export const LATEST_SETTINGS_VERSION = 5;
export const DEFAULT_SETTINGS: Settings = {
llm_model: "openhands/claude-sonnet-4-20250514",
llm_model: "openhands/claude-opus-4-5-20251101",
llm_base_url: "",
agent: "CodeActAgent",
language: "en",

View File

@ -19,6 +19,7 @@ export const VERIFIED_MODELS = [
"claude-haiku-4-5-20251001",
"claude-opus-4-20250514",
"claude-opus-4-1-20250805",
"claude-opus-4-5-20251101",
"gemini-2.5-pro",
"o4-mini",
"deepseek-chat",
@ -80,6 +81,7 @@ export const VERIFIED_OPENHANDS_MODELS = [
"gpt-5-mini-2025-08-07",
"claude-opus-4-20250514",
"claude-opus-4-1-20250805",
"claude-opus-4-5-20251101",
"gemini-2.5-pro",
"o3",
"o4-mini",
@ -91,4 +93,4 @@ export const VERIFIED_OPENHANDS_MODELS = [
];
// Default model for OpenHands provider
export const DEFAULT_OPENHANDS_MODEL = "openhands/claude-sonnet-4-20250514";
export const DEFAULT_OPENHANDS_MODEL = "openhands/claude-opus-4-5-20251101";

View File

@ -44,6 +44,7 @@ from openhands.app_server.services.injector import InjectorState
from openhands.app_server.user.specifiy_user_context import ADMIN, USER_CONTEXT_ATTR
from openhands.app_server.user.user_context import UserContext
from openhands.app_server.utils.sql_utils import Base, UtcDateTime
from openhands.sdk.utils.paging import page_iterator
_logger = logging.getLogger(__name__)
WEBHOOK_CALLBACK_VARIABLE = 'OH_WEBHOOKS_0_BASE_URL'
@ -529,32 +530,26 @@ async def poll_agent_servers(api_url: str, api_key: str, sleep_interval: int):
get_event_callback_service(state) as event_callback_service,
get_httpx_client(state) as httpx_client,
):
page_id = None
matches = 0
while True:
page = await app_conversation_info_service.search_app_conversation_info(
page_id=page_id
async for app_conversation_info in page_iterator(
app_conversation_info_service.search_app_conversation_info
):
runtime = runtimes_by_sandbox_id.get(
app_conversation_info.sandbox_id
)
for app_conversation_info in page.items:
runtime = runtimes_by_sandbox_id.get(
app_conversation_info.sandbox_id
if runtime:
matches += 1
await refresh_conversation(
app_conversation_info_service=app_conversation_info_service,
event_service=event_service,
event_callback_service=event_callback_service,
app_conversation_info=app_conversation_info,
runtime=runtime,
httpx_client=httpx_client,
)
if runtime:
matches += 1
await refresh_conversation(
app_conversation_info_service=app_conversation_info_service,
event_service=event_service,
event_callback_service=event_callback_service,
app_conversation_info=app_conversation_info,
runtime=runtime,
httpx_client=httpx_client,
)
page_id = page.next_page_id
if page_id is None:
_logger.debug(
f'Matched {len(runtimes_by_sandbox_id)} Runtimes with {matches} Conversations.'
)
break
_logger.debug(
f'Matched {len(runtimes_by_sandbox_id)} Runtimes with {matches} Conversations.'
)
except Exception as exc:
_logger.exception(
@ -608,37 +603,29 @@ async def refresh_conversation(
event_url = (
f'{url}/api/conversations/{app_conversation_info.id.hex}/events/search'
)
page_id = None
while True:
async def fetch_events_page(page_id: str | None = None) -> EventPage:
"""Helper function to fetch a page of events from the agent server."""
params: dict[str, str] = {}
if page_id:
params['page_id'] = page_id # type: ignore[unreachable]
params['page_id'] = page_id
response = await httpx_client.get(
event_url,
params=params,
headers={'X-Session-API-Key': runtime['session_api_key']},
)
response.raise_for_status()
page = EventPage.model_validate(response.json())
return EventPage.model_validate(response.json())
to_process = []
for event in page.items:
existing = await event_service.get_event(event.id)
if existing is None:
await event_service.save_event(app_conversation_info.id, event)
to_process.append(event)
for event in to_process:
async for event in page_iterator(fetch_events_page):
existing = await event_service.get_event(event.id)
if existing is None:
await event_service.save_event(app_conversation_info.id, event)
await event_callback_service.execute_callbacks(
app_conversation_info.id, event
)
page_id = page.next_page_id
if page_id is None:
_logger.debug(
f'Finished Refreshing Conversation {app_conversation_info.id}'
)
break
_logger.debug(f'Finished Refreshing Conversation {app_conversation_info.id}')
except Exception as exc:
_logger.exception(f'Error Refreshing Conversation: {exc}', stack_info=True)

View File

@ -8,6 +8,7 @@ from openhands.app_server.sandbox.sandbox_models import (
)
from openhands.app_server.services.injector import Injector
from openhands.sdk.utils.models import DiscriminatedUnionMixin
from openhands.sdk.utils.paging import page_iterator
class SandboxService(ABC):
@ -83,24 +84,11 @@ class SandboxService(ABC):
if max_num_sandboxes <= 0:
raise ValueError('max_num_sandboxes must be greater than 0')
# Get all sandboxes (we'll search through all pages)
all_sandboxes = []
page_id = None
while True:
page = await self.search_sandboxes(page_id=page_id, limit=100)
all_sandboxes.extend(page.items)
if page.next_page_id is None:
break
page_id = page.next_page_id
# Filter to only running sandboxes
running_sandboxes = [
sandbox
for sandbox in all_sandboxes
if sandbox.status == SandboxStatus.RUNNING
]
# Get all running sandboxes (iterate through all pages)
running_sandboxes = []
async for sandbox in page_iterator(self.search_sandboxes, limit=100):
if sandbox.status == SandboxStatus.RUNNING:
running_sandboxes.append(sandbox)
# If we're within the limit, no cleanup needed
if len(running_sandboxes) <= max_num_sandboxes:

View File

@ -944,6 +944,23 @@ class AgentController:
return
else:
raise LLMContextWindowExceedError()
# Check if this is a tool call validation error that should be recoverable
elif (
isinstance(e, BadRequestError)
and 'tool call validation failed' in error_str
and (
'missing properties' in error_str
or 'missing required' in error_str
)
):
# Handle tool call validation errors from Groq as recoverable errors
self.event_stream.add_event(
ErrorObservation(
content=f'Tool call validation failed: {str(e)}. Please check the tool parameters and try again.',
),
EventSource.AGENT,
)
return
else:
raise e

View File

@ -50,7 +50,7 @@ class LLMConfig(BaseModel):
completion_kwargs: Custom kwargs to pass to litellm.completion.
"""
model: str = Field(default='claude-sonnet-4-20250514')
model: str = Field(default='claude-opus-4-5-20251101')
api_key: SecretStr | None = Field(default=None)
base_url: str | None = Field(default=None)
api_version: str | None = Field(default=None)

View File

@ -60,6 +60,7 @@ def get_supported_llm_models(config: OpenHandsConfig) -> list[str]:
'openhands/gpt-5-2025-08-07',
'openhands/gpt-5-mini-2025-08-07',
'openhands/claude-opus-4-20250514',
'openhands/claude-opus-4-5-20251101',
'openhands/gemini-2.5-pro',
'openhands/o3',
'openhands/o4-mini',

View File

@ -299,6 +299,55 @@ async def test_react_to_content_policy_violation(
await controller.close()
@pytest.mark.asyncio
async def test_tool_call_validation_error_handling(
mock_agent_with_stats,
test_event_stream,
):
"""Test that tool call validation errors from Groq are handled as recoverable errors."""
mock_agent, conversation_stats, llm_registry = mock_agent_with_stats
controller = AgentController(
agent=mock_agent,
event_stream=test_event_stream,
conversation_stats=conversation_stats,
iteration_delta=10,
sid='test',
confirmation_mode=False,
headless_mode=True,
)
controller.state.agent_state = AgentState.RUNNING
# Mock the agent.step method to raise a BadRequestError with tool validation failure
def mock_step(state):
raise BadRequestError(
message='litellm.BadRequestError: GroqException - {"error":{"message":"tool call validation failed: parameters for tool str_replace_editor did not match schema: errors: [missing properties: \'path\']","type":"invalid_request_error","code":"tool_use_failed"}}',
model='groq/llama3-8b-8192',
llm_provider='groq',
)
mock_agent.step = mock_step
# Call _step which should handle the tool validation error
await controller._step()
# Verify that the agent state is still RUNNING (not ERROR)
assert controller.state.agent_state == AgentState.RUNNING
# Verify that an ErrorObservation was added to the event stream
events = list(test_event_stream.get_events())
error_observations = [e for e in events if isinstance(e, ErrorObservation)]
assert len(error_observations) == 1
error_obs = error_observations[0]
assert 'tool call validation failed' in error_obs.content
assert 'missing properties' in error_obs.content
assert 'path' in error_obs.content
await controller.close()
@pytest.mark.asyncio
async def test_run_controller_with_fatal_error(
test_event_stream, mock_memory, mock_agent_with_stats

View File

@ -1 +0,0 @@
# Trigger E2E test run