7fb933a4b9
- Call check_cmdline_and_start() from register_types so --agent-api flag works - Connect poll() to SceneTree::process_frame via deferred callable so screenshot/depth/command requests get serviced on the main thread - Default port changed to 4329 to avoid conflict with C# AgentServer on 4328 - Clean disconnect on stop() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
168 lines
5.2 KiB
C++
168 lines
5.2 KiB
C++
#pragma once
|
|
|
|
#include "core/object/class_db.h"
|
|
#include "core/object/object.h"
|
|
#include "core/os/mutex.h"
|
|
#include "core/os/thread.h"
|
|
#include "core/io/tcp_server.h"
|
|
#include "core/io/stream_peer_tcp.h"
|
|
#include "core/string/ustring.h"
|
|
#include "core/variant/dictionary.h"
|
|
#include "core/variant/variant.h"
|
|
#include "core/io/json.h"
|
|
|
|
class AgentServer : public Object {
|
|
GDCLASS(AgentServer, Object);
|
|
|
|
static AgentServer *singleton;
|
|
|
|
public:
|
|
static AgentServer *get_singleton() { return singleton; }
|
|
|
|
// HTTP request parsed structure.
|
|
struct HTTPRequest {
|
|
String method;
|
|
String path;
|
|
HashMap<String, String> query_params;
|
|
HashMap<String, String> headers;
|
|
String body;
|
|
};
|
|
|
|
// HTTP response.
|
|
struct HTTPResponse {
|
|
int status_code = 200;
|
|
String content_type = "application/json";
|
|
String body;
|
|
Vector<uint8_t> binary_body;
|
|
bool is_binary = false;
|
|
};
|
|
|
|
private:
|
|
Ref<TCPServer> tcp_server;
|
|
Thread server_thread;
|
|
bool running = false;
|
|
int port = 4329;
|
|
String auth_token;
|
|
|
|
// SSE clients for log/event streaming.
|
|
struct SSEClient {
|
|
Ref<StreamPeerTCP> peer;
|
|
String stream_type; // "logs" or "events"
|
|
uint64_t connected_at = 0;
|
|
};
|
|
Vector<SSEClient> sse_clients;
|
|
Mutex sse_mutex;
|
|
|
|
// Screenshot request coordination (main thread captures, server thread serves).
|
|
struct ScreenshotRequest {
|
|
bool pending = false;
|
|
bool ready = false;
|
|
int width = 0;
|
|
int height = 0;
|
|
String format = "png";
|
|
int quality = 90;
|
|
String camera_name;
|
|
bool annotate = false;
|
|
bool diff = false;
|
|
Vector<uint8_t> result_data;
|
|
String result_content_type;
|
|
};
|
|
ScreenshotRequest screenshot_request;
|
|
Mutex screenshot_mutex;
|
|
|
|
// Depth buffer request.
|
|
struct DepthRequest {
|
|
bool pending = false;
|
|
bool ready = false;
|
|
Vector<uint8_t> result_data;
|
|
};
|
|
DepthRequest depth_request;
|
|
Mutex depth_mutex;
|
|
|
|
// Command execution (must happen on main thread).
|
|
struct CommandRequest {
|
|
bool pending = false;
|
|
bool ready = false;
|
|
String expression;
|
|
String result;
|
|
bool success = false;
|
|
};
|
|
CommandRequest command_request;
|
|
Mutex command_mutex;
|
|
|
|
// Server thread function.
|
|
static void _server_thread_func(void *p_userdata);
|
|
void _server_loop();
|
|
void _connect_to_scene_tree();
|
|
void _handle_connection(Ref<StreamPeerTCP> p_peer);
|
|
|
|
// HTTP parsing.
|
|
HTTPRequest _parse_http_request(const String &p_raw);
|
|
void _send_response(Ref<StreamPeerTCP> p_peer, const HTTPResponse &p_response);
|
|
void _send_sse_headers(Ref<StreamPeerTCP> p_peer);
|
|
|
|
// Route handlers.
|
|
HTTPResponse _handle_request(const HTTPRequest &p_request);
|
|
|
|
// Endpoint handlers.
|
|
HTTPResponse _handle_health(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_screenshot(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_depth(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_segmentation(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_state(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_nodes(const HTTPRequest &p_request, const String &p_node_path);
|
|
HTTPResponse _handle_command(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_command_batch(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_input(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_logs(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_logs_stream(const HTTPRequest &p_request, Ref<StreamPeerTCP> p_peer);
|
|
HTTPResponse _handle_perf(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_events_stream(const HTTPRequest &p_request, Ref<StreamPeerTCP> p_peer);
|
|
HTTPResponse _handle_events_history(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_world_raycast(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_world_spawn(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_world_destroy(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_world_physics(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_world_navmesh(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_save(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_load(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_saves(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_config(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_console(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_commands_list(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_assets(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_assets_reload(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_vision_boxes(const HTTPRequest &p_request);
|
|
HTTPResponse _handle_vision_minimap(const HTTPRequest &p_request);
|
|
|
|
// Auth helpers.
|
|
bool _check_auth(const HTTPRequest &p_request);
|
|
|
|
// Utility.
|
|
static String _status_text(int p_code);
|
|
static String _json_response(const Dictionary &p_dict);
|
|
static String _json_error(int p_code, const String &p_message);
|
|
static Dictionary _node_to_dict(Node *p_node, int p_depth, int p_max_depth, const String &p_filter);
|
|
|
|
protected:
|
|
static void _bind_methods();
|
|
|
|
public:
|
|
AgentServer();
|
|
~AgentServer();
|
|
|
|
void start(int p_port = 4329, const String &p_token = "");
|
|
void stop();
|
|
bool is_running() const { return running; }
|
|
int get_port() const { return port; }
|
|
|
|
// Called from main thread each frame to service requests.
|
|
void poll();
|
|
|
|
// Push SSE data to connected clients.
|
|
void push_sse(const String &p_stream_type, const String &p_event, const String &p_data);
|
|
|
|
// Auto-start from command line.
|
|
static void check_cmdline_and_start();
|
|
};
|