Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ function MaestroConsoleInner() {
// Director's Notes Modal
directorNotesOpen,
setDirectorNotesOpen,
// Agent Inbox Modal (Unified Inbox)
agentInboxOpen,
setAgentInboxOpen,
} = useModalActions();

// --- MOBILE LANDSCAPE MODE (reading-only view) ---
Expand Down Expand Up @@ -3009,6 +3012,7 @@ function MaestroConsoleInner() {
setMarketplaceModalOpen,
setSymphonyModalOpen,
setDirectorNotesOpen,
setAgentInboxOpen,
encoreFeatures,
setShowNewGroupChatModal,
deleteGroupChatWithConfirmation,
Expand Down Expand Up @@ -3708,6 +3712,7 @@ function MaestroConsoleInner() {
onOpenDirectorNotes={
encoreFeatures.directorNotes ? () => setDirectorNotesOpen(true) : undefined
}
onOpenAgentInbox={encoreFeatures.unifiedInbox ? () => setAgentInboxOpen(true) : undefined}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Agent Inbox state/callback references =="
rg -n --type=ts --type=tsx -C2 '\bagentInboxOpen\b|\bsetAgentInboxOpen\b|\bonOpenAgentInbox\b'

echo
echo "== Active AgentInboxModal JSX mounts (non-comment lines) =="
rg -nP --type=tsx '^\s*<AgentInboxModal\b' || true

echo
echo "== Any AgentInboxModal mentions (including comments) =="
rg -n --type=tsx 'AgentInboxModal'

Repository: RunMaestro/Maestro

Length of output: 150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check if the file exists and get its line count
if [ -f "src/renderer/App.tsx" ]; then
  echo "== File found: src/renderer/App.tsx =="
  wc -l src/renderer/App.tsx
  
  echo
  echo "== Lines around 3715 (callback setup) =="
  sed -n '3710,3720p' src/renderer/App.tsx
  
  echo
  echo "== Lines 4111-4120 (alleged commented modal) =="
  sed -n '4111,4120p' src/renderer/App.tsx
  
  echo
  echo "== Search for agentInboxOpen references =="
  grep -n 'agentInboxOpen\|setAgentInboxOpen\|onOpenAgentInbox' src/renderer/App.tsx || echo "No matches found"
  
  echo
  echo "== Search for AgentInboxModal mentions =="
  grep -n 'AgentInboxModal' src/renderer/App.tsx || echo "No matches found"
else
  echo "File not found at src/renderer/App.tsx"
  # List the directory structure
  ls -la src/renderer/ 2>/dev/null || echo "src/renderer directory not found"
fi

Repository: RunMaestro/Maestro

Length of output: 1523


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search entire codebase for AgentInboxModal (excluding App.tsx) =="
find . -type f \( -name "*.tsx" -o -name "*.ts" -o -name "*.jsx" -o -name "*.js" \) -not -path "./node_modules/*" -not -path "./.git/*" | xargs grep -l 'AgentInboxModal' 2>/dev/null | grep -v 'App.tsx' || echo "No other files reference AgentInboxModal"

echo
echo "== Verify AgentInboxModal definition/export =="
find . -type f \( -name "*.tsx" -o -name "*.ts" \) -not -path "./node_modules/*" -not -path "./.git/*" | xargs grep -l 'export.*AgentInboxModal\|AgentInboxModal.*=' 2>/dev/null || echo "No definition found"

Repository: RunMaestro/Maestro

Length of output: 239


Unified Inbox callback is wired but modal render is disabled and component doesn't exist.

Line 3715 enables opening the inbox via onOpenAgentInbox callback, but the only AgentInboxModal render block (Lines 4111-4120) is fully commented out with a note that the component is TBD. The component is not defined anywhere in the codebase, making the feature non-functional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/App.tsx` at line 3715, The onOpenAgentInbox prop is wired
(onOpenAgentInbox, setAgentInboxOpen, encoreFeatures.unifiedInbox) but the modal
render (AgentInboxModal) is commented out and the component is missing; restore
or implement the AgentInboxModal component and its render path: either re-enable
the existing render block for AgentInboxModal and ensure a concrete
AgentInboxModal component is created/ exported, or replace the commented block
with a call to a newly implemented AgentInboxModal that accepts isOpen and
onClose (tied to setAgentInboxOpen), and guard its rendering behind
encoreFeatures.unifiedInbox so the callback actually opens a real modal.

autoScrollAiMode={autoScrollAiMode}
setAutoScrollAiMode={setAutoScrollAiMode}
tabSwitcherOpen={tabSwitcherOpen}
Expand Down Expand Up @@ -4103,6 +4108,17 @@ function MaestroConsoleInner() {
</Suspense>
)}

{/* --- AGENT INBOX MODAL (Encore Feature — component TBD) --- */}
{/* Gate: renders only when unifiedInbox encore feature is enabled */}
{/* {encoreFeatures.unifiedInbox && agentInboxOpen && (
<Suspense fallback={null}>
<AgentInboxModal
theme={theme}
onClose={() => setAgentInboxOpen(false)}
/>
</Suspense>
)} */}

{/* --- GIST PUBLISH MODAL --- */}
{/* Supports both file preview tabs and tab context gist publishing */}
{gistPublishModalOpen && (activeFileTab || tabGistContent) && (
Expand Down
11 changes: 11 additions & 0 deletions src/renderer/components/AppModals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,9 @@ export interface AppUtilityModalsProps {
// Director's Notes
onOpenDirectorNotes?: () => void;

// Agent Inbox (Unified Inbox)
onOpenAgentInbox?: () => void;

// Auto-scroll
autoScrollAiMode?: boolean;
setAutoScrollAiMode?: (value: boolean) => void;
Expand Down Expand Up @@ -1060,6 +1063,8 @@ export const AppUtilityModals = memo(function AppUtilityModals({
onOpenSymphony,
// Director's Notes
onOpenDirectorNotes,
// Agent Inbox (Unified Inbox)
onOpenAgentInbox,
// Auto-scroll
autoScrollAiMode,
setAutoScrollAiMode,
Expand Down Expand Up @@ -1218,6 +1223,7 @@ export const AppUtilityModals = memo(function AppUtilityModals({
onOpenLastDocumentGraph={onOpenLastDocumentGraph}
onOpenSymphony={onOpenSymphony}
onOpenDirectorNotes={onOpenDirectorNotes}
onOpenAgentInbox={onOpenAgentInbox}
autoScrollAiMode={autoScrollAiMode}
setAutoScrollAiMode={setAutoScrollAiMode}
/>
Expand Down Expand Up @@ -2013,6 +2019,8 @@ export interface AppModalsProps {
onOpenSymphony?: () => void;
// Director's Notes
onOpenDirectorNotes?: () => void;
// Agent Inbox (Unified Inbox)
onOpenAgentInbox?: () => void;
// Auto-scroll
autoScrollAiMode?: boolean;
setAutoScrollAiMode?: (value: boolean) => void;
Expand Down Expand Up @@ -2337,6 +2345,8 @@ export const AppModals = memo(function AppModals(props: AppModalsProps) {
onOpenSymphony,
// Director's Notes
onOpenDirectorNotes,
// Agent Inbox (Unified Inbox)
onOpenAgentInbox,
// Auto-scroll
autoScrollAiMode,
setAutoScrollAiMode,
Expand Down Expand Up @@ -2651,6 +2661,7 @@ export const AppModals = memo(function AppModals(props: AppModalsProps) {
onOpenMarketplace={onOpenMarketplace}
onOpenSymphony={onOpenSymphony}
onOpenDirectorNotes={onOpenDirectorNotes}
onOpenAgentInbox={onOpenAgentInbox}
autoScrollAiMode={autoScrollAiMode}
setAutoScrollAiMode={setAutoScrollAiMode}
tabSwitcherOpen={tabSwitcherOpen}
Expand Down
18 changes: 18 additions & 0 deletions src/renderer/components/QuickActionsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ interface QuickActionsModalProps {
onOpenSymphony?: () => void;
// Director's Notes
onOpenDirectorNotes?: () => void;
// Agent Inbox (Unified Inbox)
onOpenAgentInbox?: () => void;
// Auto-scroll
autoScrollAiMode?: boolean;
setAutoScrollAiMode?: (value: boolean) => void;
Expand Down Expand Up @@ -204,6 +206,7 @@ export const QuickActionsModal = memo(function QuickActionsModal(props: QuickAct
onOpenLastDocumentGraph,
onOpenSymphony,
onOpenDirectorNotes,
onOpenAgentInbox,
autoScrollAiMode,
setAutoScrollAiMode,
} = props;
Expand Down Expand Up @@ -1034,6 +1037,21 @@ export const QuickActionsModal = memo(function QuickActionsModal(props: QuickAct
},
]
: []),
// Agent Inbox (Unified Inbox) - cross-agent message hub
...(onOpenAgentInbox
? [
{
id: 'agentInbox',
label: 'Unified Inbox',
shortcut: shortcuts.agentInbox,
subtext: 'Open the unified inbox for cross-agent messages',
action: () => {
onOpenAgentInbox();
setQuickActionOpen(false);
},
},
]
: []),
// Auto-scroll toggle
...(setAutoScrollAiMode
? [
Expand Down
134 changes: 133 additions & 1 deletion src/renderer/components/SettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
Clapperboard,
HelpCircle,
AppWindow,
Inbox,
FileText,
} from 'lucide-react';
import { useSettings } from '../hooks';
import type {
Expand Down Expand Up @@ -1234,7 +1236,7 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
tabIndex={-1}
title="Encore Features"
>
<FlaskConical className="w-4 h-4" />
<Sparkles className="w-4 h-4" />
{activeTab === 'encore' && <span>Encore Features</span>}
</button>
<div className="flex-1 flex justify-end items-center pr-4">
Expand Down Expand Up @@ -3638,6 +3640,136 @@ export const SettingsModal = memo(function SettingsModal(props: SettingsModalPro
);
})()}
</div>

{/* Unified Inbox Feature Card */}
<div
className="rounded-lg p-4"
style={{
borderLeft: `3px solid ${encoreFeatures.unifiedInbox ? theme.colors.accent : theme.colors.border}`,
backgroundColor: encoreFeatures.unifiedInbox
? `${theme.colors.accent}08`
: 'transparent',
}}
>
<button
className="w-full flex items-center justify-between text-left"
onClick={() =>
setEncoreFeatures({
...encoreFeatures,
unifiedInbox: !encoreFeatures.unifiedInbox,
})
}
role="switch"
aria-checked={encoreFeatures.unifiedInbox}
>
<div className="flex items-center gap-3">
<Inbox
className="w-5 h-5"
style={{
color: encoreFeatures.unifiedInbox
? theme.colors.accent
: theme.colors.textDim,
}}
/>
<div>
<div
className="text-sm font-bold flex items-center gap-2"
style={{ color: theme.colors.textMain }}
>
Unified Inbox
<span
className="px-1.5 py-0.5 rounded text-[9px] font-bold uppercase"
style={{
backgroundColor: theme.colors.warning + '30',
color: theme.colors.warning,
}}
>
Beta
</span>
</div>
<div className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Aggregated view of pending actions across all agents
</div>
</div>
</div>
<div
className={`relative w-10 h-5 rounded-full transition-colors ${encoreFeatures.unifiedInbox ? '' : 'opacity-50'}`}
style={{
backgroundColor: encoreFeatures.unifiedInbox
? theme.colors.accent
: theme.colors.border,
}}
>
<div
className="absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform"
style={{
transform: encoreFeatures.unifiedInbox
? 'translateX(22px)'
: 'translateX(2px)',
}}
/>
</div>
</button>
</div>

{/* Tab Descriptions Feature Card */}
<div
className="rounded-lg p-4"
style={{
borderLeft: `3px solid ${encoreFeatures.tabDescription ? theme.colors.accent : theme.colors.border}`,
backgroundColor: encoreFeatures.tabDescription
? `${theme.colors.accent}08`
: 'transparent',
}}
>
<button
className="w-full flex items-center justify-between text-left"
onClick={() =>
setEncoreFeatures({
...encoreFeatures,
tabDescription: !encoreFeatures.tabDescription,
})
}
role="switch"
aria-checked={encoreFeatures.tabDescription}
>
<div className="flex items-center gap-3">
<FileText
className="w-5 h-5"
style={{
color: encoreFeatures.tabDescription
? theme.colors.accent
: theme.colors.textDim,
}}
/>
<div>
<div className="text-sm font-bold" style={{ color: theme.colors.textMain }}>
Tab Descriptions
</div>
<div className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Show AI-generated descriptions below tab names for quick context
</div>
</div>
</div>
<div
className={`relative w-10 h-5 rounded-full transition-colors ${encoreFeatures.tabDescription ? '' : 'opacity-50'}`}
style={{
backgroundColor: encoreFeatures.tabDescription
? theme.colors.accent
: theme.colors.border,
}}
>
<div
className="absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform"
style={{
transform: encoreFeatures.tabDescription
? 'translateX(22px)'
: 'translateX(2px)',
}}
/>
</div>
</button>
</div>
</div>
)}
</div>
Expand Down
1 change: 1 addition & 0 deletions src/renderer/constants/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const DEFAULT_SHORTCUTS: Record<string, Shortcut> = {
label: "Director's Notes",
keys: ['Meta', 'Shift', 'o'],
},
agentInbox: { id: 'agentInbox', label: 'Unified Inbox', keys: ['Alt', 'i'] },
};

// Non-editable shortcuts (displayed in help but not configurable)
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/hooks/keyboard/useMainKeyboardHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ export function useMainKeyboardHandler(): UseMainKeyboardHandlerReturn {
e.preventDefault();
ctx.setDirectorNotesOpen?.(true);
trackShortcut('directorNotes');
} else if (ctx.isShortcut(e, 'agentInbox') && ctx.encoreFeatures?.unifiedInbox) {
e.preventDefault();
ctx.setAgentInboxOpen?.(true);
trackShortcut('agentInbox');
} else if (ctx.isShortcut(e, 'jumpToBottom')) {
e.preventDefault();
// Jump to the bottom of the current main panel output (AI logs or terminal output)
Expand Down
12 changes: 11 additions & 1 deletion src/renderer/stores/modalStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ export type ModalId =
// Platform Warnings
| 'windowsWarning'
// Director's Notes
| 'directorNotes';
| 'directorNotes'
// Agent Inbox (Unified Inbox)
| 'agentInbox';

/**
* Type mapping from ModalId to its data type.
Expand Down Expand Up @@ -757,6 +759,10 @@ export function getModalActions() {
setDirectorNotesOpen: (open: boolean) =>
open ? openModal('directorNotes') : closeModal('directorNotes'),

// Agent Inbox Modal (Unified Inbox)
setAgentInboxOpen: (open: boolean) =>
open ? openModal('agentInbox') : closeModal('agentInbox'),

// Lightbox refs replacement - use updateModalData instead
setLightboxIsGroupChat: (isGroupChat: boolean) => updateModalData('lightbox', { isGroupChat }),
setLightboxAllowDelete: (allowDelete: boolean) => updateModalData('lightbox', { allowDelete }),
Expand Down Expand Up @@ -846,6 +852,7 @@ export function useModalActions() {
const symphonyModalOpen = useModalStore(selectModalOpen('symphony'));
const windowsWarningModalOpen = useModalStore(selectModalOpen('windowsWarning'));
const directorNotesOpen = useModalStore(selectModalOpen('directorNotes'));
const agentInboxOpen = useModalStore(selectModalOpen('agentInbox'));

// Get stable actions
const actions = getModalActions();
Expand Down Expand Up @@ -1014,6 +1021,9 @@ export function useModalActions() {
// Director's Notes Modal
directorNotesOpen,

// Agent Inbox Modal (Unified Inbox)
agentInboxOpen,

// Lightbox ref replacements (now stored as data)
lightboxIsGroupChat: lightboxData?.isGroupChat ?? false,
lightboxAllowDelete: lightboxData?.allowDelete ?? false,
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/stores/settingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ export const DEFAULT_ONBOARDING_STATS: OnboardingStats = {

export const DEFAULT_ENCORE_FEATURES: EncoreFeatureFlags = {
directorNotes: false,
unifiedInbox: false,
tabDescription: false,
};

export const DEFAULT_DIRECTOR_NOTES_SETTINGS: DirectorNotesSettings = {
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,8 @@ export interface LeaderboardSubmitResponse {
// Each key is a feature ID, value indicates whether it's enabled
export interface EncoreFeatureFlags {
directorNotes: boolean;
unifiedInbox: boolean;
tabDescription: boolean;
}

// Director's Notes settings for synopsis generation
Expand Down