Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 68 additions & 28 deletions .dev/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,28 @@
import os
import shutil
import subprocess
import sys

DEMO_CONTAINER_NAME = "valk-demo"
IMAGE_NAME = "ghcr.io/ercbot/valk-chromium-demo:latest"
DOCKER_DIR = "docker-examples/chromium-demo"


def run_with_logging(cmd, **kwargs):
"""Run a command and log any errors that occur."""
print(f"Running command: {' '.join(cmd)}")
try:
result = subprocess.run(cmd, **kwargs, stderr=subprocess.PIPE, text=True)
return result
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}")
if e.stderr:
print(f"Error output: {e.stderr}")
if kwargs.get("check", False):
raise
return e


def main():
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--rebuild-cross", action="store_true")
Expand All @@ -16,7 +32,8 @@ def main():

if args.rebuild_cross:
# You only need to do this if you're changing the linux dependencies
subprocess.run(
print("Building cross-compiler image...")
run_with_logging(
[
"docker",
"build",
Expand All @@ -33,7 +50,8 @@ def main():
os.chdir("valk-server")

# Build the valk server
subprocess.run(
print("Building valk server...")
run_with_logging(
[
"cross",
"build",
Expand All @@ -44,7 +62,8 @@ def main():
)

# Run the tests
subprocess.run(
print("Running tests...")
run_with_logging(
[
"cross",
"test",
Expand All @@ -66,7 +85,8 @@ def main():
os.chdir(DOCKER_DIR)

# Build the chromium demo
subprocess.run(
print("Building Docker image...")
run_with_logging(
[
"docker",
"build",
Expand All @@ -81,34 +101,54 @@ def main():
return

# Stop the dev container if it exists
subprocess.run(
["docker", "stop", DEMO_CONTAINER_NAME],
check=True,
)
print(f"Stopping container {DEMO_CONTAINER_NAME} if it exists...")
try:
result = run_with_logging(
["docker", "stop", DEMO_CONTAINER_NAME],
check=True,
)
print("Container stopped successfully.")
except subprocess.CalledProcessError:
print(f"Container {DEMO_CONTAINER_NAME} was not running, continuing...")
pass

# Remove the dev container if it exists
subprocess.run(
["docker", "rm", DEMO_CONTAINER_NAME],
check=True,
)
print(f"Removing container {DEMO_CONTAINER_NAME} if it exists...")
try:
result = run_with_logging(
["docker", "rm", DEMO_CONTAINER_NAME],
check=True,
)
print("Container removed successfully.")
except subprocess.CalledProcessError as e:
# Container not found, so we don't need to remove it
print(
f"Container {DEMO_CONTAINER_NAME} doesn't exist or couldn't be removed: {e.stderr}"
)
pass

# Run the dev container

subprocess.run(
[
"docker",
"run",
"-d",
"-p",
"5900:5900", # VNC port
"-p",
"8255:8255", # Valk server port
"--name",
DEMO_CONTAINER_NAME,
IMAGE_NAME,
],
check=True,
)
print(f"Starting new container {DEMO_CONTAINER_NAME}...")
try:
run_with_logging(
[
"docker",
"run",
"-d",
"-p",
"5900:5900", # VNC port
"-p",
"8255:8255", # Valk server port
"--name",
DEMO_CONTAINER_NAME,
IMAGE_NAME,
],
check=True,
)
print(f"Container {DEMO_CONTAINER_NAME} started successfully.")
except subprocess.CalledProcessError as e:
print(f"Failed to start container: {e.stderr}")
sys.exit(1)


if __name__ == "__main__":
Expand Down
97 changes: 73 additions & 24 deletions valk/debug_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@
margin: auto;
display: block;
}
.event-type {
background: #e9ecef;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.8em;
min-width: 80px;
text-align: center;
}
.request {
color: #0c5460;
background-color: #d1ecf1;
}
.response {
color: #155724;
background-color: #d4edda;
}
</style>
</head>
<body>
Expand All @@ -109,7 +125,6 @@
<button class="clear-btn" onclick="clearEvents()">Clear Events</button>
<div id="events"></div>
<div id="screenshot-modal" class="screenshot-modal" onclick="hideScreenshot()">

<img id="modal-image">
</div>

Expand All @@ -121,7 +136,7 @@
const modalImg = document.getElementById('modal-image');

function connect() {
ws = new WebSocket('ws://VALK_BASE_URL/ws/monitor');
ws = new WebSocket('ws://VALK_BASE_URL/v1/monitor');
ws.onopen = () => {
statusDiv.textContent = 'Connected';
statusDiv.className = 'connected';
Expand Down Expand Up @@ -158,32 +173,66 @@

function addEvent(data) {
const eventDiv = document.createElement('div');
eventDiv.className = 'event ' + (data.result.Ok ? 'success' : 'error');

const time = new Date(data.timestamp).toLocaleTimeString();
const action = typeof data.action === 'string' ? data.action : JSON.stringify(data.action);
const status = data.result.Ok ? 'Ok' : 'Error';
const resultData = data.result.Ok || data.result.Err;

let dataContent = '';
if (action === 'Screenshot' && resultData.data?.image) {
dataContent = `
<img src="data:image/png;base64,${resultData.data.image}"
class="screenshot-preview"
onclick="showScreenshot('${resultData.data.image}')">
// Determine if it's a Request or Response event
if (data.Request) {
// Handle Request event
const request = data.Request;
eventDiv.className = 'event';

const time = new Date(request.timestamp || Date.now()).toLocaleTimeString();
const actionType = request.action.type || "unknown";

eventDiv.innerHTML = `
<div class="event-type request">Request</div>
<div class="event-time">${time}</div>
<div class="event-action">${actionType}</div>
<div class="event-data">ID: ${request.id}</div>
`;
}
else if (data.Response) {
// Handle Response event
const response = data.Response;
eventDiv.className = `event ${response.status === 'success' ? 'success' : 'error'}`;

const time = new Date(response.timestamp).toLocaleTimeString();
const actionType = response.action.type || "unknown";
const status = response.status || "unknown";

let dataContent = '';
// Special handling for screenshot data
if (actionType === 'screenshot' && response.data && response.data.image) {
dataContent = `
<img src="data:image/png;base64,${response.data.image}"
class="screenshot-preview"
onclick="showScreenshot('${response.data.image}')">
`;
}
// Special handling for cursor position data
else if (actionType === 'cursor_position' && response.data) {
dataContent = `Position: x=${response.data.x}, y=${response.data.y}`;
}
// Error handling
else if (response.error) {
dataContent = `Error: ${formatData(response.error)}`;
}
// Generic data output
else if (response.data) {
dataContent = formatData(response.data);
}

eventDiv.innerHTML = `
<div class="event-type response">Response</div>
<div class="event-time">${time}</div>
<div class="event-action">${actionType}</div>
<div class="event-status">${status}</div>
<div class="event-data">${dataContent}</div>
`;
} else {
dataContent = formatData(resultData);
}

eventDiv.innerHTML = `
<div class="event-time">${time}</div>
<div class="event-action">${action}</div>
<div class="event-status">${status}</div>
<div class="event-data">${dataContent}</div>
`;

eventsDiv.insertBefore(eventDiv, eventsDiv.firstChild);
if (eventDiv.innerHTML) {
eventsDiv.insertBefore(eventDiv, eventsDiv.firstChild);
}
}

function clearEvents() {
Expand Down