mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-20 08:04:48 +00:00
feat: expand desktop computer-use APIs
This commit is contained in:
parent
96dcc3d5f9
commit
e638148345
43 changed files with 6359 additions and 493 deletions
15
.context/docker-test-zgvGyf/bin/Xvfb
Executable file
15
.context/docker-test-zgvGyf/bin/Xvfb
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
display="${1:-:191}"
|
||||
number="${display#:}"
|
||||
socket="/tmp/.X11-unix/X${number}"
|
||||
mkdir -p /tmp/.X11-unix
|
||||
touch "$socket"
|
||||
cleanup() {
|
||||
rm -f "$socket"
|
||||
exit 0
|
||||
}
|
||||
trap cleanup INT TERM EXIT
|
||||
while :; do
|
||||
sleep 1
|
||||
done
|
||||
4
.context/docker-test-zgvGyf/bin/dbus-launch
Executable file
4
.context/docker-test-zgvGyf/bin/dbus-launch
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
echo "DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/sandbox-agent-test-bus"
|
||||
echo "DBUS_SESSION_BUS_PID=$$"
|
||||
3
.context/docker-test-zgvGyf/bin/import
Executable file
3
.context/docker-test-zgvGyf/bin/import
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
printf '\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\000\001\000\000\000\001\010\006\000\000\000\037\025\304\211\000\000\000\013IDATx\234c\000\001\000\000\005\000\001\r\n-\264\000\000\000\000IEND\256B`\202'
|
||||
6
.context/docker-test-zgvGyf/bin/openbox
Executable file
6
.context/docker-test-zgvGyf/bin/openbox
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
trap 'exit 0' INT TERM
|
||||
while :; do
|
||||
sleep 1
|
||||
done
|
||||
57
.context/docker-test-zgvGyf/bin/xdotool
Executable file
57
.context/docker-test-zgvGyf/bin/xdotool
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
state_dir="${SANDBOX_AGENT_DESKTOP_FAKE_STATE_DIR:?missing fake state dir}"
|
||||
state_file="${state_dir}/mouse"
|
||||
mkdir -p "$state_dir"
|
||||
if [ ! -f "$state_file" ]; then
|
||||
printf '0 0\n' > "$state_file"
|
||||
fi
|
||||
|
||||
read_state() {
|
||||
read -r x y < "$state_file"
|
||||
}
|
||||
|
||||
write_state() {
|
||||
printf '%s %s\n' "$1" "$2" > "$state_file"
|
||||
}
|
||||
|
||||
command="${1:-}"
|
||||
case "$command" in
|
||||
getmouselocation)
|
||||
read_state
|
||||
printf 'X=%s\nY=%s\nSCREEN=0\nWINDOW=0\n' "$x" "$y"
|
||||
;;
|
||||
mousemove)
|
||||
shift
|
||||
x="${1:-0}"
|
||||
y="${2:-0}"
|
||||
shift 2 || true
|
||||
while [ "$#" -gt 0 ]; do
|
||||
token="$1"
|
||||
shift
|
||||
case "$token" in
|
||||
mousemove)
|
||||
x="${1:-0}"
|
||||
y="${2:-0}"
|
||||
shift 2 || true
|
||||
;;
|
||||
mousedown|mouseup)
|
||||
shift 1 || true
|
||||
;;
|
||||
click)
|
||||
if [ "${1:-}" = "--repeat" ]; then
|
||||
shift 2 || true
|
||||
fi
|
||||
shift 1 || true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
write_state "$x" "$y"
|
||||
;;
|
||||
type|key)
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
5
.context/docker-test-zgvGyf/bin/xrandr
Executable file
5
.context/docker-test-zgvGyf/bin/xrandr
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
cat <<'EOF'
|
||||
Screen 0: minimum 1 x 1, current 1440 x 900, maximum 32767 x 32767
|
||||
EOF
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env node
|
||||
const { createInterface } = require("node:readline");
|
||||
|
||||
let nextSession = 0;
|
||||
|
||||
function emit(value) {
|
||||
process.stdout.write(JSON.stringify(value) + "\n");
|
||||
}
|
||||
|
||||
function firstText(prompt) {
|
||||
if (!Array.isArray(prompt)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
for (const block of prompt) {
|
||||
if (block && block.type === "text" && typeof block.text === "string") {
|
||||
return block.text;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const rl = createInterface({
|
||||
input: process.stdin,
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
rl.on("line", (line) => {
|
||||
let msg;
|
||||
try {
|
||||
msg = JSON.parse(line);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasMethod = typeof msg?.method === "string";
|
||||
const hasId = Object.prototype.hasOwnProperty.call(msg, "id");
|
||||
const method = hasMethod ? msg.method : undefined;
|
||||
|
||||
if (method === "session/prompt") {
|
||||
const sessionId = typeof msg?.params?.sessionId === "string" ? msg.params.sessionId : "";
|
||||
const text = firstText(msg?.params?.prompt);
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
method: "session/update",
|
||||
params: {
|
||||
sessionId,
|
||||
update: {
|
||||
sessionUpdate: "agent_message_chunk",
|
||||
content: {
|
||||
type: "text",
|
||||
text: "mock: " + text,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasMethod || !hasId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "initialize") {
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
protocolVersion: 1,
|
||||
capabilities: {},
|
||||
serverInfo: {
|
||||
name: "mock-acp-agent",
|
||||
version: "0.0.1",
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "session/new") {
|
||||
nextSession += 1;
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
sessionId: "mock-session-" + nextSession,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "session/prompt") {
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
stopReason: "end_turn",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
ok: true,
|
||||
echoedMethod: method,
|
||||
},
|
||||
});
|
||||
});
|
||||
111
.context/docker-test-zgvGyf/xdg-data/sandbox-agent/bin/agent_processes/mock-acp
Executable file
111
.context/docker-test-zgvGyf/xdg-data/sandbox-agent/bin/agent_processes/mock-acp
Executable file
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env node
|
||||
const { createInterface } = require("node:readline");
|
||||
|
||||
let nextSession = 0;
|
||||
|
||||
function emit(value) {
|
||||
process.stdout.write(JSON.stringify(value) + "\n");
|
||||
}
|
||||
|
||||
function firstText(prompt) {
|
||||
if (!Array.isArray(prompt)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
for (const block of prompt) {
|
||||
if (block && block.type === "text" && typeof block.text === "string") {
|
||||
return block.text;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const rl = createInterface({
|
||||
input: process.stdin,
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
rl.on("line", (line) => {
|
||||
let msg;
|
||||
try {
|
||||
msg = JSON.parse(line);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasMethod = typeof msg?.method === "string";
|
||||
const hasId = Object.prototype.hasOwnProperty.call(msg, "id");
|
||||
const method = hasMethod ? msg.method : undefined;
|
||||
|
||||
if (method === "session/prompt") {
|
||||
const sessionId = typeof msg?.params?.sessionId === "string" ? msg.params.sessionId : "";
|
||||
const text = firstText(msg?.params?.prompt);
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
method: "session/update",
|
||||
params: {
|
||||
sessionId,
|
||||
update: {
|
||||
sessionUpdate: "agent_message_chunk",
|
||||
content: {
|
||||
type: "text",
|
||||
text: "mock: " + text,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasMethod || !hasId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "initialize") {
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
protocolVersion: 1,
|
||||
capabilities: {},
|
||||
serverInfo: {
|
||||
name: "mock-acp-agent",
|
||||
version: "0.0.1",
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "session/new") {
|
||||
nextSession += 1;
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
sessionId: "mock-session-" + nextSession,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === "session/prompt") {
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
stopReason: "end_turn",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
emit({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
ok: true,
|
||||
echoedMethod: method,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
ts=2026-03-08T07:57:29.140584296Z level=info target=sandbox_agent::telemetry message="anonymous telemetry is enabled, disable with --no-telemetry"
|
||||
ts=2026-03-08T07:57:29.141203296Z level=info target=sandbox_agent::cli message="server listening" addr=0.0.0.0:3000
|
||||
ts=2026-03-08T07:57:29.298687421Z level=info target=sandbox_agent::router span=http.request span_path=http.request message=request method=GET uri=/v1/health
|
||||
ts=2026-03-08T07:57:29.302092338Z level=info target=sandbox_agent::router span=http.request span_path=http.request status="200 OK" latency_ms=3 method=GET uri=/v1/health
|
||||
|
|
@ -0,0 +1 @@
|
|||
5a1927c6af3d83586f34112f58e0c8d6
|
||||
Loading…
Add table
Add a link
Reference in a new issue