mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-07-10 00:14:27 +00:00
fix(ui): align primary agent selection with OpenCode (#409)
## Summary This PR keeps only the UI-side fix for primary agent selection in CodeNomad. It aligns the primary agent selector with OpenCode's behavior by: - filtering primary-session agents through a shared selectable-primary rule - avoiding re-inserting an invalid current agent back into the primary selector - using the same primary-agent rule when choosing the default agent for a newly created session ## Why The earlier investigation showed that the config-loading problem was actually rooted in OMO's handling of `OPENCODE_CONFIG_DIR`, not in CodeNomad itself. However, there was still an independent UI issue in CodeNomad: - the primary selector could keep showing an agent that should no longer be selectable - new sessions could derive their default agent from a looser filter than the one used by the selector This PR keeps only that UI-side fix. ## Changes - `packages/ui/src/components/agent-selector.tsx` - use a shared `isSelectablePrimaryAgent` helper for primary-session filtering - stop force-inserting the current invalid agent back into the primary selector list - `packages/ui/src/stores/session-api.ts` - use the same `isSelectablePrimaryAgent` helper when selecting the default agent for a new session - `packages/ui/src/types/session.ts` - add `isSelectablePrimaryAgent(agent)` helper ## Scope This PR intentionally does **not** include any config merge / config copy workaround related to `OPENCODE_CONFIG_DIR`. That part was removed so this PR stays narrowly focused on the primary-agent selection behavior only. ## Validation - verified changed files are clean in editor diagnostics - confirmed this is a minimal UI-only diff --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
a0a8da97e6
commit
6d120b0d84
4 changed files with 22 additions and 16 deletions
|
|
@ -1,8 +1,8 @@
|
|||
import { Select } from "@kobalte/core/select"
|
||||
import { For, Show, createEffect, createMemo } from "solid-js"
|
||||
import { Show, createEffect, createMemo } from "solid-js"
|
||||
import { agents, fetchAgents, sessions } from "../stores/sessions"
|
||||
import { ChevronDown } from "lucide-solid"
|
||||
import type { Agent } from "../types/session"
|
||||
import { isSelectablePrimaryAgent, type Agent } from "../types/session"
|
||||
import { useI18n } from "../lib/i18n"
|
||||
import { getLogger } from "../lib/logger"
|
||||
const log = getLogger("session")
|
||||
|
|
@ -34,14 +34,7 @@ export default function AgentSelector(props: AgentSelectorProps) {
|
|||
return allAgents.filter((agent) => !agent.hidden)
|
||||
}
|
||||
|
||||
const filtered = allAgents.filter((agent) => !agent.hidden && agent.mode !== "subagent")
|
||||
|
||||
const currentAgent = allAgents.find((a) => a.name === props.currentAgent)
|
||||
if (currentAgent && !filtered.find((a) => a.name === props.currentAgent)) {
|
||||
return [currentAgent, ...filtered]
|
||||
}
|
||||
|
||||
return filtered
|
||||
return allAgents.filter(isSelectablePrimaryAgent)
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
|
|
@ -58,7 +51,6 @@ export default function AgentSelector(props: AgentSelectorProps) {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
const handleChange = async (value: Agent | null) => {
|
||||
if (value && value.name !== props.currentAgent) {
|
||||
await props.onAgentChange(value.name)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, createSignal, Show, For, createEffect } from "solid-js"
|
||||
import { Dialog } from "@kobalte/core/dialog"
|
||||
import type { Session, Agent } from "../types/session"
|
||||
import { isSelectablePrimaryAgent, type Session, type Agent } from "../types/session"
|
||||
import { getParentSessions, createSession, setActiveParentSession } from "../stores/sessions"
|
||||
import { instances, stopInstance } from "../stores/instances"
|
||||
import { agents } from "../stores/sessions"
|
||||
|
|
@ -22,7 +22,7 @@ const SessionPicker: Component<SessionPickerProps> = (props) => {
|
|||
|
||||
const instance = () => instances().get(props.instanceId)
|
||||
const parentSessions = () => getParentSessions(props.instanceId)
|
||||
const agentList = () => agents().get(props.instanceId) || []
|
||||
const agentList = () => (agents().get(props.instanceId) || []).filter(isSelectablePrimaryAgent)
|
||||
|
||||
createEffect(() => {
|
||||
const list = agentList()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
import { getIdleSinceForStatusTransition, mapSdkSessionRetry, mapSdkSessionStatus, type Session, type SessionStatus } from "../types/session"
|
||||
import {
|
||||
getIdleSinceForStatusTransition,
|
||||
isSelectablePrimaryAgent,
|
||||
mapSdkSessionRetry,
|
||||
mapSdkSessionStatus,
|
||||
type Session,
|
||||
type SessionStatus,
|
||||
} from "../types/session"
|
||||
import type { Message } from "../types/message"
|
||||
import type { FileDiff } from "@opencode-ai/sdk/v2/client"
|
||||
|
||||
|
|
@ -341,8 +348,8 @@ async function createSession(instanceId: string, agent?: string): Promise<Sessio
|
|||
const client = getOrCreateWorktreeClient(instanceId, worktreeSlug)
|
||||
|
||||
const instanceAgents = agents().get(instanceId) || []
|
||||
const nonSubagents = instanceAgents.filter((a) => a.mode !== "subagent")
|
||||
const selectedAgent = agent || (nonSubagents.length > 0 ? nonSubagents[0].name : "")
|
||||
const primaryAgents = instanceAgents.filter(isSelectablePrimaryAgent)
|
||||
const selectedAgent = agent || (primaryAgents.length > 0 ? primaryAgents[0].name : "")
|
||||
|
||||
const defaultModel = await getDefaultModel(instanceId, selectedAgent)
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,13 @@ export interface Agent {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches OpenCode TUI's primary-agent visibility rule: visible iff not a subagent and not hidden.
|
||||
*/
|
||||
export function isSelectablePrimaryAgent(agent: Agent): boolean {
|
||||
return !agent.hidden && agent.mode !== "subagent"
|
||||
}
|
||||
|
||||
// Our client-specific Provider interface (simplified version of SDK Provider)
|
||||
export interface Provider {
|
||||
id: string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue