Skip to content

Update provider DB refresh flow and add manual model config refresh#1421

Merged
zerob13 merged 4 commits intodevfrom
chore/providerjson
Apr 1, 2026
Merged

Update provider DB refresh flow and add manual model config refresh#1421
zerob13 merged 4 commits intodevfrom
chore/providerjson

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented Apr 1, 2026

Summary

  • reduce the runtime provider DB cache TTL from 12 hours to 4 hours and trigger a non-blocking upstream refresh on every app startup
  • add a configPresenter.refreshProviderDb() path so the renderer can force-refresh provider metadata and reuse the existing provider/model update events
  • add a Data Settings action to manually refresh model config metadata, with loading, success, up-to-date, and failure feedback
  • localize the new settings copy across all existing settings.json locales with region-appropriate translations
  • cover the change with targeted main and renderer tests

Approach

  • keep startup safe by continuing to load cached or built-in provider data first, then refresh in the background
  • make the loader return explicit refresh states (updated, not-modified, skipped, error) so UI feedback is deterministic instead of relying on implicit failures
  • reuse the current event-driven refresh path for provider/model stores rather than introducing a separate synchronization mechanism
  • add single-flight protection and refresh timestamp handling so forced refreshes and startup refreshes do not race each other

Testing

  • pnpm run format
  • pnpm run i18n
  • pnpm run lint
  • pnpm exec vitest --config vitest.config.ts --run test/main/presenter/configPresenter/providerDbLoader.test.ts
  • pnpm exec vitest --config vitest.config.renderer.ts --run test/renderer/components/DataSettings.test.ts

Summary by CodeRabbit

  • New Features

    • Manual "update model configuration" button in Data Settings with loading state and outcome toasts; suggestion list now shows a command icon for command items.
  • Bug Fixes

    • Configuration initialization now emits startup warnings on failures; provider DB refresh reports clearer outcomes (updated / not-modified / skipped / error).
  • Chores

    • Added localization strings for the refresh UI across many languages.
  • Tests

    • Added tests for the refresh/update flow, DataSettings UI, suggestion rendering, and environment/path behaviors.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f1ffdd67-0b36-420a-9e3b-54be63a3fb74

📥 Commits

Reviewing files that changed from the base of the PR and between d63f593 and 9c03504.

📒 Files selected for processing (2)
  • src/main/lib/agentRuntime/backgroundExecSessionManager.ts
  • test/main/lib/agentRuntime/backgroundExecSessionManager.test.ts
✅ Files skipped from review due to trivial changes (1)
  • test/main/lib/agentRuntime/backgroundExecSessionManager.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/lib/agentRuntime/backgroundExecSessionManager.ts

📝 Walkthrough

Walkthrough

Adds a structured provider DB refresh API and result type, deduplicates concurrent refreshes, changes TTL/initialization refresh behavior, exposes a presenter method, wires a renderer UI to force-refresh with localized toasts, centralizes shell/env merging utilities, and adds comprehensive tests for these flows.

Changes

Cohort / File(s) Summary
Provider DB Backend
src/main/presenter/configPresenter/index.ts, src/main/presenter/configPresenter/providerDbLoader.ts, src/shared/types/presenters/legacy.presenters.d.ts
Add ProviderDbRefreshResult type; ProviderDbLoader.refreshIfNeeded(force?) now returns detailed result (updated/not-modified/skipped/error), deduplicates in-flight refreshes, changes default TTL and startup refresh behavior; ConfigPresenter adds refreshProviderDb(force?).
Settings UI
src/renderer/settings/components/DataSettings.vue
New "model config update" UI section and button; calls configPresenter.refreshProviderDb(true), shows spinner/disabled state, guards concurrent runs, and shows toasts per result.status.
Internationalization
src/renderer/src/i18n/*/settings.json
Add localized strings for model config update/toast outcomes across multiple locales (en-US, da-DK, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW).
Shell & Env Helpers
src/main/lib/agentRuntime/shellEnvHelper.ts, src/main/lib/agentRuntime/rtkRuntimeService.ts, src/main/lib/agentRuntime/backgroundExecSessionManager.ts
Introduce path/env merge utilities, marker-based shell bootstrap, PATH normalization/merge helpers, longer shell timeout, and centralize mergeCommandEnvironment usage.
Presenter env integration
src/main/presenter/.../acpInitHelper.ts, src/main/presenter/llmProviderPresenter/acp/acpProcessManager.ts, src/main/presenter/skillPresenter/skillExecutionService.ts, src/main/presenter/toolPresenter/agentTools/agentBashHandler.ts
Refactor numerous presenters to use mergeCommandEnvironment and new PATH utilities; change where and how shell env is merged for spawns and command preparation.
UI tweak
src/renderer/src/components/chat/mentions/SuggestionList.vue
Render an icon for category === 'command' and import Icon from @iconify/vue.
Tests — Provider DB & UI
test/main/presenter/configPresenter/providerDbLoader.test.ts, test/renderer/components/DataSettings.test.ts
Add comprehensive ProviderDbLoader tests (init/TLL/304/200/error flows, metadata) and DataSettings component tests (button interaction, spinner, toasts for statuses).
Tests — Env & spawn behavior
test/main/..., test/renderer/components/SuggestionList.test.ts
Add/adjust tests for shellEnvHelper, background exec, rtk runtime, acpProcessManager, skillExecutionService, agentBashHandler, and SuggestionList icon rendering; update mocks/assertions to reflect env-merge behavior changes.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as DataSettings.vue
    participant Presenter as ConfigPresenter
    participant Loader as ProviderDbLoader
    participant Network as HTTP/Network

    User->>UI: Click "Force refresh"
    UI->>Presenter: refreshProviderDb(force=true)
    Presenter->>Loader: refreshIfNeeded(force=true)
    alt existing in-flight refresh
        Loader-->>Presenter: return existing ProviderDbRefreshResult
    else no in-flight refresh
        Loader->>Loader: evaluate freshness (lastAttemptedAt/lastUpdated, TTL)
        alt skipped (fresh & not forced)
            Loader-->>Presenter: {status: "skipped", lastUpdated, providersCount}
        else perform fetch
            Loader->>Network: fetch(sourceUrl)
            alt 304 Not Modified
                Network-->>Loader: 304
                Loader->>Loader: write lastAttemptedAt/meta
                Loader-->>Presenter: {status: "not-modified", lastUpdated, providersCount}
            else 200 OK + valid JSON
                Network-->>Loader: 200 + data
                Loader->>Loader: atomically write cache/meta, update in-memory DB
                Loader-->>Presenter: {status: "updated", lastUpdated, providersCount}
            else error/invalid
                Network-->>Loader: error/non-OK/parse
                Loader->>Loader: write attempt meta (if prior)
                Loader-->>Presenter: {status: "error", message, lastUpdated, providersCount}
            end
        end
    end
    Presenter-->>UI: ProviderDbRefreshResult
    UI->>User: show toast per status (updated / not-modified|skipped / error)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped and fetched a tiny file,
Tucked timestamps neat and stayed a while,
I de-duplicated hops and sang with glee,
Toasts in many tongues—come celebrate with me!
🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and accurately summarizes the main changes: adding manual model config refresh capability and updating the provider DB refresh flow.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/providerjson

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@zerob13 zerob13 marked this pull request as ready for review April 1, 2026 07:07
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/lib/agentRuntime/shellEnvHelper.ts (1)

239-243: Consider preserving whitespace in environment variable values.

Trimming both the key and value may unintentionally alter environment variables that legitimately contain leading/trailing whitespace. While rare, some applications depend on exact values.

💡 Suggested minimal change
-    const key = line.slice(0, separatorIndex).trim()
-    const value = line.slice(separatorIndex + 1).trim()
+    const key = line.slice(0, separatorIndex).trim()
+    const value = line.slice(separatorIndex + 1)
     if (key.length > 0) {
       env[key] = value
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/lib/agentRuntime/shellEnvHelper.ts` around lines 239 - 243, The code
currently trims both key and value which can remove intentional leading/trailing
whitespace; change the parsing in the block that computes key/value (using
separatorIndex, key, value, env) to only trim the key (keep key = line.slice(0,
separatorIndex).trim()) but do not call .trim() on the value — use value =
line.slice(separatorIndex + 1) so the original leading/trailing whitespace is
preserved before storing env[key] = value; keep the existing guard key.length >
0 unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/lib/agentRuntime/backgroundExecSessionManager.ts`:
- Around line 134-137: The spawn call currently replaces the entire environment
when options.env is provided which discards the baseline process.env; update the
env passed to spawn at the spawn(...) call (the object with cwd and env) to
start from process.env and merge/overlay options.env instead of replacing it
(i.e. use a shallow merge like { ...process.env, ...(options?.env || {}) }) so
callers can provide only deltas such as PATH without losing other environment
variables.

In `@src/main/presenter/configPresenter/acpInitHelper.ts`:
- Around line 515-551: The PATH rewrite currently calls setPathEntriesOnEnv with
includeDefaultPaths: false, which can drop standard OS search dirs if
mergeCommandEnvironment()/getShellEnvironment() provide sparse PATHs; before any
call that sets PATH (the setPathEntriesOnEnv invocation that uses
prependPathSources and later similar calls around the code paths noted), seed
the path sources with the platform default paths by adding
this.runtimeHelper.getDefaultPaths(app.getPath('home')) to the list of path
sources (or pass it as an explicit source into setPathEntriesOnEnv) so that
mergeCommandEnvironment(), getShellEnvironment(), prependPathSources,
getPathEntriesFromEnv and setPathEntriesOnEnv keep the system defaults available
when includeDefaultPaths is false.

---

Nitpick comments:
In `@src/main/lib/agentRuntime/shellEnvHelper.ts`:
- Around line 239-243: The code currently trims both key and value which can
remove intentional leading/trailing whitespace; change the parsing in the block
that computes key/value (using separatorIndex, key, value, env) to only trim the
key (keep key = line.slice(0, separatorIndex).trim()) but do not call .trim() on
the value — use value = line.slice(separatorIndex + 1) so the original
leading/trailing whitespace is preserved before storing env[key] = value; keep
the existing guard key.length > 0 unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 53393e7f-554f-45ef-aec1-05f32c1e04e4

📥 Commits

Reviewing files that changed from the base of the PR and between 7334027 and d63f593.

📒 Files selected for processing (13)
  • src/main/lib/agentRuntime/backgroundExecSessionManager.ts
  • src/main/lib/agentRuntime/rtkRuntimeService.ts
  • src/main/lib/agentRuntime/shellEnvHelper.ts
  • src/main/presenter/configPresenter/acpInitHelper.ts
  • src/main/presenter/llmProviderPresenter/acp/acpProcessManager.ts
  • src/main/presenter/skillPresenter/skillExecutionService.ts
  • src/main/presenter/toolPresenter/agentTools/agentBashHandler.ts
  • test/main/lib/agentRuntime/backgroundExecSessionManager.test.ts
  • test/main/lib/agentRuntime/rtkRuntimeService.test.ts
  • test/main/lib/agentRuntime/shellEnvHelper.test.ts
  • test/main/presenter/llmProviderPresenter/acp/acpProcessManager.test.ts
  • test/main/presenter/skillPresenter/skillExecutionService.test.ts
  • test/main/presenter/toolPresenter/agentTools/agentBashHandler.test.ts

Comment on lines +515 to +551
let env = mergeCommandEnvironment()
const systemEnvCount = Object.keys(env).length
console.log('[ACP Init] Added system environment variables:', systemEnvCount)

// Merge shell environment (includes user PATH from shell startup)
const pathKeys = ['PATH', 'Path', 'path']
const existingPaths: string[] = []
pathKeys.forEach((key) => {
const value = env[key]
if (value) existingPaths.push(value)
})

try {
const shellEnv = await getShellEnvironment()
Object.entries(shellEnv).forEach(([key, value]) => {
if (value !== undefined && value !== '' && !pathKeys.includes(key)) {
env[key] = value
}
})
const shellPath = shellEnv.PATH || shellEnv.Path || shellEnv.path
if (shellPath) {
existingPaths.unshift(shellPath)
}
env = mergeCommandEnvironment({ shellEnv })
} catch (error) {
console.warn('[ACP Init] Failed to merge shell environment variables:', error)
}

// Prepare PATH merging
const HOME_DIR = app.getPath('home')
const defaultPaths = this.runtimeHelper.getDefaultPaths(HOME_DIR)
const allPaths = [...existingPaths, ...defaultPaths]
const prependPathSources: string[] = []

// Add runtime paths to PATH if using builtin runtime
if (useBuiltinRuntime) {
const runtimePaths: string[] = []

const uvRuntimePath = this.runtimeHelper.getUvRuntimePath()
const nodeRuntimePath = this.runtimeHelper.getNodeRuntimePath()

if (uvRuntimePath) {
runtimePaths.push(uvRuntimePath)
prependPathSources.push(uvRuntimePath)
console.log('[ACP Init] Added UV runtime path:', uvRuntimePath)
}

if (process.platform === 'win32') {
if (nodeRuntimePath) {
runtimePaths.push(nodeRuntimePath)
prependPathSources.push(nodeRuntimePath)
console.log('[ACP Init] Added Node runtime path (Windows):', nodeRuntimePath)
}
} else {
if (nodeRuntimePath) {
const nodeBinPath = path.join(nodeRuntimePath, 'bin')
runtimePaths.push(nodeBinPath)
console.log('[ACP Init] Added Node runtime path (Unix):', nodeBinPath)
}
} else if (nodeRuntimePath) {
const nodeBinPath = path.join(nodeRuntimePath, 'bin')
prependPathSources.push(nodeBinPath)
console.log('[ACP Init] Added Node runtime path (Unix):', nodeBinPath)
}

if (runtimePaths.length > 0) {
allPaths.unshift(...runtimePaths)
if (prependPathSources.length > 0) {
setPathEntriesOnEnv(env, [prependPathSources, getPathEntriesFromEnv(env)], {
includeDefaultPaths: false
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Seed the default OS PATH before rewriting PATH.

includeDefaultPaths: false makes the PATH here depend entirely on the bundled/profile sources plus whatever mergeCommandEnvironment() already exposed. If getShellEnvironment() falls back or returns a sparse GUI PATH, the ACP init shell loses the standard system search dirs, so npm, git, or other helper binaries can stop resolving. The later rewrites at Line 582 and Line 604 keep carrying that trimmed PATH forward. Please seed this.runtimeHelper.getDefaultPaths(app.getPath('home')) once before these rewrites, or include it as an explicit path source.

Also applies to: 582-584, 604-606

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/configPresenter/acpInitHelper.ts` around lines 515 - 551,
The PATH rewrite currently calls setPathEntriesOnEnv with includeDefaultPaths:
false, which can drop standard OS search dirs if
mergeCommandEnvironment()/getShellEnvironment() provide sparse PATHs; before any
call that sets PATH (the setPathEntriesOnEnv invocation that uses
prependPathSources and later similar calls around the code paths noted), seed
the path sources with the platform default paths by adding
this.runtimeHelper.getDefaultPaths(app.getPath('home')) to the list of path
sources (or pass it as an explicit source into setPathEntriesOnEnv) so that
mergeCommandEnvironment(), getShellEnvironment(), prependPathSources,
getPathEntriesFromEnv and setPathEntriesOnEnv keep the system defaults available
when includeDefaultPaths is false.

@zerob13 zerob13 merged commit 677e4ed into dev Apr 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant