Skip to content

feat(droid): add Factory Droid as a provider - #7993

Draft
factory-ain3sh wants to merge 17 commits into
pingdotgg:mainfrom
factory-ain3sh:feat/droid-provider
Draft

feat(droid): add Factory Droid as a provider#7993
factory-ain3sh wants to merge 17 commits into
pingdotgg:mainfrom
factory-ain3sh:feat/droid-provider

fix(droid): stop every in-flight start when the adapter shuts down

e1712c2
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - UI Consistency succeeded Aug 23, 2026 in 2m 55s

UI Consistency: All clear

All clear

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Reviewed in-scope web changes: apps/web/src/components/Icons.tsx (DroidIcon), components/chat/providerIconUtils.ts, components/chat/ComposerPendingApprovalPanel.tsx, components/settings/{DiagnosticsSettings,ProviderModelsSection,providerDriverMeta}, lib/contextWindow.ts, and session-logic.ts.

  • DroidIcon now pins its own light/dark tone via cn("fill-[#171717] dark:fill-[#e5e5e5]", className), matching CursorIcon/GrokIcon; the currentColor issue flagged in the prior run is resolved.
  • Droid registrations are consistent with the existing Cursor/Grok pattern across PROVIDER_ICON_BY_PROVIDER, PROVIDER_CLIENT_DEFINITIONS (Early Access badge), PROVIDER_OPTIONS (new picker badge), and the custom-model placeholder map.
  • The new plan approval kind is handled in ComposerPendingApprovalPanel for both the group label and the detail aria-label; other requestKind consumers (MessagesTimeline.logic.ts tool grouping) degrade to their existing default branch without visual regression.
  • formatProviderDisplayName delegating to the shared resolveProviderDisplayName preserves prior output for built-in drivers and keeps the caller-supplied title-cased fallback for unknown drivers.

No shared-primitive, Tailwind ownership, theming, or accessibility regressions found in the changed lines.


🔍 Agent activity — 19 tool calls

💭 I'm checking the changed files in scope, including the DroidIcon component, provider utility files, and session logic tests. I recall a prior review flagged an issue with DroidIcon's fill using currentColor, but looking at the current diff, it now uses explicit light/dark hex fill colors instead, so that concern seems to have already been addressed. That's good. Now I want to make sure other icons follow a consistent pattern for dark mode styling, since the repo convention favors @variant dark in CSS but allows dark: Tailwind classes directly in TSX. I'm scanning through Icons.tsx to check icons like GrokIcon for consistency.

1. browse_code — apps/web/src/components/Icons.tsx

2. browse_code — apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx

💭 The DroidIcon now matches the pattern, addressing that earlier comment. I should check other UI surfaces where requestKind is used—there could be other places switching on requestKind that now miss the "plan" case, so let me search for requestKind usages across apps/web/src.

3. git_tools — requestKind

💭 This is confusing — the grep results at that commit show different function names and "unknown" kind variants than what the diff displayed, which had plan and approvalRequestKindFromPayload. I'm wondering if the tree reference I used for the grep didn't actually resolve to the commit I intended. The direct file view at that same ref showed "plan" as expected, but the grep must be defaulting to the main branch HEAD instead, which has since evolved with a new "unknown" request kind not present in the PR's merge base. That's a separate revision than the one I'm actually reviewing. I need to rerun the grep specifying the exact revision explicitly.

4. git_tools — requestKind ===

💭 I need to check MessagesTimeline.logic.ts to see how it classifies work log entries by requestKind, since the new "plan" kind could fall through to a default case around lines 280-320 rather than being handled properly.

5. browse_code — apps/web/src/components/chat/MessagesTimeline.logic.ts

💭 That "plan" fallback to "other" is a benign grouping case, not a real UI inconsistency. Now I want to check whether MessagesTimeline.tsx renders inline approval labels that switch on requestKind, so I'm looking for approval UI strings like "Command approval" beyond the single unknown-kind check I found.

6. git_tools — File change approval|File read approval|Command approval|approvalLabel

💭 Now I want to check other approval surfaces in the web app, like where inline approval accept/decline buttons render and whether there's a component showing icons per request kind such as a shield icon for file-read.

7. git_tools — "file-read"|'file-read'

💭 I'm checking the other in-scope diff files for UI consistency—the icon mapping and driver metadata additions for Droid look fine, but I want to verify the badgeLabel convention matches other providers and look closer at the diagnostics settings regex to see if grok is missing from the pattern. The regex gap for grok is pre-existing and unrelated to UI consistency, so I'll skip flagging it. Now I'm moving to the context window formatting refactor, checking whether the shared display name resolver covers all providers like cursor and opencode consistently.

8. browse_code — packages/contracts/src/model.ts

9. browse_code — apps/web/src/lib/contextWindow.ts

💭 Good, the "claudeAgent" case trims correctly and falls back as expected. Now I want to verify whether ProviderDriverKind.make performs schema validation against a literal union, since that could throw on something like "acmeAgent".

10. git_tools — ProviderDriverKind =

💭 I'm worried that ProviderDriverKind.make validates its slug pattern strictly and will throw if given an arbitrary string, whereas formatProviderDisplayName previously accepted any string/null/undefined without throwing—so this change could introduce a runtime failure when resolveProviderDisplayName calls into that schema. make with an invalid value. I need to check the actual slug schema definition and how make behaves in this Effect version to confirm whether it validates.

11. browse_code — packages/contracts/src/providerInstance.ts

💭 I'm checking whether .make validates its input by default in this version of Effect Schema, and looking for existing usages of ProviderDriverKind.make elsewhere in the codebase to confirm the expected behavior. The real concern is whether formatProviderDisplayName could receive an invalid provider string that would now throw where it previously just title-cased it safely — this is a behavioral regression risk since contextWindow.ts is in scope. I want to grep for callers to see what values actually get passed in.

12. git_tools — formatProviderDisplayName

💭 Let me search the entire repo to check if there are other callers in the web codebase.

13. git_tools — formatProviderDisplayName

💭 That's an unused export, not really a UI consistency issue. I want to check whether ProviderDriverKind.make is being called elsewhere with a runtime variable rather than a literal, since providerIconUtils uses it with literals but providerDisplayName.ts in client-runtime passes a runtime driver string that could throw.

14. git_tools — ProviderDriverKind.make(

💭 I see that composerDraftStore.ts already uses this pattern on runtime strings, so it's an accepted approach in the codebase. Now I'm checking the droid provider entry in session-logic.ts, which sets its picker badge to "new" while its meta uses "Early Access" as the badge label, so I want to see how other providers handle this to check for consistency.

15. browse_code — apps/web/src/session-logic.ts

16. browse_code — apps/web/src/components/settings/providerDriverMeta.ts

💭 These match existing patterns like Cursor/Grok early access and the "new" picker badge. Now I'm checking the DroidIcon's viewBox and sizing conventions compared to other icons like GrokIcon, and want to see where these provider icons actually get rendered to understand how sizing is applied by consumers. Since the SVG path lacks an explicit fill attribute, it inherits fill from the svg element's className, which works fine with tailwind-merge for consumer overrides. Now I'm moving on to check the DiagnosticsSettings regex file for context.

17. browse_code — apps/web/src/components/settings/DiagnosticsSettings.tsx

💭 Grok is missing but that's pre-existing and outside this check's scope, so I'll skip it. I'm now checking whether the web PendingApproval UI and MessagesTimeline render approval buttons differently by kind, since the mobile PendingApprovalCard has an inline ternary for "plan" that might warrant a comparable check on the web side, though that's more product behavior than a UI consistency issue. I'm tracing whether icon selection is keyed off requestKind — the timeline seems to fall back to toolGroupAction grouping "plan" approvals under "other" with a generic label like "Did N things," which seems acceptable but worth confirming by grepping requestKind usage directly in MessagesTimeline.tsx.

18. git_tools — requestKind

💭 I'm checking where pending approvals render Approve/Deny buttons in the web UI, likely within ChatComposer's ComposerPendingApprovalPanel, and considering whether this label change to support a "plan" kind needs dedicated test coverage given it's a small modification. I'm also scanning for provider-keyed lists in the web app that might be missing droid entries — icon maps, default model maps, custom placeholder maps, client definitions, and provider options all appear to have been updated, so I'm now checking whether interaction mode toggles or plan mode support have similar gaps.

19. git_tools — "grok"

💭 I'm checking that DroidIcon's SVG structure matches the pattern used by CursorIcon, both omitting fill="none", unlike GrokIcon which includes it. I'm also considering whether provider icons need to stay colorless in selected or pressed states given the color indirection guidance. The class output fill-[#171717] dark:fill-[#e5e5e5] looks consistent with Cursor's uppercase hex convention, and the mobile ProviderIcon's mono fill for droid is out of scope here. Since there are no findings and no new comments needed, I'll finalize with a success state and a concise "All clear" summary, resolving the tension between the required JSON schema and the instruction to respond exactly "All clear" by using that phrase as the summary text.


Agent Credits: 331 credits