feat(agent-teams): support category-based teammate spawning
This commit is contained in:
parent
3f859828cc
commit
e984ce7493
@ -1,4 +1,8 @@
|
|||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
|
import type { CategoriesConfig } from "../../config/schema"
|
||||||
import type { BackgroundManager } from "../../features/background-agent"
|
import type { BackgroundManager } from "../../features/background-agent"
|
||||||
|
import { resolveCategoryExecution, resolveParentContext } from "../delegate-task/executor"
|
||||||
|
import type { DelegateTaskArgs, ToolContextWithMetadata } from "../delegate-task/types"
|
||||||
import { clearInbox, ensureInbox, sendPlainInboxMessage } from "./inbox-store"
|
import { clearInbox, ensureInbox, sendPlainInboxMessage } from "./inbox-store"
|
||||||
import { assignNextColor, getTeamMember, removeTeammate, updateTeamConfig, upsertTeammate } from "./team-config-store"
|
import { assignNextColor, getTeamMember, removeTeammate, updateTeamConfig, upsertTeammate } from "./team-config-store"
|
||||||
import type { TeamTeammateMember, TeamToolContext } from "./types"
|
import type { TeamTeammateMember, TeamToolContext } from "./types"
|
||||||
@ -33,13 +37,24 @@ function resolveLaunchFailureMessage(status: string | undefined, error: string |
|
|||||||
return "teammate_launch_timeout"
|
return "teammate_launch_timeout"
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildLaunchPrompt(teamName: string, teammateName: string, userPrompt: string): string {
|
function buildLaunchPrompt(
|
||||||
return [
|
teamName: string,
|
||||||
|
teammateName: string,
|
||||||
|
userPrompt: string,
|
||||||
|
categoryPromptAppend?: string,
|
||||||
|
): string {
|
||||||
|
const sections = [
|
||||||
`You are teammate "${teammateName}" in team "${teamName}".`,
|
`You are teammate "${teammateName}" in team "${teamName}".`,
|
||||||
`When you need updates, call read_inbox with team_name="${teamName}" and agent_name="${teammateName}".`,
|
`When you need updates, call read_inbox with team_name="${teamName}" and agent_name="${teammateName}".`,
|
||||||
"Initial assignment:",
|
"Initial assignment:",
|
||||||
userPrompt,
|
userPrompt,
|
||||||
].join("\n\n")
|
]
|
||||||
|
|
||||||
|
if (categoryPromptAppend) {
|
||||||
|
sections.push("Category guidance:", categoryPromptAppend)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sections.join("\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDeliveryPrompt(teamName: string, teammateName: string, summary: string, content: string): string {
|
function buildDeliveryPrompt(teamName: string, teammateName: string, summary: string, content: string): string {
|
||||||
@ -55,14 +70,103 @@ export interface SpawnTeammateParams {
|
|||||||
teamName: string
|
teamName: string
|
||||||
name: string
|
name: string
|
||||||
prompt: string
|
prompt: string
|
||||||
|
category?: string
|
||||||
subagentType: string
|
subagentType: string
|
||||||
model?: string
|
model?: string
|
||||||
planModeRequired: boolean
|
planModeRequired: boolean
|
||||||
context: TeamToolContext
|
context: TeamToolContext
|
||||||
manager: BackgroundManager
|
manager: BackgroundManager
|
||||||
|
categoryContext?: {
|
||||||
|
client: PluginInput["client"]
|
||||||
|
userCategories?: CategoriesConfig
|
||||||
|
sisyphusJuniorModel?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SpawnExecution {
|
||||||
|
agentType: string
|
||||||
|
teammateModel: string
|
||||||
|
launchModel?: { providerID: string; modelID: string; variant?: string }
|
||||||
|
categoryPromptAppend?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSystemDefaultModel(client: PluginInput["client"]): Promise<string | undefined> {
|
||||||
|
try {
|
||||||
|
const openCodeConfig = await client.config.get()
|
||||||
|
return (openCodeConfig as { data?: { model?: string } })?.data?.model
|
||||||
|
} catch {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveSpawnExecution(params: SpawnTeammateParams): Promise<SpawnExecution> {
|
||||||
|
if (!params.category) {
|
||||||
|
const launchModel = parseModel(params.model)
|
||||||
|
return {
|
||||||
|
agentType: params.subagentType,
|
||||||
|
teammateModel: params.model ?? "native",
|
||||||
|
...(launchModel ? { launchModel } : {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params.categoryContext?.client) {
|
||||||
|
throw new Error("category_requires_client_context")
|
||||||
|
}
|
||||||
|
|
||||||
|
const parentContext = resolveParentContext({
|
||||||
|
sessionID: params.context.sessionID,
|
||||||
|
messageID: params.context.messageID,
|
||||||
|
agent: params.context.agent ?? "sisyphus",
|
||||||
|
abort: new AbortController().signal,
|
||||||
|
} as ToolContextWithMetadata)
|
||||||
|
|
||||||
|
const inheritedModel = parentContext.model
|
||||||
|
? `${parentContext.model.providerID}/${parentContext.model.modelID}`
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const systemDefaultModel = await getSystemDefaultModel(params.categoryContext.client)
|
||||||
|
|
||||||
|
const delegateArgs: DelegateTaskArgs = {
|
||||||
|
description: `[team:${params.teamName}] ${params.name}`,
|
||||||
|
prompt: params.prompt,
|
||||||
|
category: params.category,
|
||||||
|
subagent_type: "sisyphus-junior",
|
||||||
|
run_in_background: true,
|
||||||
|
load_skills: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolution = await resolveCategoryExecution(
|
||||||
|
delegateArgs,
|
||||||
|
{
|
||||||
|
manager: params.manager,
|
||||||
|
client: params.categoryContext.client,
|
||||||
|
directory: process.cwd(),
|
||||||
|
userCategories: params.categoryContext.userCategories,
|
||||||
|
sisyphusJuniorModel: params.categoryContext.sisyphusJuniorModel,
|
||||||
|
},
|
||||||
|
inheritedModel,
|
||||||
|
systemDefaultModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (resolution.error) {
|
||||||
|
throw new Error(resolution.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolution.categoryModel) {
|
||||||
|
throw new Error("category_model_not_resolved")
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
agentType: resolution.agentToUse,
|
||||||
|
teammateModel: `${resolution.categoryModel.providerID}/${resolution.categoryModel.modelID}`,
|
||||||
|
launchModel: resolution.categoryModel,
|
||||||
|
categoryPromptAppend: resolution.categoryPromptAppend,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function spawnTeammate(params: SpawnTeammateParams): Promise<TeamTeammateMember> {
|
export async function spawnTeammate(params: SpawnTeammateParams): Promise<TeamTeammateMember> {
|
||||||
|
const execution = await resolveSpawnExecution(params)
|
||||||
|
|
||||||
let teammate: TeamTeammateMember | undefined
|
let teammate: TeamTeammateMember | undefined
|
||||||
let launchedTaskID: string | undefined
|
let launchedTaskID: string | undefined
|
||||||
|
|
||||||
@ -74,8 +178,9 @@ export async function spawnTeammate(params: SpawnTeammateParams): Promise<TeamTe
|
|||||||
teammate = {
|
teammate = {
|
||||||
agentId: `${params.name}@${params.teamName}`,
|
agentId: `${params.name}@${params.teamName}`,
|
||||||
name: params.name,
|
name: params.name,
|
||||||
agentType: params.subagentType,
|
agentType: execution.agentType,
|
||||||
model: params.model ?? "native",
|
...(params.category ? { category: params.category } : {}),
|
||||||
|
model: execution.teammateModel,
|
||||||
prompt: params.prompt,
|
prompt: params.prompt,
|
||||||
color: assignNextColor(current),
|
color: assignNextColor(current),
|
||||||
planModeRequired: params.planModeRequired,
|
planModeRequired: params.planModeRequired,
|
||||||
@ -97,14 +202,14 @@ export async function spawnTeammate(params: SpawnTeammateParams): Promise<TeamTe
|
|||||||
ensureInbox(params.teamName, params.name)
|
ensureInbox(params.teamName, params.name)
|
||||||
sendPlainInboxMessage(params.teamName, "team-lead", params.name, params.prompt, "initial_prompt", teammate.color)
|
sendPlainInboxMessage(params.teamName, "team-lead", params.name, params.prompt, "initial_prompt", teammate.color)
|
||||||
|
|
||||||
const resolvedModel = parseModel(params.model)
|
|
||||||
const launched = await params.manager.launch({
|
const launched = await params.manager.launch({
|
||||||
description: `[team:${params.teamName}] ${params.name}`,
|
description: `[team:${params.teamName}] ${params.name}`,
|
||||||
prompt: buildLaunchPrompt(params.teamName, params.name, params.prompt),
|
prompt: buildLaunchPrompt(params.teamName, params.name, params.prompt, execution.categoryPromptAppend),
|
||||||
agent: params.subagentType,
|
agent: execution.agentType,
|
||||||
parentSessionID: params.context.sessionID,
|
parentSessionID: params.context.sessionID,
|
||||||
parentMessageID: params.context.messageID,
|
parentMessageID: params.context.messageID,
|
||||||
...(resolvedModel ? { model: resolvedModel } : {}),
|
...(execution.launchModel ? { model: execution.launchModel } : {}),
|
||||||
|
...(params.category ? { category: params.category } : {}),
|
||||||
parentAgent: params.context.agent,
|
parentAgent: params.context.agent,
|
||||||
})
|
})
|
||||||
launchedTaskID = launched.id
|
launchedTaskID = launched.id
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
|
||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
|
import type { CategoriesConfig } from "../../config/schema"
|
||||||
import type { BackgroundManager } from "../../features/background-agent"
|
import type { BackgroundManager } from "../../features/background-agent"
|
||||||
import { clearInbox } from "./inbox-store"
|
import { clearInbox } from "./inbox-store"
|
||||||
import { validateAgentName, validateTeamName } from "./name-validation"
|
import { validateAgentName, validateTeamName } from "./name-validation"
|
||||||
@ -13,13 +15,20 @@ import { getTeamMember, readTeamConfigOrThrow, removeTeammate, updateTeamConfig
|
|||||||
import { cancelTeammateRun, spawnTeammate } from "./teammate-runtime"
|
import { cancelTeammateRun, spawnTeammate } from "./teammate-runtime"
|
||||||
import { resetOwnerTasks } from "./team-task-store"
|
import { resetOwnerTasks } from "./team-task-store"
|
||||||
|
|
||||||
export function createSpawnTeammateTool(manager: BackgroundManager): ToolDefinition {
|
export interface AgentTeamsSpawnOptions {
|
||||||
|
client?: PluginInput["client"]
|
||||||
|
userCategories?: CategoriesConfig
|
||||||
|
sisyphusJuniorModel?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createSpawnTeammateTool(manager: BackgroundManager, options?: AgentTeamsSpawnOptions): ToolDefinition {
|
||||||
return tool({
|
return tool({
|
||||||
description: "Spawn a teammate using native internal agent execution.",
|
description: "Spawn a teammate using native internal agent execution.",
|
||||||
args: {
|
args: {
|
||||||
team_name: tool.schema.string().describe("Team name"),
|
team_name: tool.schema.string().describe("Team name"),
|
||||||
name: tool.schema.string().describe("Teammate name"),
|
name: tool.schema.string().describe("Teammate name"),
|
||||||
prompt: tool.schema.string().describe("Initial teammate prompt"),
|
prompt: tool.schema.string().describe("Initial teammate prompt"),
|
||||||
|
category: tool.schema.string().optional().describe("Optional category (spawns sisyphus-junior with category model/prompt)") ,
|
||||||
subagent_type: tool.schema.string().optional().describe("Agent name to run (default: sisyphus-junior)"),
|
subagent_type: tool.schema.string().optional().describe("Agent name to run (default: sisyphus-junior)"),
|
||||||
model: tool.schema.string().optional().describe("Optional model override in provider/model format"),
|
model: tool.schema.string().optional().describe("Optional model override in provider/model format"),
|
||||||
plan_mode_required: tool.schema.boolean().optional().describe("Enable plan mode flag in teammate metadata"),
|
plan_mode_required: tool.schema.boolean().optional().describe("Enable plan mode flag in teammate metadata"),
|
||||||
@ -37,15 +46,37 @@ export function createSpawnTeammateTool(manager: BackgroundManager): ToolDefinit
|
|||||||
return JSON.stringify({ error: agentError })
|
return JSON.stringify({ error: agentError })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.category && input.subagent_type && input.subagent_type !== "sisyphus-junior") {
|
||||||
|
return JSON.stringify({ error: "category_conflicts_with_subagent_type" })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.category && input.model) {
|
||||||
|
return JSON.stringify({ error: "category_conflicts_with_model_override" })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.category && !options?.client) {
|
||||||
|
return JSON.stringify({ error: "category_requires_client_context" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedSubagentType = input.category ? "sisyphus-junior" : input.subagent_type ?? "sisyphus-junior"
|
||||||
|
|
||||||
const teammate = await spawnTeammate({
|
const teammate = await spawnTeammate({
|
||||||
teamName: input.team_name,
|
teamName: input.team_name,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
prompt: input.prompt,
|
prompt: input.prompt,
|
||||||
subagentType: input.subagent_type ?? "sisyphus-junior",
|
category: input.category,
|
||||||
|
subagentType: resolvedSubagentType,
|
||||||
model: input.model,
|
model: input.model,
|
||||||
planModeRequired: input.plan_mode_required ?? false,
|
planModeRequired: input.plan_mode_required ?? false,
|
||||||
context,
|
context,
|
||||||
manager,
|
manager,
|
||||||
|
categoryContext: options?.client
|
||||||
|
? {
|
||||||
|
client: options.client,
|
||||||
|
userCategories: options.userCategories,
|
||||||
|
sisyphusJuniorModel: options.sisyphusJuniorModel,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
|||||||
import { existsSync, mkdtempSync, rmSync } from "node:fs"
|
import { existsSync, mkdtempSync, rmSync } from "node:fs"
|
||||||
import { tmpdir } from "node:os"
|
import { tmpdir } from "node:os"
|
||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
import type { BackgroundManager } from "../../features/background-agent"
|
import type { BackgroundManager } from "../../features/background-agent"
|
||||||
import { createAgentTeamsTools } from "./tools"
|
import { createAgentTeamsTools } from "./tools"
|
||||||
import { getTeamDir, getTeamInboxPath, getTeamTaskDir } from "./paths"
|
import { getTeamDir, getTeamInboxPath, getTeamTaskDir } from "./paths"
|
||||||
@ -11,12 +12,14 @@ interface LaunchCall {
|
|||||||
description: string
|
description: string
|
||||||
prompt: string
|
prompt: string
|
||||||
agent: string
|
agent: string
|
||||||
|
category?: string
|
||||||
parentSessionID: string
|
parentSessionID: string
|
||||||
parentMessageID: string
|
parentMessageID: string
|
||||||
parentAgent?: string
|
parentAgent?: string
|
||||||
model?: {
|
model?: {
|
||||||
providerID: string
|
providerID: string
|
||||||
modelID: string
|
modelID: string
|
||||||
|
variant?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +104,25 @@ function createFailingLaunchManager(): { manager: BackgroundManager; cancelCalls
|
|||||||
return { manager, cancelCalls }
|
return { manager, cancelCalls }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCategoryClientMock(): PluginInput["client"] {
|
||||||
|
return {
|
||||||
|
config: {
|
||||||
|
get: async () => ({ data: { model: "openai/gpt-5.3-codex" } }),
|
||||||
|
},
|
||||||
|
provider: {
|
||||||
|
list: async () => ({ data: { connected: ["openai", "anthropic"] } }),
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
list: async () => ({
|
||||||
|
data: [
|
||||||
|
{ provider: "openai", id: "gpt-5.3-codex" },
|
||||||
|
{ provider: "anthropic", id: "claude-haiku-4-5" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
} as unknown as PluginInput["client"]
|
||||||
|
}
|
||||||
|
|
||||||
function createContext(sessionID = "ses-main"): TestToolContext {
|
function createContext(sessionID = "ses-main"): TestToolContext {
|
||||||
return {
|
return {
|
||||||
sessionID,
|
sessionID,
|
||||||
@ -275,6 +297,75 @@ describe("agent-teams tools functional", () => {
|
|||||||
expect(clearedOwnerTask.owner).toBeUndefined()
|
expect(clearedOwnerTask.owner).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("spawns teammate using category resolution like delegate-task", async () => {
|
||||||
|
//#given
|
||||||
|
const { manager, launchCalls } = createMockManager()
|
||||||
|
const tools = createAgentTeamsTools(manager, { client: createCategoryClientMock() })
|
||||||
|
const context = createContext()
|
||||||
|
|
||||||
|
await executeJsonTool(tools, "team_create", { team_name: "core" }, context)
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const spawned = await executeJsonTool(
|
||||||
|
tools,
|
||||||
|
"spawn_teammate",
|
||||||
|
{
|
||||||
|
team_name: "core",
|
||||||
|
name: "worker_1",
|
||||||
|
prompt: "Handle release prep",
|
||||||
|
category: "quick",
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
) as { name?: string; error?: string }
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(spawned.error).toBeUndefined()
|
||||||
|
expect(spawned.name).toBe("worker_1")
|
||||||
|
expect(launchCalls).toHaveLength(1)
|
||||||
|
expect(launchCalls[0].agent).toBe("sisyphus-junior")
|
||||||
|
expect(launchCalls[0].category).toBe("quick")
|
||||||
|
expect(launchCalls[0].model).toBeDefined()
|
||||||
|
const resolvedModel = launchCalls[0].model!
|
||||||
|
expect(launchCalls[0].prompt).toContain("Category guidance:")
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const config = await executeJsonTool(tools, "read_config", { team_name: "core" }, context) as {
|
||||||
|
members: Array<{ name: string; category?: string; model?: string }>
|
||||||
|
}
|
||||||
|
|
||||||
|
//#then
|
||||||
|
const teammate = config.members.find((member) => member.name === "worker_1")
|
||||||
|
expect(teammate).toBeDefined()
|
||||||
|
expect(teammate?.category).toBe("quick")
|
||||||
|
expect(teammate?.model).toBe(`${resolvedModel.providerID}/${resolvedModel.modelID}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("rejects category with incompatible subagent_type", async () => {
|
||||||
|
//#given
|
||||||
|
const { manager } = createMockManager()
|
||||||
|
const tools = createAgentTeamsTools(manager, { client: createCategoryClientMock() })
|
||||||
|
const context = createContext()
|
||||||
|
|
||||||
|
await executeJsonTool(tools, "team_create", { team_name: "core" }, context)
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const result = await executeJsonTool(
|
||||||
|
tools,
|
||||||
|
"spawn_teammate",
|
||||||
|
{
|
||||||
|
team_name: "core",
|
||||||
|
name: "worker_1",
|
||||||
|
prompt: "Handle release prep",
|
||||||
|
category: "quick",
|
||||||
|
subagent_type: "oracle",
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
) as { error?: string }
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(result.error).toBe("category_conflicts_with_subagent_type")
|
||||||
|
})
|
||||||
|
|
||||||
test("rejects invalid task id input for task_get", async () => {
|
test("rejects invalid task id input for task_get", async () => {
|
||||||
//#given
|
//#given
|
||||||
const { manager } = createMockManager()
|
const { manager } = createMockManager()
|
||||||
|
|||||||
@ -1,16 +1,31 @@
|
|||||||
import type { ToolDefinition } from "@opencode-ai/plugin"
|
import type { ToolDefinition } from "@opencode-ai/plugin"
|
||||||
import type { BackgroundManager } from "../../features/background-agent"
|
import type { BackgroundManager } from "../../features/background-agent"
|
||||||
|
import type { PluginInput } from "@opencode-ai/plugin"
|
||||||
|
import type { CategoriesConfig } from "../../config/schema"
|
||||||
import { createReadInboxTool, createSendMessageTool } from "./messaging-tools"
|
import { createReadInboxTool, createSendMessageTool } from "./messaging-tools"
|
||||||
import { createTeamCreateTool, createTeamDeleteTool, createTeamReadConfigTool } from "./team-lifecycle-tools"
|
import { createTeamCreateTool, createTeamDeleteTool, createTeamReadConfigTool } from "./team-lifecycle-tools"
|
||||||
import { createTeamTaskCreateTool, createTeamTaskGetTool, createTeamTaskListTool } from "./team-task-tools"
|
import { createTeamTaskCreateTool, createTeamTaskGetTool, createTeamTaskListTool } from "./team-task-tools"
|
||||||
import { createTeamTaskUpdateTool } from "./team-task-update-tool"
|
import { createTeamTaskUpdateTool } from "./team-task-update-tool"
|
||||||
import { createForceKillTeammateTool, createProcessShutdownTool, createSpawnTeammateTool } from "./teammate-tools"
|
import { createForceKillTeammateTool, createProcessShutdownTool, createSpawnTeammateTool } from "./teammate-tools"
|
||||||
|
|
||||||
export function createAgentTeamsTools(manager: BackgroundManager): Record<string, ToolDefinition> {
|
export interface AgentTeamsToolOptions {
|
||||||
|
client?: PluginInput["client"]
|
||||||
|
userCategories?: CategoriesConfig
|
||||||
|
sisyphusJuniorModel?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createAgentTeamsTools(
|
||||||
|
manager: BackgroundManager,
|
||||||
|
options?: AgentTeamsToolOptions,
|
||||||
|
): Record<string, ToolDefinition> {
|
||||||
return {
|
return {
|
||||||
team_create: createTeamCreateTool(),
|
team_create: createTeamCreateTool(),
|
||||||
team_delete: createTeamDeleteTool(),
|
team_delete: createTeamDeleteTool(),
|
||||||
spawn_teammate: createSpawnTeammateTool(manager),
|
spawn_teammate: createSpawnTeammateTool(manager, {
|
||||||
|
client: options?.client,
|
||||||
|
userCategories: options?.userCategories,
|
||||||
|
sisyphusJuniorModel: options?.sisyphusJuniorModel,
|
||||||
|
}),
|
||||||
send_message: createSendMessageTool(manager),
|
send_message: createSendMessageTool(manager),
|
||||||
read_inbox: createReadInboxTool(),
|
read_inbox: createReadInboxTool(),
|
||||||
read_config: createTeamReadConfigTool(),
|
read_config: createTeamReadConfigTool(),
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export const TeamTeammateMemberSchema = z.object({
|
|||||||
agentType: z.string().refine((value) => value !== "team-lead", {
|
agentType: z.string().refine((value) => value !== "team-lead", {
|
||||||
message: "agent_type_reserved",
|
message: "agent_type_reserved",
|
||||||
}),
|
}),
|
||||||
|
category: z.string().optional(),
|
||||||
model: z.string(),
|
model: z.string(),
|
||||||
prompt: z.string(),
|
prompt: z.string(),
|
||||||
color: z.string(),
|
color: z.string(),
|
||||||
@ -108,6 +109,7 @@ export const TeamSpawnInputSchema = z.object({
|
|||||||
team_name: z.string(),
|
team_name: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
prompt: z.string(),
|
prompt: z.string(),
|
||||||
|
category: z.string().optional(),
|
||||||
subagent_type: z.string().optional(),
|
subagent_type: z.string().optional(),
|
||||||
model: z.string().optional(),
|
model: z.string().optional(),
|
||||||
plan_mode_required: z.boolean().optional(),
|
plan_mode_required: z.boolean().optional(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user