Files
Brad Beebe ac3a84ba5a fix(opencode): Fix hardcoding default build OpenCode agent when sending responses (#1131)
* fix(opencode): default agent switching to disabled

* fix(opencode): keep plan-approval build handoff; default no-switch for review feedback only

The agent switch cookie is shared by plan approval and code review, so
flipping the stored default to `disabled` also removed OpenCode's
plan-approval hand-off for every user who never configured the setting.

Make the unset default surface-aware instead: `getAgentSwitchSettings('plan')`
keeps the historical build hand-off, `getAgentSwitchSettings('review')`
stays on the current agent. An explicit user choice still applies to both
surfaces. Settings and the agent warning resolve the default from the mode
they render in, and the OpenCode "agent not available" warning now names
plan approval on the plan path.

Claude-Session: https://claude.ai/code/session_01H5KQWqXqjrPxyxUNso1QHS

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-07-26 22:08:04 -07:00

91 lines
2.5 KiB
TypeScript

/**
* Hook for fetching and validating OpenCode agents
*/
import { useState, useEffect, useCallback } from 'react';
import type { Origin } from '@plannotator/core/agents';
import { getAgentSwitchSettings, type AgentSwitchSurface } from '../utils/agentSwitch';
export interface Agent {
id: string;
name: string;
description?: string;
}
export interface UseAgentsResult {
agents: Agent[];
isLoading: boolean;
/** Validate if an agent exists (case-insensitive) */
validateAgent: (agentName: string) => boolean;
/** Get warning message if current settings point to invalid agent, null if valid */
getAgentWarning: () => string | null;
}
/**
* Fetch available agents from OpenCode API
* Only fetches when origin is 'opencode'
*/
export function useAgents(origin: Origin | null, surface: AgentSwitchSurface = 'plan'): UseAgentsResult {
const [agents, setAgents] = useState<Agent[]>([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (origin !== 'opencode') return;
setIsLoading(true);
fetch('/api/agents')
.then(res => res.json())
.then((data: { agents?: Agent[] }) => {
if (data.agents?.length) {
setAgents(data.agents);
}
})
.catch(() => {
setAgents([]);
})
.finally(() => {
setIsLoading(false);
});
}, [origin]);
const validateAgent = useCallback((agentName: string): boolean => {
if (agents.length === 0) return true; // No agents = can't validate, assume ok
return agents.some(a => a.id.toLowerCase() === agentName.toLowerCase());
}, [agents]);
const getAgentWarning = useCallback((): string | null => {
if (agents.length === 0) return null; // Can't validate without agents
const settings = getAgentSwitchSettings(surface);
if (settings.switchTo === 'disabled') {
return null;
}
if (settings.switchTo === 'custom') {
if (settings.customName) {
const exists = validateAgent(settings.customName);
if (!exists) {
return `Agent "${settings.customName}" not found in OpenCode. It may cause errors.`;
}
}
return null;
}
// Regular agent selection
const exists = validateAgent(settings.switchTo);
if (!exists) {
return `Agent "${settings.switchTo}" not found in OpenCode. Select another or it may cause errors.`;
}
return null;
}, [agents, validateAgent, surface]);
return {
agents,
isLoading,
validateAgent,
getAgentWarning,
};
}