From 74efad08f5dce199785c92b9a0ec3a39fc3773fe Mon Sep 17 00:00:00 2001 From: zhnd Date: Sat, 11 Apr 2026 15:36:19 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20housekeeping=20=E2=80=94=20remove=20de?= =?UTF-8?q?ad=20code,=20update=20docs=20and=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove unused usage API infrastructure (usage_commands, usage_service, config_service, usage types) that was never called from the frontend - Remove leftover src-tauri/migrations/ directory (migrations live in crates/shared/migrations/) - Remove empty LoginPromptProps types file - Update README.md with new features (Usage, Insights, Skills & Marketplace) and development prerequisites - Rewrite QUICKSTART.md as a proper development guide with daemon compilation instructions - Update crates/daemon/README.md to reflect current architecture - Upgrade pnpm/action-setup@v4 to @v6 in CI workflows for Node.js 24 compatibility Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/check.yml | 2 +- .github/workflows/publish.yml | 2 +- .vscode/cspell.json | 35 +++ .vscode/extensions.json | 9 + .vscode/settings.json | 35 +++ QUICKSTART.md | 162 ++++--------- README.md | 82 +++++-- crates/daemon/README.md | 226 +++--------------- .../usage/components/login-prompt/types.ts | 1 - .../20260124000001_create_users_table.sql | 11 - src-tauri/src/commands/mod.rs | 7 - src-tauri/src/commands/usage_commands.rs | 38 --- src-tauri/src/services/config_service.rs | 65 ----- src-tauri/src/services/mod.rs | 4 - src-tauri/src/services/usage_service.rs | 89 ------- src-tauri/src/types/mod.rs | 2 - src-tauri/src/types/usage.rs | 25 -- 17 files changed, 229 insertions(+), 566 deletions(-) create mode 100644 .vscode/cspell.json create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json delete mode 100644 packages/ui/src/modules/usage/components/login-prompt/types.ts delete mode 100644 src-tauri/migrations/20260124000001_create_users_table.sql delete mode 100644 src-tauri/src/commands/usage_commands.rs delete mode 100644 src-tauri/src/services/config_service.rs delete mode 100644 src-tauri/src/services/usage_service.rs delete mode 100644 src-tauri/src/types/usage.rs diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 9100791..4d3f0a6 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -81,7 +81,7 @@ jobs: path: packages/ui/src/generated - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v5 - name: Setup Node.js uses: actions/setup-node@v6 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 186fe4e..8d6bfac 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 - name: Setup Node.js uses: actions/setup-node@v6 diff --git a/.vscode/cspell.json b/.vscode/cspell.json new file mode 100644 index 0000000..6d6809b --- /dev/null +++ b/.vscode/cspell.json @@ -0,0 +1,35 @@ +// cSpell Settings +{ + // Version of the setting file. Always 0.2 + "version": "0.2", + // language - current active spelling language + "language": "en", + // words - list of words to be always considered correct + "words": [ + "cdylib", + "chrono", + "fsevent", + "githubusercontent", + "lumo", + "mkdirp", + "reqwest", + "rlib", + "rustls", + "serde", + "shiki", + "snapdom", + "sqlx", + "staticlib", + "streetsidesoftware", + "tauri", + "tsmerge", + "typeshare", + "visualstudio", + "vsmarketplacebadge", + "zumer" + ], + // flagWords - list of words to be always considered incorrect + // This is useful for offensive words and common spelling errors. + // For example "hte" should be "the" + "flagWords": ["hte"] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..fbcdff4 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "biomejs.biome", + "tauri-apps.tauri-vscode", + "rust-lang.rust-analyzer", + "bradlc.vscode-tailwindcss", + "streetsidesoftware.code-spell-checker" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a93b4b1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + // Biome as default formatter & linter + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + + // Disable built-in JS/TS validation to avoid conflicts + "js/ts.validate.enabled": false, + + // Per-language formatter overrides (ensure Biome is used) + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + + // Tauri + "rust-analyzer.cargo.features": "all" +} diff --git a/QUICKSTART.md b/QUICKSTART.md index 25d55b8..fe10c91 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,147 +1,89 @@ -# Lumo OTLP Daemon - 快速启动指南 +# Lumo — 开发快速入门 -## 5 分钟快速开始 +## 环境要求 -### 1. 安装 Daemon +| 工具 | 最低版本 | 安装方式 | +|------|---------|---------| +| Node.js | >= 24.12 | [nodejs.org](https://nodejs.org/) | +| pnpm | >= 10.26 | `npm install -g pnpm` | +| Rust (stable) | >= 1.77.2 | [rustup.rs](https://rustup.rs/) | +| typeshare-cli | latest | `cargo install typeshare-cli` | +| Tauri 平台依赖 | — | [Tauri v2 Prerequisites](https://v2.tauri.app/start/prerequisites/) | -```bash -# 在项目根目录执行 -./scripts/install-daemon.sh -``` - -这会自动: -- ✅ 编译 daemon -- ✅ 安装到 `/usr/local/bin/lumo-daemon` -- ✅ 配置 launchd 自动启动 -- ✅ 启动服务 - -### 2. 验证运行 - -```bash -# 检查健康状态 -curl http://localhost:4318/health - -# 应返回: -# {"status":"healthy","service":"lumo-daemon","version":"0.1.0"} -``` - -### 3. 配置 Claude Code +## 首次启动 ```bash -# 设置环境变量 -export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 - -# 然后正常使用 Claude Code -claude code -``` +# 1. 安装前端依赖 +pnpm install -### 4. 查看接收到的数据 +# 2. 编译 daemon(首次必须,后续 daemon 代码变更后也需要重新编译) +cargo build -p lumo-daemon -```bash -# 实时查看日志 -tail -f ~/Library/Logs/com.lumo.daemon/stdout.log +# 3. 启动开发环境(会自动生成 TypeScript 类型 + 启动前端 dev server + 启动 Tauri 应用) +pnpm tauri:dev ``` -当你使用 Claude Code 执行命令时,会看到类似这样的输出: +> **注意**:`pnpm tauri:dev` 会自动运行 `pnpm generate-types`(Rust → TypeScript 类型生成)和 `pnpm dev`(Next.js dev server),但**不会**自动编译 daemon。首次或 daemon 代码变更后需要手动执行 `cargo build -p lumo-daemon`。 -``` -2026-01-25T12:00:00.000Z INFO lumo_daemon: Received OTLP trace export request -2026-01-25T12:00:00.000Z INFO lumo_daemon: Service: claude-code -2026-01-25T12:00:00.000Z INFO lumo_daemon: Scope: claude-code-instrumentation -2026-01-25T12:00:00.000Z INFO lumo_daemon: Span[5B8EFFF7]: name='tool.Read', kind=Internal, duration=125000ns, attributes=[tool.name=Read, file.path=/path/to/file] -2026-01-25T12:00:00.000Z INFO lumo_daemon: Processed 1 spans successfully -``` +## 日常开发 -## 常用命令 - -### 服务管理 +### 全栈开发(推荐) ```bash -# 查看状态 -launchctl list | grep com.lumo.daemon - -# 停止服务 -launchctl unload ~/Library/LaunchAgents/com.lumo.daemon.plist - -# 启动服务 -launchctl load ~/Library/LaunchAgents/com.lumo.daemon.plist - -# 卸载 -./scripts/uninstall-daemon.sh +pnpm tauri:dev # 启动 Tauri 应用 + 前端 dev server ``` -### 日志查看 +### 仅前端 ```bash -# 标准输出(主要日志) -tail -f ~/Library/Logs/com.lumo.daemon/stdout.log - -# 错误日志 -tail -f ~/Library/Logs/com.lumo.daemon/stderr.log +pnpm dev # Next.js dev server (localhost:3000) +pnpm build # 构建静态站点到 packages/ui/out/ +pnpm lint # Biome 代码检查 +pnpm check # Biome 代码检查 + 格式化(自动修复) ``` -### 测试端点 +### 仅 Rust ```bash -# 健康检查 -curl http://localhost:4318/health - -# 发送测试 trace -curl -X POST http://localhost:4318/v1/traces \ - -H "Content-Type: application/json" \ - -d '{"resourceSpans":[{"scopeSpans":[{"spans":[{"traceId":"TEST123","spanId":"SPAN456","name":"test","kind":1,"startTimeUnixNano":"1000000000"}]}]}]}' +cargo check # 检查所有 crate +cargo check -p app # 检查 Tauri 应用(包名是 "app") +cargo check -p lumo-daemon # 检查 daemon +cargo check -p shared # 检查共享库 +cargo run -p lumo-daemon # 直接运行 daemon ``` -## 故障排查 - -### 问题:端口已被占用 +### 类型生成 ```bash -# 查看谁在使用 4318 端口 -lsof -i :4318 - -# 如需更换端口,编辑 plist -nano ~/Library/LaunchAgents/com.lumo.daemon.plist -# 修改 LUMO_SERVER_ADDRESS 环境变量 -# 然后重新加载服务 +pnpm generate-types # 从 Rust #[typeshare] 结构体生成 TypeScript 类型 ``` -### 问题:服务无法启动 +修改了 `src-tauri/src/types/` 中的 `#[typeshare]` 结构体后需要重新生成。`pnpm tauri:dev` 启动时会自动运行。 -```bash -# 查看错误日志 -cat ~/Library/Logs/com.lumo.daemon/stderr.log +## 何时需要重新编译 Daemon -# 手动运行 daemon 查看详细错误 -/usr/local/bin/lumo-daemon -``` +Daemon 是独立的 HTTP 服务,通过 Tauri 应用管理其生命周期。以下情况需要重新编译: -### 问题:收不到 Claude Code 数据 - -1. 确认环境变量已设置: -```bash -echo $OTEL_EXPORTER_OTLP_ENDPOINT -# 应输出:http://localhost:4318 -``` - -2. 确认 daemon 正在运行: ```bash -curl http://localhost:4318/health +cargo build -p lumo-daemon ``` -3. 查看 daemon 日志是否有请求进来 +- 修改了 `crates/daemon/` 下的代码 +- 修改了 `crates/shared/` 下的代码(daemon 和 Tauri app 共用) +- 修改了 `crates/shared/migrations/` 中的数据库迁移 -## 下一步 +> `pnpm tauri build`(生产构建)会自动编译 daemon,但 `pnpm tauri:dev`(开发模式)不会。 -- 📖 查看 [daemon/README.md](daemon/README.md) 了解详细文档 -- 🔍 探索接收到的 trace 数据结构 -- 🚀 等待后续版本支持数据库存储和可视化 +## 项目结构概览 -## 当前限制(MVP 版本) - -- ✅ 接收并打印 OTLP 数据 -- ❌ 暂不支持数据持久化 -- ❌ 暂无 UI 查看器 -- ❌ 仅支持 macOS +``` +lumo/ +├── packages/ui/ # Next.js 前端(SSG 模式) +├── crates/ +│ ├── daemon/ # OTLP 遥测接收服务(Axum HTTP) +│ └── shared/ # 共享库(数据库实体、仓库、迁移) +├── src-tauri/ # Tauri 桌面应用(命令、服务、类型) +└── scripts/ # 构建和安装脚本 +``` -后续版本会逐步添加这些功能。 +详细架构说明见 [CLAUDE.md](CLAUDE.md)。 diff --git a/README.md b/README.md index 597bc4b..f69a7fc 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,10 @@

Why • - ScreenshotsFeaturesHow It WorksInstall • - Getting Started • + DevelopmacOS TroubleshootingTech Stack

@@ -142,6 +141,40 @@ Usage insights derived directly from local telemetry: --- +### Usage + +Monitor your Claude Pro/Max subscription usage in real time: + +- Session limit (5-hour window) and weekly limits +- Per-model breakdown (Opus, Sonnet) +- Extra usage spend tracking +- Data fetched from Anthropic's official OAuth API using your existing Claude Code credentials +- Auto-refreshes every 30 minutes to avoid rate limits + +--- + +### Insights + +Generate and view Claude Code `/insights` reports directly within Lumo: + +- One-click report generation (invokes `claude /insights` CLI) +- Browse previously generated reports +- View interactive HTML reports in an embedded viewer +- Reports analyze your session patterns, friction points, and suggest CLAUDE.md improvements + +--- + +### Skills & Marketplace + +Manage Claude Code skills and plugins: + +- Browse, install, and uninstall skills +- View skill details and configuration +- Browse the plugin marketplace +- Install community plugins + +--- + ### Claude Code Wrapped A lightweight "wrapped" summary for your Claude Code habits: @@ -220,33 +253,37 @@ Use this if you want to develop or modify Lumo locally. --- -## Getting Started +## Developing from Source ### Prerequisites -- Node.js >= 24.12 -- pnpm >= 10.26 -- Rust (stable) -- Platform dependencies for Tauri v2 +| Tool | Version | Purpose | +|------|---------|---------| +| Node.js | >= 24.12 | Frontend runtime | +| pnpm | >= 10.26 | Package manager | +| Rust (stable) | >= 1.77.2 | Backend + daemon | +| typeshare-cli | latest | Rust → TypeScript type generation (`cargo install typeshare-cli`) | +| [Tauri v2 deps](https://v2.tauri.app/start/prerequisites/) | — | Platform-specific build dependencies | -### Install & Run +### First-time Setup ```bash git clone https://github.com/zhnd/lumo.git cd lumo pnpm install + +# Build the daemon (required before first launch) +cargo build -p lumo-daemon + +# Start the app pnpm tauri:dev ``` -This starts the daemon, builds the frontend, and launches the desktop app. - -When the app starts, it will also try to configure Claude Code OTEL/hook settings in: +> **Important**: `pnpm tauri:dev` does NOT automatically compile the daemon. You must run `cargo build -p lumo-daemon` before the first launch, and again whenever you modify code under `crates/daemon/` or `crates/shared/`. -```bash -~/.claude/settings.json -``` +On startup, the app will configure Claude Code OTEL/hook settings in `~/.claude/settings.json` automatically. -You can review or edit that file at any time. +See [QUICKSTART.md](QUICKSTART.md) for a more detailed development guide. --- @@ -301,13 +338,16 @@ Then try launching the app again. ``` lumo/ -├── crates/daemon/ # OTLP receiver service +├── crates/daemon/ # OTLP receiver service (Axum HTTP) ├── crates/shared/ # Database entities, repositories, migrations -├── src-tauri/ # Tauri backend (IPC commands) -└── packages/ui/ # Desktop UI - ├── app/ # Next.js routes - ├── modules/ # Overview, Sessions, Tools, Performance, Wrapped - └── components/ # Shared UI components +├── src-tauri/ # Tauri backend (commands, services, types) +└── packages/ui/ # Desktop UI (Next.js SSG) + ├── app/ # Routes + └── src/ + ├── modules/ # Page modules (Overview, Sessions, Tools, Performance, + │ # Usage, Insights, Skills, Marketplace, Wrapped) + ├── bridges/ # Tauri IPC wrappers + └── components/ # Shared UI components ``` --- diff --git a/crates/daemon/README.md b/crates/daemon/README.md index 3dc4b01..29dd15c 100644 --- a/crates/daemon/README.md +++ b/crates/daemon/README.md @@ -1,209 +1,53 @@ -# Lumo Daemon - OTLP Receiver for Claude Code +# Lumo Daemon -独立的后台守护进程,接收 Claude Code 的 OTLP (OpenTelemetry Protocol) 遥测数据。 +独立的后台 HTTP 服务,接收 Claude Code 的 OTLP 遥测数据和 Hook 事件,持久化到 SQLite。 -## 功能特性 +## 功能 -- ✅ 接收 OTLP/HTTP JSON 格式的 trace 数据 -- ✅ 标准 OTLP 端点:`http://localhost:4318/v1/traces` -- ✅ 健康检查端点:`http://localhost:4318/health` -- ✅ 自动启动(macOS launchd) -- ✅ 优雅关闭处理 -- ✅ 结构化日志输出 -- ✅ MVP 版本:打印接收到的数据到控制台 +- 接收 OTLP/HTTP JSON 格式的 metrics 和 logs 数据 +- 接收 Claude Code hook 通知(session 开始/结束、tool 使用等) +- 数据持久化到 SQLite(`~/.lumo/lumo.db`) +- macOS launchd 自动启动,由 Tauri 应用管理生命周期 -## 安装(macOS) +## API 端点 -### 前置要求 +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/health` | 健康检查 | +| POST | `/v1/metrics` | 接收 OTLP metrics(protobuf JSON) | +| POST | `/v1/logs` | 接收 OTLP logs/events(protobuf JSON) | +| POST | `/notify` | 接收 Claude Code hook 通知 | -- Rust 工具链 -- macOS 系统 - -### 安装步骤 - -```bash -# 1. 进入项目根目录 -cd /path/to/lumo - -# 2. 运行安装脚本(会自动编译、安装、启动) -./scripts/install-daemon.sh -``` - -安装脚本会: -1. 编译 daemon(release 模式) -2. 复制二进制到 `/usr/local/bin/lumo-daemon` -3. 创建 launchd plist 配置 -4. 启动服务并设置自动启动 - -### 验证安装 - -```bash -# 检查服务状态 -launchctl list | grep com.lumo.daemon - -# 测试健康检查 -curl http://localhost:4318/health - -# 应返回: -# {"status":"healthy","service":"lumo-daemon","version":"0.1.0"} -``` - -## 配置 Claude Code - -配置 Claude Code 将 OTLP 数据发送到 daemon: - -```bash -export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 -``` - -然后运行 Claude Code 命令,daemon 会接收并打印 trace 数据。 - -## 查看日志 - -```bash -# 实时查看标准输出日志 -tail -f ~/Library/Logs/com.lumo.daemon/stdout.log - -# 查看错误日志 -tail -f ~/Library/Logs/com.lumo.daemon/stderr.log -``` - -## 管理服务 - -### 停止服务 - -```bash -launchctl unload ~/Library/LaunchAgents/com.lumo.daemon.plist -``` - -### 启动服务 - -```bash -launchctl load ~/Library/LaunchAgents/com.lumo.daemon.plist -``` - -### 重启服务 - -```bash -launchctl unload ~/Library/LaunchAgents/com.lumo.daemon.plist -launchctl load ~/Library/LaunchAgents/com.lumo.daemon.plist -``` - -### 完全卸载 +## 开发 ```bash -./scripts/uninstall-daemon.sh -``` - -## 环境变量配置 - -daemon 支持以下环境变量(在 plist 文件中配置): - -- `LUMO_SERVER_ADDRESS`: 监听地址(默认:`127.0.0.1:4318`) -- `RUST_LOG`: 日志级别(默认:`lumo_daemon=info,tower_http=info`) - -修改配置: - -```bash -# 编辑 plist 文件 -nano ~/Library/LaunchAgents/com.lumo.daemon.plist - -# 重新加载 -launchctl unload ~/Library/LaunchAgents/com.lumo.daemon.plist -launchctl load ~/Library/LaunchAgents/com.lumo.daemon.plist -``` - -## 测试 OTLP 端点 - -发送测试 trace 数据: - -```bash -curl -X POST http://localhost:4318/v1/traces \ - -H "Content-Type: application/json" \ - -d '{ - "resourceSpans": [{ - "scopeSpans": [{ - "spans": [{ - "traceId": "5B8EFFF798038103D269B633813FC60C", - "spanId": "EEE19B7EC3C1B174", - "name": "test-span", - "kind": 1, - "startTimeUnixNano": "1544712660000000000", - "endTimeUnixNano": "1544712661000000000", - "attributes": [{ - "key": "test.attribute", - "value": {"stringValue": "test value"} - }] - }] - }] - }] - }' -``` - -检查日志应该能看到接收到的 span 信息。 - -## 架构说明 - +cargo run -p lumo-daemon # 运行 daemon +RUST_LOG=debug cargo run -p lumo-daemon # debug 日志级别 +cargo build -p lumo-daemon # 编译(dev 模式) +cargo build -p lumo-daemon --release # 编译(release 模式) ``` -Claude Code → OTLP export → lumo-daemon:4318 → Parse → Print to console - (未来:存储到数据库) -``` - -### 模块结构 - -- `src/main.rs` - 入口点 -- `src/server.rs` - Axum HTTP 服务器设置 -- `src/handlers/` - HTTP 处理器 - - `health.rs` - 健康检查 - - `traces.rs` - OTLP trace 接收 -- `src/otlp/parser.rs` - OTLP JSON 数据结构定义 -- `src/config.rs` - 配置管理 -- `src/shutdown.rs` - 优雅关闭处理 - -### 设计原则 - -- **模块化**:易于扩展新功能(如数据库存储) -- **标准化**:遵循 OTLP 规范 -- **可观测性**:结构化日志,易于调试 -- **可靠性**:优雅关闭,自动重启 - -## 路线图 -### MVP (当前版本) -- [x] 接收 OTLP JSON 数据 -- [x] 打印到控制台 -- [x] macOS launchd 自动启动 +## 配置 -### 未来版本 -- [ ] SQLite 数据库存储 -- [ ] 数据转换和分析 -- [ ] Tauri 应用集成(查看器) -- [ ] Windows 支持(Windows Service) +环境变量: -## 故障排查 +| 变量 | 默认值 | 说明 | +|------|--------|------| +| `LUMO_HOST` | `127.0.0.1` | 监听地址 | +| `LUMO_PORT` | `4318` | 监听端口 | +| `RUST_LOG` | `info` | 日志级别 | -### 服务无法启动 +## 生命周期管理 -```bash -# 检查日志 -cat ~/Library/Logs/com.lumo.daemon/stderr.log - -# 手动运行查看错误 -/usr/local/bin/lumo-daemon -``` - -### 端口被占用 - -检查 4318 端口是否被其他进程占用: - -```bash -lsof -i :4318 -``` +Daemon 由 Tauri 应用的 `DaemonManager` 管理(`src-tauri/src/daemon/`): -### 查看详细日志 +1. 二进制文件打包在 Tauri 应用资源中 +2. 首次启动时安装到 `~/.lumo/bin/lumo-daemon` +3. 注册为 macOS `launchd` agent(`com.zhnd.lumo-daemon`) +4. 每次应用启动时通过 `GET /health` 健康检查 -修改 plist 中的 `RUST_LOG` 环境变量为 `debug` 或 `trace`。 +开发时需要手动编译 daemon:`cargo build -p lumo-daemon`。`pnpm tauri:dev` 不会自动编译 daemon,但 `pnpm tauri build` 会。 -## 许可证 +## 架构 -同主项目 +详细的代码结构和开发指南见 [CLAUDE.md](CLAUDE.md)。 diff --git a/packages/ui/src/modules/usage/components/login-prompt/types.ts b/packages/ui/src/modules/usage/components/login-prompt/types.ts deleted file mode 100644 index 7592fa3..0000000 --- a/packages/ui/src/modules/usage/components/login-prompt/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type LoginPromptProps = {}; diff --git a/src-tauri/migrations/20260124000001_create_users_table.sql b/src-tauri/migrations/20260124000001_create_users_table.sql deleted file mode 100644 index 57873f7..0000000 --- a/src-tauri/migrations/20260124000001_create_users_table.sql +++ /dev/null @@ -1,11 +0,0 @@ --- Create users table -CREATE TABLE users ( - id TEXT PRIMARY KEY, - name TEXT NOT NULL, - email TEXT NOT NULL UNIQUE, - created_at TEXT DEFAULT CURRENT_TIMESTAMP, - updated_at TEXT DEFAULT CURRENT_TIMESTAMP -); - --- Create index on email for faster lookups -CREATE INDEX idx_users_email ON users(email); diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index e352f41..53d4afe 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -10,7 +10,6 @@ pub mod subscription_usage_commands; pub mod system_commands; pub mod tools_commands; pub mod trends_commands; -pub mod usage_commands; pub mod user_commands; pub mod projects_commands; pub mod marketplace_commands; @@ -30,7 +29,6 @@ pub use subscription_usage_commands::*; pub use system_commands::*; pub use tools_commands::*; pub use trends_commands::*; -pub use usage_commands::*; pub use user_commands::*; pub use projects_commands::*; pub use marketplace_commands::*; @@ -82,11 +80,6 @@ macro_rules! app_commands { commands::save_image_to_path, // Daemon commands commands::get_daemon_status, - // Usage commands - commands::get_usage_limits, - commands::save_api_key, - commands::has_api_key, - commands::delete_api_key, // Insights commands commands::list_insights_reports, commands::generate_insights_report, diff --git a/src-tauri/src/commands/usage_commands.rs b/src-tauri/src/commands/usage_commands.rs deleted file mode 100644 index 6b76c3e..0000000 --- a/src-tauri/src/commands/usage_commands.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Usage commands -//! -//! Tauri IPC commands for API key management and usage limit queries. - -use tauri::command; - -use crate::services::{ConfigService, UsageService}; -use crate::types::UsageLimits; - -/// Get usage limits from Anthropic API -#[command] -pub async fn get_usage_limits() -> Result { - let api_key = ConfigService::get_api_key() - .map_err(|e| e.to_string())? - .ok_or_else(|| "API key not configured".to_string())?; - - UsageService::fetch_usage_limits(&api_key) - .await - .map_err(|e| e.to_string()) -} - -/// Save Anthropic API key -#[command] -pub async fn save_api_key(api_key: String) -> Result<(), String> { - ConfigService::save_api_key(&api_key).map_err(|e| e.to_string()) -} - -/// Check if API key is configured -#[command] -pub async fn has_api_key() -> Result { - Ok(ConfigService::has_api_key()) -} - -/// Delete stored API key -#[command] -pub async fn delete_api_key() -> Result<(), String> { - ConfigService::delete_api_key().map_err(|e| e.to_string()) -} diff --git a/src-tauri/src/services/config_service.rs b/src-tauri/src/services/config_service.rs deleted file mode 100644 index 0f90c19..0000000 --- a/src-tauri/src/services/config_service.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Config service -//! -//! Manages persistent configuration stored in ~/.lumo/config.json. - -use anyhow::{Context, Result}; -use serde::{Deserialize, Serialize}; -use std::fs; -use std::path::PathBuf; - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Config { - #[serde(skip_serializing_if = "Option::is_none")] - pub anthropic_api_key: Option, -} - -pub struct ConfigService; - -impl ConfigService { - fn config_path() -> Result { - let home = dirs::home_dir().context("Could not find home directory")?; - Ok(home.join(".lumo").join("config.json")) - } - - fn read_config() -> Result { - let path = Self::config_path()?; - if !path.exists() { - return Ok(Config::default()); - } - let content = fs::read_to_string(&path).context("Failed to read config file")?; - let config: Config = - serde_json::from_str(&content).context("Failed to parse config file")?; - Ok(config) - } - - fn write_config(config: &Config) -> Result<()> { - let path = Self::config_path()?; - if let Some(parent) = path.parent() { - fs::create_dir_all(parent).context("Failed to create config directory")?; - } - let content = serde_json::to_string_pretty(config).context("Failed to serialize config")?; - fs::write(&path, content).context("Failed to write config file")?; - Ok(()) - } - - pub fn save_api_key(api_key: &str) -> Result<()> { - let mut config = Self::read_config()?; - config.anthropic_api_key = Some(api_key.to_string()); - Self::write_config(&config) - } - - pub fn get_api_key() -> Result> { - let config = Self::read_config()?; - Ok(config.anthropic_api_key) - } - - pub fn has_api_key() -> bool { - Self::get_api_key().map(|k| k.is_some()).unwrap_or(false) - } - - pub fn delete_api_key() -> Result<()> { - let mut config = Self::read_config()?; - config.anthropic_api_key = None; - Self::write_config(&config) - } -} diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index d989a3d..bfc547f 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -5,7 +5,6 @@ mod analytics_service; mod claude_config_service; mod claude_session_service; -mod config_service; pub mod notification_poller; mod notification_settings_service; pub mod session_cache; @@ -17,7 +16,6 @@ mod subscription_usage_service; pub mod time_range; mod tools_service; mod trends_service; -mod usage_service; mod projects_service; mod marketplace_service; mod skills_service; @@ -26,14 +24,12 @@ mod wrapped_service; pub use analytics_service::AnalyticsService; pub use claude_config_service::ClaudeConfigService; pub use claude_session_service::ClaudeSessionService; -pub use config_service::ConfigService; pub use notification_settings_service::NotificationSettingsService; pub use stats_service::StatsService; pub use insights_service::InsightsService; pub use subscription_usage_service::SubscriptionUsageService; pub use tools_service::ToolsService; pub use trends_service::TrendsService; -pub use usage_service::UsageService; pub use projects_service::ProjectsService; pub use marketplace_service::MarketplaceService; pub use skills_service::SkillsService; diff --git a/src-tauri/src/services/usage_service.rs b/src-tauri/src/services/usage_service.rs deleted file mode 100644 index d7fa1f6..0000000 --- a/src-tauri/src/services/usage_service.rs +++ /dev/null @@ -1,89 +0,0 @@ -//! Usage service -//! -//! Fetches rate limit information from the Anthropic API. - -use anyhow::{Context, Result}; - -use crate::types::{RateLimitHeader, UsageLimits}; - -pub struct UsageService; - -impl UsageService { - /// Fetch usage limits by making a minimal API request and reading response headers. - pub async fn fetch_usage_limits(api_key: &str) -> Result { - let client = reqwest::Client::new(); - - let response = client - .post("https://api.anthropic.com/v1/messages") - .header("x-api-key", api_key) - .header("anthropic-version", "2023-06-01") - .header("content-type", "application/json") - .body( - serde_json::json!({ - "model": "claude-haiku-4-5-20251001", - "max_tokens": 1, - "messages": [{"role": "user", "content": "h"}] - }) - .to_string(), - ) - .send() - .await - .context("Failed to send request to Anthropic API")?; - - let headers: Vec = response - .headers() - .iter() - .filter(|(name, _)| name.as_str().starts_with("anthropic-ratelimit-")) - .filter_map(|(name, value)| { - value.to_str().ok().map(|v| RateLimitHeader { - name: name.to_string(), - value: v.to_string(), - }) - }) - .collect(); - - // Extract status from headers (e.g. anthropic-ratelimit-tokens-remaining) - let status = Self::determine_status(&headers); - let resets_at = Self::extract_reset_time(&headers); - - Ok(UsageLimits { - status, - resets_at, - headers, - }) - } - - fn determine_status(headers: &[RateLimitHeader]) -> String { - // Check for tokens-remaining to determine status - let tokens_remaining = headers - .iter() - .find(|h| h.name == "anthropic-ratelimit-tokens-remaining") - .and_then(|h| h.value.parse::().ok()); - - let tokens_limit = headers - .iter() - .find(|h| h.name == "anthropic-ratelimit-tokens-limit") - .and_then(|h| h.value.parse::().ok()); - - match (tokens_remaining, tokens_limit) { - (Some(remaining), Some(limit)) if limit > 0 => { - let ratio = remaining as f64 / limit as f64; - if ratio <= 0.0 { - "rejected".to_string() - } else if ratio <= 0.1 { - "allowed_warning".to_string() - } else { - "allowed".to_string() - } - } - _ => "allowed".to_string(), - } - } - - fn extract_reset_time(headers: &[RateLimitHeader]) -> Option { - headers - .iter() - .find(|h| h.name == "anthropic-ratelimit-tokens-reset") - .map(|h| h.value.clone()) - } -} diff --git a/src-tauri/src/types/mod.rs b/src-tauri/src/types/mod.rs index 1b0c35a..57a9a54 100644 --- a/src-tauri/src/types/mod.rs +++ b/src-tauri/src/types/mod.rs @@ -10,7 +10,6 @@ mod stats; mod subscription_usage; mod tools; mod trends; -mod usage; mod marketplace; mod skills; mod insights; @@ -24,7 +23,6 @@ pub use stats::*; pub use subscription_usage::*; pub use tools::*; pub use trends::*; -pub use usage::*; pub use marketplace::*; pub use skills::*; pub use insights::*; diff --git a/src-tauri/src/types/usage.rs b/src-tauri/src/types/usage.rs deleted file mode 100644 index fb2aa69..0000000 --- a/src-tauri/src/types/usage.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Usage types -//! -//! Types for Anthropic API rate limit / usage information. - -use serde::{Deserialize, Serialize}; -use typeshare::typeshare; - -/// Rate limit header from Anthropic API response -#[typeshare] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RateLimitHeader { - pub name: String, - pub value: String, -} - -/// Usage limits from Anthropic API -#[typeshare] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct UsageLimits { - pub status: String, - pub resets_at: Option, - pub headers: Vec, -}