Add v2 rewrite: monorepo with desktop and web apps, shared packages, docs, and wireframes

This commit is contained in:
2026-05-14 13:13:21 -04:00
parent 6d7eed9230
commit 379c07b50c
49 changed files with 11607 additions and 0 deletions

View File

@@ -0,0 +1,313 @@
import { z } from "zod";
export const ScreenSchema = z.enum(["home", "workspace", "model", "memo", "agents"]);
export type Screen = z.infer<typeof ScreenSchema>;
export const HoldingSchema = z.object({
ticker: z.string(),
name: z.string(),
price: z.number(),
changePct: z.number(),
weight: z.number()
});
export type Holding = z.infer<typeof HoldingSchema>;
export const AgentSchema = z.object({
id: z.string(),
name: z.string(),
status: z.enum(["idle", "queued", "running", "completed", "paused", "failed"]),
progress: z.number().min(0).max(100),
action: z.string(),
pipeline: z.enum(["research", "competitive", "cross-cutting"]).optional(),
confidence: z.enum(["high", "medium", "low"]).optional()
});
export type Agent = z.infer<typeof AgentSchema>;
export const CompanySchema = z.object({
id: z.string(),
ticker: z.string(),
name: z.string(),
sector: z.string(),
subIndustry: z.string().optional(),
price: z.number(),
changePct: z.number(),
thesis: z.string(),
founded: z.string().optional(),
headquarters: z.string().optional(),
employees: z.number().optional()
});
export type Company = z.infer<typeof CompanySchema>;
export const ModelRowSchema = z.object({
label: z.string(),
kind: z.enum(["actual", "forecast", "total"]),
values: z.array(z.string())
});
export type ModelRow = z.infer<typeof ModelRowSchema>;
export const MemoSectionSchema = z.object({
id: z.string(),
title: z.string(),
content: z.string(),
updatedAt: z.string().optional(),
primaryAgent: z.string().optional()
});
export type MemoSection = z.infer<typeof MemoSectionSchema>;
export const MemoCitationSchema = z.object({
id: z.string(),
label: z.string(),
sectionId: z.string(),
type: z.enum(["sec_filing", "earnings_transcript", "analyst_report", "model", "internal_note"]),
title: z.string(),
reference: z.string(),
verificationStatus: z.enum(["verified", "unverified", "flagged"]),
sourceUrl: z.string().optional()
});
export type MemoCitation = z.infer<typeof MemoCitationSchema>;
export const MemoAnnotationSchema = z.object({
id: z.string(),
sectionId: z.string(),
kind: z.enum(["highlight", "comment", "strike"]),
selectedText: z.string(),
comment: z.string().optional(),
createdBy: z.string(),
createdAt: z.string(),
status: z.enum(["open", "resolved"])
});
export type MemoAnnotation = z.infer<typeof MemoAnnotationSchema>;
export const MemoSectionReviewSchema = z.object({
sectionId: z.string(),
status: z.enum(["pending", "in_review", "approved", "changes_requested"]),
updatedAt: z.string().optional()
});
export type MemoSectionReview = z.infer<typeof MemoSectionReviewSchema>;
export const CatalystSchema = z.object({
id: z.string(),
date: z.string(),
event: z.string(),
impact: z.enum(["high", "medium", "low"]),
thesisRelevance: z.enum(["supports", "challenges", "neutral"]),
source: z.string().optional()
});
export type Catalyst = z.infer<typeof CatalystSchema>;
export const AlertSchema = z.object({
id: z.string(),
companyId: z.string().optional(),
timestamp: z.string(),
type: z.enum(["filing", "price_move", "earnings_surprise", "peer_event"]),
description: z.string(),
thesisImpact: z.enum(["positive", "negative", "neutral"]),
status: z.enum(["new", "reviewed"]),
targetSection: z.string().optional()
});
export type Alert = z.infer<typeof AlertSchema>;
export const RiskSchema = z.object({
id: z.string(),
companyId: z.string(),
risk: z.string(),
category: z.enum(["business", "financial", "competitive", "regulatory", "esg"]),
severity: z.enum(["high", "medium", "low"]),
likelihood: z.enum(["high", "medium", "low"]),
mitigation: z.string(),
status: z.enum(["open", "mitigated", "accepted"])
});
export type Risk = z.infer<typeof RiskSchema>;
export const EarningsScheduleSchema = z.object({
id: z.string(),
companyId: z.string(),
quarter: z.string(),
expectedDate: z.string(),
timing: z.enum(["bmo", "amc"]).optional(),
actualRevenue: z.string().optional(),
expectedRevenue: z.string().optional(),
actualEps: z.string().optional(),
expectedEps: z.string().optional()
});
export type EarningsSchedule = z.infer<typeof EarningsScheduleSchema>;
export const FilingSchema = z.object({
id: z.string(),
companyId: z.string(),
formType: z.string(),
filedDate: z.string(),
title: z.string(),
keyChanges: z.string().optional(),
reviewed: z.boolean().optional()
});
export type Filing = z.infer<typeof FilingSchema>;
export const ExportRecordSchema = z.object({
id: z.string(),
type: z.enum(["pdf", "excel", "ppt"]),
title: z.string(),
companyId: z.string().optional(),
format: z.string(),
fileSize: z.string().optional(),
status: z.enum(["processing", "complete", "failed"]),
createdAt: z.string(),
downloadUrl: z.string().optional()
});
export type ExportRecord = z.infer<typeof ExportRecordSchema>;
export const WorkspaceSectionSchema = z.object({
id: z.string(),
title: z.string(),
content: z.string(),
validationState: z.enum(["verified", "flagged", "unverified", "failed"]),
sourceAgent: z.string().optional()
});
export type WorkspaceSection = z.infer<typeof WorkspaceSectionSchema>;
export const SnapshotSchema = z.object({
id: z.string(),
timestamp: z.string(),
label: z.string().optional(),
type: z.enum(["auto", "manual"]),
changeCount: z.number()
});
export type Snapshot = z.infer<typeof SnapshotSchema>;
export type ClientSettings = {
theme: "light" | "dark" | "system";
density: "comfortable" | "compact" | "dense";
sidebarWidth: number;
navCollapsed: Record<string, boolean>;
keybindings: Record<string, string>;
};
export type ServerSettings = {
agentConfigs: Record<string, unknown>;
dataSources: Record<string, boolean>;
exportPipelines: Record<string, unknown>;
};
export type RpcRequestMap = {
"portfolio.get": undefined;
"portfolio.addHolding": { ticker: string };
"portfolio.removeHolding": { ticker: string };
"company.get": { companyId: string };
"company.search": { query: string };
"company.setActive": { companyId: string };
"workspace.getSection": { companyId: string; section: string };
"workspace.listSources": { companyId: string };
"catalyst.list": { companyId: string };
"alert.list": { companyId?: string; since?: string };
"risk.list": { companyId: string };
"risk.add": { companyId: string; risk: Omit<Risk, "id" | "companyId"> };
"earnings.getSchedule": { companyId: string };
"filing.list": { companyId: string; since?: string };
"model.get": { companyId: string; tab: string };
"model.updateCell": { companyId: string; tab: string; row: number; col: number; value: string };
"model.runScenario": { companyId: string; scenario: string; overrides: Record<string, string> };
"memo.get": { companyId: string };
"memo.updateSection": {
companyId: string;
sectionId: string;
title?: string;
content: string;
};
"memo.addAnnotation": {
companyId: string;
sectionId: string;
kind: "highlight" | "comment" | "strike";
selectedText: string;
comment?: string;
};
"memo.resolveAnnotation": {
companyId: string;
annotationId: string;
};
"memo.updateSectionReview": {
companyId: string;
sectionId: string;
status: "pending" | "in_review" | "approved" | "changes_requested";
};
"memo.acceptEdit": { companyId: string; editId: string };
"memo.rejectEdit": { companyId: string; editId: string; reason?: string };
"agent.list": { companyId?: string };
"agent.start": { agentId: string; companyId: string };
"agent.pause": { agentId: string };
"agent.restart": { agentId: string };
"agent.chat": { agentId: string; message: string };
"agent.configure": { agentId: string; config: Record<string, unknown> };
"agent.getTrace": { agentId: string; runId: string };
"agent.runPipeline": { companyId: string; pipeline: string };
"export.list": { companyId?: string };
"export.create": { type: string; companyId: string; options?: Record<string, unknown> };
"export.download": { exportId: string };
"settings.get": { scope: "client" | "server" };
"settings.update": { scope: "client" | "server"; changes: Record<string, unknown> };
};
export type RpcResponseMap = {
"portfolio.get": { id: string; name: string; holdings: Holding[]; activeCompanyId: string };
"portfolio.addHolding": { holding: Holding };
"portfolio.removeHolding": { ok: boolean };
"company.get": { company: Company };
"company.search": { results: Array<{ ticker: string; name: string; sector: string }> };
"company.setActive": { ok: boolean };
"workspace.getSection": { content: WorkspaceSection; validationState: string };
"workspace.listSources": { sources: Array<{ type: string; title: string; metadata: string }> };
"catalyst.list": { catalysts: Catalyst[] };
"alert.list": { alerts: Alert[] };
"risk.list": { risks: Risk[] };
"risk.add": { risk: Risk };
"earnings.getSchedule": { schedule: EarningsSchedule[] };
"filing.list": { filings: Filing[] };
"model.get": { headers: string[]; rows: ModelRow[] };
"model.updateCell": { ok: boolean; affectedCells: string[] };
"model.runScenario": { headers: string[]; rows: ModelRow[] };
"memo.get": {
status: "draft" | "review" | "final";
sections: MemoSection[];
citations: MemoCitation[];
annotations: MemoAnnotation[];
sectionReviews: MemoSectionReview[];
};
"memo.updateSection": {
section: MemoSection;
status: "draft" | "review" | "final";
savedAt: string;
};
"memo.addAnnotation": { annotation: MemoAnnotation };
"memo.resolveAnnotation": { annotation: MemoAnnotation };
"memo.updateSectionReview": { review: MemoSectionReview };
"memo.acceptEdit": { ok: boolean };
"memo.rejectEdit": { ok: boolean };
"agent.list": { agents: Agent[] };
"agent.start": { runId: string };
"agent.pause": { ok: boolean };
"agent.restart": { runId: string };
"agent.chat": { response: string };
"agent.configure": { ok: boolean };
"agent.getTrace": { steps: Array<{ step: number; label: string; detail: string }> };
"agent.runPipeline": { runIds: string[] };
"export.list": { exports: ExportRecord[] };
"export.create": { exportId: string };
"export.download": { data: ArrayBuffer };
"settings.get": { settings: ClientSettings | ServerSettings };
"settings.update": { ok: boolean };
};
export type RpcMethod = keyof RpcRequestMap;
export type RpcError = {
code: "NOT_FOUND" | "VALIDATION_ERROR" | "INTERNAL_ERROR" | "AGENT_FAILED" | "CONFLICT" | "RATE_LIMITED";
message: string;
detail?: unknown;
};
export type RpcResult<T extends RpcMethod> =
| { ok: true; data: RpcResponseMap[T] }
| { ok: false; error: RpcError };
export type RpcClient = {
call<T extends RpcMethod>(method: T, payload: RpcRequestMap[T]): Promise<RpcResult<T>>;
};