Replace the custom Pi API fetch client with the @earendil-works/pi-coding-agent SDK, enabling support for multiple LLM providers (Anthropic, OpenAI, DeepSeek, Google Gemini, xAI/ZAI) while maintaining backward compatibility. Key changes: - Add piSdk.ts with SDK session management and provider auto-detection - Refactor client.ts to delegate to SDK adapter, keeping public API surface - Update documentation to reflect multi-provider environment variables - Add RPC contracts for LLM model selection and provider configuration - Update agent runner to support provider-specific tools and parameters Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.7 KiB
MosaicIQ - Agent Instructions & Project Documentation
You are helping implement MosaicIQ, an AI-native equity research workspace.
Use the attached MosaicIQ Design Document v3 as the primary reference for product intent, UX direction, architecture, screen specs, agent behavior, and implementation details. This file is intentionally light; the design doc contains the fuller guidance.
Required Environment Variables
An LLM provider API key is required. This application uses the Pi Coding Agent SDK for all LLM operations. Set at least one of the following:
export ANTHROPIC_API_KEY=sk-ant-...
# or
export OPENAI_API_KEY=sk-...
# or
export DEEPSEEK_API_KEY=...
# or
export GOOGLE_API_KEY=...
# or
export ZAI_API_KEY=...
API Details
- SDK:
@earendil-works/pi-coding-agent— multi-provider agent framework - Providers: Anthropic, OpenAI, DeepSeek, Google Gemini, xAI/ZAI, and more
- Client: SDK-backed client in
packages/shared/src/llm/piSdk.ts - Default model: First available from configured provider (prefers Anthropic)
- Features: Streaming, tool use, structured output, multi-agent pipelines
All agent execution, memo generation, and AI-powered features depend on at least one provider API key.
Core Direction
Build a clean, fast, local-first equity research application with a t3-code-style architecture:
- Clear client/server boundary
- Typed RPC layer for all client/server communication
- Local-first persistence
- Simple, composable React components
- Minimal magic, strong types, predictable state
- Practical implementation over over-engineering
Product Identity
The product name is MosaicIQ.
Do not use old/internal names like “Meridian” in user-facing UI unless the design doc explicitly says it is internal.
Design Feel
Follow the design doc’s editorial research-workstation style:
- Serif display typography for headings
- Monospace for tickers, numbers, metadata, financial tables, and code-like labels
- Sans-serif for body/UI text
- Warm neutral palette with one restrained rust accent
- Hairline borders and whitespace instead of heavy cards, shadows, or gradients
- Dense but calm layout for analysts working on desktop screens
Keep the UI serious, analytical, and professional.
Architecture Rules
Prefer the structure described in the design doc:
- Client never reads or writes storage directly
- Client talks to the server through typed RPC methods
- Server owns SQLite persistence, agent orchestration, file I/O, and export logic
- Client owns UI state such as active screen, panels, collapsed nav, search, and display preferences
- Use schema validation and safe defaults for settings
- Keep the path open for future remote/server deployment
Agent Behavior
Agents should feel like collaborative research analysts, not black-box tools.
They should:
- Surface assumptions
- Cite or reference source material when possible
- Flag uncertainty
- Ask for clarification only when needed
- Support review, acceptance, rejection, and revision workflows
- Avoid pushing unvalidated conclusions directly into final outputs
Use the design doc’s agent system, validation loop, and screen guidance for details.
Implementation Priorities
Start simple and build in layers:
- App shell and navigation
- Portfolio/company workspace
- Financial model table UI
- Memo editor
- Agent orchestration UI
- RPC/server persistence
- Export flows
- Validation/review loops
Do not try to implement everything at once. Favor small, working vertical slices.
Coding Style
- Use TypeScript throughout
- Keep components small and readable
- Prefer explicit state and typed data contracts
- Avoid unnecessary abstractions
- Avoid large monolithic files
- Keep styling consistent with the design tokens in the design doc
- Make empty, loading, error, and disabled states feel intentional
Dev Server
NEVER start, stop, restart, or manage the app/dev server. Do not run npm run dev, pnpm dev, yarn dev, vite, vite preview, Electron launch commands, or equivalent server/app-start commands.
The user runs the app independently. Your job is to write/edit code and run non-server verification commands such as typecheck, lint, tests, or production build when requested or appropriate.
Do not open or navigate a browser to the local app unless the user explicitly asks for browser inspection and confirms that they already have the app running.
When Unsure
Refer back to the MosaicIQ Design Document v3. It contains additional helpful information on:
- Design tokens
- Screen specifications
- Component behavior
- RPC methods
- SSE events
- Data/state shape
- Persistence/versioning
- Agent workflows
- Export center
- Accessibility and keyboard shortcuts
Default to the design doc unless it conflicts with a newer explicit instruction.
LLM Client Reference
The Pi API client is located at packages/shared/src/llm/client.ts.
Available Functions
streamResponse(prompt, options)
Stream a response from Pi with progress callbacks.
import { streamResponse } from "@mosaiciq/shared/llm";
const response = await streamResponse("Analyze this data", {
model: "pi", // Optional, defaults to "pi"
maxTokens: 4096, // Optional, defaults to 4096
temperature: 0, // Optional, defaults to 0
onProgress: (text) => console.log(text), // Optional progress callback
signal: abortSignal, // Optional AbortSignal for cancellation
});
complete(prompt, options)
Get a complete response without streaming.
import { complete } from "@mosaiciq/shared/llm";
const response = await complete("Summarize this report", {
model: "pi",
maxTokens: 2048,
temperature: 0.5,
});
streamStructuredResponse(prompt, schema, options)
Stream a response and parse as JSON using the provided schema.
import { streamStructuredResponse } from "@mosaiciq/shared/llm";
const result = await streamStructuredResponse(
"Extract financial metrics",
{
revenue: "number",
growth: "number",
margin: "number",
},
{
onProgress: (text) => updateUI(text),
signal,
}
);
completeStructured(prompt, schema, options)
Get a complete structured JSON response.
import { completeStructured } from "@mosaiciq/shared/llm";
const data = await completeStructured(
"Parse this earnings report",
{
eps: "number",
revenue: "string",
guidance: "string",
}
);
isConfigured()
Check if the Pi API key is properly configured.
import { isConfigured } from "@mosaiciq/shared/llm";
if (!isConfigured()) {
console.error("PI_API_KEY is not set");
}
Usage in Agents
When implementing agents that use the Pi API:
import { streamResponse, isConfigured } from "../llm/client.js";
export async function executeMyAgent(db: Db, companyId: string) {
if (!isConfigured()) {
throw new Error("PI_API_KEY is not configured");
}
const prompt = buildAgentPrompt(context);
const result = await streamResponse(prompt, {
onProgress: (text) => updateProgress(text),
signal,
});
return result;
}
Monorepo Structure
local_research_app/
├── apps/
│ ├── desktop/ # Electron main process (RPC server, file I/O)
│ └── web/ # React web UI (client)
├── packages/
│ ├── contracts/ # Shared TypeScript types (RPC, domain models)
│ └── shared/ # Shared utilities, DB, LLM client, agents
├── docs/
│ └── architecture.md # Architecture documentation
├── agent.md # This file - agent instructions
├── pnpm-workspace.yaml # PNPM workspace configuration
└── package.json # Root package.json
Key Files by Concern
RPC Layer
packages/contracts/src/rpc.ts- RPC method definitions and typesapps/desktop/src/rpc.ts- RPC server implementationapps/web/src/rpcClient.ts- RPC client wrapper
Data Layer
packages/shared/src/db/database.ts- SQLite database setuppackages/shared/src/db/schema.ts- Database schemapackages/shared/src/db/queries.ts- Database query functions
LLM Layer
packages/shared/src/llm/client.ts- Pi API clientpackages/shared/src/llm/prompts.ts- Agent prompt templatespackages/shared/src/llm/context.ts- Context building for agents
Agents
packages/shared/src/agents/runner.ts- Individual agent executionpackages/shared/src/agents/executor.ts- Agent pipeline orchestrationpackages/shared/src/agents/index.ts- Agent registry and exports
Export
packages/shared/src/export/excel.ts- Excel export (ExcelJS)packages/shared/src/export/pdf.ts- PDF exportpackages/shared/src/export/pptx.ts- PowerPoint export (PptxGenJS)