Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
6c5f3ff
Add /exit slash command (#1)
0xSHKWON May 25, 2026
d2d8615
Add Korean stock research section and CLAUDE.md (#2)
0xSHKWON May 25, 2026
8935f3d
Add Korean stock data pipe (Phase 1) (#3)
0xSHKWON May 29, 2026
650f8dd
Add Korean disclosure tools (Phase 2) (#4)
0xSHKWON May 29, 2026
37c5b75
Add Korea-specific tools — short balance, foreign ownership, NPS hold…
0xSHKWON May 29, 2026
72e2023
Adapt skills for Korean market — DCF market-branch + 물적분할 skill (Phas…
0xSHKWON May 29, 2026
5ed1495
KR financials: normalized summary-first + cross-signal research playb…
0xSHKWON May 30, 2026
8eb246b
KR eval harness: fixed question bank + record/replay + LLM-judge scor…
0xSHKWON May 31, 2026
b18890e
read_filings_kr: DART 사업보고서 narrative extraction (사업의 내용·위험관리·MD&A) (…
0xSHKWON Jun 1, 2026
1478a49
get_market_data_kr: 현재가·시총·PER/PBR·목표주가 컨센서스 (Naver keyless) (#11)
0xSHKWON Jun 2, 2026
2038f68
DCF 순부채 부호 수정: KR 이자부채(totalDebt)·단기금융상품 정규화 + EV→Equity 부호 규칙 (#12)
0xSHKWON Jun 3, 2026
10fe1ba
한국 주식 리서치: 견고성 레이어 + governance 본문 (DART 쿼터·서킷브레이커 / keyless 티어링 / dr…
0xSHKWON Jun 4, 2026
89d6150
한국 주식 리서치 품질개선: 종목 해석·사업부문 데이터·밸류에이션 스킬·eval 정확도 게이트 (#14)
0xSHKWON Jun 20, 2026
c3b7ac3
resolveKrSecurity 분기 단위테스트 (모킹) — 이름→코드 해석 회귀 가드
0xSHKWON Jun 20, 2026
15fbac2
Merge KR equity-research fork (#1–#15) onto upstream main
0xSHKWON Jun 20, 2026
b38b736
Desktop app (Electron + Bun sidecar) + general-user README
0xSHKWON Jun 20, 2026
2ba36f8
Merge remote-tracking branch 'origin/main' into desktop-app-architecture
0xSHKWON Jun 20, 2026
ac3e02d
README/DEVELOPMENT: reflect merged capability — self-expansion, multi…
0xSHKWON Jun 20, 2026
685a9db
fix(desktop): stage real bun binary, not a dangling symlink
0xSHKWON Jun 20, 2026
c4a0828
desktop: forced-update gate + help example prompts + compact redesign
0xSHKWON Jun 20, 2026
1e86712
ci: cross-platform desktop release workflow (mac arm64 + win x64)
0xSHKWON Jun 20, 2026
90f1e7d
desktop: app icon (three.js icosahedron) + full-width top drag region
0xSHKWON Jun 20, 2026
b9ef24f
README: top download buttons (macOS/Windows direct links) + stable ar…
0xSHKWON Jun 20, 2026
96b0b22
release: v1.0.0 — version bump + CI write permission + dynamic versio…
0xSHKWON Jun 21, 2026
6522cda
release: sync desktop package-lock to v1.0.0
0xSHKWON Jun 21, 2026
ef82648
review fixes: sidecar crash/stop fails in-flight runs; drop dead xlsx…
0xSHKWON Jun 21, 2026
f92e295
Desktop app (Electron + Bun sidecar) + 1.0.0 (#16)
0xSHKWON Jun 21, 2026
05a5b29
README: first-run unsigned-app bypass note (macOS right-click→open / …
0xSHKWON Jun 21, 2026
960f1f4
Update README.md
0xSHKWON Jun 21, 2026
e9d3741
fix(desktop): ad-hoc sign macOS app + strip bundle symlinks (fixes 'd…
0xSHKWON Jun 21, 2026
65d7ce5
README: correct first-run bypass for macOS 15/26 (System Settings → O…
0xSHKWON Jun 21, 2026
1090ef0
desktop: Windows in-app auto-update via electron-updater
0xSHKWON Jun 21, 2026
3eb8840
desktop: split Help into two tabs (프롬프트 예시 / API 키 가이드)
0xSHKWON Jun 21, 2026
17ac7ee
release: v1.0.1
0xSHKWON Jun 21, 2026
e623e48
release: update.json latest=1.0.1
0xSHKWON Jun 21, 2026
86fd0db
README: add market-positioning section (3 buckets vs the empty slot w…
0xSHKWON Jun 21, 2026
bddc09f
build(desktop): stage production-only core deps (≈310MB smaller)
0xSHKWON Jun 21, 2026
137fe93
release: v1.0.2 (production-only core bundle ≈310MB smaller)
0xSHKWON Jun 21, 2026
a5db68d
release: update.json latest=1.0.2
0xSHKWON Jun 21, 2026
492b65f
release: v1.0.3 — fix invalid Gemini/xAI model ids (404)
0xSHKWON Jun 21, 2026
fd6d071
release: update.json latest=1.0.3
0xSHKWON Jun 21, 2026
2bbf2ef
release: v1.1.0 — collapsible reasoning timeline in desktop chat
0xSHKWON Jun 21, 2026
6dd1f49
Merge pull request #19 from 0xSHKWON/collapsible-reasoning-toggle
0xSHKWON Jun 21, 2026
8169e62
release: update.json latest=1.1.0
0xSHKWON Jun 21, 2026
f2573f1
release: v1.1.1 — hide menu bar on Windows/Linux
0xSHKWON Jun 24, 2026
264db30
release: update.json latest=1.1.1
0xSHKWON Jun 24, 2026
6de3b24
release: v1.1.2 — ECOS (한국은행) 거시 금리·환율 연동
0xSHKWON Jun 29, 2026
90609ab
release: update.json latest=1.1.2
0xSHKWON Jun 29, 2026
31d3cc3
feat(kr): 실측 β + ERP 4.87% 핀 + β 측정법 질문(CLI·데스크탑) (#22)
0xSHKWON Jul 1, 2026
9e3fbdf
fix(kr): 신뢰성 감사 수정 — P0 4건 + 주관성 P1 3건 + eval CI 승격 (#23)
0xSHKWON Jul 3, 2026
1bf188b
ci: make kr-eval-replay opt-in (run-eval label only), unblock main (#24)
0xSHKWON Jul 3, 2026
f90ea21
docs: README·DEVELOPMENT 최신화 — 신뢰 원칙과 신규 도구를 사용자 언어로
0xSHKWON Jul 3, 2026
bc3fffa
feat(landing): 프로덕트 소개 랜딩 페이지 추가 (#25)
0xSHKWON Jul 7, 2026
897c8ee
ci(pages): landing/ 을 GitHub Pages로 자동 배포 (#26)
0xSHKWON Jul 7, 2026
96f5dff
feat(kr): M4 — 컨센서스 추정치·주가 시계열 도구 + 한국어 유사도·이력 캐싱 + 셀프리뷰 반영 (#27)
0xSHKWON Jul 27, 2026
cdbba47
merge: upstream/main (v1.0.3) — bash 툴+권한 엔진, GPT-5.6, Ollama Cloud, …
0xSHKWON Jul 31, 2026
4192660
fork(model): gpt-5.5 를 선택 가능 상태로 유지 — 직전 세대 보존 정책
0xSHKWON Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,46 @@ jobs:

- name: Run ${{ matrix.task }}
run: ${{ matrix.command }}

# KR-eval regression run (replay mode — recorded tool fixtures, no DART/KRX/Naver network;
# LLM keys for agent + judge come from repo secrets). This is OPT-IN: it runs only when a
# PR carries the `run-eval` label, NOT on every main push. Rationale: agent + judge are
# live LLM calls (token cost per run), and KR_EVAL_REQUIRE_RUN makes a keyless run FAIL —
# so gating main pushes on it would turn main red until OPENAI_API_KEY (etc.) is set as a
# repo secret. Keeping it label-only keeps main green with zero token cost by default.
# To re-enable an always-on gate once secrets are configured: add `github.event_name ==
# 'push'` (and restore the weekly `schedule` cron in `on:`) to the condition below.
#
# MAINTENANCE: fixtures are verbatim recorded tool outputs — whenever a tool's OUTPUT
# SHAPE changes (new fields the skills/prompts instruct the agent to read), re-record
# with `bun run kr-eval:record` in a keyed environment, or replay answers will hedge on
# missing fields and judge scores will drift.
kr-eval-replay:
if: >-
github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'run-eval'
runs-on: ubuntu-latest
# Rapid successive merges: only the newest main run carries signal — cancel superseded ones.
concurrency:
group: kr-eval-replay-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile --ignore-scripts

- name: KR eval (replay)
run: bun run kr-eval:replay
env:
KR_EVAL_REQUIRE_RUN: '1'
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
# Optional repo variables to pin models to whatever key is configured
# (defaults: agent + judge = gpt-5.5, which needs OPENAI_API_KEY).
KR_RUNNER_MODEL: ${{ vars.KR_RUNNER_MODEL }}
KR_EVAL_JUDGE_MODEL: ${{ vars.KR_EVAL_JUDGE_MODEL }}
33 changes: 33 additions & 0 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Deploy landing page

on:
push:
branches: [main]
paths:
- 'landing/**'
- '.github/workflows/deploy-pages.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: landing
- id: deployment
uses: actions/deploy-pages@v4
67 changes: 67 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Release Desktop

# Build the desktop app on each OS's own runner so the bundled bun binary matches
# the target platform (prepare-core.mjs stages the host's bun). Pushing a tag like
# `v1.0.0` publishes a DRAFT GitHub Release with the dmg/exe; review then publish.
on:
push:
tags: ['v*']
workflow_dispatch: # manual run → uploads installers as workflow artifacts (no publish)

# electron-builder needs write access to create/upload the draft GitHub Release.
permissions:
contents: write

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-14 # Apple Silicon (arm64)
- os: windows-latest # x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- uses: actions/setup-node@v4
with:
node-version: 20

# Core deps for the staged sidecar. --ignore-scripts skips the playwright/
# better-sqlite3 build (the sidecar uses bun:sqlite, no chromium).
- name: Install core dependencies
run: bun install --frozen-lockfile --ignore-scripts

# Desktop deps. postinstall runs electron-rebuild for better-sqlite3 against
# this runner's Electron ABI — must happen on the target OS.
- name: Install desktop dependencies
working-directory: desktop
run: npm ci

- name: Stage core, build, package${{ startsWith(github.ref, 'refs/tags/') && ' & publish' || '' }}
working-directory: desktop
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Unsigned for now. To sign: add CSC_LINK/CSC_KEY_PASSWORD (mac) and
# WIN_CSC_LINK/WIN_CSC_KEY_PASSWORD (win) as repo secrets and drop this.
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
run: |
npm run stage
npx electron-vite build
npx electron-builder --publish ${{ startsWith(github.ref, 'refs/tags/') && 'always' || 'never' }}

- name: Upload installers
uses: actions/upload-artifact@v4
with:
name: dexter-${{ matrix.os }}
path: |
desktop/release/*.dmg
desktop/release/*.exe
desktop/release/*.blockmap
desktop/release/latest*.yml
if-no-files-found: warn
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,7 @@ logs/
coverage.json

# Scratchpad files
scratchpads/*
scratchpads/*

# Claude Code runtime locks
.claude/scheduled_tasks.lock
42 changes: 23 additions & 19 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# Repository Guidelines

- Repo: https://github.com/virattt/dexter
- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, Ink (React for CLI), and LangChain.
- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, a terminal UI (`@mariozechner/pi-tui`), and LangChain.

## Project Structure

- Source code: `src/`
- Agent core: `src/agent/` (agent loop, prompts, scratchpad, token counting, types)
- CLI interface: `src/cli.tsx` (Ink/React), entry point: `src/index.tsx`
- Components: `src/components/` (Ink UI components)
- Hooks: `src/hooks/` (React hooks for agent runner, model selection, input history)
- CLI interface: `src/cli.ts` (pi-tui; no JSX), entry point: `src/index.tsx` (the `.tsx` extension is historical)
- Components: `src/components/` (pi-tui UI components, plain `.ts`)
- Model/LLM: `src/model/llm.ts` (multi-provider LLM abstraction)
- Tools: `src/tools/` (financial search, web search, browser, skill tool)
- Tools: `src/tools/` (financial data, web search, browser, skill tool)
- Tool descriptions: `src/tools/descriptions/` (rich descriptions injected into system prompt)
- Finance tools: `src/tools/finance/` (prices, fundamentals, filings, insider trades, etc.)
- Search tools: `src/tools/search/` (Exa preferred, Tavily fallback)
- Korean tools: `src/tools/finance-kr/` (DART/KRX/Naver — financials, filings, foreign ownership, short balance, NPS, market data)
- Search tools: `src/tools/search/` (Exa → Perplexity → Tavily → LangSearch fallback chain)
- Browser: `src/tools/browser/` (Playwright-based web scraping)
- Skills: `src/skills/` (SKILL.md-based extensible workflows, e.g. DCF valuation)
- Utils: `src/utils/` (env, config, caching, token estimation, markdown tables)
- Evals: `src/evals/` (LangSmith evaluation runner with Ink UI)
- Evals: `src/evals/` (LangSmith evaluation runner). KR eval harness: `scripts/kr-eval/` (record/replay + LLM-judge)
- Config: `.dexter/settings.json` (persisted model/provider selection)
- Environment: `.env` (API keys; see `env.example`)
- Scripts: `scripts/release.sh`
Expand All @@ -27,16 +27,17 @@

- Runtime: Bun (primary). Use `bun` for all commands.
- Install deps: `bun install`
- Run: `bun run start` or `bun run src/index.tsx`
- Run: `bun start`
- Dev (watch mode): `bun run dev`
- Type-check: `bun run typecheck`
- Tests: `bun test`
- Evals: `bun run src/evals/run.ts` (full) or `bun run src/evals/run.ts --sample 10` (sampled)
- KR evals: `bun run kr-eval` (live) / `kr-eval:record` / `kr-eval:replay` (deterministic, no keys)
- CI runs `bun run typecheck` and `bun test` on push/PR.

## Coding Style & Conventions

- Language: TypeScript (ESM, strict mode). JSX via React (Ink for CLI rendering).
- Language: TypeScript (ESM, strict mode). The CLI renders via `@mariozechner/pi-tui` (no JSX in `src/cli.ts`).
- Prefer strict typing; avoid `any`.
- Keep files concise; extract helpers rather than duplicating code.
- Add brief comments for tricky or non-obvious logic.
Expand All @@ -45,26 +46,28 @@

## LLM Providers

- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Ollama (local).
- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Moonshot, DeepSeek, Ollama (local).
- Default model: `gpt-5.5`. Provider detection is prefix-based (`claude-` -> Anthropic, `gemini-` -> Google, etc.).
- Fast models for lightweight tasks: see `FAST_MODELS` map in `src/model/llm.ts`.
- Anthropic uses explicit `cache_control` on system prompt for prompt caching cost savings.
- Users switch providers/models via `/model` command in the CLI.

## Tools

- `financial_search`: primary tool for all financial data queries (prices, metrics, filings). Delegates to multiple sub-tools internally.
- `financial_metrics`: direct metric lookups (revenue, market cap, etc.).
- `get_financials`: US financial statements, metrics, segments (Financial Datasets). Routes multi-company/metric queries internally.
- `get_market_data`: US prices, company news, insider trades, 13F holdings.
- `read_filings`: SEC filing reader for 10-K, 10-Q, 8-K documents.
- `web_search`: general web search (Exa if `EXASEARCH_API_KEY` set, else Tavily if `TAVILY_API_KEY` set).
- `stock_screener`: screen US stocks by financial criteria (P/E, growth, margins).
- Korean tools (`src/tools/finance-kr/`, all take 6-digit tickers): `get_financials_kr`, `get_filings_kr`, `get_large_holders_kr`, `get_insider_trades_kr`, `read_filings_kr` (DART, gated on `DART_API_KEY`); `get_market_data_kr`, `get_foreign_ownership_kr` (Naver, keyless); `get_short_balance_kr` (KRX login); `get_nps_holdings` (data.go.kr).
- `web_search`: general web search; provider fallback chain Exa → Perplexity → Tavily → LangSearch (registered if ≥1 key set).
- `browser`: Playwright-based web scraping for reading pages the agent discovers.
- `skill`: invokes SKILL.md-defined workflows (e.g. DCF valuation). Each skill runs at most once per query.
- Tool registry: `src/tools/registry.ts`. Tools are conditionally included based on env vars.
- Tool registry: `src/tools/registry.ts`. US finance + screener tools register unconditionally (they 401 at call-time without `FINANCIAL_DATASETS_API_KEY`); KR, web_search, and X tools are gated by their env vars.

## Skills

- Skills live as `SKILL.md` files with YAML frontmatter (`name`, `description`) and markdown body (instructions).
- Built-in skills: `src/skills/dcf/SKILL.md`.
- Built-in skills (`src/skills/<name>/SKILL.md`): `dcf` (DCF valuation; branches US/KR internally), `kr-spinoff` (물적/인적분할 analysis), `write-memo`, `x-research`.
- Discovery: `src/skills/registry.ts` scans for SKILL.md files at startup.
- Skills are exposed to the LLM as metadata in the system prompt; the LLM invokes them via the `skill` tool.

Expand All @@ -73,15 +76,16 @@
- Agent loop: `src/agent/agent.ts`. Iterative tool-calling loop with configurable max iterations (default 10).
- Scratchpad: `src/agent/scratchpad.ts`. Single source of truth for all tool results within a query.
- Context management: Anthropic-style. Full tool results kept in context; oldest results cleared when token threshold exceeded.
- Final answer: generated in a separate LLM call with full scratchpad context (no tools bound).
- Final answer: the text of the turn where the model stops emitting tool calls (`handleDirectResponse`). Tools stay bound on every call — there is no separate no-tools finalization pass, so answer quality is governed by the system prompt.
- Events: agent yields typed events (`tool_start`, `tool_end`, `thinking`, `answer_start`, `done`, etc.) for real-time UI updates.

## Environment Variables

- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`
- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`, `MOONSHOT_API_KEY`, `DEEPSEEK_API_KEY`
- Ollama: `OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`)
- Finance: `FINANCIAL_DATASETS_API_KEY`
- Search: `EXASEARCH_API_KEY` (preferred), `TAVILY_API_KEY` (fallback)
- US finance: `FINANCIAL_DATASETS_API_KEY`
- Korean data: `DART_API_KEY` (재무·공시), `KRX_ID`+`KRX_PW` or `KRX_COOKIE` (공매도), `DATA_GO_KR_SERVICE_KEY` (국민연금). Naver tools (외국인·현재가) need no key.
- Search: `EXASEARCH_API_KEY`, `PERPLEXITY_API_KEY`, `TAVILY_API_KEY`, `LANGSEARCH_API_KEY` (fallback chain in that order)
- Tracing: `LANGSMITH_API_KEY`, `LANGSMITH_ENDPOINT`, `LANGSMITH_PROJECT`, `LANGSMITH_TRACING`
- Never commit `.env` files or real API keys.

Expand Down
Loading
Loading