Skip to content

Commit 8bcad71

Browse files
committed
feat: v0.15.1 — Ollama 本地模型接入、AI 处理器重构与认证体系增强
Ollama 本地模型支持: - 新增 electron/ai/ollama/ 本地模型管理模块 - 新增 useOllamaStatus Hook 与 ollama 类型定义 - AI 配置层支持本地模型切换 AI 处理器全面重构: - 新增 sessionAnalyzeHandler / videoAnalyzeHandler - 全部 Handler 重构(anchorPoint/evaluate/feynman/flashcard/optimizeCard/predict/recommend/rescue/socratic/summarize/tag/visionExtract) - ai/index.ts 统一调度与 utils.ts 工具优化 认证体系增强: - AuthContext 认证上下文重构 - LoginPage / RegisterPage 登录注册页优化 - AIProviderSettings 设置页改进 前端基础设施: - env.d.ts 环境类型声明更新 - apiClient HTTP 客户端优化 - sessionAnalyzer / visionWorker AI 核心更新 - package.json 依赖升级 后端更新: - config.py / auth.py 认证配置优化 - glm_provider.py 模型提供者更新 - nginx.conf 路由配置调整 CI/CD 与自动化: - 新增 version-release.yml 版本自动发布流水线 - 新增 .releaserc.json 语义化发布配置 - 新增 scripts/ 脚本集(session-detect/record/route、version-bump) - 新增根 package.json 统一脚本入口 - 全部 workflows 更新(deploy-server/website/pr-check/release) 官网更新: - download 页面与 Footer 更新 - 新增 beian.png 备案图标 README 更新至 v0.15.1
1 parent b0aeb02 commit 8bcad71

56 files changed

Lines changed: 3493 additions & 345 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/deploy-server.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Deploy AI Gateway
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [master]
66
paths: ['server/**']
77

88
jobs:

‎.github/workflows/deploy-website.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Deploy Website
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [master]
66
paths: ['website/**']
77

88
jobs:

‎.github/workflows/pr-check.yml‎

Lines changed: 116 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,42 @@ name: PR Quality Check
22

33
on:
44
pull_request:
5-
branches: [main]
5+
branches: [master]
66

77
jobs:
8-
quality:
8+
# ===========================================================================
9+
# 路径变更检测 —— 决定哪些子项目需要执行检查
10+
# ===========================================================================
11+
changes:
12+
runs-on: ubuntu-latest
13+
outputs:
14+
client: ${{ steps.filter.outputs.client }}
15+
sync-service: ${{ steps.filter.outputs.sync-service }}
16+
ai-gateway: ${{ steps.filter.outputs.ai-gateway }}
17+
website: ${{ steps.filter.outputs.website }}
18+
steps:
19+
- uses: actions/checkout@v4
20+
- uses: dorny/paths-filter@v3
21+
id: filter
22+
with:
23+
filters: |
24+
client:
25+
- 'client/**'
26+
sync-service:
27+
- 'server/sync-service/**'
28+
- 'server/shared/**'
29+
ai-gateway:
30+
- 'server/ai-gateway/**'
31+
- 'server/shared/**'
32+
website:
33+
- 'website/**'
34+
35+
# ===========================================================================
36+
# Client —— React + Vite + Electron 前端
37+
# ===========================================================================
38+
client:
39+
needs: changes
40+
if: needs.changes.outputs.client == 'true'
941
runs-on: ubuntu-latest
1042
steps:
1143
- uses: actions/checkout@v4
@@ -15,7 +47,85 @@ jobs:
1547
cache: 'npm'
1648
cache-dependency-path: client/package-lock.json
1749
- run: cd client && npm ci
18-
- run: cd client && npm run lint
19-
- run: cd client && npx tsc --noEmit
20-
- run: cd client && npm run test -- --run
21-
- run: cd client && npm run build
50+
- name: Lint
51+
run: cd client && npm run lint
52+
- name: Typecheck
53+
run: cd client && npx tsc --noEmit
54+
- name: Test
55+
run: cd client && npm run test -- --run
56+
- name: Build
57+
run: cd client && npm run build
58+
59+
# ===========================================================================
60+
# Server / sync-service —— Go + Gin 同步服务
61+
# ===========================================================================
62+
sync-service:
63+
needs: changes
64+
if: needs.changes.outputs.sync-service == 'true'
65+
runs-on: ubuntu-latest
66+
defaults:
67+
run:
68+
working-directory: server/sync-service
69+
steps:
70+
- uses: actions/checkout@v4
71+
- uses: actions/setup-go@v5
72+
with:
73+
go-version: '1.25'
74+
cache-dependency-path: server/sync-service/go.sum
75+
- name: Lint (go vet)
76+
run: go vet ./...
77+
- name: Build
78+
run: go build ./...
79+
- name: Test
80+
run: go test ./... -v -count=1
81+
82+
# ===========================================================================
83+
# Server / ai-gateway —— Python + FastAPI AI 网关
84+
# ===========================================================================
85+
ai-gateway:
86+
needs: changes
87+
if: needs.changes.outputs.ai-gateway == 'true'
88+
runs-on: ubuntu-latest
89+
defaults:
90+
run:
91+
working-directory: server/ai-gateway
92+
steps:
93+
- uses: actions/checkout@v4
94+
- uses: actions/setup-python@v5
95+
with:
96+
python-version: '3.12'
97+
cache: 'pip'
98+
cache-dependency-path: server/ai-gateway/requirements.txt
99+
- name: Install dependencies
100+
run: |
101+
pip install -r requirements.txt
102+
pip install ruff pytest pytest-asyncio httpx
103+
- name: Lint (ruff)
104+
run: ruff check .
105+
- name: Test
106+
run: pytest tests/ -v --tb=short
107+
108+
# ===========================================================================
109+
# Website —— Next.js 官网
110+
# ===========================================================================
111+
website:
112+
needs: changes
113+
if: needs.changes.outputs.website == 'true'
114+
runs-on: ubuntu-latest
115+
defaults:
116+
run:
117+
working-directory: website
118+
steps:
119+
- uses: actions/checkout@v4
120+
- uses: actions/setup-node@v4
121+
with:
122+
node-version: 20
123+
cache: 'npm'
124+
cache-dependency-path: website/package-lock.json
125+
- run: npm ci
126+
- name: Lint
127+
run: npm run lint
128+
- name: Typecheck
129+
run: npx tsc --noEmit
130+
- name: Build
131+
run: npm run build

‎.github/workflows/release.yml‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
name: Release Electron App
22

3+
# 由 semantic-release 创建的 v* tag 触发:构建 Electron 安装包并附加到对应 Release
34
on:
45
push:
5-
branches: [main]
6-
paths: ['client/**']
6+
tags: ['v*']
7+
8+
# 上传构建产物到 GitHub Release 需要写权限
9+
permissions:
10+
contents: write
711

812
jobs:
913
lint-test:
@@ -42,7 +46,6 @@ jobs:
4246
release:
4347
needs: build
4448
runs-on: ubuntu-latest
45-
if: startsWith(github.ref, 'refs/tags/v')
4649
steps:
4750
- uses: actions/download-artifact@v4
4851
with:
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Version & Release
2+
3+
# 语义化版本自动化:
4+
# 合并到 master 时触发,
5+
# 依据 Conventional Commits 计算 SemVer 版本,
6+
# 自动更新 package.json/package-lock.json、生成 CHANGELOG、创建 Git tag 与 GitHub Release。
7+
on:
8+
push:
9+
branches: [master]
10+
11+
# 同一分支串行执行,避免并发发布产生 tag/版本竞争
12+
concurrency:
13+
group: version-release-${{ github.ref }}
14+
cancel-in-progress: false
15+
16+
# semantic-release 需要写入仓库内容(提交、tag、release)及评论 issue/PR
17+
permissions:
18+
contents: write
19+
issues: write
20+
pull-requests: write
21+
22+
jobs:
23+
release:
24+
name: Semantic Release
25+
runs-on: ubuntu-latest
26+
# 发布提交自身携带 [skip ci] 已可被 GitHub 拦截,此处再加一层双保险,防止回环触发
27+
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
28+
steps:
29+
- name: Checkout(拉取完整历史用于提交分析)
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
persist-credentials: true
34+
35+
- name: Setup Node
36+
uses: actions/setup-node@v4
37+
with:
38+
node-version: 20
39+
40+
- name: Install release tooling
41+
run: npm install --no-audit --no-fund
42+
43+
- name: Semantic Release
44+
env:
45+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
run: npx semantic-release

‎.releaserc.json‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"branches": [
3+
"master"
4+
],
5+
"tagFormat": "v${version}",
6+
"plugins": [
7+
[
8+
"@semantic-release/commit-analyzer",
9+
{
10+
"preset": "conventionalcommits",
11+
"releaseRules": [
12+
{ "breaking": true, "release": "major" },
13+
{ "type": "feat", "release": "minor" },
14+
{ "type": "fix", "release": "patch" },
15+
{ "type": "perf", "release": "patch" },
16+
{ "type": "refactor", "release": "patch" },
17+
{ "type": "revert", "release": "patch" },
18+
{ "type": "docs", "release": false },
19+
{ "type": "style", "release": false },
20+
{ "type": "test", "release": false },
21+
{ "type": "build", "release": false },
22+
{ "type": "ci", "release": false },
23+
{ "type": "chore", "release": false }
24+
],
25+
"parserOpts": {
26+
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"]
27+
}
28+
}
29+
],
30+
[
31+
"@semantic-release/release-notes-generator",
32+
{
33+
"preset": "conventionalcommits",
34+
"presetConfig": {
35+
"types": [
36+
{ "type": "feat", "section": "✨ 新功能" },
37+
{ "type": "fix", "section": "🐛 缺陷修复" },
38+
{ "type": "perf", "section": "⚡ 性能优化" },
39+
{ "type": "refactor", "section": "♻️ 重构" },
40+
{ "type": "revert", "section": "⏪ 回滚" },
41+
{ "type": "docs", "section": "📝 文档", "hidden": true },
42+
{ "type": "style", "section": "💄 样式", "hidden": true },
43+
{ "type": "test", "section": "✅ 测试", "hidden": true },
44+
{ "type": "build", "section": "📦 构建", "hidden": true },
45+
{ "type": "ci", "section": "👷 CI", "hidden": true },
46+
{ "type": "chore", "section": "🔧 杂项", "hidden": true }
47+
]
48+
}
49+
}
50+
],
51+
[
52+
"@semantic-release/changelog",
53+
{
54+
"changelogFile": "CHANGELOG.md",
55+
"changelogTitle": "# 更新日志\n\n本项目所有值得关注的变更都会记录在此文件中。\n版本号遵循 [语义化版本 SemVer](https://semver.org/lang/zh-CN/),提交信息遵循 [Conventional Commits](https://www.conventionalcommits.org/zh-hans/)。"
56+
}
57+
],
58+
[
59+
"@semantic-release/exec",
60+
{
61+
"prepareCmd": "node scripts/version-bump.mjs ${nextRelease.version}"
62+
}
63+
],
64+
[
65+
"@semantic-release/git",
66+
{
67+
"assets": [
68+
"CHANGELOG.md",
69+
"client/package.json",
70+
"client/package-lock.json",
71+
"website/package.json",
72+
"website/package-lock.json"
73+
],
74+
"message": "chore(release): v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
75+
}
76+
],
77+
"@semantic-release/github"
78+
]
79+
}

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<p align="center"><strong>你的 AI 智能学习伙伴 — 让每一分钟学习都高效有价值</strong></p>
44
<p align="center">
55
<img src="https://img.shields.io/badge/status-beta-green.svg" alt="Status" />
6-
<img src="https://img.shields.io/badge/version-v0.14.0-blue.svg" alt="Version" />
6+
<img src="https://img.shields.io/badge/version-v0.15.1-blue.svg" alt="Version" />
77
<img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License" />
88
</p>
99
</p>

‎client/.env.example‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ VITE_API_HEALTH_URL=https://entropydecrease.com/health
2323
# 开发环境: http://127.0.0.1:8000
2424
# 生产环境: https://entropydecrease.com
2525
VITE_AI_GATEWAY_URL=https://entropydecrease.com
26+
27+
# ---- Ollama 本地推理(可选) ----
28+
# Ollama 服务地址,默认自动检测 localhost:11434
29+
# 仅在自定义端口或远程 Ollama 时需要配置
30+
# VITE_OLLAMA_BASE_URL=http://localhost:11434

‎client/electron/ai/handlers/anchorPointHandler.ts‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import { safeHandle } from '../../ipcUtils.js';
88
import { logger } from '../../logger.js';
9-
import { postJson, gatewayUrl, type AIFeatureDef } from '../utils.js';
9+
import { callWithLocalFallback, gatewayUrl, type AIFeatureDef } from '../utils.js';
10+
import { generateText } from '../ollama/OllamaProvider.js';
1011

1112
// ================================================================
1213
// IPC Handler
@@ -53,18 +54,26 @@ function register(): void {
5354
}
5455

5556
try {
56-
const { data: resp, requestId } = await postJson<typeof reqBody, AnchorPointGenResp>(
57+
const localHandler = async (): Promise<AnchorPointGenResp> => {
58+
const prompt = `从以下笔记中生成记忆锚点,返回JSON: {"anchor_points": [{"concept": "...", "association": "...", "memory_technique": "...", "importance": 0.8}], "status": "ok"}\n\n笔记:\n${args.content}`;
59+
const result = await generateText(prompt, '你是一个记忆锚点生成助手。请仅返回JSON。', { temperature: 0.6, maxTokens: 1024 });
60+
const parsed = JSON.parse(result.content);
61+
return { anchor_points: parsed.anchor_points ?? [], status: 'ok', model: result.model, tokens_used: result.tokens_used, latency_ms: result.latency_ms };
62+
};
63+
64+
const { data: resp, source, requestId } = await callWithLocalFallback<typeof reqBody, AnchorPointGenResp>(
5765
'/api/v1/ai/anchor-point',
5866
reqBody,
67+
localHandler,
5968
args.authToken,
6069
args.userApiKey,
6170
60000,
6271
);
6372

6473
const elapsed = Date.now() - startMs;
65-
logger.info(`[AI] [anchor-point] ✔ Success: anchor_points=${resp.anchor_points.length}, status=${resp.status}, model=${resp.model}, tokens=${resp.tokens_used}, total=${elapsed}ms, reqId=${requestId ?? 'N/A'}`);
74+
logger.info(`[AI] [anchor-point] ✔ Success (${source}): anchor_points=${resp.anchor_points.length}, status=${resp.status}, model=${resp.model}, tokens=${resp.tokens_used}, total=${elapsed}ms, reqId=${requestId ?? 'N/A'}`);
6675
return {
67-
anchorPoints: resp.anchor_points.map((ap) => ({
76+
anchorPoints: resp.anchor_points.map((ap: { concept: string; association: string; memory_technique: string; importance: number }) => ({
6877
concept: ap.concept,
6978
association: ap.association,
7079
memoryTechnique: ap.memory_technique,
@@ -75,6 +84,7 @@ function register(): void {
7584
tokensUsed: resp.tokens_used,
7685
latencyMs: resp.latency_ms,
7786
requestId,
87+
source,
7888
};
7989
} catch (err) {
8090
const elapsed = Date.now() - startMs;

0 commit comments

Comments
 (0)