gui: support multiple concurrent bypass requests per agent
Frontend changes to match the backend's multi-request support: - bypassResolved signal now includes the request ID - ChatPane tracks pendingBypasses as a map (id -> request) - onBypassRequested adds to the map; onBypassResolved removes by ID - currentBypass shows the first pending request for the active agent - Switching agents updates the banner to show that agent's pending request - Approve/Deny now remove only the specific resolved request This allows each agent to have multiple pending bypass requests without blocking other agents, and the banner correctly shows requests only for the currently active agent.
This commit is contained in:
parent
5c0f463e4d
commit
50ebcedb8a
|
|
@ -7,12 +7,27 @@ Item {
|
|||
id: chatPane
|
||||
property bool sidebarVisible: true
|
||||
property int maxVisibleBlocks: 80
|
||||
property var pendingBypass: null // {sessionId, id, cmd, cwd}
|
||||
property bool hasPendingBypass: false
|
||||
// Map of pending bypass requests: id -> {sessionId, agentId, id, cmd, cwd}
|
||||
property var pendingBypasses: ({})
|
||||
property var currentBypass: null // The one currently shown in the banner
|
||||
signal toggleSidebar()
|
||||
// Do not opt the chat pane into focus navigation.
|
||||
activeFocusOnTab: false
|
||||
|
||||
// Helper to get the first pending bypass for the active agent
|
||||
function updateCurrentBypass() {
|
||||
var activeKey = ollie.activeSessionId + ":" + ollie.activeAgentId
|
||||
for (var id in pendingBypasses) {
|
||||
var req = pendingBypasses[id]
|
||||
var key = req.sessionId + ":" + req.agentId
|
||||
if (key === activeKey) {
|
||||
currentBypass = req
|
||||
return
|
||||
}
|
||||
}
|
||||
currentBypass = null
|
||||
}
|
||||
|
||||
// Expose method to set prompt text (for Edit & Resend)
|
||||
function setPromptText(text) {
|
||||
promptInput.text = text
|
||||
|
|
@ -175,7 +190,7 @@ Item {
|
|||
color: "#fff3e0" // amber light
|
||||
border.color: "#ff9800"
|
||||
border.width: 1
|
||||
visible: chatPane.hasPendingBypass
|
||||
visible: chatPane.currentBypass !== null
|
||||
z: 100
|
||||
|
||||
ColumnLayout {
|
||||
|
|
@ -192,7 +207,7 @@ Item {
|
|||
}
|
||||
|
||||
Label {
|
||||
text: chatPane.pendingBypass ? chatPane.pendingBypass.cmd : ""
|
||||
text: chatPane.currentBypass ? chatPane.currentBypass.cmd : ""
|
||||
font.family: "monospace"
|
||||
font.pixelSize: theme.fontSize > 0 ? theme.fontSize : 12
|
||||
wrapMode: Text.WrapAnywhere
|
||||
|
|
@ -201,10 +216,10 @@ Item {
|
|||
}
|
||||
|
||||
Label {
|
||||
text: chatPane.pendingBypass ? "cwd: " + chatPane.pendingBypass.cwd : ""
|
||||
text: chatPane.currentBypass ? "cwd: " + chatPane.currentBypass.cwd : ""
|
||||
font.pixelSize: theme.fontSize > 0 ? theme.fontSize - 1 : 10
|
||||
color: "#666"
|
||||
visible: chatPane.pendingBypass && chatPane.pendingBypass.cwd !== ""
|
||||
visible: chatPane.currentBypass && chatPane.currentBypass.cwd !== ""
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
|
@ -215,10 +230,8 @@ Item {
|
|||
text: "Approve"
|
||||
highlighted: true
|
||||
onClicked: {
|
||||
if (chatPane.pendingBypass) {
|
||||
ollie.resolveBypass(chatPane.pendingBypass.sessionId, chatPane.pendingBypass.agentId, chatPane.pendingBypass.id, true)
|
||||
chatPane.pendingBypass = null
|
||||
chatPane.hasPendingBypass = false
|
||||
if (chatPane.currentBypass) {
|
||||
ollie.resolveBypass(chatPane.currentBypass.sessionId, chatPane.currentBypass.agentId, chatPane.currentBypass.id, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,10 +239,8 @@ Item {
|
|||
Button {
|
||||
text: "Deny"
|
||||
onClicked: {
|
||||
if (chatPane.pendingBypass) {
|
||||
ollie.resolveBypass(chatPane.pendingBypass.sessionId, chatPane.pendingBypass.agentId, chatPane.pendingBypass.id, false)
|
||||
chatPane.pendingBypass = null
|
||||
chatPane.hasPendingBypass = false
|
||||
if (chatPane.currentBypass) {
|
||||
ollie.resolveBypass(chatPane.currentBypass.sessionId, chatPane.currentBypass.agentId, chatPane.currentBypass.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -580,56 +591,46 @@ Connections {
|
|||
target: ollie
|
||||
function onActiveSessionIdChanged() {
|
||||
if (!ollie.activeAgentId) chatPane.loadChat()
|
||||
// Hide bypass banner if it's not for the now-active session
|
||||
if (chatPane.pendingBypass && chatPane.pendingBypass.sessionId !== ollie.activeSessionId) {
|
||||
chatPane.hasPendingBypass = false
|
||||
}
|
||||
// Update current bypass for the new active agent
|
||||
chatPane.updateCurrentBypass()
|
||||
}
|
||||
function onActiveAgentIdChanged() {
|
||||
if (ollie.activeAgentId) chatPane.loadChat()
|
||||
// Hide bypass banner if it's not for the now-active agent
|
||||
if (chatPane.pendingBypass &&
|
||||
(chatPane.pendingBypass.sessionId !== ollie.activeSessionId ||
|
||||
chatPane.pendingBypass.agentId !== ollie.activeAgentId)) {
|
||||
chatPane.hasPendingBypass = false
|
||||
}
|
||||
// Update current bypass for the new active agent
|
||||
chatPane.updateCurrentBypass()
|
||||
}
|
||||
function onBypassRequested(sessionId, agentId, id, cmd, cwd) {
|
||||
// Show bypass request only for the currently active agent
|
||||
if (sessionId === ollie.activeSessionId && agentId === ollie.activeAgentId) {
|
||||
chatPane.pendingBypass = {
|
||||
// Add to pending bypasses map
|
||||
var newMap = chatPane.pendingBypasses
|
||||
newMap[id] = {
|
||||
sessionId: sessionId,
|
||||
agentId: agentId,
|
||||
id: id,
|
||||
cmd: cmd,
|
||||
cwd: cwd
|
||||
}
|
||||
chatPane.hasPendingBypass = true
|
||||
chatPane.pendingBypasses = newMap
|
||||
chatPane.updateCurrentBypass()
|
||||
}
|
||||
}
|
||||
function onBypassResolved(sessionId, agentId) {
|
||||
// Clear bypass banner if it was for this agent (resolved by CLI or another client)
|
||||
if (chatPane.pendingBypass &&
|
||||
chatPane.pendingBypass.sessionId === sessionId &&
|
||||
chatPane.pendingBypass.agentId === agentId) {
|
||||
chatPane.pendingBypass = null
|
||||
chatPane.hasPendingBypass = false
|
||||
function onBypassResolved(sessionId, agentId, requestId) {
|
||||
// Remove the specific resolved request from the map
|
||||
if (chatPane.pendingBypasses[requestId]) {
|
||||
var newMap = chatPane.pendingBypasses
|
||||
delete newMap[requestId]
|
||||
chatPane.pendingBypasses = newMap
|
||||
chatPane.updateCurrentBypass()
|
||||
}
|
||||
}
|
||||
|
||||
// Public functions for keyboard shortcuts
|
||||
function approveBypass() {
|
||||
if (chatPane.pendingBypass) {
|
||||
ollie.resolveBypass(chatPane.pendingBypass.sessionId, chatPane.pendingBypass.agentId, chatPane.pendingBypass.id, true)
|
||||
chatPane.pendingBypass = null
|
||||
chatPane.hasPendingBypass = false
|
||||
if (chatPane.currentBypass) {
|
||||
ollie.resolveBypass(chatPane.currentBypass.sessionId, chatPane.currentBypass.agentId, chatPane.currentBypass.id, true)
|
||||
}
|
||||
}
|
||||
function denyBypass() {
|
||||
if (chatPane.pendingBypass) {
|
||||
ollie.resolveBypass(chatPane.pendingBypass.sessionId, chatPane.pendingBypass.agentId, chatPane.pendingBypass.id, false)
|
||||
chatPane.pendingBypass = null
|
||||
chatPane.hasPendingBypass = false
|
||||
if (chatPane.currentBypass) {
|
||||
ollie.resolveBypass(chatPane.currentBypass.sessionId, chatPane.currentBypass.agentId, chatPane.currentBypass.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ void Ollie9pClient::handleEvent(const QString &eventLine)
|
|||
}
|
||||
emit pendingBypassCountChanged(sidStr, aidStr);
|
||||
}
|
||||
emit bypassResolved(sidStr, aidStr);
|
||||
emit bypassResolved(sidStr, aidStr, id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -895,7 +895,7 @@ bool Ollie9pClient::resolveBypass(const QString &sessionId, const QString &agent
|
|||
m_pendingBypasses.remove(key);
|
||||
}
|
||||
emit pendingBypassCountChanged(sessionId, agentId);
|
||||
emit bypassResolved(sessionId, agentId);
|
||||
emit bypassResolved(sessionId, agentId, id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ signals:
|
|||
void agentStateChanged(const QString &sessionId, const QString &agentId, const QString &state);
|
||||
void chatReceived(const QString &text);
|
||||
void bypassRequested(const QString &sessionId, const QString &agentId, const QString &id, const QString &cmd, const QString &cwd);
|
||||
void bypassResolved(const QString &sessionId, const QString &agentId);
|
||||
void bypassResolved(const QString &sessionId, const QString &agentId, const QString &requestId);
|
||||
void pendingBypassCountChanged(const QString &sessionId, const QString &agentId);
|
||||
void procStarted(const QString &sessionId, const QString &agentId, const QString &payload);
|
||||
void rootBackendsLoadedChanged();
|
||||
|
|
|
|||
Loading…
Reference in New Issue