-
Notifications
You must be signed in to change notification settings - Fork 1
overview architecture
Infi follows a strict layered architecture. Domain types are leaf nodes with no I/O dependencies. Infrastructure handles persistence, agent orchestration, and external APIs. Commands bridge the frontend to backend via Tauri IPC. The frontend communicates exclusively through invoke calls and never imports Rust code directly.
| Layer | Path | Responsibility | Dependencies |
|---|---|---|---|
| Domain | src/domain/ |
Pure types: analyses, runs, entities, sources, metrics, blocks, stances, projections, portfolios. No I/O. |
serde, chrono
|
| Infrastructure | src/infra/ |
SQLite persistence, ACP agent lifecycle, data-source providers, OS keychain, app configuration, price history, CSV parsing, shell utilities. |
rusqlite, pmcp, agent-client-protocol, reqwest, keyring, tokio
|
| Commands | src/commands/ |
Tauri #[tauri::command] handlers bridging frontend IPC to domain + infra. Contains the generate_analysis orchestration, export/publish, and source management. |
domain, infra, tauri
|
| Prompts | src/prompts.rs |
Handlebars templates and prompt-building logic for the main analysis pass and explanation pass. |
domain, infra/db, handlebars
|
| State | src/state.rs |
AppState holding the Database handle and a map of CancellationTokens for active runs. Managed by Tauri as shared state. |
infra/db, tokio-util
|
| Frontend | frontend/src/ |
React SPA: research composer, live agent progress, report viewer, portfolio management, settings. |
@tauri-apps/api, @tanstack/react-query, custom store, react, Tailwind |
graph TD
subgraph Frontend["Tauri Window (Vite + React)"]
RP[Research Page]
AP[Analysis Page]
PP[Portfolio Page]
SP[Settings Page]
end
subgraph Commands["Tauri Commands (src/commands)"]
CA[create_analysis]
GA[generate_analysis]
GR[get_report]
end
subgraph Domain["Domain (src/domain)"]
AN[Analysis, Block, Stance]
PR[Projection, Portfolio, Metrics]
end
subgraph Infra["Infrastructure (src/infra)"]
DB[(SQLite Database)]
ACP[ACP Agent Lifecycle]
SRC[Data Sources - 12 providers]
KS[OS Keychain]
CFG[App Config]
end
subgraph External["External"]
AGENT[ACP Agent - Codex, Claude, etc.]
MCP[MCP Server - infi-analysis stdio]
API[Data Provider APIs]
end
RP -->|invoke| CA
AP -->|invoke| GA
AP -->|invoke| GR
PP -->|invoke| CA
CA --> Domain
GA --> ACP
GR --> DB
ACP --> AGENT
AGENT --> MCP
MCP --> SRC
SRC --> API
ACP --> DB
Domain types are leaf nodes — nothing in domain imports from infra, commands, or the frontend. Infrastructure depends on domain. Commands depend on both. This constraint keeps the domain model testable and framework-agnostic.
- The user composes a research query on the Research Page and picks an ACP agent.
-
create_analysiswrites anAnalysisrow (status:queued) and aRunrow to SQLite. -
generate_analysisresolves the agent binary viaagent_discovery, spawns it as a child process, and connects over ACP stdio. - The agent calls MCP tools exposed by
analysis_mcp_serverto submit plan entries, fetch data from providers, write structured blocks (metrics, stances, projections), and finally submit aFinalStance. - Progress events stream to the frontend via a Tauri
Channel. - When the agent finishes, the run status updates to
completedorfailed, and the report becomes available in the report viewer.
sequenceDiagram
participant U as User
participant FE as Frontend
participant CMD as Commands
participant ACP as ACP Client
participant AG as Agent
participant MCP as MCP Server
participant DB as SQLite
U->>FE: Enter research query
FE->>CMD: create_analysis(query)
CMD->>DB: Insert analysis + run
CMD-->>FE: analysis_id, run_id
FE->>CMD: generate_analysis(analysis_id)
CMD->>ACP: spawn agent process
ACP->>AG: launch with MCP server
loop Agent execution
AG->>MCP: fetch_data(provider, ticker)
MCP-->>AG: structured data
AG->>MCP: submit_metric(...)
AG->>MCP: submit_stance(...)
AG->>MCP: submit_projection(...)
MCP->>DB: persist blocks
MCP-->>ACP: progress event
ACP-->>FE: Channel(progress)
end
AG->>MCP: submit_final_stance(...)
MCP->>DB: update run status
FE->>CMD: get_analysis_report(id)
CMD->>DB: load report
DB-->>FE: structured report
The application starts in src/main.rs. It initializes the logger, fixes PATH on Unix, captures the shell PATH, then either runs as an MCP server (if --analysis-mcp-server is passed), prints environment info (if --printenv is passed), or launches the Tauri window with all commands registered.
| File | Purpose |
|---|---|
src/main.rs |
Application entry point, Tauri builder, command registration |
src/lib.rs |
Module re-exports |
src/state.rs |
AppState with database handle and active run cancellations |
src/commands/mod.rs |
All Tauri IPC command handlers (1942 lines) |
src/domain/analysis.rs |
Core analysis types: Analysis, AnalysisReport, AnalysisBlock, FinalStance
|
src/domain/portfolio.rs |
Portfolio types: Portfolio, PortfolioHolding, PortfolioTransaction
|
src/infra/db/mod.rs |
SQLite schema, migrations, and all persistence operations (5268 lines) |
src/infra/acp/analysis_generator/client.rs |
ACP client that spawns and communicates with agents |
src/infra/acp/analysis_mcp_server/tool.rs |
MCP tool definitions the agent calls to submit data |
src/prompts.rs |
Handlebars prompt templates for analysis and explanation passes |