Skip to content

Commit

Permalink
feat: hide not finished agents + add request logo
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminshafii committed Jan 7, 2025
1 parent 33f8f68 commit 9eea0d6
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 77 deletions.
6 changes: 3 additions & 3 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ Assistant Guidelines:

Project Structure:
- Main app is in packages/desktop
- Frontend: packages/desktop/src/renderer
- Backend: packages/desktop/src/electron
- packages/landing-v0 containts landing page and in the future all account logins and signups
- Frontend: packages/desktop/src/renderer (vite)
- Backend: packages/desktop/src/electron (electron)
- packages/landing-v0 containts landing page and in the future all account logins and signups (nextjs app dir)



Expand Down
12 changes: 10 additions & 2 deletions packages/desktop/src/agents/add-to-mac-calendar-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,18 @@ const AddToCalendarUI: React.FC<AddToCalendarUIProps> = ({

export const AddToMacCalendarAgent: Agent = {
id: 'add-to-mac-calendar',
name: 'Add to Calendar',
description: 'Creates calendar events from detected content',
name: 'Calendar Manager',
description: 'Automatically adds events to your Mac calendar',
type: 'event' as AgentType,
isActive: true,
isReady: false,
miniApp: () => <AddToCalendarUI context={{
id: 'preview',
title: 'Calendar Preview',
vitalInformation: '',
type: 'event',
source: 'preview'
}} />,

eventAction(context: RecognizedContext, onSuccess?: () => void): React.ReactNode {
return <AddToCalendarUI context={context} onSuccess={onSuccess} />;
Expand Down
7 changes: 5 additions & 2 deletions packages/desktop/src/agents/base-agent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ReactNode } from 'react';
import { RecognizedContext } from '@/components/event-classification';

export type AgentType = 'invoice' | 'calendar' | 'task' | 'event' | 'goal';
export type AgentType = 'task' | 'event' | 'invoice' | 'goal' | 'business';

export interface RecognizedContext {
id: string;
Expand All @@ -13,11 +14,13 @@ export interface RecognizedContext {
export interface Agent {
id: string;
name: string;
displayName?: () => ReactNode;
description: string;
type: AgentType;
isActive: boolean;
eventAction: (context: RecognizedContext, onSuccess?: () => void) => ReactNode;
isReady: boolean;
miniApp?: () => ReactNode;
eventAction(context: RecognizedContext, onSuccess?: () => void): ReactNode;
}

export interface ClassificationResult {
Expand Down
1 change: 1 addition & 0 deletions packages/desktop/src/agents/business-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ export const BusinessAgent: Agent = {
description: 'Automatically processes and stores business-related information from your screen content',
type: 'business' as AgentType,
isActive: true,
isReady: false,
miniApp: () => <BusinessInfoView />,

eventAction(context: RecognizedContext, onSuccess?: () => void): React.ReactNode {
Expand Down
10 changes: 5 additions & 5 deletions packages/desktop/src/agents/goal-planning-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,14 +351,14 @@ const GoalPlanningDashboard: React.FC = () => {

export const GoalPlanningAgent: Agent = {
id: 'goal-planning',
name: 'Goal Planning',
description: 'Analyzes markdown files to extract and track goals',
name: 'Goal Planner',
description: 'Helps you track and manage your goals and objectives',
type: 'goal' as AgentType,
isActive: true,

isReady: false,
miniApp: () => <GoalPlanningDashboard />,

eventAction(context: RecognizedContext, onSuccess?: () => void): React.ReactNode {
return <GoalPlanningUI context={context} onSuccess={onSuccess} />;
},

miniApp: () => <GoalPlanningDashboard />,
};
116 changes: 68 additions & 48 deletions packages/desktop/src/agents/invoice-agent.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Agent, RecognizedContext, AgentType } from './base-agent';
import * as React from 'react';
import { Button } from '../components/ui/button';
import {
Dialog,
DialogContent,
DialogTrigger,
} from '@/components/ui/dialog';
import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
import { useState, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import requestLogo from '@/assets/request-req-logo.png';
import {
Table,
TableBody,
Expand Down Expand Up @@ -41,6 +38,16 @@ interface InvoiceAgentUIProps {
onSuccess?: () => void;
}

const RequestLogo = ({ className }: { className?: string }) => (
<img
src={requestLogo}
alt="Request Network"
width={20}
height={20}
className={className}
/>
);

const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
context,
onSuccess,
Expand All @@ -53,7 +60,7 @@ const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
if (open && !result && !isProcessing) {
console.log('0xHypr', 'Modal opened, starting invoice processing', {
contextId: context.id,
vitalInfo: context.vitalInformation
vitalInfo: context.vitalInformation,
});
processInvoice(context.vitalInformation);
}
Expand All @@ -72,16 +79,18 @@ const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
console.log('0xHypr', 'Transforming invoice data:', invoice);

// Transform buyerInfo to ensure miscellaneous is a Record<string, unknown>
const transformedBuyerInfo: BusinessInfo | undefined = invoice.buyerInfo ? {
businessName: invoice.buyerInfo.businessName || '',
email: invoice.buyerInfo.email,
firstName: invoice.buyerInfo.firstName,
lastName: invoice.buyerInfo.lastName,
phone: invoice.buyerInfo.phone,
address: invoice.buyerInfo.address,
taxRegistration: invoice.buyerInfo.taxRegistration,
miscellaneous: {},
} : undefined;
const transformedBuyerInfo: BusinessInfo | undefined = invoice.buyerInfo
? {
businessName: invoice.buyerInfo.businessName || '',
email: invoice.buyerInfo.email,
firstName: invoice.buyerInfo.firstName,
lastName: invoice.buyerInfo.lastName,
phone: invoice.buyerInfo.phone,
address: invoice.buyerInfo.address,
taxRegistration: invoice.buyerInfo.taxRegistration,
miscellaneous: {},
}
: undefined;

const transformedValues: Partial<ExtendedInvoice> = {
sellerInfo: {
Expand All @@ -95,25 +104,28 @@ const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
miscellaneous: invoice.sellerInfo?.miscellaneous || {},
},
buyerInfo: transformedBuyerInfo,
invoiceItems: invoice.invoiceItems?.map(item => ({
name: item.name || 'Untitled Item',
quantity: item.quantity || 1,
unitPrice: item.unitPrice || '0',
currency: item.currency || 'ETH',
tax: {
type: item.tax?.type || 'percentage',
amount: item.tax?.amount || '0'
},
reference: item.reference || '',
deliveryDate: item.deliveryDate || new Date().toISOString(),
deliveryPeriod: item.deliveryPeriod || '',
})) || [],
paymentTerms: invoice.paymentTerms ? {
dueDate: invoice.paymentTerms.dueDate,
lateFeesPercent: invoice.paymentTerms.lateFeesPercent,
lateFeesFix: invoice.paymentTerms.lateFeesFix,
miscellaneous: {},
} as ExtendedPaymentTerms : undefined,
invoiceItems:
invoice.invoiceItems?.map((item) => ({
name: item.name || 'Untitled Item',
quantity: item.quantity || 1,
unitPrice: item.unitPrice || '0',
currency: item.currency || 'ETH',
tax: {
type: item.tax?.type || 'percentage',
amount: item.tax?.amount || '0',
},
reference: item.reference || '',
deliveryDate: item.deliveryDate || new Date().toISOString(),
deliveryPeriod: item.deliveryPeriod || '',
})) || [],
paymentTerms: invoice.paymentTerms
? ({
dueDate: invoice.paymentTerms.dueDate,
lateFeesPercent: invoice.paymentTerms.lateFeesPercent,
lateFeesFix: invoice.paymentTerms.lateFeesFix,
miscellaneous: {},
} as ExtendedPaymentTerms)
: undefined,
note: invoice.note || '',
terms: invoice.terms || '',
purchaseOrderId: invoice.purchaseOrderId,
Expand All @@ -128,7 +140,7 @@ const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
from: open,
to: newOpen,
hasResult: !!result,
isProcessing
isProcessing,
});
setOpen(newOpen);
};
Expand All @@ -142,15 +154,15 @@ const InvoiceAgentUI: React.FC<InvoiceAgentUIProps> = ({
return (
<div className="flex items-center justify-between p-4 border-b">
<div className="flex flex-col">
<h3 className="font-medium">Invoice Request</h3>
<div className="flex items-center gap-2">
<h3 className="font-medium">Invoice Request</h3>
<RequestLogo className="opacity-80" />
</div>
<p className="text-sm text-muted-foreground">{context.title}</p>
</div>
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogTrigger asChild>
<Button
variant="outline"
disabled={isProcessing}
>
<Button variant="outline" disabled={isProcessing}>
{isProcessing ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Expand Down Expand Up @@ -243,9 +255,7 @@ const RequestsView: React.FC = () => {
{request.amount} {request.currency.value}
</TableCell>
<TableCell>{request.status}</TableCell>
<TableCell>
{request.payer?.value || 'No recipient'}
</TableCell>
<TableCell>{request.payer?.value || 'No recipient'}</TableCell>
</TableRow>
))}
</TableBody>
Expand All @@ -255,15 +265,25 @@ const RequestsView: React.FC = () => {
};

export const InvoiceAgent: Agent = {
id: 'request-network-agent',
name: 'Automatically Create Request Network Invoice',
id: 'invoice-agent',
name: 'Invoice Manager',
displayName: () => (
<div className="flex items-center gap-2">
<RequestLogo />
Invoice Manager
</div>
),
description:
'Automatically creates invoices for your workflow based on your screen content',
'Automatically processes and creates invoices from detected content',
type: 'invoice' as AgentType,
isActive: true,
isReady: true,
miniApp: () => <RequestsView />,

eventAction(context: RecognizedContext, onSuccess?: () => void): React.ReactNode {
eventAction(
context: RecognizedContext,
onSuccess?: () => void
): React.ReactNode {
return <InvoiceAgentUI context={context} onSuccess={onSuccess} />;
},
};
5 changes: 3 additions & 2 deletions packages/desktop/src/agents/task-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -506,10 +506,11 @@ const TaskDashboardView: React.FC = () => {

export const AddTaskToObsidianAgent: Agent = {
id: 'add-task-to-obsidian',
name: 'Add Task to Obsidian',
description: 'Creates tasks in your Obsidian vault from detected content',
name: 'Task Manager',
description: 'Automatically adds tasks to your Obsidian vault',
type: 'task' as AgentType,
isActive: true,
isReady: false,
miniApp: () => <TaskDashboardView />,

eventAction(context: RecognizedContext, onSuccess?: () => void): React.ReactNode {
Expand Down
Binary file added packages/desktop/src/assets/request-req-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 21 additions & 7 deletions packages/desktop/src/components/active-agents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React from 'react';
import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { useClassificationStore } from '@/stores/classification-store';
import { useDashboardStore } from '@/stores/dashboard-store';

export function ActiveAgents() {
const { agents, recognizedItems } = useClassificationStore();
const isDemoMode = useDashboardStore((state) => state.isDemoMode);

// Ensure recognizedItems is always an array
const items = Array.isArray(recognizedItems) ? recognizedItems : [];
Expand All @@ -15,7 +17,6 @@ export function ActiveAgents() {
today.setHours(0, 0, 0, 0);

const todayItems = agentItems.filter(item => {

const itemDate = new Date(item.data.startTime);
return itemDate >= today;
});
Expand All @@ -26,15 +27,22 @@ export function ActiveAgents() {
};
};

const activeAgents = agents.filter(agent => agent.isActive);
const activeAgents = agents.filter(agent =>
agent.isActive && (isDemoMode || agent.isReady)
);

return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-2xl font-bold">Active Agents</h2>
<Badge variant="outline">
{activeAgents.length} Active
</Badge>
<div className="flex gap-2">
{isDemoMode && (
<Badge variant="secondary">Demo Mode</Badge>
)}
<Badge variant="outline">
{activeAgents.length} Active
</Badge>
</div>
</div>

<div className="grid gap-4">
Expand All @@ -45,8 +53,11 @@ export function ActiveAgents() {
<Card key={agent.id} className="hover:shadow-md transition-shadow">
<CardContent className="py-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<span className="font-medium">{agent.name}</span>
<div className="flex flex-col">
{agent.displayName ? agent.displayName() : <span className="font-medium">{agent.name}</span>}
{!agent.isReady && (
<span className="text-xs text-muted-foreground">Demo Only</span>
)}
</div>
<div className="flex items-center space-x-2">
<Badge variant="secondary" className="text-xs">
Expand All @@ -66,6 +77,9 @@ export function ActiveAgents() {
<Card>
<CardContent className="p-6 text-center text-muted-foreground">
<p>No active agents</p>
{!isDemoMode && (
<p className="text-sm mt-2">Enable demo mode to see all available agents</p>
)}
</CardContent>
</Card>
)}
Expand Down
12 changes: 7 additions & 5 deletions packages/desktop/src/components/ai-agent-store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export function AIAgentStore() {
};

const currentViewingAgent = agents.find(agent => agent.id === viewingAgent);

const visibleAgents = agents.filter(agent => isDemoMode || agent.isReady);

return (
<>
Expand All @@ -35,21 +37,21 @@ export function AIAgentStore() {
<CardDescription>Enable or disable AI agents</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-4">
{agents.map((agent) => (
{visibleAgents.map((agent) => (
<div key={agent.id} className="flex items-center justify-between">
<div>
<h3 className="font-medium">{agent.name}</h3>
{agent.displayName ? agent.displayName() : <h3 className="font-medium">{agent.name}</h3>}
<p className="text-sm text-muted-foreground">{agent.description}</p>
</div>
<div className="flex items-center gap-2">
{agent.miniApp && (
<Button
variant="ghost"
size="icon"
// size="icon"
onClick={() => setViewingAgent(agent.id)}
className="h-8 w-8"
// className="h-8 w-8"
>
<Eye className="h-4 w-4" />
Open Agent
</Button>
)}
<Button
Expand Down
Loading

0 comments on commit 9eea0d6

Please sign in to comment.