The OpenCode, AMP, and Droid configurations were showing in Raw JSON format instead of Structured format like Claude Code does. This made them difficult to edit and understand.
Added full structured editors for all three tools with:
interface OpenCodeModel {
id: string
name: string
provider: string
context_length?: number
max_output_tokens?: number
supports_vision?: boolean
supports_tools?: boolean
}
interface OpenCodeProvider {
id: string
name: string
type: string
base_url: string
api_key: string
timeout?: number
retry_attempts?: number
}
interface OpenCodeConfig {
provider?: string
model?: string
endpoint?: string
api_key_env?: string
features?: { ... }
models?: { ... }
providers?: { ... }
mcp?: { ... }
skills?: { ... }
}
interface AMPProvider { ... }
interface AMPModelCapability { ... }
interface AMPModel { ... }
interface AMPConfig {
models?: { ... }
features?: { ... }
ui?: { ... }
logging?: { ... }
}
interface DroidModel {
model: string
id: string
baseUrl: string
apiKey: string
provider: string
displayName?: string
enabled?: boolean
capabilities?: Array<string>
temperature?: number
topP?: number
// etc.
}
interface DroidConfig {
customModels?: Array<DroidModel>
providers?: { ... }
features?: { ... }
logging?: { ... }
ui?: { ... }
enabledPlugins?: Record<string, boolean>
}
Sections:
Features:
Sections:
Features:
Sections:
Features:
const [opencodeConfig, setOpenCodeConfig] = useState<OpenCodeConfig | null>(null)
const [ampConfig, setAMPConfig] = useState<AMPConfig | null>(null)
const [droidConfig, setDroidConfig] = useState<DroidConfig | null>(null)
Added parsing for all three configs:
else if (activeConfig === "opencode" && resp.content) {
try {
setOpenCodeConfig(JSON.parse(resp.content))
} catch {
setOpenCodeConfig(null)
}
} else if (activeConfig === "amp" && resp.content) {
try {
setAMPConfig(JSON.parse(resp.content))
} catch {
setAMPConfig(null)
}
} else if (activeConfig === "droid" && resp.content) {
try {
setDroidConfig(JSON.parse(resp.content))
} catch {
setDroidConfig(null)
}
}
if (activeConfig === "opencode" && opencodeConfig)
return JSON.stringify(opencodeConfig, null, 2) + "\n"
if (activeConfig === "amp" && ampConfig)
return JSON.stringify(ampConfig, null, 2) + "\n"
if (activeConfig === "droid" && droidConfig)
return JSON.stringify(droidConfig, null, 2) + "\n"
Re-parses all three configs after save to ensure latest data.
Resets all three configs when clicking Reset button.
Shows structured view when any of the five configs are active.
{activeConfig === "opencode" && opencodeConfig && (
<OpenCodeEditor config={opencodeConfig} onChange={...} />
)}
{activeConfig === "amp" && ampConfig && (
<AMPEditor config={ampConfig} onChange={...} />
)}
{activeConfig === "droid" && droidConfig && (
<DroidEditor config={droidConfig} onChange={...} />
)}
┌─────────────────────────────────────┐
│ Raw JSON Editor │
│ { │
│ "provider": "openai-compatible", │
│ "model": "glm-5.1", │
│ ... │
│ } │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ ● Global Settings │
│ Provider: [openai-compatible] │
│ Model: [glm-5.1 ] │
│ Endpoint: [http://localhost:5000] │
│ │
│ ● Features │
│ ☑ streaming │
│ ☑ tool use │
│ ☐ auto backup │
│ │
│ ● Custom Providers [+ Add]│
│ ┌─ omnillm ────────────┐ │
│ │ Type: [openai-compatible] │
│ │ URL: [http://...] │
│ └────────────────────────┘ │
└─────────────────────────────────────┘
bun run omni restart --rebuild
Refresh browser to see structured editors
Verify save/reload works correctly for all three
| File | Lines Added | Description |
|---|---|---|
frontend/src/pages/ConfigPage.tsx |
~820 | Added 3 new editors + state management |
Each tool has unique configuration structure:
providers.custom[] arraymodels.providers[] and models.custom[]customModels[] with different field namesOrganized by usage frequency:
| Feature | Claude | Codex | OpenCode | AMP | Droid |
|---|---|---|---|---|---|
| Env Vars | ✅ | ❌ | ✅ | ❌ | ❌ |
| Plugins | ✅ | ❌ | ❌ | ❌ | ✅ |
| Providers | ❌ | ✅ | ✅ | ✅ | ✅ |
| Models | ❌ | ✅ | ✅ | ✅ | ✅ |
| UI Settings | ❌ | ❌ | ❌ | ✅ | ✅ |
| Parameters | ❌ | ❌ | ❌ | ✅ | ✅ |
All editors now follow consistent patterns while respecting each tool’s unique structure.