refactor(core): resolve default agent info (#27125)
This commit is contained in:
@@ -1094,8 +1094,8 @@ export class Agent implements ACPAgent {
|
|||||||
|
|
||||||
const currentModeId = await (async () => {
|
const currentModeId = await (async () => {
|
||||||
if (!availableModes.length) return undefined
|
if (!availableModes.length) return undefined
|
||||||
const defaultAgentName = await AppRuntime.runPromise(AgentModule.Service.use((svc) => svc.defaultAgent()))
|
const defaultAgent = await AppRuntime.runPromise(AgentModule.Service.use((svc) => svc.defaultInfo()))
|
||||||
const resolvedModeId = availableModes.find((mode) => mode.name === defaultAgentName)?.id ?? availableModes[0].id
|
const resolvedModeId = availableModes.find((mode) => mode.name === defaultAgent.name)?.id ?? availableModes[0].id
|
||||||
this.sessionManager.setMode(sessionId, resolvedModeId)
|
this.sessionManager.setMode(sessionId, resolvedModeId)
|
||||||
return resolvedModeId
|
return resolvedModeId
|
||||||
})()
|
})()
|
||||||
@@ -1328,7 +1328,7 @@ export class Agent implements ACPAgent {
|
|||||||
if (!current) {
|
if (!current) {
|
||||||
this.sessionManager.setModel(session.id, model)
|
this.sessionManager.setModel(session.id, model)
|
||||||
}
|
}
|
||||||
const agent = session.modeId ?? (await AppRuntime.runPromise(AgentModule.Service.use((svc) => svc.defaultAgent())))
|
const agent = session.modeId ?? (await AppRuntime.runPromise(AgentModule.Service.use((svc) => svc.defaultInfo()))).name
|
||||||
|
|
||||||
const parts: Array<
|
const parts: Array<
|
||||||
| { type: "text"; text: string; synthetic?: boolean; ignored?: boolean }
|
| { type: "text"; text: string; synthetic?: boolean; ignored?: boolean }
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ const GeneratedAgent = Schema.Struct({
|
|||||||
export interface Interface {
|
export interface Interface {
|
||||||
readonly get: (agent: string) => Effect.Effect<Info>
|
readonly get: (agent: string) => Effect.Effect<Info>
|
||||||
readonly list: () => Effect.Effect<Info[]>
|
readonly list: () => Effect.Effect<Info[]>
|
||||||
|
readonly defaultInfo: () => Effect.Effect<Info>
|
||||||
readonly defaultAgent: () => Effect.Effect<string>
|
readonly defaultAgent: () => Effect.Effect<string>
|
||||||
readonly generate: (input: {
|
readonly generate: (input: {
|
||||||
description: string
|
description: string
|
||||||
@@ -333,23 +334,28 @@ export const layer = Layer.effect(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultAgent = Effect.fnUntraced(function* () {
|
const defaultInfo = Effect.fnUntraced(function* () {
|
||||||
const c = yield* config.get()
|
const c = yield* config.get()
|
||||||
if (c.default_agent) {
|
if (c.default_agent) {
|
||||||
const agent = agents[c.default_agent]
|
const agent = agents[c.default_agent]
|
||||||
if (!agent) throw new Error(`default agent "${c.default_agent}" not found`)
|
if (!agent) throw new Error(`default agent "${c.default_agent}" not found`)
|
||||||
if (agent.mode === "subagent") throw new Error(`default agent "${c.default_agent}" is a subagent`)
|
if (agent.mode === "subagent") throw new Error(`default agent "${c.default_agent}" is a subagent`)
|
||||||
if (agent.hidden === true) throw new Error(`default agent "${c.default_agent}" is hidden`)
|
if (agent.hidden === true) throw new Error(`default agent "${c.default_agent}" is hidden`)
|
||||||
return agent.name
|
return agent
|
||||||
}
|
}
|
||||||
const visible = Object.values(agents).find((a) => a.mode !== "subagent" && a.hidden !== true)
|
const visible = Object.values(agents).find((a) => a.mode !== "subagent" && a.hidden !== true)
|
||||||
if (!visible) throw new Error("no primary visible agent found")
|
if (!visible) throw new Error("no primary visible agent found")
|
||||||
return visible.name
|
return visible
|
||||||
|
})
|
||||||
|
|
||||||
|
const defaultAgent = Effect.fnUntraced(function* () {
|
||||||
|
return (yield* defaultInfo()).name
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get,
|
get,
|
||||||
list,
|
list,
|
||||||
|
defaultInfo,
|
||||||
defaultAgent,
|
defaultAgent,
|
||||||
} satisfies State
|
} satisfies State
|
||||||
}),
|
}),
|
||||||
@@ -362,6 +368,9 @@ export const layer = Layer.effect(
|
|||||||
list: Effect.fn("Agent.list")(function* () {
|
list: Effect.fn("Agent.list")(function* () {
|
||||||
return yield* InstanceState.useEffect(state, (s) => s.list())
|
return yield* InstanceState.useEffect(state, (s) => s.list())
|
||||||
}),
|
}),
|
||||||
|
defaultInfo: Effect.fn("Agent.defaultInfo")(function* () {
|
||||||
|
return yield* InstanceState.useEffect(state, (s) => s.defaultInfo())
|
||||||
|
}),
|
||||||
defaultAgent: Effect.fn("Agent.defaultAgent")(function* () {
|
defaultAgent: Effect.fn("Agent.defaultAgent")(function* () {
|
||||||
return yield* InstanceState.useEffect(state, (s) => s.defaultAgent())
|
return yield* InstanceState.useEffect(state, (s) => s.defaultAgent())
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper
|
|||||||
const list = yield* registry.tools({
|
const list = yield* registry.tools({
|
||||||
providerID: ctx.query.provider,
|
providerID: ctx.query.provider,
|
||||||
modelID: ctx.query.model,
|
modelID: ctx.query.model,
|
||||||
agent: yield* agents.get(yield* agents.defaultAgent()),
|
agent: yield* agents.defaultInfo(),
|
||||||
})
|
})
|
||||||
return list.map((item) => ({
|
return list.map((item) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
|||||||
@@ -1083,8 +1083,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
})
|
})
|
||||||
|
|
||||||
const createUserMessage = Effect.fn("SessionPrompt.createUserMessage")(function* (input: PromptInput) {
|
const createUserMessage = Effect.fn("SessionPrompt.createUserMessage")(function* (input: PromptInput) {
|
||||||
const agentName = input.agent || (yield* agents.defaultAgent())
|
const agentName = input.agent
|
||||||
const ag = yield* agents.get(agentName)
|
const ag = agentName ? yield* agents.get(agentName) : yield* agents.defaultInfo()
|
||||||
if (!ag) {
|
if (!ag) {
|
||||||
const available = (yield* agents.list()).filter((a) => !a.hidden).map((a) => a.name)
|
const available = (yield* agents.list()).filter((a) => !a.hidden).map((a) => a.name)
|
||||||
const hint = available.length ? ` Available agents: ${available.join(", ")}` : ""
|
const hint = available.length ? ` Available agents: ${available.join(", ")}` : ""
|
||||||
@@ -1875,7 +1875,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
yield* bus.publish(Session.Event.Error, { sessionID: input.sessionID, error: error.toObject() })
|
yield* bus.publish(Session.Event.Error, { sessionID: input.sessionID, error: error.toObject() })
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
const agentName = cmd.agent ?? input.agent ?? (yield* agents.defaultAgent())
|
const agentName = cmd.agent ?? input.agent
|
||||||
|
|
||||||
const raw = input.arguments.match(argsRegex) ?? []
|
const raw = input.arguments.match(argsRegex) ?? []
|
||||||
const args = raw.map((arg) => arg.replace(quoteTrimRegex, ""))
|
const args = raw.map((arg) => arg.replace(quoteTrimRegex, ""))
|
||||||
@@ -1928,7 +1928,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
|
|
||||||
yield* getModel(taskModel.providerID, taskModel.modelID, input.sessionID)
|
yield* getModel(taskModel.providerID, taskModel.modelID, input.sessionID)
|
||||||
|
|
||||||
const agent = yield* agents.get(agentName)
|
const agent = agentName ? yield* agents.get(agentName) : yield* agents.defaultInfo()
|
||||||
if (!agent) {
|
if (!agent) {
|
||||||
const available = (yield* agents.list()).filter((a) => !a.hidden).map((a) => a.name)
|
const available = (yield* agents.list()).filter((a) => !a.hidden).map((a) => a.name)
|
||||||
const hint = available.length ? ` Available agents: ${available.join(", ")}` : ""
|
const hint = available.length ? ` Available agents: ${available.join(", ")}` : ""
|
||||||
@@ -1952,7 +1952,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
|
|||||||
]
|
]
|
||||||
: [...templateParts, ...(input.parts ?? [])]
|
: [...templateParts, ...(input.parts ?? [])]
|
||||||
|
|
||||||
const userAgent = isSubtask ? (input.agent ?? (yield* agents.defaultAgent())) : agentName
|
const userAgent = isSubtask ? (input.agent ?? (yield* agents.defaultInfo()).name) : agent.name
|
||||||
const userModel = isSubtask
|
const userModel = isSubtask
|
||||||
? input.model
|
? input.model
|
||||||
? Provider.parseModel(input.model)
|
? Provider.parseModel(input.model)
|
||||||
|
|||||||
@@ -638,6 +638,14 @@ it.instance("defaultAgent returns build when no default_agent config", () =>
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.instance("defaultInfo returns resolved build agent when no default_agent config", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const agent = yield* load((svc) => svc.defaultInfo())
|
||||||
|
expect(agent.name).toBe("build")
|
||||||
|
expect(agent.mode).toBe("primary")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.instance(
|
it.instance(
|
||||||
"defaultAgent respects default_agent config set to plan",
|
"defaultAgent respects default_agent config set to plan",
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ describe("tool.registry", () => {
|
|||||||
const promptTools = yield* registry.tools({
|
const promptTools = yield* registry.tools({
|
||||||
providerID: ProviderID.opencode,
|
providerID: ProviderID.opencode,
|
||||||
modelID: ModelID.make("test"),
|
modelID: ModelID.make("test"),
|
||||||
agent: yield* agents.get(yield* agents.defaultAgent()),
|
agent: yield* agents.defaultInfo(),
|
||||||
})
|
})
|
||||||
const promptTool = promptTools.find((tool) => tool.id === "sql")
|
const promptTool = promptTools.find((tool) => tool.id === "sql")
|
||||||
if (!promptTool) throw new Error("custom sql tool was not returned for prompts")
|
if (!promptTool) throw new Error("custom sql tool was not returned for prompts")
|
||||||
|
|||||||
Reference in New Issue
Block a user