Skip to content

refactor(web): dissolve reconcileFromDaemonConfig bridge utility (LUM-2239)#33464

Merged
vex-assistant-bot[bot] merged 3 commits into
mainfrom
devin/1780594491-lum-2239-dissolve-reconcile-from-daemon-config
Jun 4, 2026
Merged

refactor(web): dissolve reconcileFromDaemonConfig bridge utility (LUM-2239)#33464
vex-assistant-bot[bot] merged 3 commits into
mainfrom
devin/1780594491-lum-2239-dissolve-reconcile-from-daemon-config

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Prompt / plan

Dissolve the reconcileFromDaemonConfig transitional bridge utility. The function extracted service mode/provider fields from the daemon config's services key into a flat DaemonConfigReconciliation interface. Now that DaemonConfig is hand-typed and both consumers have direct access to the config object via useDaemonConfigQuery(), the indirection adds no value.

Changes:

  • Inline direct field access in web-search-card.tsx (daemonConfig.services?.["web-search"]?.mode / ?.provider)
  • Inline direct field access in image-generation-card.tsx (daemonConfig.services?.["image-generation"]?.mode)
  • Delete reconcileFromDaemonConfig() function from ai-utils.ts
  • Delete DaemonConfigReconciliation interface from ai-types.ts
  • Remove unused ServiceMode import from ai-utils.ts

Why safe: Pure behavioral no-op. The function only read fields from the config and returned them — consumers now read the same fields directly. No new logic, no changed data flow.

Closes LUM-2239

Test plan

  • Pre-commit hooks pass (lint, typecheck, generic-examples)
  • Full bunx tsc --noEmit passes cleanly
  • CI verification

Link to Devin session: https://app.devin.ai/sessions/4b3b130bbf274e5487da3b4992883093
Requested by: @ashleeradka

…-2239)

The function extracted service mode/provider fields from the daemon config
into a flat DaemonConfigReconciliation interface. Now that DaemonConfig is
hand-typed and consumers have direct access to the config via
useDaemonConfigQuery(), the indirection adds no value.

Inline direct field access in both consumers (web-search-card,
image-generation-card), delete the function and the
DaemonConfigReconciliation type.

Closes LUM-2239

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@linear

linear Bot commented Jun 4, 2026

Copy link
Copy Markdown

LUM-2239

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ed20e7ffe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return {
serverWebSearchMode: (reconciled.webSearchMode ?? getLocalSetting(LS_WEB_SEARCH_MODE, "your-own")) as ServiceMode,
serverWebSearchProvider: reconciled.webSearchProvider ?? getLocalSetting(LS_WEB_SEARCH_PROVIDER, "inference-provider-native"),
serverWebSearchMode: (wsService?.mode ?? getLocalSetting(LS_WEB_SEARCH_MODE, "your-own")) as ServiceMode,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate daemon service modes before casting

When the config endpoint returns an unexpected or future services["web-search"].mode, this now seeds webSearchMode with that raw string instead of falling back as reconcileFromDaemonConfig() did. In that version-skew/corrupt-config scenario the segment control has no active option, the card renders the Your Own branch, and a subsequent save can write the invalid mode back; the image-generation path added the same direct cast. Please preserve the previous mode === "managed" || mode === "your-own" guard before treating daemon data as ServiceMode.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — the old function had if (wsMode === "managed" || wsMode === "your-own") guards that only set the result for known ServiceMode values. My initial ?? replacement would pass through unexpected strings. Fixed in b5d1110 — both cards now validate before using the daemon value.

The dissolved reconcileFromDaemonConfig() only assigned mode fields when
they matched a known ServiceMode value ("managed" | "your-own"). The
initial inline replacement used ?? which falls through on unexpected
strings. Restore the explicit guard so unknown/future mode values fall
back to localStorage defaults.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

View 2 additional findings in Devin Review.

Open in Devin Review

if (!daemonConfig) return getLocalSetting(LS_IMAGE_GEN_MODE, "your-own") as ServiceMode;
const reconciled = reconcileFromDaemonConfig(daemonConfig);
return reconciled.imageGenMode ?? (getLocalSetting(LS_IMAGE_GEN_MODE, "your-own") as ServiceMode);
const mode = daemonConfig.services?.["image-generation"]?.mode;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🟡 Image generation mode now accepts invalid raw config values without validation

serverImageGenMode now directly casts daemonConfig.services["image-generation"].mode to ServiceMode, so any non-enum string in raw config is treated as a valid UI mode. The daemon’s GET /v1/config response is based on raw config (loadRawConfig) rather than schema-validated config, and PATCH /v1/config accepts arbitrary objects via deep-merge, so malformed/stale mode values can exist and be returned (assistant/src/runtime/routes/conversation-query-routes.ts:447-452, assistant/src/config/loader.ts:875-916, assistant/src/runtime/routes/conversation-query-routes.ts:586-603). This regresses the previous guard logic and can leave the segment control in an invalid state and allow re-saving the invalid mode value.

Suggested change
const mode = daemonConfig.services?.["image-generation"]?.mode;
return ((daemonConfig.services?.["image-generation"]?.mode === "managed" || daemonConfig.services?.["image-generation"]?.mode === "your-own") ? daemonConfig.services["image-generation"]?.mode : getLocalSetting(LS_IMAGE_GEN_MODE, "your-own")) as ServiceMode;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Already fixed in b5d1110 — the mode validation guard was restored in the previous commit.

const reconciled = reconcileFromDaemonConfig(daemonConfig);
const wsService = daemonConfig.services?.["web-search"];
const mode = wsService?.mode;
return {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🟡 Web search mode now uses unchecked raw config values

serverWebSearchMode now uses wsService?.mode with a direct cast to ServiceMode instead of validating that the value is actually "managed" | "your-own". Because /v1/config returns raw file contents and config patching does not enforce schema-level validation on incoming partials, invalid mode strings can reach this component (assistant/src/runtime/routes/conversation-query-routes.ts:447-452, assistant/src/config/loader.ts:875-916, assistant/src/runtime/routes/conversation-query-routes.ts:586-603). That can produce a mode value that is not one of the segment options and can be re-submitted back to config, propagating bad state.

Suggested change
return {
serverWebSearchMode: ((wsService?.mode === "managed" || wsService?.mode === "your-own") ? wsService.mode : getLocalSetting(LS_WEB_SEARCH_MODE, "your-own")) as ServiceMode,
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Already fixed in b5d1110 — both cards now validate mode === "managed" || mode === "your-own" before using the daemon value, matching the original guard logic.

return {
serverWebSearchMode: (reconciled.webSearchMode ?? getLocalSetting(LS_WEB_SEARCH_MODE, "your-own")) as ServiceMode,
serverWebSearchProvider: reconciled.webSearchProvider ?? getLocalSetting(LS_WEB_SEARCH_PROVIDER, "inference-provider-native"),
serverWebSearchMode: (mode === "managed" || mode === "your-own" ? mode : getLocalSetting(LS_WEB_SEARCH_MODE, "your-own")) as ServiceMode,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🚩 Provider fallback semantic change depends on whether empty-string providers can still exist

serverWebSearchProvider now uses nullish fallback (wsService?.provider ?? ...) (apps/web/src/domains/settings/ai/web-search-card.tsx:52), whereas the removed helper only propagated truthy providers. I did not mark this as a confirmed bug because validated configs should keep provider as a non-empty enum, but /v1/config is sourced from raw config (assistant/src/runtime/routes/conversation-query-routes.ts:447-452) and loadRawConfig only enforces object shape, not field-level schema (assistant/src/config/loader.ts:875-916). If legacy or manual writes can still persist "", this may surface as an invalid dropdown value and should be verified.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Valid finding — the old code used if (wsProvider) (truthy check) which treats empty string as falsy. Fixed in 85a4ec5 by switching from ?? to || to preserve the original semantics.

The old reconcileFromDaemonConfig used `if (wsProvider)` which treats
empty string as falsy. Use || instead of ?? to preserve this behavior.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@vex-assistant-bot vex-assistant-bot Bot left a comment

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.

APPROVE

Value: Removes a dead transitional layer between DaemonConfig and the two settings cards that still used it. Net -31 lines, no behavior change at HEAD 85a4ec55.

What this does: Deletes reconcileFromDaemonConfig() + DaemonConfigReconciliation interface; inlines direct daemonConfig.services?.[...] reads in web-search-card.tsx and image-generation-card.tsx. The bridge was a vestige of the pre-hand-typed-DaemonConfig era — now redundant since useDaemonConfigQuery() already exposes the same shape.

Refactor-regression sniff (verified at HEAD):

  • mode validation guard preserved: (mode === "managed" || mode === "your-own" ? mode : getLocalSetting(...)). Matches the old if (wsMode === "managed" || wsMode === "your-own") semantics — invalid raw config values fall back to LS, not the segment-control wedge that Codex P2 flagged on 2ed20e7.
  • Provider truthy-fallback preserved: switched from ?? to || so empty-string provider still falls through to LS_WEB_SEARCH_PROVIDER. Matches the old if (wsProvider) truthy check.
  • The remaining as ServiceMode cast wraps the validated conditional, not the raw daemon value — narrowing-after-guard, exception-allowed per runtime-boundary rule.

Bot loop:

  • Codex P2 (validate before cast) on 2ed20e7 → addressed in b5d1110.
  • Devin re-review at 85a4ec5 re-flagged 2 of the same findings + 1 provider-semantic flag → Devin self-noted both first two were already in b5d1110, then shipped 85a4ec5 to fix the provider ??||. Tight fix loop, ~6 min start to settle.
  • Codex hasn't re-reviewed since the fixes landed — re-triggering on this approval.

Clean follow-up to the Settings/AI decomposition arc (#33246/#33256/#33286/#33321/#33352). Tech-debt cleanup that fell out of #33352 review, as planned.

Vellum Constitution — Trust-seeking: validation guards stay explicit at the daemon boundary; raw config strings never silently propagate into the segment control state.

@vex-assistant-bot

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@vex-assistant-bot vex-assistant-bot Bot merged commit 8b350ce into main Jun 4, 2026
7 checks passed
@vex-assistant-bot vex-assistant-bot Bot deleted the devin/1780594491-lum-2239-dissolve-reconcile-from-daemon-config branch June 4, 2026 17:54
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