diff --git a/modules/agent_api/agent_server.cpp b/modules/agent_api/agent_server.cpp index bde6c82ffe..a0840c046e 100644 --- a/modules/agent_api/agent_server.cpp +++ b/modules/agent_api/agent_server.cpp @@ -31,7 +31,7 @@ AgentServer::~AgentServer() { } void AgentServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("start", "port", "token"), &AgentServer::start, DEFVAL(4328), DEFVAL("")); + ClassDB::bind_method(D_METHOD("start", "port", "token"), &AgentServer::start, DEFVAL(4329), DEFVAL("")); ClassDB::bind_method(D_METHOD("stop"), &AgentServer::stop); ClassDB::bind_method(D_METHOD("is_running"), &AgentServer::is_running); ClassDB::bind_method(D_METHOD("get_port"), &AgentServer::get_port); @@ -58,6 +58,20 @@ void AgentServer::start(int p_port, const String &p_token) { running = true; server_thread.start(_server_thread_func, this); print_line(vformat("AgentServer: Listening on http://0.0.0.0:%d", port)); + + // Connect poll() to the SceneTree's process_frame signal so screenshot/depth/command + // requests get serviced on the main thread each frame. Deferred because SceneTree + // may not exist yet during module init. + callable_mp(this, &AgentServer::_connect_to_scene_tree).call_deferred(); +} + +void AgentServer::_connect_to_scene_tree() { + SceneTree *tree = SceneTree::get_singleton(); + if (tree) { + tree->connect("process_frame", callable_mp(this, &AgentServer::poll)); + } else { + ERR_PRINT("AgentServer: SceneTree not available, poll() won't run — screenshots will timeout."); + } } void AgentServer::stop() { @@ -68,6 +82,12 @@ void AgentServer::stop() { running = false; server_thread.wait_to_finish(); + // Disconnect from SceneTree if connected. + SceneTree *tree = SceneTree::get_singleton(); + if (tree && tree->is_connected("process_frame", callable_mp(this, &AgentServer::poll))) { + tree->disconnect("process_frame", callable_mp(this, &AgentServer::poll)); + } + { MutexLock lock(sse_mutex); sse_clients.clear(); @@ -81,7 +101,7 @@ void AgentServer::check_cmdline_and_start() { // Check --agent-api flag or AGENT_API env var. List cmdline_args = OS::get_singleton()->get_cmdline_args(); bool should_start = false; - int custom_port = 4328; + int custom_port = 4329; String custom_token; for (const String &arg : cmdline_args) { diff --git a/modules/agent_api/agent_server.h b/modules/agent_api/agent_server.h index 2f7b4a0cb2..cd42133426 100644 --- a/modules/agent_api/agent_server.h +++ b/modules/agent_api/agent_server.h @@ -41,7 +41,7 @@ private: Ref tcp_server; Thread server_thread; bool running = false; - int port = 4328; + int port = 4329; String auth_token; // SSE clients for log/event streaming. @@ -93,6 +93,7 @@ private: // Server thread function. static void _server_thread_func(void *p_userdata); void _server_loop(); + void _connect_to_scene_tree(); void _handle_connection(Ref p_peer); // HTTP parsing. @@ -150,7 +151,7 @@ public: AgentServer(); ~AgentServer(); - void start(int p_port = 4328, const String &p_token = ""); + void start(int p_port = 4329, const String &p_token = ""); void stop(); bool is_running() const { return running; } int get_port() const { return port; } diff --git a/modules/agent_api/register_types.cpp b/modules/agent_api/register_types.cpp index 44f767974b..6e37517520 100644 --- a/modules/agent_api/register_types.cpp +++ b/modules/agent_api/register_types.cpp @@ -15,6 +15,7 @@ void initialize_agent_api_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(AgentServer); agent_server_singleton = memnew(AgentServer); Engine::get_singleton()->add_singleton(Engine::Singleton("AgentServer", AgentServer::get_singleton())); + AgentServer::check_cmdline_and_start(); } void uninitialize_agent_api_module(ModuleInitializationLevel p_level) {