-
Notifications
You must be signed in to change notification settings - Fork 14
features reasoning and models
Active contributors: Nik, Ran
DroidProxy exposes a fixed catalog of models that Factory Droid can use as custom models. Each model is defined once in src/Sources/DroidProxyModelCatalog.swift, then written into Factory's ~/.factory/settings.json customModels array by the Apply button in src/Sources/SettingsView.swift. The catalog carries each model's supported reasoning levels, but the proxy never injects reasoning. Droid CLI's per-session model picker reads the native reasoning metadata DroidProxy registers and forwards the chosen level upstream unchanged.
The full catalog from src/Sources/DroidProxyModelCatalog.swift. Antigravity, Kimi, and Cursor models all use provider: "openai" (or generic-chat-completion-api for Cursor) with a /v1 base URL so Droid sends POST /v1/chat/completions.
| Display name | baseModel |
idSlug |
providerKey | levels (default) | max tokens | baseURL |
|---|---|---|---|---|---|---|
| Fable 5 | claude-fable-5 |
fable-5 |
claude | low/medium/high/xhigh/max (xhigh) | 128000 | http://localhost:8317 |
| Opus 4.8 | claude-opus-4-8 |
opus-4-8 |
claude | low/medium/high/xhigh/max (xhigh) | 128000 | http://localhost:8317 |
| Sonnet 4.6 | claude-sonnet-4-6 |
sonnet-4-6 |
claude | low/medium/high/max (high) | 64000 | http://localhost:8317 |
| GPT 5.4 | gpt-5.4 |
gpt-5.4 |
codex | low/medium/high/xhigh (high) | 128000 | http://localhost:8317/v1 |
| GPT 5.5 | gpt-5.5 |
gpt-5.5 |
codex | low/medium/high/xhigh (high) | 128000 | http://localhost:8317/v1 |
| Gemini 3.1 Pro (High) | gemini-pro-agent |
antigravity-gemini-3.1-pro |
antigravity | high (high) | 65536 | http://localhost:8317/v1 |
| Gemini 3.1 Pro (Low) | gemini-3.1-pro-low |
gemini-3.1-pro-low |
antigravity | low (low) | 65536 | http://localhost:8317/v1 |
| Gemini 3 Flash | gemini-3-flash |
antigravity-gemini-3-flash |
antigravity | high (high) | 65536 | http://localhost:8317/v1 |
| Gemini 3.5 Flash | gemini-3-flash-agent |
gemini-3.5-flash |
antigravity | medium/high (high) | 65536 | http://localhost:8317/v1 |
| Gemini 3.5 Flash (Low) | gemini-3.5-flash-low |
gemini-3.5-flash-low |
antigravity | low (low) | 65536 | http://localhost:8317/v1 |
| Gemini 3.1 Flash Lite | gemini-3.1-flash-lite |
gemini-3.1-flash-lite |
antigravity | high (high) | 65536 | http://localhost:8317/v1 |
| Claude Sonnet 4.6 (Thinking) | ag-c46s-thinking |
ag-c46s-thinking |
antigravity | high (high) | 64000 | http://localhost:8317/v1 |
| Claude Opus 4.6 (Thinking) | ag-c46o-thinking |
ag-c46o-thinking |
antigravity | high (high) | 64000 | http://localhost:8317/v1 |
| GPT-OSS 120B (Medium) | gpt-oss-120b-medium |
gpt-oss-120b-medium |
antigravity | medium (medium) | 32768 | http://localhost:8317/v1 |
| Kimi K2.6 | kimi-k2.6 |
kimi-k2.6 |
kimi | high (high) | 262144 | http://localhost:8317/v1 |
| Cursor Composer 2.5 (beta) | cursor-composer-2.5 |
cursor-composer-2.5 |
cursor | high (high) | 128000 | http://localhost:8317/v1 |
| Cursor Small (beta) | cursor-small |
cursor-small |
cursor | high (high) | 64000 | http://localhost:8317/v1 |
The two Cursor models are appended only when the BETA_FLAG UserDefaults flag is on; they use provider: "generic-chat-completion-api". The Antigravity models are built by the antigravityModel(...) helper, which fixes provider: "openai", providerKey: "antigravity", and baseURL: "http://localhost:8317/v1".
| Type | Role |
|---|---|
DroidProxyModelKind |
Enum tagging each definition: claudeAdaptive, codex, kimi, antigravity, cursor. |
DroidProxyThinkingLevel |
A reasoning level as value (low/medium/high/xhigh/max) plus displayName. |
DroidProxyModelDefinition |
One model: baseModel, idSlug, displayName, maxOutputTokens, provider, providerKey, baseURL, kind, levels, defaultLevelValue. |
simpleID |
Computed custom:droidproxy:<idSlug> — the stable Factory id for the model. |
settingsEntry |
Computed [String: Any] matching Factory's custom-model schema. When levels is non-empty it embeds enableThinking: true, the full supportedReasoningEfforts array, defaultReasoningEffort, and a reasoningEffort (the only level when there is exactly one, otherwise the defaultLevelValue). Keeping all reasoning metadata explicit means Droid/Factory does not have to infer the supported efforts from built-in model defaults. Antigravity entries prefix the display name with Antigravity:. |
DroidProxyModelCatalog.definitions |
The ordered list of all definitions (Cursor entries gated by BETA_FLAG). |
settingsModels(providerIsEnabled:) |
Maps definitions to settingsEntry dicts, skipping any whose providerKey is disabled. |
allSettingsIDs |
Set of every simpleID, used to detect and remove prior DroidProxy entries. |
applyFactoryCustomModels() in src/Sources/SettingsView.swift is the writer.
graph TD
A[User clicks Apply / Re-apply] --> B[Read ~/.factory/settings.json]
B --> C[Take existing customModels array]
C --> D[Remove entries whose id is in allSettingsIDs,\nlegacy ids, custom:droidproxy:*, or custom:CC:*]
D --> E[enabledFactorySettingsModels:\nsettingsModels filtered by provider enabled state]
E --> F[Append entries, reindex with index = startIndex + offset]
F --> G[Write timestamped settings.json.droidproxy-*.bak backup]
G --> H[Serialize prettyPrinted + sortedKeys]
H --> I[Unescape backslash-slash to plain slash]
I --> J[Atomic write to settings.json]
J --> K[factoryModelsInstalled = true]
enabledFactorySettingsModels() calls DroidProxyModelCatalog.settingsModels with a closure that maps each providerKey to a ServiceType and checks serverManager.isProviderEnabled. checkFactoryModelsInstalled() compares the set of DroidProxy ids currently in settings.json against the expected enabled set to drive the "Applied" badge and the Apply/Re-apply label.
For two Antigravity Claude models, the baseModel sent by Droid is not the backend's model id. ThinkingProxy rewrites it in place (preserving JSON key order) before forwarding:
graph LR
A[Request model field] --> B{antigravityModelAliases?}
B -- ag-c46s-thinking --> C[claude-sonnet-4-6]
B -- ag-c46o-thinking --> D[claude-opus-4-6-thinking]
B -- otherwise --> E[forwarded unchanged]
A similar map rewrites cursor-composer-2.5 to composer-2.5. See ThinkingProxy for the full rewrite pipeline.
The proxy does not inject reasoning, reasoning_effort, thinking, or output_config. Each settingsEntry advertises enableThinking, the supported efforts, and a default reasoningEffort; Droid CLI's per-session selector picks the level from that native metadata and sends it in the request body, which the proxy forwards unchanged.
One narrow exception keeps a model usable at its top level: Sonnet 4.6 exposes max in Droid's selector, but Sonnet's adaptive thinking rejects output_config.effort:max upstream (HTTP 400). When a Sonnet 4.6 request arrives with output_config.effort == "max", ThinkingProxy converts it to classic extended thinking (thinking:{type:enabled,budget_tokens}) and pins max_tokens. Lower efforts pass through as adaptive untouched. See Thinking proxy for the transform.
-
src/Sources/SettingsView.swiftreads the catalog (settingsModels,allSettingsIDs) to write and verify~/.factory/settings.json. -
src/Sources/ServerManager.swiftsuppliesisProviderEnabled, which gates whether a provider's models are written. -
src/Sources/ThinkingProxy.swiftperforms the Antigravity and Cursor model-alias rewrites at request time.
- Add a
DroidProxyModelDefinitiontodefinitionsinsrc/Sources/DroidProxyModelCatalog.swift(use theantigravityModel(...)helper for Antigravity-routed models). - Set its
levelsanddefaultLevelValue; they flow intosettingsEntryassupportedReasoningEfforts,defaultReasoningEffort, andreasoningEffort. - If the backend expects a different model id than
baseModel, add an entry toantigravityModelAliases(orcursorModelAliases) insrc/Sources/ThinkingProxy.swift. - Users click Apply in Settings to write the new entry into
~/.factory/settings.json.
| File | Role |
|---|---|
src/Sources/DroidProxyModelCatalog.swift |
Catalog of model definitions, levels, and settingsEntry schema. |
src/Sources/SettingsView.swift |
applyFactoryCustomModels, enabledFactorySettingsModels, checkFactoryModelsInstalled. |
src/Sources/ThinkingProxy.swift |
Request-time Antigravity/Cursor model-alias rewriting. |
src/Sources/AuthStatus.swift |
ServiceType, which maps providerKeys to provider enable state. |