diff --git a/server/bundles/io.cloudbeaver.model/plugin.xml b/server/bundles/io.cloudbeaver.model/plugin.xml index 13d24f69e9..c49a85863b 100644 --- a/server/bundles/io.cloudbeaver.model/plugin.xml +++ b/server/bundles/io.cloudbeaver.model/plugin.xml @@ -48,8 +48,10 @@ class="io.cloudbeaver.websocket.event.client.WSSessionTaskWithParametersConfirmationEvent"/> - + + 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 c5afcf3a15..ee71669c45 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 @@ -1071,12 +1071,12 @@ public class WebSession extends BaseWebSession removeAttribute(actionId); } - public void handleAiFunctionConfirmation(@NotNull String taskId, boolean confirmed) { + public void handleActionConfirmation(@NotNull String actionId, boolean confirmed) { if (confirmed) { - runAsyncTaskJob(taskId); + runAsyncTaskJob(actionId); } else { try { - asyncTaskCancel(taskId); + asyncTaskCancel(actionId); } catch (DBWebException e) { log.error("Error cancelling function confirmation task", e); addSessionError(e); @@ -1084,6 +1084,16 @@ public class WebSession extends BaseWebSession } } + public void handleActionResult(@NotNull String actionId, @NotNull Object result) { + CompletableFuture future = getAttribute(actionId); + if (future != null) { + future.complete(result); + removeAttribute(actionId); + } else { + log.error("Received unexpected action result event for actionId: " + actionId); + } + } + @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/WSActionConfirmationClientEvent.java similarity index 56% rename from server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSAiFunctionCallConfirmationClientEvent.java rename to server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSActionConfirmationClientEvent.java index 7373c7f0bc..aaffdadbd0 100644 --- 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/WSActionConfirmationClientEvent.java @@ -20,44 +20,26 @@ 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 class WSActionConfirmationClientEvent extends WSClientEvent { - public static final String ID = "cb_client_ai_function_call_confirmation"; + public static final String ID = "cb_client_action_confirmation"; @NotNull - private final String conversationId; - @NotNull - private final String messageId; - @NotNull - private final String taskId; + private final String actionId; private final boolean confirmed; - public WSAiFunctionCallConfirmationClientEvent( - @NotNull String conversationId, - @NotNull String messageId, - @NotNull String taskId, + public WSActionConfirmationClientEvent( + @NotNull String actionId, boolean confirmed ) { - super(ID, WSConstants.TOPIC_AI); - this.conversationId = conversationId; - this.messageId = messageId; - this.taskId = taskId; + super(ID, WSConstants.TOPIC_SESSION_ACTION); + this.actionId = actionId; this.confirmed = confirmed; } @NotNull - public String getConversationId() { - return conversationId; - } - - @NotNull - public String getMessageId() { - return messageId; - } - - @NotNull - public String getTaskId() { - return taskId; + public String getActionId() { + return actionId; } public boolean isConfirmed() { diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSActionResultClientEvent.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSActionResultClientEvent.java new file mode 100644 index 0000000000..3fcba47ac4 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/websocket/event/client/WSActionResultClientEvent.java @@ -0,0 +1,50 @@ +/* + * 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 WSActionResultClientEvent extends WSClientEvent { + + public static final String ID = "cb_client_action_result"; + + @NotNull + private final String actionId; + @NotNull + private final Object result; + + public WSActionResultClientEvent( + @NotNull String actionId, + @NotNull Object result + ) { + super(ID, WSConstants.TOPIC_SESSION_ACTION); + this.actionId = actionId; + this.result = result; + } + + @NotNull + public String getActionId() { + return actionId; + } + + @NotNull + public Object getResult() { + return result; + } +} diff --git a/server/bundles/io.cloudbeaver.server/schema/service.events.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.events.graphqls index bd3b47d321..d4bf6ba5a8 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.events.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.events.graphqls @@ -40,6 +40,8 @@ enum CBClientEventId { cb_client_projects_active, cb_client_session_ping, cb_client_cancel_action @since(version: "26.0.2") + cb_client_action_confirmation @since(version: "26.0.3") + cb_client_action_result @since(version: "26.0.3") } "Client subscribes on topic to receive only related events" @@ -144,6 +146,22 @@ type CBActionCancelledEvent implements CBClientEvent @since(version: "26.0.2") { actionId: String! } +"User's action result" +type CBActionResultEvent implements CBClientEvent @since(version: "26.0.3") { + id: CBClientEventId! + topicId: CBEventTopic + actionId: String! + result: Object! +} + +"User's action confirmation" +type CBActionConfirmationEvent implements CBClientEvent @since(version: "26.0.3") { + id: CBClientEventId! + topicId: CBEventTopic + actionId: String! + confirmed: Boolean +} + "Async task info status event" type WSAsyncTaskInfo @since(version: "24.3.1") { id: CBServerEventId! 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 f20670d9ea..55ca50be9a 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 @@ -98,10 +98,17 @@ public class CBClientEventProcessor { } break; } - case WSAiFunctionCallConfirmationClientEvent.ID: { + case WSActionConfirmationClientEvent.ID: { if (webSession instanceof WebSession session) { - var event = (WSAiFunctionCallConfirmationClientEvent) clientEvent; - session.handleAiFunctionConfirmation(event.getTaskId(), event.isConfirmed()); + var event = (WSActionConfirmationClientEvent) clientEvent; + session.handleActionConfirmation(event.getActionId(), event.isConfirmed()); + } + break; + } + case WSActionResultClientEvent.ID: { + if (webSession instanceof WebSession session) { + var event = (WSActionResultClientEvent) clientEvent; + session.handleActionResult(event.getActionId(), event.getResult()); } break; }