Files
Neon-Desk/README.md

132 lines
4.7 KiB
Markdown

# Fiscal Clone 3.0
Turbopack-first rebuild of a fiscal.ai-style terminal with Vercel AI SDK integration.
## Stack
- Next.js 16 App Router
- Bun runtime/tooling
- Elysia route layer mounted in Next Route Handlers
- Turbopack for `dev` and `build`
- Better Auth (email/password + magic link)
- Drizzle ORM (SQLite) + Better Auth Drizzle adapter
- Internal API routes via Elysia app module (`lib/server/api/app.ts`)
- Eden Treaty for type-safe frontend API calls
- Workflow DevKit Local World for background task execution
- SQLite-backed domain storage (watchlist, holdings, filings, tasks, insights)
- Vercel AI SDK (`ai`) with dual-model routing:
- Ollama (`@ai-sdk/openai`) for lightweight filing extraction/parsing
- Zhipu (`zhipu-ai-provider`) for heavyweight narrative reports (`https://api.z.ai/api/coding/paas/v4`)
## Run locally
```bash
bun install
bun run db:generate
bun run db:migrate
bun run dev
```
Open [http://localhost:3000](http://localhost:3000).
The default database path is `data/fiscal.sqlite` via `DATABASE_URL=file:data/fiscal.sqlite`.
## Production build
```bash
bun run db:migrate
bun run build
bun run start
```
## Docker deployment
```bash
cp .env.example .env
docker compose up --build -d
```
For local Docker, host port mapping comes from `docker-compose.override.yml` (default `http://localhost:3000` via `APP_PORT`).
The app calls Zhipu directly via AI SDK for heavy reports and calls Ollama for lightweight filing extraction.
When running in Docker and Ollama runs on the host, set `OLLAMA_BASE_URL=http://host.docker.internal:11434`.
Zhipu always targets the Coding API endpoint (`https://api.z.ai/api/coding/paas/v4`).
On container startup, the app applies Drizzle migrations automatically before launching Next.js.
The app stores SQLite data in Docker volume `fiscal_sqlite_data` (mounted to `/app/data`) and workflow local data in `fiscal_workflow_data` (mounted to `/app/.workflow-data`).
Workflow Local World uses filesystem state plus an in-memory queue. On container restart, queued in-flight jobs may be lost.
Docker images use Bun (`oven/bun:1.3.5-alpine`) for build and runtime.
## Coolify deployment
This compose setup is compatible with Coolify as-is (it uses named Docker volumes, not host bind mounts).
Required environment variables in Coolify:
- `DATABASE_URL=file:/app/data/fiscal.sqlite`
- `BETTER_AUTH_SECRET=<long-random-secret>`
- `BETTER_AUTH_BASE_URL=https://fiscal.b11studio.xyz`
- `BETTER_AUTH_TRUSTED_ORIGINS=https://fiscal.b11studio.xyz`
- `WORKFLOW_TARGET_WORLD=local`
- Optional: `WORKFLOW_LOCAL_DATA_DIR=/app/.workflow-data`
Operational constraints for Coolify:
- Keep this service to a single instance/replica. SQLite is file-based and not appropriate for multi-replica shared-write deployments.
- Ensure the two named volumes are persisted (`fiscal_sqlite_data`, `fiscal_workflow_data`).
- Workflow Local queueing is in-memory; in-flight queued jobs may be lost on restarts.
- Docker build forces `WORKFLOW_TARGET_WORLD=local` to avoid stale Coolify build args referencing `@workflow/world-postgres`.
- Runtime Compose config also pins `WORKFLOW_TARGET_WORLD=local` for the same reason.
## Environment
Use root `.env` or root `.env.local`:
```env
# leave blank for same-origin API
NEXT_PUBLIC_API_URL=
DATABASE_URL=file:data/fiscal.sqlite
BETTER_AUTH_SECRET=replace-with-a-long-random-secret
BETTER_AUTH_BASE_URL=https://fiscal.b11studio.xyz
BETTER_AUTH_TRUSTED_ORIGINS=https://fiscal.b11studio.xyz
ZHIPU_API_KEY=
ZHIPU_MODEL=glm-4.7-flashx
# optional generation tuning
AI_TEMPERATURE=0.2
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=qwen3:8b
OLLAMA_API_KEY=ollama
SEC_USER_AGENT=Fiscal Clone <support@fiscal.local>
WORKFLOW_TARGET_WORLD=local
WORKFLOW_LOCAL_DATA_DIR=.workflow-data
WORKFLOW_LOCAL_QUEUE_CONCURRENCY=100
```
If `ZHIPU_API_KEY` is unset, the app uses local fallback analysis so task workflows still run.
If Ollama is unavailable, filing extraction falls back to deterministic metadata-based extraction and still proceeds to heavy report generation.
`ZHIPU_BASE_URL` is deprecated and ignored; runtime always uses `https://api.z.ai/api/coding/paas/v4`.
## API surface
All endpoints below are defined in Elysia at `lib/server/api/app.ts` and exposed via `app/api/[[...slugs]]/route.ts`.
- `ALL /api/auth/*` (Better Auth handler)
- `GET /api/health`
- `GET /api/me`
- `GET|POST /api/watchlist`
- `DELETE /api/watchlist/:id`
- `GET|POST /api/portfolio/holdings`
- `PATCH|DELETE /api/portfolio/holdings/:id`
- `GET /api/portfolio/summary`
- `POST /api/portfolio/refresh-prices`
- `POST /api/portfolio/insights/generate`
- `GET /api/portfolio/insights/latest`
- `GET /api/filings`
- `POST /api/filings/sync`
- `POST /api/filings/:accessionNumber/analyze`
- `GET /api/tasks`
- `GET /api/tasks/:taskId`