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);