import { z } from "zod"; export const ScreenSchema = z.enum(["home", "workspace", "model", "memo", "agents"]); export type Screen = z.infer; 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; 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; 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; export const ModelRowSchema = z.object({ label: z.string(), kind: z.enum(["actual", "forecast", "total"]), values: z.array(z.string()) }); export type ModelRow = z.infer; 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; 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; 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; 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; export const MemoSchema = z.object({ status: z.enum(["draft", "review", "final"]), sections: z.array(MemoSectionSchema), citations: z.array(MemoCitationSchema), annotations: z.array(MemoAnnotationSchema), sectionReviews: z.array(MemoSectionReviewSchema) }); export type Memo = z.infer; 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; 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; 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; 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; 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; 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; 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; 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; export type ClientSettings = z.infer; export type ServerSettings = z.infer; 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 }; "workspace.updateSection": { companyId: string; section: string; content: string }; "catalyst.list": { companyId: string }; "alert.list": { companyId?: string; since?: string }; "risk.list": { companyId: string }; "risk.add": { companyId: string; risk: Omit }; "earnings.getSchedule": { companyId: string }; "filing.list": { companyId: string; since?: string }; "model.get": { companyId: string; tab: string }; "model.list": undefined; "model.set": { provider: string; modelId: string; thinkingLevel?: "off" | "minimal" | "low" | "medium" | "high" }; "model.updateCell": { companyId: string; tab: string; row: number; col: number; value: string }; "model.createRow": { companyId: string; tab: string; label: string; kind: "actual" | "forecast" | "total"; values?: string[] }; "model.deleteRow": { companyId: string; tab: string; row: number }; "model.runScenario": { companyId: string; scenario: string; overrides: Record }; "memo.get": { companyId: string }; "memo.addSection": { companyId: string; title: string; afterSectionId?: string; }; "memo.deleteSection": { companyId: string; sectionId: 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 }; "agent.getTrace": { agentId: string; runId: string }; "agent.runPipeline": { companyId: string; pipeline: string }; "validation.run": { companyId: string; agentType?: "sv" | "qa" | "rt" | "all" }; "validation.getStatus": { companyId: string; sectionId?: string }; "export.list": { companyId?: string }; "export.create": { type: "pdf" | "excel" | "ppt"; companyId: string; options?: Record }; "export.download": { exportId: string }; "settings.get": { scope: "client" | "server" }; "settings.update": import("./rpcSchemas.js").SettingsUpdatePayload; }; 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 }> }; "workspace.updateSection": { content: WorkspaceSection; savedAt: 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.list": { models: Array<{ provider: string; modelId: string; name: string; available: boolean }> }; "model.set": { ok: boolean; provider: string; modelId: string }; "model.updateCell": { ok: boolean; affectedCells: string[] }; "model.createRow": { row: ModelRow; position: number }; "model.deleteRow": { ok: boolean }; "model.runScenario": { headers: string[]; rows: ModelRow[] }; "memo.get": { status: "draft" | "review" | "final"; sections: MemoSection[]; citations: MemoCitation[]; annotations: MemoAnnotation[]; sectionReviews: MemoSectionReview[]; }; "memo.addSection": { section: MemoSection; }; "memo.deleteSection": { ok: boolean; }; "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[] }; "validation.run": { sourceVerification?: { passed: boolean; confidence: string; issues: Array<{ severity: string; message: string; suggestion?: string }>; notes: string; timestamp: string }; modelQA?: { passed: boolean; confidence: string; issues: Array<{ severity: string; message: string; suggestion?: string }>; notes: string; timestamp: string }; redTeam?: { passed: boolean; confidence: string; issues: Array<{ severity: string; message: string; suggestion?: string }>; notes: string; timestamp: string }; }; "validation.getStatus": { validationState: "verified" | "flagged" | "unverified" | "failed"; lastValidated?: 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 = | { ok: true; data: RpcResponseMap[T] } | { ok: false; error: RpcError }; export type RpcClient = { call(method: T, payload: RpcRequestMap[T]): Promise>; }; // ============== SSE Events ============== export type ServerEventType = | "agent.progress" | "agent.completed" | "agent.failed" | "agent.started" | "agent.streaming" | "validation.updated" | "memo.updated" | "model.updated"; export type AgentProgressEvent = { type: "agent.progress"; data: { runId: string; agentId: string; companyId: string; progress: number; action: string; timestamp: string; }; }; export type AgentCompletedEvent = { type: "agent.completed"; data: { runId: string; agentId: string; companyId: string; output: unknown; duration: number; timestamp: string; }; }; export type AgentFailedEvent = { type: "agent.failed"; data: { runId: string; agentId: string; companyId: string; error: string; timestamp: string; }; }; export type AgentStartedEvent = { type: "agent.started"; data: { runId: string; agentId: string; companyId: string; pipeline?: string; timestamp: string; }; }; export type AgentStreamingEvent = { type: "agent.streaming"; data: { runId: string; agentId: string; companyId: string; chunk: string; timestamp: string; }; }; export type ValidationUpdatedEvent = { type: "validation.updated"; data: { companyId: string; sectionId?: string; validationState: "verified" | "flagged" | "unverified" | "failed"; agentId: string; notes?: string; timestamp: string; }; }; export type MemoUpdatedEvent = { type: "memo.updated"; data: { companyId: string; sectionId: string; content: string; updatedAt: string; }; }; export type ModelUpdatedEvent = { type: "model.updated"; data: { companyId: string; tab: string; cell?: { row: number; col: number }; timestamp: string; }; }; export type ServerEvent = | AgentProgressEvent | AgentCompletedEvent | AgentFailedEvent | AgentStartedEvent | AgentStreamingEvent | ValidationUpdatedEvent | MemoUpdatedEvent | ModelUpdatedEvent;