Skip to content

Commit 040f829

Browse files
committed
Add DeepSeek, Grok, Mistral providers; expand model dropdowns
note_generation.py: - Add _provider() detection for deepseek, grok, mistral/codestral - Add _make_client() for all three (all use OpenAI-compat API): DeepSeek → https://api.deepseek.com (deepseek_key.txt) xAI Grok → https://api.x.ai/v1 (grok_key.txt) Mistral → https://api.mistral.ai/v1 (mistral_key.txt) - Refactor _make_client() to use shared _read_key() helper main.js / app.js: - Read/write deepseek_key.txt, grok_key.txt, mistral_key.txt - Add DeepSeek, xAI Grok, Mistral credential fields in Settings Model dropdowns (NOTE_MODEL & VERIFY_MODEL): - OpenAI: GPT-5.1/5.2, GPT-4.1/mini/nano, o3/o4-mini/o3-mini - Anthropic: Opus 4.6, Sonnet 4.6/4.5/3.5, Haiku 4.5/3.5 - Gemini: 2.5 Pro, 2.5 Flash, 2.5 Flash Lite, 2.0 Flash - DeepSeek: deepseek-chat (V3), deepseek-reasoner (R1) - Grok: grok-3, grok-3-mini - Mistral: mistral-large/medium/small, codestral
1 parent 4f7dfe8 commit 040f829

4 files changed

Lines changed: 84 additions & 34 deletions

File tree

electron/main.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ function loadCredentials() {
115115
openai: read('openai_api.txt'),
116116
anthropic: read('anthropic_key.txt'),
117117
gemini: read('gemini_api.txt'),
118+
deepseek: read('deepseek_key.txt'),
119+
grok: read('grok_key.txt'),
120+
mistral: read('mistral_key.txt'),
118121
};
119122
}
120123

@@ -125,6 +128,9 @@ function saveCredentials(data) {
125128
openai: 'openai_api.txt',
126129
anthropic: 'anthropic_key.txt',
127130
gemini: 'gemini_api.txt',
131+
deepseek: 'deepseek_key.txt',
132+
grok: 'grok_key.txt',
133+
mistral: 'mistral_key.txt',
128134
};
129135
for (const [key, file] of Object.entries(map)) {
130136
if (data[key] !== undefined && data[key].trim()) {

electron/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "auto-note",
3-
"version": "0.9.7",
3+
"version": "0.9.8",
44
"description": "AutoNote — lecture notes generator from Canvas recordings",
55
"homepage": "https://github.com/nodeeeeee/Auto-Note",
66
"author": {

electron/renderer/app.js

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -814,19 +814,39 @@ const CONSTANTS_DEF = [
814814
['English','en'],['Chinese (中文)','zh'],
815815
]],
816816
['generate', 'NOTE_MODEL', 'Note generation LLM', 'gpt-5.1', [
817-
['gpt-5.1','gpt-5.1'],['gpt-5.2','gpt-5.2'],['gpt-4.1','gpt-4.1'],['gpt-4.1-mini','gpt-4.1-mini'],
818-
['o3','o3'],['o1','o1'],
819-
['Gemini 2.5 Pro','gemini-2.5-pro'],['Gemini 2.5 Flash','gemini-2.5-flash'],
820-
['Gemini 2.0 Flash','gemini-2.0-flash'],['Gemini 1.5 Pro','gemini-1.5-pro'],
817+
// ── OpenAI ──────────────────────────────────────────────────────────
818+
['GPT-5.1 ★','gpt-5.1'],['GPT-5.2','gpt-5.2'],
819+
['GPT-4.1','gpt-4.1'],['GPT-4.1 mini','gpt-4.1-mini'],['GPT-4.1 nano','gpt-4.1-nano'],
820+
['o3 (reasoning)','o3'],['o4-mini (reasoning)','o4-mini'],['o3-mini','o3-mini'],
821+
// ── Anthropic ───────────────────────────────────────────────────────
821822
['Claude Opus 4.6','claude-opus-4-6'],['Claude Sonnet 4.6','claude-sonnet-4-6'],
822-
['Claude Sonnet 4.5','claude-sonnet-4-5'],['Claude Sonnet 3.5','claude-3-5-sonnet-20241022'],
823-
['Claude Haiku 4.5','claude-haiku-4-5-20251001'],
823+
['Claude Sonnet 4.5','claude-sonnet-4-5'],['Claude Haiku 4.5','claude-haiku-4-5-20251001'],
824+
['Claude Sonnet 3.5','claude-3-5-sonnet-20241022'],['Claude Haiku 3.5','claude-3-5-haiku-20241022'],
825+
// ── Google Gemini ───────────────────────────────────────────────────
826+
['Gemini 2.5 Pro','gemini-2.5-pro'],['Gemini 2.5 Flash','gemini-2.5-flash'],
827+
['Gemini 2.5 Flash Lite','gemini-2.5-flash-lite'],['Gemini 2.0 Flash','gemini-2.0-flash'],
828+
// ── DeepSeek ────────────────────────────────────────────────────────
829+
['DeepSeek V3 (chat)','deepseek-chat'],['DeepSeek R1 (reasoning)','deepseek-reasoner'],
830+
// ── xAI Grok ────────────────────────────────────────────────────────
831+
['Grok 3','grok-3'],['Grok 3 mini','grok-3-mini'],
832+
// ── Mistral ─────────────────────────────────────────────────────────
833+
['Mistral Large','mistral-large-latest'],['Mistral Medium','mistral-medium-latest'],
834+
['Mistral Small','mistral-small-latest'],['Codestral','codestral-latest'],
824835
]],
825836
['generate', 'VERIFY_MODEL', 'Verification LLM', 'gpt-4.1-mini', [
826-
['gpt-4.1-mini','gpt-4.1-mini'],['gpt-4.1','gpt-4.1'],['gpt-5.1','gpt-5.1'],
827-
['Gemini 2.5 Flash','gemini-2.5-flash'],['Gemini 2.0 Flash','gemini-2.0-flash'],
828-
['Claude Haiku 4.5','claude-haiku-4-5-20251001'],
829-
['Claude Sonnet 3.5','claude-3-5-sonnet-20241022'],['Claude Sonnet 4.5','claude-sonnet-4-5'],
837+
// ── OpenAI ──────────────────────────────────────────────────────────
838+
['GPT-4.1 mini ★','gpt-4.1-mini'],['GPT-4.1 nano','gpt-4.1-nano'],
839+
['GPT-4.1','gpt-4.1'],['GPT-5.1','gpt-5.1'],['o4-mini (reasoning)','o4-mini'],
840+
// ── Anthropic ───────────────────────────────────────────────────────
841+
['Claude Haiku 4.5','claude-haiku-4-5-20251001'],['Claude Haiku 3.5','claude-3-5-haiku-20241022'],
842+
['Claude Sonnet 4.6','claude-sonnet-4-6'],['Claude Sonnet 3.5','claude-3-5-sonnet-20241022'],
843+
// ── Google Gemini ───────────────────────────────────────────────────
844+
['Gemini 2.5 Flash','gemini-2.5-flash'],['Gemini 2.5 Flash Lite','gemini-2.5-flash-lite'],
845+
['Gemini 2.0 Flash','gemini-2.0-flash'],
846+
// ── DeepSeek ────────────────────────────────────────────────────────
847+
['DeepSeek V3 (chat)','deepseek-chat'],
848+
// ── xAI / Mistral ───────────────────────────────────────────────────
849+
['Grok 3 mini','grok-3-mini'],['Mistral Small','mistral-small-latest'],
830850
]],
831851
['generate', 'DETAIL_LEVEL', 'Default detail level', '8', null],
832852
['generate', 'CHAPTER_SIZE', 'Slides per GPT call', '15', null],
@@ -952,6 +972,14 @@ async function loadSettingsData() {
952972
<div class="row">
953973
<div class="col expand"><label class="label">Gemini API Key</label>
954974
${mkRevealField('cred-gemini', 'AIza…', creds.gemini)}</div>
975+
<div class="col expand"><label class="label">DeepSeek API Key</label>
976+
${mkRevealField('cred-deepseek', 'sk-…', creds.deepseek)}</div>
977+
</div>
978+
<div class="row">
979+
<div class="col expand"><label class="label">xAI (Grok) API Key</label>
980+
${mkRevealField('cred-grok', 'xai-…', creds.grok)}</div>
981+
<div class="col expand"><label class="label">Mistral API Key</label>
982+
${mkRevealField('cred-mistral', 'key…', creds.mistral)}</div>
955983
</div>
956984
`;
957985
}
@@ -1020,6 +1048,9 @@ async function saveAllSettings() {
10201048
openai: document.getElementById('cred-openai')?.value || '',
10211049
anthropic: document.getElementById('cred-anthropic')?.value || '',
10221050
gemini: document.getElementById('cred-gemini')?.value || '',
1051+
deepseek: document.getElementById('cred-deepseek')?.value || '',
1052+
grok: document.getElementById('cred-grok')?.value || '',
1053+
mistral: document.getElementById('cred-mistral')?.value || '',
10231054
});
10241055
} catch (e) { errors.push('Credentials: ' + e.message); }
10251056

note_generation.py

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,12 @@ def _provider(model: str) -> str:
505505
return "gemini"
506506
if model.startswith("claude"):
507507
return "anthropic"
508+
if model.startswith("deepseek"):
509+
return "deepseek"
510+
if model.startswith("grok"):
511+
return "grok"
512+
if model.startswith(("mistral", "codestral", "pixtral", "magistral")):
513+
return "mistral"
508514
return "openai"
509515

510516

@@ -513,39 +519,46 @@ def _provider(model: str) -> str:
513519

514520
def _make_client(provider: str):
515521
import os
516-
if provider == "gemini":
517-
from openai import OpenAI
518-
key = os.environ.get("GEMINI_API_KEY", "")
522+
from openai import OpenAI
523+
524+
def _read_key(env_var: str, filename: str, label: str) -> str:
525+
key = os.environ.get(env_var, "")
519526
if not key:
520-
kf = DATA_DIR / "gemini_api.txt"
527+
kf = DATA_DIR / filename
521528
if kf.exists():
522529
key = kf.read_text().strip()
523530
if not key:
524-
raise RuntimeError("No Gemini API key found (set gemini_api.txt or GEMINI_API_KEY)")
531+
raise RuntimeError(
532+
f"No {label} API key found "
533+
f"(set {filename} in ~/.auto_note/ or {env_var} env var)"
534+
)
535+
return key
536+
537+
if provider == "gemini":
525538
return OpenAI(
526-
api_key=key,
539+
api_key=_read_key("GEMINI_API_KEY", "gemini_api.txt", "Gemini"),
527540
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
528541
)
529542
elif provider == "anthropic":
530543
from anthropic import Anthropic
531-
key = os.environ.get("ANTHROPIC_API_KEY", "")
532-
if not key:
533-
kf = DATA_DIR / "anthropic_key.txt"
534-
if kf.exists():
535-
key = kf.read_text().strip()
536-
if not key:
537-
raise RuntimeError("No Anthropic API key found (set anthropic_key.txt or ANTHROPIC_API_KEY)")
538-
return Anthropic(api_key=key)
544+
return Anthropic(api_key=_read_key("ANTHROPIC_API_KEY", "anthropic_key.txt", "Anthropic"))
545+
elif provider == "deepseek":
546+
return OpenAI(
547+
api_key=_read_key("DEEPSEEK_API_KEY", "deepseek_key.txt", "DeepSeek"),
548+
base_url="https://api.deepseek.com",
549+
)
550+
elif provider == "grok":
551+
return OpenAI(
552+
api_key=_read_key("GROK_API_KEY", "grok_key.txt", "xAI Grok"),
553+
base_url="https://api.x.ai/v1",
554+
)
555+
elif provider == "mistral":
556+
return OpenAI(
557+
api_key=_read_key("MISTRAL_API_KEY", "mistral_key.txt", "Mistral"),
558+
base_url="https://api.mistral.ai/v1",
559+
)
539560
else: # openai
540-
from openai import OpenAI
541-
key = os.environ.get("OPENAI_API_KEY", "")
542-
if not key:
543-
kf = DATA_DIR / "openai_api.txt"
544-
if kf.exists():
545-
key = kf.read_text().strip()
546-
if not key:
547-
raise RuntimeError("No OpenAI API key found (set openai_api.txt or OPENAI_API_KEY)")
548-
return OpenAI(api_key=key)
561+
return OpenAI(api_key=_read_key("OPENAI_API_KEY", "openai_api.txt", "OpenAI"))
549562

550563

551564
def _get_client_for(model: str):

0 commit comments

Comments
 (0)