fix(server): use the keys the user sent, and more review fixes

Found by the second PR review:
- With AWS_BEARER_TOKEN_BEDROCK set on the server, a request with the
  user's AWS keys ran on the server's token: the Bedrock SDK prefers it.
  Checked with Bedrock: invalid user keys used to get an answer.
- An OpenAI key with the official URL filled in (the settings form does
  that) went to the Responses API. Back to main's rule: a configured base
  URL uses Chat Completions.
- A user's Ollama key went to the server's OLLAMA_BASE_URL, for chat and
  for the model list. Like every other provider, it goes to the user's
  base URL or Ollama Cloud.
- The server's keyless Ollama and EdgeOne were not counted in the quota.
- AI_MODEL models on the server's keys ran on any provider with a server
  key, not only on AI_PROVIDER.
- A user's Azure key without a base URL used the server's resource name.
- The admin panel's Test button failed whenever access codes were set.
- DeepSeek's errors in the stream (plain text) were shown as they were,
  without a hint and also on the server's keys. Bedrock's throttling in
  the stream was not recognised as a rate limit.
- The EdgeOne function accepted text/plain; x=application/json, which
  other sites can send without a CORS preflight.
- Desktop app: a launch that found the old port taken for a moment (the
  previous version still quitting after an update) remembered the new
  port for good. The new port is kept only when Windows reserves the old
  one. A failed read of the presets file moved it aside as corrupt, and a
  save could then replace the presets. Switching presets on the same port
  now reloads the page. The dev launcher no longer misses a preset change
  made before or during a restart.
This commit is contained in:
dayuan.jiang
2026-10-05 10:52:37 +09:00
parent 080f44716f
commit d5f31cb253
19 changed files with 499 additions and 91 deletions
+37 -36
View File
@@ -224,6 +224,39 @@ async function main() {
let configWatcher = null
let restartPending = false
// Restart Next.js when the preset env vars really changed
async function applyPresetChange() {
if (restartPending) return
const newContent = readPresetEnvFile()
if (newContent === null || newContent === presetEnvContent) return
restartPending = true
presetEnvContent = newContent
console.log(
"\n🔄 Preset configuration changed, restarting Next.js server...",
)
// Kill current Next.js process
killProcess(nextProcess)
// Wait a bit for process to die
await new Promise((r) => setTimeout(r, 1000))
// Reload preset and restart
nextProcess = startNextServer(loadPresetEnv(newContent))
try {
await waitForServer(NEXT_URL)
console.log("✅ Next.js server restarted with new configuration\n")
} catch (err) {
console.error("❌ Failed to restart Next.js:", err.message)
}
restartPending = false
// A change written during the restart was skipped above
applyPresetChange()
}
function setupConfigWatcher() {
if (!existsSync(userDataPath)) {
// Directory doesn't exist yet, check again later
@@ -236,45 +269,13 @@ async function main() {
configWatcher = watch(
userDataPath,
{ persistent: false },
async (_eventType, filename) => {
if (filename !== PRESET_ENV_FILE || restartPending) return
// Only restart when the preset env vars really changed
const newContent = readPresetEnvFile()
if (newContent === null || newContent === presetEnvContent)
return
restartPending = true
presetEnvContent = newContent
console.log(
"\n🔄 Preset configuration changed, restarting Next.js server...",
)
// Kill current Next.js process
killProcess(nextProcess)
// Wait a bit for process to die
await new Promise((r) => setTimeout(r, 1000))
// Reload preset and restart
nextProcess = startNextServer(loadPresetEnv(newContent))
try {
await waitForServer(NEXT_URL)
console.log(
"✅ Next.js server restarted with new configuration\n",
)
} catch (err) {
console.error(
"❌ Failed to restart Next.js:",
err.message,
)
}
restartPending = false
(_eventType, filename) => {
if (filename === PRESET_ENV_FILE) applyPresetChange()
},
)
console.log("👀 Watching for preset configuration changes...")
// Electron may have written its preset before the watch started
applyPresetChange()
} catch (_err) {
// Directory might not be ready yet, try again later
setTimeout(setupConfigWatcher, 5000)