diff --git a/packages/chrome-extension/src/background.ts b/packages/chrome-extension/src/background.ts index 0e9e326f..bffcbd27 100644 --- a/packages/chrome-extension/src/background.ts +++ b/packages/chrome-extension/src/background.ts @@ -39,6 +39,27 @@ chrome.debugger.onDetach.addListener((source) => { } }); +// Auto-dismiss beforeunload dialogs so agent navigation isn't blocked. +// Regular dialogs (alert/confirm/prompt) are left for the agent to handle +// via handle_dialog, but a notification event is sent. +chrome.debugger.onEvent.addListener((source, method, params) => { + if (method !== 'Page.javascriptDialogOpening' || !source.tabId) return; + const p = params as { type?: string; message?: string; url?: string }; + + if (p.type === 'beforeunload') { + chrome.debugger.sendCommand(source, 'Page.handleJavaScriptDialog', { accept: true }) + .catch(() => { /* tab may have closed */ }); + console.log(`[Markus] Auto-dismissed beforeunload dialog on tab ${source.tabId}`); + return; + } + + const pageId = pm.peekPageId(source.tabId); + client.send({ + event: 'dialog_opened', + data: { tabId: source.tabId, pageId, type: p.type, message: p.message }, + }); +}); + // Handle popup status queries chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => { if (msg.type === 'getStatus') { diff --git a/packages/web-ui/src/components/ChatTeamSidebar.tsx b/packages/web-ui/src/components/ChatTeamSidebar.tsx index 4a3fe263..bf428f95 100644 --- a/packages/web-ui/src/components/ChatTeamSidebar.tsx +++ b/packages/web-ui/src/components/ChatTeamSidebar.tsx @@ -887,46 +887,18 @@ export function ChatTeamSidebar({ return ( <>
- {/* Header with title + pause toggle */} + {/* Header with title + manage button */}
{isMobile && }

{t('chat.title')}

-
- {globalPaused === null ? ( - - - {t('common:status.loading', { defaultValue: '...' })} - - ) : ( - - )} -
-
- {/* Action bar */} - {isAdmin && ( -
-
+ {isAdmin && ( +
@@ -936,10 +908,9 @@ export function ChatTeamSidebar({ const rect = el.getBoundingClientRect(); const vw = window.innerWidth; const pad = 8; - if (rect.right > vw - pad) el.style.left = 'auto'; - if (rect.right > vw - pad) el.style.right = '0'; + if (rect.right > vw - pad) { el.style.left = 'auto'; el.style.right = '0'; } if (rect.left < pad) { el.style.left = '0'; el.style.right = 'auto'; } - }} className="absolute left-0 top-full mt-1 w-48 max-w-[calc(100vw-1rem)] bg-surface-secondary border border-border-default rounded-lg shadow-xl z-30 overflow-hidden"> + }} className="absolute right-0 top-full mt-1 w-48 max-w-[calc(100vw-1rem)] bg-surface-secondary border border-border-default rounded-lg shadow-xl z-30 overflow-hidden"> + {globalPaused !== null && ( + + )}
)}
-
- )} + )} +
{/* Sidebar content */}
diff --git a/packages/web-ui/src/components/NotificationBell.tsx b/packages/web-ui/src/components/NotificationBell.tsx index 19ce64f6..e28e95b6 100644 --- a/packages/web-ui/src/components/NotificationBell.tsx +++ b/packages/web-ui/src/components/NotificationBell.tsx @@ -420,6 +420,7 @@ export function NotificationBell({ collapsed, userId, embeddedMode, onClose, sid invalidateApiCache('/approvals'); invalidateApiCache('/notifications'); invalidateApiCache('/tasks'); + invalidateApiCache('/taskboard'); invalidateApiCache('/requirements'); window.dispatchEvent(new CustomEvent('markus:data-changed')); setTimeout(() => fetchData(), 800); diff --git a/packages/web-ui/src/locales/en/agent.json b/packages/web-ui/src/locales/en/agent.json index 9e6bb0b4..7e6f5a72 100644 --- a/packages/web-ui/src/locales/en/agent.json +++ b/packages/web-ui/src/locales/en/agent.json @@ -342,6 +342,10 @@ "since": "since {{time}}", "refresh": "↻ Refresh", "queue": "Queue ({{count}})", + "expandQueue": "Show {{count}} more…", + "collapseQueue": "Collapse", + "staleProcessingWarning": "Stale processing items detected (agent is idle)", + "agentDetails": "Agent Details", "triageDecision": "Triage Decision", "processingItem": "Processing: {{id}}…", "deferred": "Deferred: {{count}}", diff --git a/packages/web-ui/src/locales/zh-CN/agent.json b/packages/web-ui/src/locales/zh-CN/agent.json index 46a10db1..a24fbdc8 100644 --- a/packages/web-ui/src/locales/zh-CN/agent.json +++ b/packages/web-ui/src/locales/zh-CN/agent.json @@ -342,6 +342,10 @@ "since": "自 {{time}} 起", "refresh": "↻ 刷新", "queue": "队列({{count}})", + "expandQueue": "展开剩余 {{count}} 项…", + "collapseQueue": "收起", + "staleProcessingWarning": "存在异常处理中项目(Agent 已空闲)", + "agentDetails": "Agent 详情", "triageDecision": "分拣决策", "processingItem": "处理中:{{id}}…", "deferred": "已推迟:{{count}}", diff --git a/packages/web-ui/src/pages/AgentBuilder.tsx b/packages/web-ui/src/pages/AgentBuilder.tsx index 62be5a7f..79f50814 100644 --- a/packages/web-ui/src/pages/AgentBuilder.tsx +++ b/packages/web-ui/src/pages/AgentBuilder.tsx @@ -577,13 +577,13 @@ export function AgentBuilder({ authUser }: { authUser?: AuthUser } = {}) { )} {sharePrompt && (
setSharePrompt(null)}> -
e.stopPropagation()}> +
e.stopPropagation()}>

{t('common:share')}

{t('share.imagePrompt')}

- {(mind?.queuedItems?.length ?? 0) > 0 && ( -
-

{t('agent:profilePage.mind.queue', { count: mind!.queuedItems.length })}

-
- {mind!.queuedItems.map((item, i) => ( -
- {i + 1} - {MAILBOX_TYPE_ICONS[item.sourceType] ?? '●'} - {t(`agent:profilePage.mind.priority.${PRIORITY_KEYS[item.priority] ?? item.priority}`, { defaultValue: `P${item.priority}` })} - {item.summary} - {new Date(item.queuedAt).toLocaleTimeString()} -
- ))} -
+ {hasStaleProcessingItems && ( +
+ + {t('agent:profilePage.mind.staleProcessingWarning')}
)} + + {(mind?.queuedItems?.length ?? 0) > 0 && (() => { + const items = mind!.queuedItems; + const shouldCollapse = items.length > QUEUE_COLLAPSE_THRESHOLD; + const visibleItems = shouldCollapse && !queueExpanded ? items.slice(0, QUEUE_COLLAPSE_THRESHOLD) : items; + const typeCounts = items.reduce>((acc, item) => { + acc[item.sourceType] = (acc[item.sourceType] ?? 0) + 1; + return acc; + }, {}); + return ( +
+
+

{t('agent:profilePage.mind.queue', { count: items.length })}

+
+ {Object.entries(typeCounts).map(([type, count]) => ( + + {MAILBOX_TYPE_ICONS[type] ?? '●'} {count} + + ))} +
+
+
+ {visibleItems.map((item, i) => ( +
+ {i + 1} + {MAILBOX_TYPE_ICONS[item.sourceType] ?? '●'} + {t(`agent:profilePage.mind.priority.${PRIORITY_KEYS[item.priority] ?? item.priority}`, { defaultValue: `P${item.priority}` })} + {item.summary} + {new Date(item.queuedAt).toLocaleTimeString()} +
+ ))} + {shouldCollapse && ( + + )} +
+
+ ); + })()} {/* ── Last Triage Decision ── */} - {mind?.lastTriage && ( -
-
- 🧠 -

{t('agent:profilePage.mind.triageDecision')}

- {new Date(mind.lastTriage.timestamp).toLocaleTimeString()} -
-

{mind.lastTriage.reasoning}

-
- {t('agent:profilePage.mind.processingItem', { id: mind.lastTriage.processedItemId.slice(0, 12) })} - {mind.lastTriage.deferredItemIds.length > 0 && ( - {t('agent:profilePage.mind.deferred', { count: mind.lastTriage.deferredItemIds.length })} - )} - {mind.lastTriage.droppedItemIds.length > 0 && ( - {t('agent:profilePage.mind.dropped', { count: mind.lastTriage.droppedItemIds.length })} - )} - {(mind.lastTriage.inlineCompletedIds?.length ?? 0) > 0 && ( - {t('agent:profilePage.mind.inlineCompleted', { count: mind.lastTriage.inlineCompletedIds!.length })} - )} -
-
- )} + {mind?.lastTriage && (() => { + const triageAgeMs = Date.now() - new Date(mind.lastTriage.timestamp).getTime(); + const isStale = triageAgeMs > 60_000; + return ( +
+
+ + 🧠 +

{t('agent:profilePage.mind.triageDecision')}

+ {new Date(mind.lastTriage.timestamp).toLocaleTimeString()} +
+

{mind.lastTriage.reasoning}

+
+ {t('agent:profilePage.mind.processingItem', { id: mind.lastTriage.processedItemId.slice(0, 12) })} + {mind.lastTriage.deferredItemIds.length > 0 && ( + {t('agent:profilePage.mind.deferred', { count: mind.lastTriage.deferredItemIds.length })} + )} + {mind.lastTriage.droppedItemIds.length > 0 && ( + {t('agent:profilePage.mind.dropped', { count: mind.lastTriage.droppedItemIds.length })} + )} + {(mind.lastTriage.inlineCompletedIds?.length ?? 0) > 0 && ( + {t('agent:profilePage.mind.inlineCompleted', { count: mind.lastTriage.inlineCompletedIds!.length })} + )} +
+
+
+ ); + })()} {/* ── Mailbox History ── */}
diff --git a/packages/web-ui/src/pages/ArtifactDetail.tsx b/packages/web-ui/src/pages/ArtifactDetail.tsx index a3436906..87a46971 100644 --- a/packages/web-ui/src/pages/ArtifactDetail.tsx +++ b/packages/web-ui/src/pages/ArtifactDetail.tsx @@ -995,17 +995,17 @@ export function ArtifactDetail({ type, name, onBack, authUser: _authUser, readOn {/* Version bump notification */} {!readOnly && contentDirty && !showVersionBump && ( -
- {t('versionBump.contentModified')} -
)} {!readOnly && showVersionBump && ( -
+
- {t('versionBump.newVersion')} + {t('versionBump.newVersion')} { @@ -1023,7 +1023,7 @@ export function ArtifactDetail({ type, name, onBack, authUser: _authUser, readOn