mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
ac3a84ba5a
* 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>
91 lines
2.5 KiB
TypeScript
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,
|
|
};
|
|
}
|