Skip to content

Commit

Permalink
Merge branch 'main' into adding-auth-to-solve
Browse files Browse the repository at this point in the history
  • Loading branch information
jfhucka authored Nov 19, 2024
2 parents 274fec7 + 6054189 commit 3a45c4d
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 205 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pip install surfkit
- Docker
- Python >= 3.10
- MacOS or Linux
- [Qemu](https://www.qemu.org/download/#macos)

### Python

Expand All @@ -58,7 +57,7 @@ from surfkit import solve

task = solve(
"Search for the most common variety of french duck",
agent_type="mariyadavydova/SurfSlicer",
agent_type="pbarker/SurfPizza",
device_type="desktop",
)

Expand All @@ -80,7 +79,7 @@ surfkit find
Create a new agent

```
surfkit create agent -t mariyadavydova/SurfSlicer -n agent01
surfkit create agent -t pbarker/SurfPizza -n agent01
```

List running agents
Expand All @@ -94,7 +93,7 @@ surfkit list agents
Create an Ubuntu desktop for our agent to use.

```
surfkit create device --provider qemu -n desktop01
surfkit create device --provider docker -n desktop01
```

List running devices
Expand Down
410 changes: 262 additions & 148 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ pyyaml = "^6.0.1"
toolfuse = "^0.1.15"
devicebay = "^0.1.11"
litellm = "^1.35.8"
tiktoken = "^0.6.0"
rich = "^13.7.1"
tqdm = "^4.66.4"
agentdesk = "^0.2.93"
kubernetes = "^30.1.0"
taskara = "^0.1.151"
agentdesk = "^0.2.104"
taskara = "^0.1.161"


[tool.poetry.group.dev.dependencies]
Expand Down
7 changes: 7 additions & 0 deletions surfkit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import warnings
from cryptography.utils import CryptographyDeprecationWarning

# Suppress specific cryptography deprecation warnings
warnings.filterwarnings("ignore", category=CryptographyDeprecationWarning)

# Suppress only UserWarnings coming from Pydantic's _fields.py
warnings.filterwarnings(
"ignore", category=UserWarning, module="pydantic._internal._fields"
)
warnings.filterwarnings(
"ignore", category=UserWarning, module="pydantic._internal._fields"
)

from surfkit.client import solve
from taskara import Task, TaskStatus
49 changes: 21 additions & 28 deletions surfkit/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import yaml
from namesgenerator import get_random_name
from tabulate import tabulate
from agentdesk.vm.ec2 import EC2Provider
from agentdesk.runtime.ec2 import EC2Provider


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -133,10 +133,10 @@ def create_device(
help="The type of device to create. Options are 'desktop'",
),
provider: str = typer.Option(
"qemu",
"docker",
"--provider",
"-p",
help="The provider type for the desktop. Options are 'ec2', 'gce', and 'qemu'",
help="The provider type for the desktop. Options are 'docker', 'kube', 'ec2', 'gce', and 'qemu'",
),
image: Optional[str] = typer.Option(
None, help="The image to use for the desktop. Defaults to Ubuntu Jammy."
Expand All @@ -157,7 +157,7 @@ def create_device(
),
):
from agentdesk.server.models import V1ProviderData
from agentdesk.vm.load import load_provider
from agentdesk.runtime.load import load_provider

if type != "desktop":
typer.echo("Currently only 'desktop' type is supported.")
Expand Down Expand Up @@ -215,7 +215,6 @@ def create_tracker(
False, "--auth-enabled", "-e", help="Whether to enable auth for the tracker."
),
):

if runtime == "docker":
from taskara.runtime.docker import DockerConnectConfig, DockerTrackerRuntime

Expand Down Expand Up @@ -390,7 +389,6 @@ def create_agent(
),
debug: bool = typer.Option(False, help="Run the agent with debug logging"),
):

from surfkit.server.models import V1AgentType
from surfkit.types import AgentType

Expand Down Expand Up @@ -427,10 +425,9 @@ def create_agent(
raise ValueError(f"Unknown runtime '{runtime}'")

if type:

from typing import List

from surfkit.config import AGENTSEA_HUB_API_URL, GlobalConfig
from surfkit.config import AGENTSEA_HUB_API_URL

all_types: List[AgentType] = []

Expand Down Expand Up @@ -625,13 +622,13 @@ def list_devices(
None, "--provider", "-p", help="The provider type for the desktop."
),
):
from agentdesk.vm import DesktopVM
from agentdesk.vm.load import load_provider
from agentdesk.runtime import DesktopInstance
from agentdesk.runtime.load import load_provider

from surfkit.util import convert_unix_to_datetime

provider_is_refreshed = {}
vms = DesktopVM.find()
vms = DesktopInstance.find()
if not vms:
print("No desktops found")
else:
Expand All @@ -648,7 +645,7 @@ def list_devices(
if not desktop.reserved_ip:
_provider.refresh(log=False)
provider_is_refreshed[desktop.provider.type] = True
desktop = DesktopVM.get(desktop.name)
desktop = DesktopInstance.get(desktop.name)
if not desktop:
continue

Expand Down Expand Up @@ -788,8 +785,6 @@ def list_evals():

@list_group.command("types")
def list_types():
from typing import List

from surfkit.config import AGENTSEA_HUB_API_URL
from surfkit.types import AgentType

Expand Down Expand Up @@ -877,7 +872,6 @@ def list_tasks(
None, "--tracker", "-t", help="The tracker to list tasks from."
),
):

from taskara import Task, V1Tasks
from taskara.runtime.base import Tracker

Expand Down Expand Up @@ -982,7 +976,6 @@ def get_agent(
None, "--runtime", "-r", help="Get agent directly from the runtime"
),
):

from surfkit.runtime.agent.base import AgentInstance

active_runtimes = AgentInstance.active_runtimes()
Expand Down Expand Up @@ -1039,11 +1032,11 @@ def get_device(
None, "--provider", "-p", help="The provider type for the desktop."
),
):
from agentdesk.vm import DesktopVM
from agentdesk.vm.load import load_provider
from agentdesk.runtime import DesktopInstance
from agentdesk.runtime.load import load_provider

if name:
desktop = DesktopVM.get(name)
desktop = DesktopInstance.get(name)
if not desktop:
raise ValueError("desktop not found")
if not desktop.provider:
Expand All @@ -1055,7 +1048,7 @@ def get_device(
_provider = load_provider(desktop.provider)
if not desktop.reserved_ip:
_provider.refresh(log=False)
desktop = DesktopVM.get(name)
desktop = DesktopInstance.get(name)
if not desktop:
print(f"Desktop '{name}' not found")
return
Expand Down Expand Up @@ -1196,10 +1189,10 @@ def delete_device(
None, "--provider", "-p", help="The provider type for the desktop."
),
):
from agentdesk.vm import DesktopVM
from agentdesk.vm.load import load_provider
from agentdesk.runtime import DesktopInstance
from agentdesk.runtime.load import load_provider

desktop = DesktopVM.get(name)
desktop = DesktopInstance.get(name)
if not desktop:
raise ValueError("desktop not found")
if not desktop.provider:
Expand All @@ -1212,7 +1205,7 @@ def delete_device(
if not desktop.reserved_ip:
typer.echo("refreshing provider...")
_provider.refresh(log=False)
desktop = DesktopVM.get(name)
desktop = DesktopInstance.get(name)
if not desktop:
print(f"Desktop '{name}' not found")
return
Expand Down Expand Up @@ -1277,9 +1270,9 @@ def view_device(
False, "--background", "-b", help="Run the viewer in background mode"
),
):
from agentdesk.vm import DesktopVM
from agentdesk.runtime import DesktopInstance

desktop = DesktopVM.get(name)
desktop = DesktopInstance.get(name)
if not desktop:
raise ValueError(f"Desktop '{name}' not found")

Expand Down Expand Up @@ -1354,7 +1347,7 @@ def new(
"--template",
"-t",
help="Template to use. Options are 'surf4v' or 'surfskelly'",
)
),
):
from rich.prompt import Prompt

Expand Down Expand Up @@ -1700,7 +1693,7 @@ def get_tracker_logs(
@app.command("config")
def config():
"""
Retrieve tracker logs
CLI configuration
"""
from surfkit.config import (
AGENTSEA_AUTH_URL,
Expand Down
4 changes: 1 addition & 3 deletions surfkit/cli/templates/agents/surf4v.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@


class Surf4v(AgentTemplate):

def template(self, agent_name: str) -> str:

return f"""
from typing import List, Type, Tuple, Optional
import logging
Expand All @@ -14,7 +12,7 @@ def template(self, agent_name: str) -> str:
import os
from devicebay import Device
from agentdesk import Desktop
from agentdesk.device_v1 import Desktop
from toolfuse.util import AgentUtils
from pydantic import BaseModel
from surfkit.agent import TaskAgent
Expand Down
3 changes: 1 addition & 2 deletions surfkit/cli/templates/agents/surfskelly.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@


class SurfSkelly(AgentTemplate):

def template(self, agent_name: str) -> str:

return f"""
from typing import List, Type, Tuple, Optional
import logging
Expand All @@ -14,6 +12,7 @@ def template(self, agent_name: str) -> str:
import os
from devicebay import Device
from agentdesk.device_v1 import Desktop
from rich.console import Console
from pydantic import BaseModel
from surfkit.agent import TaskAgent
Expand Down
44 changes: 34 additions & 10 deletions surfkit/cli/view.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# from __future__ import annotations
import atexit
import os
import random
import time
import urllib.parse
import webbrowser
Expand All @@ -11,7 +10,7 @@
from agentdesk.key import SSHKeyPair
from agentdesk.proxy import cleanup_proxy, ensure_ssh_proxy
from agentdesk.util import check_command_availability, find_open_port, get_docker_host
from agentdesk.vm.base import DesktopVM
from agentdesk.runtime.base import DesktopInstance
from docker.api.client import APIClient
from docker.models.containers import Container

Expand All @@ -22,7 +21,7 @@


def view(
desk: DesktopVM,
desk: DesktopInstance,
agent: AgentInstance,
tracker_addr: str,
task_id: str,
Expand All @@ -31,8 +30,29 @@ def view(
) -> None:
"""Opens the desktop in a browser window"""

desk_port = 6080
if desk.requires_proxy:
is_container = False
desk_url = "ws://localhost:6080"
if desk.provider and desk.provider.type == "kube":
from agentdesk.runtime.kube import KubernetesProvider, KubeConnectConfig

if not desk.provider.args:
raise ValueError(f"No args for kube provider while deleting {desk.id}")

cfg = KubeConnectConfig.model_validate_json(desk.provider.args["cfg"])
provider = KubernetesProvider(cfg=cfg)

desk_port, _ = provider.proxy(desk.name)
print(f"Desktop proxy created on port {desk_port}")

time.sleep(2)
desk_url = f"http://localhost:{desk_port}"
is_container = True

elif desk.provider and desk.provider.type == "docker":
desk_url = f"http://localhost:{desk.vnc_port}"
is_container = True

elif desk.requires_proxy:
keys = SSHKeyPair.find(name=desk.key_pair_name)
if not keys:
raise ValueError(
Expand All @@ -48,10 +68,11 @@ def view(
6080,
desk.ssh_port,
"agentsea",
desk.addr,
desk.addr or "",
key_pair.decrypt_private_key(key_pair.private_key),
)
atexit.register(cleanup_proxy, proxy_pid)
desk_url = f"http://localhost:{desk_port}"

agent_port = agent.port
agent_proxy_pid = None
Expand All @@ -73,7 +94,7 @@ def view(
ui_container: Optional[Container] = None

for container in client.containers.list():
if container.image.tags[0] == UI_IMG: # type: ignore
if container.image.tags and container.image.tags[0] == UI_IMG: # type: ignore
print("found running UI container")
# Retrieve the host port for the existing container
host_port = container.attrs["NetworkSettings"]["Ports"]["3000/tcp"][0][ # type: ignore
Expand All @@ -100,11 +121,14 @@ def view(

encoded_agent_addr = urllib.parse.quote(f"http://localhost:{agent_port}")
encoded_task_addr = urllib.parse.quote(tracker_addr)
encoded_vnc_addr = urllib.parse.quote(f"ws://localhost:{desk_port}")
encoded_vnc_addr = urllib.parse.quote(desk_url)
encoded_task_id = urllib.parse.quote(task_id)

# Construct the URL with the encoded parameters
url = f"http://localhost:{host_port}/?agentAddr={encoded_agent_addr}&vncAddr={encoded_vnc_addr}&taskAddr={encoded_task_addr}&taskID={encoded_task_id}"
if is_container:
# Construct the URL with the encoded parameters
url = f"http://localhost:{host_port}/container?agentAddr={encoded_agent_addr}&vncAddr={encoded_vnc_addr}&taskAddr={encoded_task_addr}&taskID={encoded_task_id}"
else:
url = f"http://localhost:{host_port}/?agentAddr={encoded_agent_addr}&vncAddr={encoded_vnc_addr}&taskAddr={encoded_task_addr}&taskID={encoded_task_id}"

if auth_token:
encoded_auth_token = urllib.parse.quote(auth_token)
Expand Down
Loading

0 comments on commit 3a45c4d

Please sign in to comment.