This commit is contained in:
ZacharyZhang-NY committed 2026-03-17 12:31:06 -04:00
1 parent 54bcc77ef7
commit 7a3db27ffa
33 files changed
+5906 -3089

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
import type { DepartmentId } from "./types";
export const DEPARTMENT_LABELS: Record<string, string> = {
executive: "Executive Suite",
engineering: "Engineering",
product: "Product & Design",
marketing: "Marketing",
sales: "Sales & BD",
hr: "People & Culture",
finance: "Finance & Legal",
legal: "Legal",
operations: "Operations",
customer_support: "Customer Success",
research: "Research",
design: "Design",
};
export const DEPARTMENT_OPTIONS: Array<{ value: DepartmentId | ""; label: string }> = [
{ value: "", label: "Any department" },
{ value: "executive", label: "Executive" },
{ value: "engineering", label: "Engineering" },
{ value: "product", label: "Product" },
{ value: "marketing", label: "Marketing" },
{ value: "sales", label: "Sales" },
{ value: "hr", label: "Human Resources" },
{ value: "finance", label: "Finance" },
{ value: "legal", label: "Legal" },
{ value: "operations", label: "Operations" },
{ value: "customer_support", label: "Customer Support" },
{ value: "research", label: "Research" },
{ value: "design", label: "Design" },
];
export const DEPARTMENT_COLORS: Record<DepartmentId, string> = {
executive: "#8b5cf6",
engineering: "#3b82f6",
product: "#f59e0b",
marketing: "#ec4899",
sales: "#10b981",
hr: "#6366f1",
finance: "#14b8a6",
legal: "#a78bfa",
operations: "#f97316",
customer_support: "#06b6d4",
research: "#8b5cf6",
design: "#f43f5e",
};
+24 -29
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import type { AgentMessageRecord, AgentMetrics, AutomationRuleRecord, BrowserActionRecord, CommentRecord, CompanyMetrics, CompanyTemplate, DesktopEvent, DocumentRecord, InboxItem, KnowledgeEntryRecord, MeetingRecord, ProfileSnapshot, SocialAccountRecord, SprintRecord, StandupReport, WorkflowPipelineRecord } from "./types";
import type { AgentMessageRecord, AgentMetrics, BrowserActionRecord, CommentRecord, CompanyMetrics, CompanyTemplate, DesktopEvent, InboxItem, ProfileSnapshot, StandupReport } from "./types";
export const IPC_CHANNELS = {
loadSnapshot: "agent-company:load-snapshot",
@@ -41,7 +41,6 @@ export const IPC_CHANNELS = {
getApiPort: "agent-company:get-api-port",
rendererEvent: "agent-company:event",
getInbox: "agent-company:get-inbox",
dismissInboxItem: "agent-company:dismiss-inbox-item",
getCompanyMetrics: "agent-company:get-company-metrics",
getAgentMetrics: "agent-company:get-agent-metrics",
getStandupReport: "agent-company:get-standup-report",
@@ -52,32 +51,24 @@ export const IPC_CHANNELS = {
listBrowserActions: "agent-company:list-browser-actions",
cancelBrowserAction: "agent-company:cancel-browser-action",
triggerBrowserLogin: "agent-company:trigger-browser-login",
// Meetings
saveMeeting: "agent-company:save-meeting",
deleteMeeting: "agent-company:delete-meeting",
// Documents
saveDocument: "agent-company:save-document",
deleteDocument: "agent-company:delete-document",
// Knowledge Base
saveKnowledgeEntry: "agent-company:save-knowledge-entry",
deleteKnowledgeEntry: "agent-company:delete-knowledge-entry",
// Sprints
saveSprint: "agent-company:save-sprint",
deleteSprint: "agent-company:delete-sprint",
// Automation
saveAutomationRule: "agent-company:save-automation-rule",
deleteAutomationRule: "agent-company:delete-automation-rule",
toggleAutomationRule: "agent-company:toggle-automation-rule",
getAutomationLog: "agent-company:get-automation-log",
// Agent Messages
sendAgentMessage: "agent-company:send-agent-message",
listAgentMessages: "agent-company:list-agent-messages",
markMessageRead: "agent-company:mark-message-read",
// Workflows
saveWorkflow: "agent-company:save-workflow",
deleteWorkflow: "agent-company:delete-workflow",
runWorkflow: "agent-company:run-workflow",
// Auto-assign
autoAssignTask: "agent-company:auto-assign-task",
} as const;
@@ -175,6 +166,7 @@ export const approvalInputSchema = z.object({
});
export const approvalDecisionSchema = z.object({
companyId: z.string().uuid(),
approvalId: z.string().uuid(),
state: z.enum(["approved", "rejected", "revision_requested"]),
decisionNote: z.string().max(400).default(""),
@@ -211,6 +203,7 @@ export const sidebarBadgesSchema = z.object({
failedRuns: z.number(),
todoTasks: z.number(),
budgetWarnings: z.number(),
unreadMessages: z.number(),
});
export type SidebarBadges = z.infer<typeof sidebarBadgesSchema>;
@@ -245,11 +238,6 @@ export const triggerHeartbeatSchema = z.object({
trigger: z.enum(["manual", "timer", "assignment", "goal_activated", "approval_resolved", "subtask_completed", "comment", "report_blocked", "report_failed", "recovery", "message", "peer_request"]).default("manual"),
});
export const inboxDismissSchema = z.object({
itemId: z.string(),
companyId: z.string().uuid(),
});
export const metricsQuerySchema = z.object({
companyId: z.string().uuid(),
agentId: z.string().uuid().optional(),
@@ -342,7 +330,6 @@ export const browserActionQuerySchema = z.object({
limit: z.number().int().min(1).max(100).default(50),
});
// ── Automation Schemas ──────────────────────────────────────────────────
export const automationRuleInputSchema = z.object({
id: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
companyId: z.string().uuid(),
@@ -391,8 +378,9 @@ export const messageQuerySchema = z.object({
companyId: z.string().uuid(),
agentId: z.string().uuid().optional(),
channel: z.enum(["direct", "department", "company", "project", "incident"]).optional(),
channelTargetId: z.string().nullable().optional(),
unreadOnly: z.boolean().optional(),
limit: z.number().int().min(1).max(200).default(50),
limit: z.number().int().min(1).max(500).default(200),
});
export const workflowInputSchema = z.object({
@@ -411,6 +399,22 @@ export const workflowInputSchema = z.object({
status: z.enum(["draft", "active", "paused", "completed", "failed"]).default("draft"),
});
export const toggleAutomationRuleSchema = z.object({
id: z.string().uuid(),
companyId: z.string().uuid(),
status: z.enum(["active", "paused"]),
});
export const markMessageReadSchema = z.object({
messageId: z.string().uuid(),
companyId: z.string().uuid(),
});
export const runWorkflowSchema = z.object({
id: z.string().uuid(),
companyId: z.string().uuid(),
});
export const autoAssignSchema = z.object({
taskId: z.string().uuid(),
companyId: z.string().uuid(),
@@ -459,7 +463,6 @@ export type DesktopApi = {
triggerHeartbeat: (input: z.infer<typeof triggerHeartbeatSchema>) => Promise<DesktopResult<string>>;
getApiPort: () => Promise<DesktopResult<number>>;
getInbox: (companyId: string) => Promise<DesktopResult<InboxItem[]>>;
dismissInboxItem: (input: z.infer<typeof inboxDismissSchema>) => Promise<DesktopResult<boolean>>;
getCompanyMetrics: (input: z.infer<typeof metricsQuerySchema>) => Promise<DesktopResult<CompanyMetrics>>;
getAgentMetrics: (input: z.infer<typeof metricsQuerySchema>) => Promise<DesktopResult<AgentMetrics>>;
getStandupReport: (companyId: string) => Promise<DesktopResult<StandupReport>>;
@@ -470,32 +473,24 @@ export type DesktopApi = {
listBrowserActions: (input: z.infer<typeof browserActionQuerySchema>) => Promise<DesktopResult<BrowserActionRecord[]>>;
cancelBrowserAction: (input: z.infer<typeof cancelRunSchema>) => Promise<DesktopResult<boolean>>;
triggerBrowserLogin: (socialAccountId: string) => Promise<DesktopResult<boolean>>;
// Meetings
saveMeeting: (input: z.infer<typeof meetingInputSchema>) => Promise<DesktopResult<string>>;
deleteMeeting: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
// Documents
saveDocument: (input: z.infer<typeof documentInputSchema>) => Promise<DesktopResult<string>>;
deleteDocument: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
// Knowledge Base
saveKnowledgeEntry: (input: z.infer<typeof knowledgeEntryInputSchema>) => Promise<DesktopResult<string>>;
deleteKnowledgeEntry: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
// Sprints
saveSprint: (input: z.infer<typeof sprintInputSchema>) => Promise<DesktopResult<string>>;
deleteSprint: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
// Automation
saveAutomationRule: (input: z.infer<typeof automationRuleInputSchema>) => Promise<DesktopResult<string>>;
deleteAutomationRule: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
toggleAutomationRule: (input: { id: string; companyId: string; status: "active" | "paused" }) => Promise<DesktopResult<boolean>>;
toggleAutomationRule: (input: z.infer<typeof toggleAutomationRuleSchema>) => Promise<DesktopResult<boolean>>;
getAutomationLog: (companyId: string) => Promise<DesktopResult<Array<{ ruleId: string; ruleName: string; trigger: string; action: string; executedAt: string }>>>;
// Agent Messages
sendAgentMessage: (input: z.infer<typeof agentMessageInputSchema>) => Promise<DesktopResult<string>>;
listAgentMessages: (input: z.infer<typeof messageQuerySchema>) => Promise<DesktopResult<AgentMessageRecord[]>>;
markMessageRead: (input: { messageId: string; companyId: string }) => Promise<DesktopResult<boolean>>;
// Workflows
markMessageRead: (input: z.infer<typeof markMessageReadSchema>) => Promise<DesktopResult<boolean>>;
saveWorkflow: (input: z.infer<typeof workflowInputSchema>) => Promise<DesktopResult<string>>;
deleteWorkflow: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
runWorkflow: (input: { id: string; companyId: string }) => Promise<DesktopResult<boolean>>;
// Auto-assign
runWorkflow: (input: z.infer<typeof runWorkflowSchema>) => Promise<DesktopResult<boolean>>;
autoAssignTask: (input: z.infer<typeof autoAssignSchema>) => Promise<DesktopResult<string>>;
subscribe: (callback: (event: DesktopEvent) => void) => () => void;
};
+4 -75
View File
@@ -122,7 +122,6 @@ export interface WorkspaceRecord {
updatedAt: string;
}
// ── Departments ────────────────────────────────────────────────────────
export type DepartmentId =
| "executive"
| "engineering"
@@ -298,7 +297,6 @@ export interface ProfileSnapshot {
secrets: SecretRecord[];
comments: CommentRecord[];
socialAccounts: SocialAccountRecord[];
browserActions: BrowserActionRecord[];
meetings: MeetingRecord[];
documents: DocumentRecord[];
knowledgeBase: KnowledgeEntryRecord[];
@@ -331,8 +329,6 @@ export interface RunStatusEvent {
message: string;
}
export type HeartbeatTrigger = "manual" | "timer" | "assignment" | "goal_activated" | "approval_resolved" | "subtask_completed" | "comment" | "report_blocked" | "report_failed" | "recovery" | "message" | "peer_request";
export interface CommentRecord {
id: string;
companyId: string;
@@ -343,11 +339,6 @@ export interface CommentRecord {
createdAt: string;
}
export interface OrgChartNode {
agent: AgentRecord;
children: OrgChartNode[];
}
export interface HeartbeatStatusEvent {
type: "heartbeat-status";
agentId: string;
@@ -384,7 +375,6 @@ export type DesktopEvent =
| AutomationFiredEvent
| NewMessageEvent;
// ── Inbox ──────────────────────────────────────────────────────────────
export type InboxItemType = "pending_approval" | "failed_run" | "budget_warning" | "blocked_task" | "review_needed" | "agent_message";
export interface InboxItem {
@@ -398,23 +388,21 @@ export interface InboxItem {
agentId: string | null;
agentName: string | null;
createdAt: string;
dismissed: boolean;
}
// ── Performance Metrics ────────────────────────────────────────────────
export interface AgentMetrics {
agentId: string;
agentName: string;
tasksCompleted: number;
tasksAssigned: number;
tasksFailed: number;
successRate: number; // 0-100
successRate: number;
avgRunDurationSec: number;
totalCostUsd: number;
runsTotal: number;
runsSucceeded: number;
runsFailed: number;
reviewCycles: number; // how many times work was sent back for revision
reviewCycles: number;
lastActiveAt: string | null;
}
@@ -434,7 +422,6 @@ export interface CompanyMetrics {
agentMetrics: AgentMetrics[];
}
// ── Company Template ───────────────────────────────────────────────────
export interface CompanyTemplate {
id: string;
name: string;
@@ -461,10 +448,9 @@ export interface CompanyTemplate {
}>;
}
// ── Social Media / Browser Automation ──────────────────────────────
export type SocialPlatform = "twitter" | "linkedin" | "instagram" | "facebook" | "reddit" | "youtube" | "tiktok" | "bluesky" | "other";
export type SocialAccountStatus = "active" | "logged_in" | "login_required" | "suspended" | "paused";
export type BrowserActionType = "post" | "reply" | "like" | "follow" | "browse_feed" | "screenshot" | "navigate" | "search" | "dm" | "custom_script";
export type BrowserActionType = "post" | "reply" | "like" | "follow" | "browse_feed" | "screenshot" | "navigate" | "search";
export type BrowserActionStatus = "queued" | "running" | "succeeded" | "failed" | "cancelled" | "approval_required";
export interface SocialAccountRecord {
@@ -474,12 +460,9 @@ export interface SocialAccountRecord {
accountName: string;
displayName: string;
profileUrl: string;
/** Secret ID for stored credentials (username/password/cookies) */
credentialSecretId: string | null;
status: SocialAccountStatus;
/** Whether posts require Board approval before publishing */
requireApproval: boolean;
/** JSON metadata: bio, follower count, etc. */
metadataJson: string;
lastUsedAt: string | null;
createdAt: string;
@@ -493,14 +476,10 @@ export interface BrowserActionRecord {
agentId: string;
taskId: string | null;
actionType: BrowserActionType;
/** JSON payload: content, targetUrl, selector, script, etc. */
payloadJson: string;
status: BrowserActionStatus;
/** Result summary after execution */
resultSummary: string;
/** Screenshot path after execution */
screenshotPath: string | null;
/** Approval ID if approval was required */
approvalId: string | null;
errorMessage: string | null;
startedAt: string | null;
@@ -509,7 +488,6 @@ export interface BrowserActionRecord {
updatedAt: string;
}
// ── Meetings ──────────────────────────────────────────────────────────
export type MeetingType =
| "standup"
| "sprint_planning"
@@ -544,7 +522,6 @@ export interface MeetingRecord {
updatedAt: string;
}
// ── Documents ─────────────────────────────────────────────────────────
export type DocumentType =
| "prd"
| "technical_spec"
@@ -586,7 +563,6 @@ export interface DocumentRecord {
updatedAt: string;
}
// ── Knowledge Base ────────────────────────────────────────────────────
export type KnowledgeCategory =
| "lesson_learned"
| "best_practice"
@@ -612,7 +588,6 @@ export interface KnowledgeEntryRecord {
updatedAt: string;
}
// ── Sprints ───────────────────────────────────────────────────────────
export type SprintStatus = "planning" | "active" | "review" | "completed" | "cancelled";
export interface SprintRecord {
@@ -630,25 +605,6 @@ export interface SprintRecord {
updatedAt: string;
}
// ── Performance Reviews ───────────────────────────────────────────────
export type ReviewStatus = "draft" | "submitted" | "acknowledged";
export interface PerformanceReviewRecord {
id: string;
companyId: string;
agentId: string;
reviewerAgentId: string;
period: string; // e.g., "2026-Q1"
rating: number; // 1-5
strengths: string;
areasForImprovement: string;
goals: string;
status: ReviewStatus;
createdAt: string;
updatedAt: string;
}
// ── Standup Report ─────────────────────────────────────────────────────
export interface StandupReport {
companyId: string;
generatedAt: string;
@@ -669,10 +625,9 @@ export interface StandupReport {
companyHighlights: string[];
blockers: string[];
pendingApprovals: number;
budgetUtilization: number; // 0-100
budgetUtilization: number;
}
// ── Automation Engine ─────────────────────────────────────────────────
export type AutomationTrigger =
| "task_status_changed"
| "task_created"
@@ -713,25 +668,19 @@ export interface AutomationRuleRecord {
name: string;
description: string;
trigger: AutomationTrigger;
/** JSON conditions: e.g., {"status": "blocked", "department": "engineering"} */
conditionsJson: string;
action: AutomationAction;
/** JSON action config: e.g., {"targetAgentId": "...", "message": "..."} */
actionConfigJson: string;
/** Source department that triggers (null = any) */
sourceDepartment: DepartmentId | null;
/** Target department for cross-department rules (null = same) */
targetDepartment: DepartmentId | null;
priority: number;
status: AutomationStatus;
/** How many times this rule has fired */
executionCount: number;
lastExecutedAt: string | null;
createdAt: string;
updatedAt: string;
}
// ── Agent Messages (Direct Communication) ─────────────────────────────
export type MessageChannel = "direct" | "department" | "company" | "project" | "incident";
export type MessagePriority = "urgent" | "normal" | "low";
@@ -739,24 +688,18 @@ export interface AgentMessageRecord {
id: string;
companyId: string;
fromAgentId: string;
/** null = broadcast to channel */
toAgentId: string | null;
channel: MessageChannel;
/** Department/project/incident ID for channel messages */
channelTargetId: string | null;
subject: string;
body: string;
priority: MessagePriority;
/** Whether the recipient has read this message */
readAt: string | null;
/** Parent message ID for threads */
parentMessageId: string | null;
/** JSON: attached entity references [{type, id, title}] */
attachmentsJson: string;
createdAt: string;
}
// ── Workflow Pipeline ──────────────────────────────────────────────────
export type WorkflowStatus = "draft" | "active" | "paused" | "completed" | "failed";
export interface WorkflowPipelineRecord {
@@ -764,13 +707,11 @@ export interface WorkflowPipelineRecord {
companyId: string;
name: string;
description: string;
/** JSON array of pipeline steps */
stepsJson: string;
triggerType: AutomationTrigger;
triggerConfigJson: string;
status: WorkflowStatus;
currentStepIndex: number;
/** How many times this pipeline has run */
runCount: number;
lastRunAt: string | null;
createdAt: string;
@@ -784,19 +725,7 @@ export interface WorkflowStep {
configJson: string;
assigneeDepartment: DepartmentId | null;
assigneeAgentId: string | null;
/** Wait for approval before proceeding */
requiresApproval: boolean;
/** Timeout in seconds (0 = no timeout) */
timeoutSec: number;
/** Status of this step */
status: "pending" | "running" | "completed" | "failed" | "skipped";
}
// ── Cross-Department Trigger Table ────────────────────────────────────
export interface CrossDeptTrigger {
sourceEvent: string;
sourceDepartment: DepartmentId;
targetDepartment: DepartmentId;
targetAction: string;
description: string;
}