diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml
index 8f6f3cc06d..bb44460101 100644
--- a/server/bundles/io.cloudbeaver.model/plugin.xml
+++ b/server/bundles/io.cloudbeaver.model/plugin.xml
@@ -46,6 +46,8 @@
class="io.cloudbeaver.websocket.event.client.WSSessionTaskConfirmationEvent"/>
+
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
index 36f2f22a21..73c0fb5b7e 100644
--- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
- * Copyright (C) 2010-2025 DBeaver Corp and others
+ * Copyright (C) 2010-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -614,6 +614,21 @@ public class WebSession extends BaseWebSession
return runAsyncTask(asyncTask, runnable);
}
+ @Nullable
+ public WebAsyncTaskInfo runAsyncTaskJob(@NotNull String taskId) {
+ WebAsyncTaskInfo asyncTask;
+ synchronized (asyncTasks) {
+ asyncTask = asyncTasks.get(taskId);
+ }
+ if (asyncTask == null || asyncTask.getJob() == null) {
+ addSessionError(new DBWebException("Task '" + taskId + "' should exist and have a job"));
+ return null;
+ }
+ asyncTask.setRunning(true);
+ asyncTask.getJob().schedule();
+ return asyncTask;
+ }
+
public WebAsyncTaskInfo runAsyncTask(@NotNull WebAsyncTaskInfo asyncTask, @NotNull WebAsyncTaskProcessor> runnable) {
AbstractJob job = new AbstractCancelableJob(asyncTask.getName()) {
@NotNull
@@ -1049,6 +1064,19 @@ public class WebSession extends BaseWebSession
}
}
+ public void handleAiFunctionConfirmation(@NotNull String taskId, boolean confirmed) {
+ if (confirmed) {
+ runAsyncTaskJob(taskId);
+ } else {
+ try {
+ asyncTaskCancel(taskId);
+ } catch (DBWebException e) {
+ log.error("Error cancelling function confirmation task", e);
+ addSessionError(e);
+ }
+ }
+ }
+
@NotNull
private String getTaskConfirmationAttributeName(@NotNull String taskId) {
return WebSQLConstants.TASK_CONFIRMATION_ATTR_PREFIX + taskId;
diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSAiFunctionCallConfirmationClientEvent.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSAiFunctionCallConfirmationClientEvent.java
new file mode 100644
index 0000000000..7373c7f0bc
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSAiFunctionCallConfirmationClientEvent.java
@@ -0,0 +1,66 @@
+/*
+ * DBeaver - Universal Database Manager
+ * Copyright (C) 2010-2026 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.cloudbeaver.websocket.event.client;
+
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.model.websocket.WSConstants;
+import org.jkiss.dbeaver.model.websocket.event.WSClientEvent;
+
+public class WSAiFunctionCallConfirmationClientEvent extends WSClientEvent {
+
+ public static final String ID = "cb_client_ai_function_call_confirmation";
+
+ @NotNull
+ private final String conversationId;
+ @NotNull
+ private final String messageId;
+ @NotNull
+ private final String taskId;
+ private final boolean confirmed;
+
+ public WSAiFunctionCallConfirmationClientEvent(
+ @NotNull String conversationId,
+ @NotNull String messageId,
+ @NotNull String taskId,
+ boolean confirmed
+ ) {
+ super(ID, WSConstants.TOPIC_AI);
+ this.conversationId = conversationId;
+ this.messageId = messageId;
+ this.taskId = taskId;
+ this.confirmed = confirmed;
+ }
+
+ @NotNull
+ public String getConversationId() {
+ return conversationId;
+ }
+
+ @NotNull
+ public String getMessageId() {
+ return messageId;
+ }
+
+ @NotNull
+ public String getTaskId() {
+ return taskId;
+ }
+
+ public boolean isConfirmed() {
+ return confirmed;
+ }
+}
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java
index fef9fffdc0..ef9b2de5d5 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/websockets/CBClientEventProcessor.java
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
- * Copyright (C) 2010-2024 DBeaver Corp and others
+ * Copyright (C) 2010-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,6 +91,13 @@ public class CBClientEventProcessor {
}
break;
}
+ case WSAiFunctionCallConfirmationClientEvent.ID: {
+ if (webSession instanceof WebSession session) {
+ var event = (WSAiFunctionCallConfirmationClientEvent) clientEvent;
+ session.handleAiFunctionConfirmation(event.getTaskId(), event.isConfirmed());
+ }
+ break;
+ }
default:
var e = new DBWebException("Unknown client event: " + clientEvent.getId());
log.error(e.getMessage(), e);