Skip to content

Commit

Permalink
Merge branch 'main' into kevin
Browse files Browse the repository at this point in the history
  • Loading branch information
SmartManoj committed Jan 25, 2025
2 parents ae1f01f + e619929 commit a316d5b
Show file tree
Hide file tree
Showing 29 changed files with 131 additions and 171 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/openhands-resolver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ jobs:
run: |
python -m pip index versions openhands-ai > openhands_versions.txt
OPENHANDS_VERSION=$(head -n 1 openhands_versions.txt | awk '{print $2}' | tr -d '()')
echo -e "\nopenhands-ai==${OPENHANDS_VERSION}" >> requirements.txt
# Ensure requirements.txt ends with newline before appending
if [ -f requirements.txt ] && [ -s requirements.txt ]; then
sed -i -e '$a\' requirements.txt
fi
echo "openhands-ai==${OPENHANDS_VERSION}" >> requirements.txt
cat requirements.txt
- name: Cache pip dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ describe("Sidebar", () => {
const settingsModal = screen.getByTestId("ai-config-modal");

// Click the advanced options switch to show the API key input
const advancedOptionsSwitch = within(settingsModal).getByTestId("advanced-option-switch");
const advancedOptionsSwitch = within(settingsModal).getByTestId(
"advanced-option-switch",
);
await user.click(advancedOptionsSwitch);

const apiKeyInput = within(settingsModal).getByLabelText(/API\$KEY/i);
Expand Down
14 changes: 7 additions & 7 deletions frontend/__tests__/initial-query.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { describe, it, expect } from "vitest";
import store from "../src/store";
import {
setInitialQuery,
clearInitialQuery,
setInitialPrompt,
clearInitialPrompt,
} from "../src/state/initial-query-slice";

describe("Initial Query Behavior", () => {
it("should clear initial query when clearInitialQuery is dispatched", () => {
it("should clear initial query when clearInitialPrompt is dispatched", () => {
// Set up initial query in the store
store.dispatch(setInitialQuery("test query"));
expect(store.getState().initialQuery.initialQuery).toBe("test query");
store.dispatch(setInitialPrompt("test query"));
expect(store.getState().initialQuery.initialPrompt).toBe("test query");

// Clear the initial query
store.dispatch(clearInitialQuery());
store.dispatch(clearInitialPrompt());

// Verify initial query is cleared
expect(store.getState().initialQuery.initialQuery).toBeNull();
expect(store.getState().initialQuery.initialPrompt).toBeNull();
});
});
4 changes: 4 additions & 0 deletions frontend/src/api/open-hands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,14 @@ class OpenHands {
static async createConversation(
githubToken?: string,
selectedRepository?: string,
initialUserMsg?: string,
imageUrls?: string[],
): Promise<Conversation> {
const body = {
github_token: githubToken,
selected_repository: selectedRepository,
initial_user_msg: initialUserMsg,
image_urls: imageUrls,
};

const { data } = await openHands.post<Conversation>(
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/agent-status-map.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const AGENT_STATUS_MAP: {
},
[AgentState.AWAITING_USER_INPUT]: {
message: I18nKey.CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE,
indicator: IndicatorColor.ORANGE,
indicator: IndicatorColor.BLUE,
},
[AgentState.PAUSED]: {
message: I18nKey.CHAT_INTERFACE$AGENT_PAUSED_MESSAGE,
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/hooks/mutation/use-create-conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useNavigate } from "react-router";
import posthog from "posthog-js";
import { useDispatch, useSelector } from "react-redux";
import OpenHands from "#/api/open-hands";
import { setInitialQuery } from "#/state/initial-query-slice";
import { setInitialPrompt } from "#/state/initial-query-slice";
import { RootState } from "#/store";
import { useAuth } from "#/context/auth-context";

Expand All @@ -18,7 +18,7 @@ export const useCreateConversation = () => {
);

return useMutation({
mutationFn: (variables: { q?: string }) => {
mutationFn: async (variables: { q?: string }) => {
if (
!variables.q?.trim() &&
!selectedRepository &&
Expand All @@ -28,10 +28,13 @@ export const useCreateConversation = () => {
throw new Error("No query provided");
}

if (variables.q) dispatch(setInitialQuery(variables.q));
if (variables.q) dispatch(setInitialPrompt(variables.q));

return OpenHands.createConversation(
gitHubToken || undefined,
selectedRepository || undefined,
variables.q,
files,
);
},
onSuccess: async ({ conversation_id: conversationId }, { q }) => {
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/hooks/query/use-github-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useConfig } from "./use-config";
import OpenHands from "#/api/open-hands";

export const useGitHubUser = () => {
const { gitHubToken, setUserId } = useAuth();
const { gitHubToken, setUserId, logout } = useAuth();
const { data: config } = useConfig();

const user = useQuery({
Expand All @@ -29,5 +29,11 @@ export const useGitHubUser = () => {
}
}, [user.data]);

React.useEffect(() => {
if (user.isError) {
logout();
}
}, [user.isError]);

return user;
};
2 changes: 1 addition & 1 deletion frontend/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const handlers = [
{ id: 2, full_name: "octocat/earth" },
]),
),
http.get("https://api.github.com/user", () => {
http.get("/api/github/user", () => {
const user: GitHubUser = {
id: 1,
login: "octocat",
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/routes/_oh.app/event-handler.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React from "react";
import { useWSStatusChange } from "./hooks/use-ws-status-change";
import { useHandleWSEvents } from "./hooks/use-handle-ws-events";
import { useHandleRuntimeActive } from "./hooks/use-handle-runtime-active";

export function EventHandler({ children }: React.PropsWithChildren) {
useWSStatusChange();
useHandleWSEvents();
useHandleRuntimeActive();

Expand Down
68 changes: 0 additions & 68 deletions frontend/src/routes/_oh.app/hooks/use-ws-status-change.ts

This file was deleted.

21 changes: 19 additions & 2 deletions frontend/src/routes/_oh.app/route.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useDisclosure } from "@nextui-org/react";
import React from "react";
import { Outlet } from "react-router";
import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { FaServer } from "react-icons/fa";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
Expand All @@ -11,7 +11,7 @@ import {
useConversation,
} from "#/context/conversation-context";
import { Controls } from "#/components/features/controls/controls";
import { clearMessages } from "#/state/chat-slice";
import { clearMessages, addUserMessage } from "#/state/chat-slice";
import { clearTerminal } from "#/state/command-slice";
import { useEffectOnce } from "#/hooks/use-effect-once";
import CodeIcon from "#/icons/code.svg?react";
Expand All @@ -36,6 +36,8 @@ import { ServedAppLabel } from "#/components/layout/served-app-label";
import { TerminalStatusLabel } from "#/components/features/terminal/terminal-status-label";
import { useSettings } from "#/hooks/query/use-settings";
import { MULTI_CONVERSATION_UI } from "#/utils/feature-flags";
import { clearFiles, clearInitialPrompt } from "#/state/initial-query-slice";
import { RootState } from "#/store";

function AppContent() {
useConversationConfig();
Expand All @@ -46,6 +48,9 @@ function AppContent() {
const { data: conversation, isFetched } = useUserConversation(
conversationId || null,
);
const { initialPrompt, files } = useSelector(
(state: RootState) => state.initialQuery,
);
const dispatch = useDispatch();
const endSession = useEndSession();

Expand Down Expand Up @@ -74,6 +79,18 @@ function AppContent() {
dispatch(clearMessages());
dispatch(clearTerminal());
dispatch(clearJupyter());
if (conversationId && (initialPrompt || files.length > 0)) {
dispatch(
addUserMessage({
content: initialPrompt || "",
imageUrls: files || [],
timestamp: new Date().toISOString(),
pending: true,
}),
);
dispatch(clearInitialPrompt());
dispatch(clearFiles());
}
}, [conversationId]);

useEffectOnce(() => {
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/state/initial-query-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";

type SliceState = {
files: string[]; // base64 encoded images
initialQuery: string | null;
initialPrompt: string | null;
selectedRepository: string | null;
importedProjectZip: string | null; // base64 encoded zip
};

const initialState: SliceState = {
files: [],
initialQuery: null,
initialPrompt: null,
selectedRepository: null,
importedProjectZip: null,
};
Expand All @@ -27,11 +27,11 @@ export const selectedFilesSlice = createSlice({
clearFiles(state) {
state.files = [];
},
setInitialQuery(state, action: PayloadAction<string>) {
state.initialQuery = action.payload;
setInitialPrompt(state, action: PayloadAction<string>) {
state.initialPrompt = action.payload;
},
clearInitialQuery(state) {
state.initialQuery = null;
clearInitialPrompt(state) {
state.initialPrompt = null;
},
setSelectedRepository(state, action: PayloadAction<string | null>) {
state.selectedRepository = action.payload;
Expand All @@ -49,8 +49,8 @@ export const {
addFile,
removeFile,
clearFiles,
setInitialQuery,
clearInitialQuery,
setInitialPrompt,
clearInitialPrompt,
setSelectedRepository,
clearSelectedRepository,
setImportedProjectZip,
Expand Down
3 changes: 2 additions & 1 deletion openhands/agenthub/codeact_agent/function_calling.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
_BASH_DESCRIPTION = """Execute a bash command in the terminal.
* Long running commands: For commands that may run indefinitely, it should be run in the background and the output should be redirected to a file, e.g. command = `python3 app.py > server.log 2>&1 &`.
* Interact with running process: If a bash command returns exit code `-1`, this means the process is not yet finished. By setting `is_input` to `true`, the assistant can interact with the running process and send empty `command` to retrieve any additional logs, or send additional text (set `command` to the text) to STDIN of the running process, or send command like `C-c` (Ctrl+C), `C-d` (Ctrl+D), `C-z` (Ctrl+Z) to interrupt the process.
* One command at a time: You can only execute one bash command at a time. If you need to run multiple commands sequentially, you can use `&&` or `;` to chain them together.
"""

CmdRunTool = ChatCompletionToolParam(
Expand All @@ -44,7 +45,7 @@
'properties': {
'command': {
'type': 'string',
'description': 'The bash command to execute. Can be empty string to view additional logs when previous exit code is `-1`. Can be `C-c` (Ctrl+C) to interrupt the currently running process.',
'description': 'The bash command to execute. Can be empty string to view additional logs when previous exit code is `-1`. Can be `C-c` (Ctrl+C) to interrupt the currently running process. Note: You can only execute one bash command at a time. If you need to run multiple commands sequentially, you can use `&&` or `;` to chain them together.',
},
'is_input': {
'type': 'string',
Expand Down
4 changes: 0 additions & 4 deletions openhands/controller/agent_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,6 @@ async def set_agent_state_to(self, new_state: AgentState) -> None:
EventSource.ENVIRONMENT,
)

if new_state == AgentState.INIT and self.state.resume_state:
await self.set_agent_state_to(self.state.resume_state)
self.state.resume_state = None

def get_agent_state(self) -> AgentState:
"""Returns the current state of the agent.
Expand Down
4 changes: 0 additions & 4 deletions openhands/core/schema/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@


class ActionTypeSchema(BaseModel):
INIT: str = Field(default='initialize')
"""Initializes the agent. Only sent by client.
"""

MESSAGE: str = Field(default='message')
"""Represents a message.
"""
Expand Down
4 changes: 0 additions & 4 deletions openhands/core/schema/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ class AgentState(str, Enum):
"""The agent is loading.
"""

INIT = 'init'
"""The agent is initialized.
"""

RUNNING = 'running'
"""The agent is running.
"""
Expand Down
6 changes: 0 additions & 6 deletions openhands/resolver/resolve_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,12 +567,6 @@ def int_or_none(value):
choices=['issue', 'pr'],
help='Type of issue to resolve, either open issue or pr comments.',
)
parser.add_argument(
'--target-branch',
type=str,
default=None,
help="Target branch to pull and create PR against (for PRs). If not specified, uses the PR's base branch.",
)
parser.add_argument(
'--is-experimental',
type=lambda x: x.lower() == 'true',
Expand Down
6 changes: 6 additions & 0 deletions openhands/runtime/impl/remote/remote_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ def _wait_until_alive_impl(self):
assert 'pod_status' in runtime_data
pod_status = runtime_data['pod_status'].lower()
self.log('debug', f'Pod status: {pod_status}')
restart_count = runtime_data.get('restart_count', 0)
if restart_count != 0:
restart_reasons = runtime_data.get('restart_reasons')
self.log(
'debug', f'Pod restarts: {restart_count}, reasons: {restart_reasons}'
)

# FIXME: We should fix it at the backend of /start endpoint, make sure
# the pod is created before returning the response.
Expand Down
Loading

0 comments on commit a316d5b

Please sign in to comment.