Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(frontend): Multi-project support #5376

Draft
wants to merge 47 commits into
base: main
Choose a base branch
from
Draft

Conversation

amanape
Copy link
Member

@amanape amanape commented Dec 3, 2024

Assumptions

Data

type ProjectState =
  | "cold"
  | "cooling"
  | "finished"
  | "running"
  | "waiting"
  | "warm";

interface Conversation {
  id: string;
  name: string;
  repo: string | null;
  lastUpdated: string;
  state: ProjectState;
}

Flow

NOTE: The /app has now been renamed to /conversation

Loading existing session

  1. Open panel
  2. GET /api/conversations
  3. Select conversation
  4. Navigate to /conversation?cid={conversationId}
  5. GET /api/conversations/:conversationId/permissions
  6. Send conversationId query param to the backend through the WebSocket when sending initEvent (on connection)
  7. WebSocket returns events linked to conversationId

Deleting a conversation

  1. Open panel
  2. GET /api/conversations
  3. Confirm deletion of selected conversation
  4. DELETE /api/conversations/:conversationId

Renaming a conversation

  1. Open panel
  2. GET /api/conversations
  3. Enter new title
  4. PUT /api/conversations/:conversationId BODY { title: string }

Creating a new conversation

  1. Go to /conversation
  2. POST /api/conversations
  3. [URL search params updated to /conversation?cid={newConversationId}]
  4. [Invalidate cached conversations]
  5. GET /api/conversations/:conversationId/permissions
  6. Send newConversationId query param to the backend through the WebSocket when sending initEvent (on connection)

Additional Behavior

  • WebSocket context enabled prop set to enabled={!!permissions && permissions?.includes("write:chat")}
  • If user does not have permissions (!permissions?.includes("write:chat")) to a conversation, endSession is called and the user is navigated back to the home screen

Endpoints

async getUserConversations(): Promise<Conversation[]> {
  const { data } = await openHands.get<Conversation[]>("/api/conversations");
  return data;
}

async deleteUserConversation(conversationId: string): Promise<void> {
  await openHands.delete(`/api/conversations/${conversationId}`);
}

async updateUserConversation(
  conversationId: string,
  conversation: Partial<Omit<Conversation, "id">>,
): Promise<void> {
  await openHands.put(`/api/conversations/${conversationId}`, conversation);
}

async createConversation(): Promise<Conversation> {
  const { data } = await openHands.post<Conversation>("/api/conversations");
  return data;
}

async getConversationPermissions(conversationId: string): Promise<string[]> {
  const { data } = await openHands.get<string[]>(
    `/api/conversations/${conversationId}/permissions`,
  );
  return data;
}

Notes

  • The plan is to only pass the conversation ID to the WS, authentication (especially in the SaaS) will require a separate a new auth token generated by the server
  • I am not super convinced of the permissions implementation, but it is what I came up with at the moment (especially since we plan to build upon this feature)

Blocked by #5493


To run this PR locally, use the following command:

docker run -it --rm   -p 3000:3000   -v /var/run/docker.sock:/var/run/docker.sock   --add-host host.docker.internal:host-gateway   -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:f2ad06d-nikolaik   --name openhands-app-f2ad06d   docker.all-hands.dev/all-hands-ai/openhands:f2ad06d

@amanape amanape self-assigned this Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant