fix: correct config.data.model access pattern and use dynamic config paths

- Fixed delegate-task/tools.ts to access openCodeConfig.data.model instead of openCodeConfig.model
- Updated error messages to use getOpenCodeConfigPaths() for cross-platform paths
- Fixed 12 test mocks to use correct { data: { model: ... } } structure
- Fixes delegation failing with 'requires a default model' even when model is configured
This commit is contained in:
Kenny
2026-01-18 22:08:27 -05:00
parent f39f77d155
commit 6956ce0a19
3 changed files with 23 additions and 15 deletions

View File

@@ -22,6 +22,7 @@ import { loadAllPluginComponents } from "../features/claude-code-plugin-loader";
import { createBuiltinMcps } from "../mcp";
import type { OhMyOpenCodeConfig } from "../config";
import { log } from "../shared";
import { getOpenCodeConfigPaths } from "../shared/opencode-config-dir";
import { migrateAgentConfig } from "../shared/permission-compat";
import { PROMETHEUS_SYSTEM_PROMPT, PROMETHEUS_PERMISSION } from "../agents/prometheus-prompt";
import { DEFAULT_CATEGORIES } from "../tools/delegate-task/constants";
@@ -100,9 +101,10 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
}
if (!(config.model as string | undefined)?.trim()) {
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null })
throw new Error(
'oh-my-opencode requires a default model.\n\n' +
'Add this to ~/.config/opencode/opencode.jsonc:\n\n' +
`Add this to ${paths.configJsonc}:\n\n` +
' "model": "anthropic/claude-sonnet-4-5"\n\n' +
'(Replace with your preferred provider/model)'
)

View File

@@ -125,7 +125,7 @@ describe("sisyphus-task", () => {
)
// #then returns descriptive error message
expect(result).toContain("No default model configured")
expect(result).toContain("oh-my-opencode requires a default model")
})
})
@@ -304,7 +304,7 @@ describe("sisyphus-task", () => {
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
session: {
create: async () => ({ data: { id: "test-session" } }),
prompt: async () => ({ data: {} }),
@@ -363,7 +363,7 @@ describe("sisyphus-task", () => {
const mockManager = { launch: async () => ({}) }
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
session: {
create: async () => ({ data: { id: "test-session" } }),
prompt: async () => ({ data: {} }),
@@ -406,7 +406,7 @@ describe("sisyphus-task", () => {
const mockManager = { launch: async () => ({}) }
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
session: {
create: async () => ({ data: { id: "test-session" } }),
prompt: async () => ({ data: {} }),
@@ -453,7 +453,7 @@ describe("sisyphus-task", () => {
const mockManager = { launch: async () => ({}) }
const mockClient = {
app: { agents: async () => ({ data: [] }) },
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
session: {
get: async () => ({ data: { directory: "/project" } }),
create: async () => ({ data: { id: "test-session" } }),
@@ -528,7 +528,7 @@ describe("sisyphus-task", () => {
],
}),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
app: {
agents: async () => ({ data: [] }),
},
@@ -586,7 +586,7 @@ describe("sisyphus-task", () => {
data: [],
}),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
}
const tool = createDelegateTask({
@@ -638,7 +638,7 @@ describe("sisyphus-task", () => {
messages: async () => ({ data: [] }),
status: async () => ({ data: {} }),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
app: {
agents: async () => ({ data: [{ name: "ultrabrain", mode: "subagent" }] }),
},
@@ -698,7 +698,7 @@ describe("sisyphus-task", () => {
}),
status: async () => ({ data: { "ses_sync_success": { type: "idle" } } }),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
app: {
agents: async () => ({ data: [{ name: "ultrabrain", mode: "subagent" }] }),
},
@@ -751,7 +751,7 @@ describe("sisyphus-task", () => {
messages: async () => ({ data: [] }),
status: async () => ({ data: {} }),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
app: {
agents: async () => ({ data: [{ name: "ultrabrain", mode: "subagent" }] }),
},
@@ -805,7 +805,7 @@ describe("sisyphus-task", () => {
}),
status: async () => ({ data: {} }),
},
config: { get: async () => ({ model: SYSTEM_DEFAULT_MODEL }) },
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
app: { agents: async () => ({ data: [] }) },
}

View File

@@ -11,7 +11,7 @@ import { discoverSkills } from "../../features/opencode-skill-loader"
import { getTaskToastManager } from "../../features/task-toast-manager"
import type { ModelFallbackInfo } from "../../features/task-toast-manager/types"
import { subagentSessions, getSessionAgent } from "../../features/claude-code-session-state"
import { log, getAgentToolRestrictions, resolveModel } from "../../shared"
import { log, getAgentToolRestrictions, resolveModel, getOpenCodeConfigPaths } from "../../shared"
type OpencodeClient = PluginInput["client"]
@@ -415,7 +415,7 @@ ${textContent || "(No text output)"}`
let systemDefaultModel: string | undefined
try {
const openCodeConfig = await client.config.get()
systemDefaultModel = (openCodeConfig as { model?: string })?.model
systemDefaultModel = (openCodeConfig as { data?: { model?: string } })?.data?.model
} catch {
// Config fetch failed, proceed without system default
systemDefaultModel = undefined
@@ -434,7 +434,13 @@ ${textContent || "(No text output)"}`
if (args.category) {
// Guard: require system default model for category delegation
if (!systemDefaultModel) {
return `No default model configured. Set a model in your OpenCode config (model field).`
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null })
return (
'oh-my-opencode requires a default model.\n\n' +
`Add this to ${paths.configJsonc}:\n\n` +
' "model": "anthropic/claude-sonnet-4-5"\n\n' +
'(Replace with your preferred provider/model)'
)
}
const resolved = resolveCategoryConfig(args.category, {