feat(agent-teams): add team, message, and task Zod schemas

- TeamConfigSchema with lead/teammate members
- TeamMemberSchema and TeamTeammateMemberSchema
- InboxMessageSchema with 5 message types
- SendMessageInputSchema as discriminated union
- Import TaskObjectSchema from tools/task/types.ts
- 39 comprehensive tests covering all schemas

Task 3/25 complete
This commit is contained in:
YeonGyu-Kim
2026-02-11 19:13:09 +09:00
parent 3e2e4e29df
commit d65912bc63
2 changed files with 825 additions and 169 deletions

View File

@@ -1,10 +1,198 @@
/// <reference types="bun-types" />
import { describe, expect, test } from "bun:test"
import { TeamTeammateMemberSchema } from "./types"
import { describe, it, expect } from "bun:test"
import { z } from "zod"
import {
TeamConfigSchema,
TeamMemberSchema,
TeamTeammateMemberSchema,
MessageTypeSchema,
InboxMessageSchema,
TeamTaskSchema,
TeamCreateInputSchema,
TeamDeleteInputSchema,
SendMessageInputSchema,
ReadInboxInputSchema,
ReadConfigInputSchema,
TeamSpawnInputSchema,
ForceKillTeammateInputSchema,
ProcessShutdownApprovedInputSchema,
} from "./types"
describe("agent-teams types", () => {
test("rejects reserved agentType for teammate schema", () => {
//#given
describe("TeamConfigSchema", () => {
it("validates a complete team config", () => {
// given
const validConfig = {
name: "my-team",
description: "A test team",
createdAt: "2026-02-11T10:00:00Z",
leadAgentId: "agent-123",
leadSessionId: "ses-456",
members: [
{
agentId: "agent-123",
name: "Lead Agent",
agentType: "lead",
color: "blue",
},
{
agentId: "agent-789",
name: "Worker 1",
agentType: "teammate",
color: "green",
category: "quick",
model: "claude-sonnet-4-5",
prompt: "You are a helpful assistant",
planModeRequired: false,
joinedAt: "2026-02-11T10:05:00Z",
cwd: "/tmp",
subscriptions: ["task-updates"],
backendType: "native" as const,
isActive: true,
sessionID: "ses-789",
backgroundTaskID: "task-123",
},
],
}
// when
const result = TeamConfigSchema.safeParse(validConfig)
// then
expect(result.success).toBe(true)
})
it("rejects invalid team config", () => {
// given
const invalidConfig = {
name: "",
description: "A test team",
createdAt: "invalid-date",
leadAgentId: "",
leadSessionId: "ses-456",
members: [],
}
// when
const result = TeamConfigSchema.safeParse(invalidConfig)
// then
expect(result.success).toBe(false)
})
})
describe("TeamMemberSchema", () => {
it("validates a lead member", () => {
// given
const leadMember = {
agentId: "agent-123",
name: "Lead Agent",
agentType: "lead",
color: "blue",
}
// when
const result = TeamMemberSchema.safeParse(leadMember)
// then
expect(result.success).toBe(true)
})
it("rejects invalid member", () => {
// given
const invalidMember = {
agentId: "",
name: "",
agentType: "invalid",
color: "invalid",
}
// when
const result = TeamMemberSchema.safeParse(invalidMember)
// then
expect(result.success).toBe(false)
})
})
describe("TeamTeammateMemberSchema", () => {
it("validates a complete teammate member", () => {
// given
const teammateMember = {
agentId: "agent-789",
name: "Worker 1",
agentType: "teammate",
color: "green",
category: "quick",
model: "claude-sonnet-4-5",
prompt: "You are a helpful assistant",
planModeRequired: false,
joinedAt: "2026-02-11T10:05:00Z",
cwd: "/tmp",
subscriptions: ["task-updates"],
backendType: "native" as const,
isActive: true,
sessionID: "ses-789",
backgroundTaskID: "task-123",
}
// when
const result = TeamTeammateMemberSchema.safeParse(teammateMember)
// then
expect(result.success).toBe(true)
})
it("validates teammate member with optional fields missing", () => {
// given
const minimalTeammate = {
agentId: "agent-789",
name: "Worker 1",
agentType: "teammate",
color: "green",
category: "quick",
model: "claude-sonnet-4-5",
prompt: "You are a helpful assistant",
planModeRequired: false,
joinedAt: "2026-02-11T10:05:00Z",
cwd: "/tmp",
subscriptions: [],
backendType: "native" as const,
isActive: true,
}
// when
const result = TeamTeammateMemberSchema.safeParse(minimalTeammate)
// then
expect(result.success).toBe(true)
})
it("rejects invalid teammate member", () => {
// given
const invalidTeammate = {
agentId: "",
name: "Worker 1",
agentType: "teammate",
color: "green",
category: "quick",
model: "claude-sonnet-4-5",
prompt: "You are a helpful assistant",
planModeRequired: false,
joinedAt: "invalid-date",
cwd: "/tmp",
subscriptions: [],
backendType: "invalid" as const,
isActive: true,
}
// when
const result = TeamTeammateMemberSchema.safeParse(invalidTeammate)
// then
expect(result.success).toBe(false)
})
it("rejects reserved agentType for teammate schema", () => {
// given
const invalidTeammate = {
agentId: "worker@team",
name: "worker",
@@ -14,17 +202,520 @@ describe("agent-teams types", () => {
prompt: "do work",
color: "blue",
planModeRequired: false,
joinedAt: Date.now(),
joinedAt: "2026-02-11T10:05:00Z",
cwd: "/tmp",
subscriptions: [],
backendType: "native",
isActive: false,
}
//#when
// when
const result = TeamTeammateMemberSchema.safeParse(invalidTeammate)
//#then
// then
expect(result.success).toBe(false)
})
})
describe("MessageTypeSchema", () => {
it("validates all 5 message types", () => {
// given
const types = ["message", "broadcast", "shutdown_request", "shutdown_response", "plan_approval_response"]
// when & then
types.forEach(type => {
const result = MessageTypeSchema.safeParse(type)
expect(result.success).toBe(true)
expect(result.data).toBe(type)
})
})
it("rejects invalid message type", () => {
// given
const invalidType = "invalid_type"
// when
const result = MessageTypeSchema.safeParse(invalidType)
// then
expect(result.success).toBe(false)
})
})
describe("InboxMessageSchema", () => {
it("validates a complete inbox message", () => {
// given
const message = {
id: "msg-123",
type: "message" as const,
sender: "agent-123",
recipient: "agent-456",
content: "Hello world",
summary: "Greeting",
timestamp: "2026-02-11T10:00:00Z",
read: false,
requestId: "req-123",
approve: true,
}
// when
const result = InboxMessageSchema.safeParse(message)
// then
expect(result.success).toBe(true)
})
it("validates message with optional fields missing", () => {
// given
const minimalMessage = {
id: "msg-123",
type: "broadcast" as const,
sender: "agent-123",
recipient: "agent-456",
content: "Hello world",
summary: "Greeting",
timestamp: "2026-02-11T10:00:00Z",
read: false,
}
// when
const result = InboxMessageSchema.safeParse(minimalMessage)
// then
expect(result.success).toBe(true)
})
it("rejects invalid inbox message", () => {
// given
const invalidMessage = {
id: "",
type: "invalid" as const,
sender: "",
recipient: "",
content: "",
summary: "",
timestamp: "invalid-date",
read: "not-boolean",
}
// when
const result = InboxMessageSchema.safeParse(invalidMessage)
// then
expect(result.success).toBe(false)
})
})
describe("TeamTaskSchema", () => {
it("validates a task object", () => {
// given
const task = {
id: "T-12345678-1234-1234-1234-123456789012",
subject: "Implement feature",
description: "Add new functionality",
status: "pending" as const,
activeForm: "Implementing feature",
blocks: [],
blockedBy: [],
owner: "agent-123",
metadata: { priority: "high" },
repoURL: "https://github.com/user/repo",
parentID: "T-parent",
threadID: "thread-123",
}
// when
const result = TeamTaskSchema.safeParse(task)
// then
expect(result.success).toBe(true)
})
it("rejects invalid task", () => {
// given
const invalidTask = {
id: "invalid-id",
subject: "",
description: "Add new functionality",
status: "invalid" as const,
activeForm: "Implementing feature",
blocks: [],
blockedBy: [],
}
// when
const result = TeamTaskSchema.safeParse(invalidTask)
// then
expect(result.success).toBe(false)
})
})
describe("TeamCreateInputSchema", () => {
it("validates create input with description", () => {
// given
const input = {
team_name: "my-team",
description: "A test team",
}
// when
const result = TeamCreateInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates create input without description", () => {
// given
const input = {
team_name: "my-team",
}
// when
const result = TeamCreateInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid create input", () => {
// given
const input = {
team_name: "invalid team name with spaces and special chars!",
}
// when
const result = TeamCreateInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("TeamDeleteInputSchema", () => {
it("validates delete input", () => {
// given
const input = {
team_name: "my-team",
}
// when
const result = TeamDeleteInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid delete input", () => {
// given
const input = {
team_name: "",
}
// when
const result = TeamDeleteInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("SendMessageInputSchema", () => {
it("validates message type input", () => {
// given
const input = {
team_name: "my-team",
type: "message" as const,
recipient: "agent-456",
content: "Hello world",
summary: "Greeting",
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates broadcast type input", () => {
// given
const input = {
team_name: "my-team",
type: "broadcast" as const,
content: "Team announcement",
summary: "Announcement",
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates shutdown_request type input", () => {
// given
const input = {
team_name: "my-team",
type: "shutdown_request" as const,
recipient: "agent-456",
content: "Please shutdown",
summary: "Shutdown request",
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates shutdown_response type input", () => {
// given
const input = {
team_name: "my-team",
type: "shutdown_response" as const,
request_id: "req-123",
approve: true,
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates plan_approval_response type input", () => {
// given
const input = {
team_name: "my-team",
type: "plan_approval_response" as const,
request_id: "req-456",
approve: false,
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects message type without recipient", () => {
// given
const input = {
team_name: "my-team",
type: "message" as const,
content: "Hello world",
summary: "Greeting",
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
it("rejects shutdown_response without request_id", () => {
// given
const input = {
team_name: "my-team",
type: "shutdown_response" as const,
approve: true,
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
it("rejects invalid team_name", () => {
// given
const input = {
team_name: "invalid team name",
type: "broadcast" as const,
content: "Hello",
summary: "Greeting",
}
// when
const result = SendMessageInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("ReadInboxInputSchema", () => {
it("validates read inbox input", () => {
// given
const input = {
team_name: "my-team",
agent_name: "worker-1",
unread_only: true,
mark_as_read: false,
}
// when
const result = ReadInboxInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("validates minimal read inbox input", () => {
// given
const input = {
team_name: "my-team",
agent_name: "worker-1",
}
// when
const result = ReadInboxInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid read inbox input", () => {
// given
const input = {
team_name: "",
agent_name: "",
}
// when
const result = ReadInboxInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("ReadConfigInputSchema", () => {
it("validates read config input", () => {
// given
const input = {
team_name: "my-team",
}
// when
const result = ReadConfigInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid read config input", () => {
// given
const input = {
team_name: "",
}
// when
const result = ReadConfigInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("TeamSpawnInputSchema", () => {
it("validates spawn input", () => {
// given
const input = {
team_name: "my-team",
name: "worker-1",
category: "quick",
prompt: "You are a helpful assistant",
}
// when
const result = TeamSpawnInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid spawn input", () => {
// given
const input = {
team_name: "invalid team",
name: "",
category: "quick",
prompt: "You are a helpful assistant",
}
// when
const result = TeamSpawnInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("ForceKillTeammateInputSchema", () => {
it("validates force kill input", () => {
// given
const input = {
team_name: "my-team",
teammate_name: "worker-1",
}
// when
const result = ForceKillTeammateInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid force kill input", () => {
// given
const input = {
team_name: "",
teammate_name: "",
}
// when
const result = ForceKillTeammateInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})
describe("ProcessShutdownApprovedInputSchema", () => {
it("validates shutdown approved input", () => {
// given
const input = {
team_name: "my-team",
teammate_name: "worker-1",
}
// when
const result = ProcessShutdownApprovedInputSchema.safeParse(input)
// then
expect(result.success).toBe(true)
})
it("rejects invalid shutdown approved input", () => {
// given
const input = {
team_name: "",
teammate_name: "",
}
// when
const result = ProcessShutdownApprovedInputSchema.safeParse(input)
// then
expect(result.success).toBe(false)
})
})

View File

@@ -1,82 +1,52 @@
import { z } from "zod"
import { TaskObjectSchema } from "../task/types"
export const TEAM_COLOR_PALETTE = [
"blue",
"green",
"yellow",
"purple",
"orange",
"pink",
"cyan",
"red",
] as const
// Team member schemas
export const TeamMemberSchema = z.object({
agentId: z.string().min(1),
name: z.string().min(1),
agentType: z.enum(["lead", "teammate"]),
color: z.string().min(1),
})
export const TeamTaskStatusSchema = z.enum(["pending", "in_progress", "completed", "deleted"])
export type TeamTaskStatus = z.infer<typeof TeamTaskStatusSchema>
export type TeamMember = z.infer<typeof TeamMemberSchema>
export const TeamLeadMemberSchema = z.object({
agentId: z.string(),
name: z.literal("team-lead"),
agentType: z.literal("team-lead"),
model: z.string(),
joinedAt: z.number(),
cwd: z.string(),
subscriptions: z.array(z.unknown()).default([]),
}).strict()
export const TeamTeammateMemberSchema = z.object({
agentId: z.string(),
name: z.string(),
agentType: z.string().refine((value) => value !== "team-lead", {
message: "agent_type_reserved",
}),
category: z.string(),
model: z.string(),
prompt: z.string(),
color: z.string(),
planModeRequired: z.boolean().default(false),
joinedAt: z.number(),
cwd: z.string(),
subscriptions: z.array(z.unknown()).default([]),
backendType: z.literal("native").default("native"),
isActive: z.boolean().default(false),
export const TeamTeammateMemberSchema = TeamMemberSchema.extend({
category: z.string().min(1),
model: z.string().min(1),
prompt: z.string().min(1),
planModeRequired: z.boolean(),
joinedAt: z.string().datetime(),
cwd: z.string().min(1),
subscriptions: z.array(z.string()),
backendType: z.literal("native"),
isActive: z.boolean(),
sessionID: z.string().optional(),
backgroundTaskID: z.string().optional(),
}).strict()
}).refine(
(data) => data.agentType === "teammate",
"TeamTeammateMemberSchema requires agentType to be 'teammate'"
).refine(
(data) => data.agentType !== "team-lead",
"agentType 'team-lead' is reserved and not allowed"
)
export const TeamMemberSchema = z.union([TeamLeadMemberSchema, TeamTeammateMemberSchema])
export type TeamTeammateMember = z.infer<typeof TeamTeammateMemberSchema>
// Team config schema
export const TeamConfigSchema = z.object({
name: z.string(),
description: z.string().default(""),
createdAt: z.number(),
leadAgentId: z.string(),
leadSessionId: z.string(),
members: z.array(TeamMemberSchema),
}).strict()
name: z.string().min(1),
description: z.string().optional(),
createdAt: z.string().datetime(),
leadAgentId: z.string().min(1),
leadSessionId: z.string().min(1),
members: z.array(z.union([TeamMemberSchema, TeamTeammateMemberSchema])),
})
export const TeamInboxMessageSchema = z.object({
from: z.string(),
text: z.string(),
timestamp: z.string(),
read: z.boolean().default(false),
summary: z.string().optional(),
color: z.string().optional(),
}).strict()
export type TeamConfig = z.infer<typeof TeamConfigSchema>
export const TeamTaskSchema = z.object({
id: z.string(),
subject: z.string(),
description: z.string(),
activeForm: z.string().optional(),
status: TeamTaskStatusSchema,
blocks: z.array(z.string()).default([]),
blockedBy: z.array(z.string()).default([]),
owner: z.string().optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
}).strict()
export const TeamSendMessageTypeSchema = z.enum([
// Message schemas
export const MessageTypeSchema = z.enum([
"message",
"broadcast",
"shutdown_request",
@@ -84,118 +54,113 @@ export const TeamSendMessageTypeSchema = z.enum([
"plan_approval_response",
])
export type TeamLeadMember = z.infer<typeof TeamLeadMemberSchema>
export type TeamTeammateMember = z.infer<typeof TeamTeammateMemberSchema>
export type TeamMember = z.infer<typeof TeamMemberSchema>
export type TeamConfig = z.infer<typeof TeamConfigSchema>
export type TeamInboxMessage = z.infer<typeof TeamInboxMessageSchema>
export type TeamTask = z.infer<typeof TeamTaskSchema>
export type TeamSendMessageType = z.infer<typeof TeamSendMessageTypeSchema>
export type MessageType = z.infer<typeof MessageTypeSchema>
export const InboxMessageSchema = z.object({
id: z.string().min(1),
type: MessageTypeSchema,
sender: z.string().min(1),
recipient: z.string().min(1),
content: z.string().optional(),
summary: z.string().optional(),
timestamp: z.string().datetime(),
read: z.boolean(),
requestId: z.string().optional(),
approve: z.boolean().optional(),
})
export type InboxMessage = z.infer<typeof InboxMessageSchema>
// Task schema (reuse from task/types.ts)
export const TeamTaskSchema = TaskObjectSchema
export type TeamTask = z.infer<typeof TeamTaskSchema>
// Input schemas for tools
export const TeamCreateInputSchema = z.object({
team_name: z.string(),
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
description: z.string().optional(),
})
export type TeamCreateInput = z.infer<typeof TeamCreateInputSchema>
export const TeamDeleteInputSchema = z.object({
team_name: z.string(),
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
})
export const TeamReadConfigInputSchema = z.object({
team_name: z.string(),
})
export type TeamDeleteInput = z.infer<typeof TeamDeleteInputSchema>
export const TeamSpawnInputSchema = z.object({
team_name: z.string(),
name: z.string(),
prompt: z.string(),
category: z.string(),
subagent_type: z.string().optional(),
model: z.string().optional(),
plan_mode_required: z.boolean().optional(),
})
function normalizeTeamRecipient(recipient: string): string {
const trimmed = recipient.trim()
const atIndex = trimmed.indexOf("@")
if (atIndex <= 0) {
return trimmed
}
return trimmed.slice(0, atIndex)
}
export const TeamSendMessageInputSchema = z.object({
team_name: z.string(),
type: TeamSendMessageTypeSchema,
recipient: z.string().optional().transform((value) => {
if (value === undefined) {
return undefined
}
return normalizeTeamRecipient(value)
export const SendMessageInputSchema = z.discriminatedUnion("type", [
z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
type: z.literal("message"),
recipient: z.string().min(1),
content: z.string().optional(),
summary: z.string().optional(),
}),
content: z.string().optional(),
summary: z.string().optional(),
request_id: z.string().optional(),
approve: z.boolean().optional(),
sender: z.string().optional(),
})
z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
type: z.literal("broadcast"),
content: z.string().optional(),
summary: z.string().optional(),
}),
z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
type: z.literal("shutdown_request"),
recipient: z.string().min(1),
content: z.string().optional(),
summary: z.string().optional(),
}),
z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
type: z.literal("shutdown_response"),
request_id: z.string().min(1),
approve: z.boolean(),
}),
z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
type: z.literal("plan_approval_response"),
request_id: z.string().min(1),
approve: z.boolean(),
}),
])
export const TeamReadInboxInputSchema = z.object({
team_name: z.string(),
agent_name: z.string(),
export type SendMessageInput = z.infer<typeof SendMessageInputSchema>
export const ReadInboxInputSchema = z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
agent_name: z.string().min(1),
unread_only: z.boolean().optional(),
mark_as_read: z.boolean().optional(),
})
export const TeamTaskCreateInputSchema = z.object({
team_name: z.string(),
subject: z.string(),
description: z.string(),
active_form: z.string().optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
export type ReadInboxInput = z.infer<typeof ReadInboxInputSchema>
export const ReadConfigInputSchema = z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
})
export const TeamTaskUpdateInputSchema = z.object({
team_name: z.string(),
task_id: z.string(),
status: TeamTaskStatusSchema.optional(),
owner: z.string().optional(),
subject: z.string().optional(),
description: z.string().optional(),
active_form: z.string().optional(),
add_blocks: z.array(z.string()).optional(),
add_blocked_by: z.array(z.string()).optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
export type ReadConfigInput = z.infer<typeof ReadConfigInputSchema>
export const TeamSpawnInputSchema = z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
name: z.string().min(1),
category: z.string().min(1),
prompt: z.string().min(1),
})
export const TeamTaskListInputSchema = z.object({
team_name: z.string(),
export type TeamSpawnInput = z.infer<typeof TeamSpawnInputSchema>
export const ForceKillTeammateInputSchema = z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
teammate_name: z.string().min(1),
})
export const TeamTaskGetInputSchema = z.object({
team_name: z.string(),
task_id: z.string(),
export type ForceKillTeammateInput = z.infer<typeof ForceKillTeammateInputSchema>
export const ProcessShutdownApprovedInputSchema = z.object({
team_name: z.string().regex(/^[A-Za-z0-9_-]+$/, "Team name must contain only letters, numbers, hyphens, and underscores").max(64),
teammate_name: z.string().min(1),
})
export const TeamForceKillInputSchema = z.object({
team_name: z.string(),
agent_name: z.string(),
})
export const TeamProcessShutdownInputSchema = z.object({
team_name: z.string(),
agent_name: z.string(),
})
export interface TeamToolContext {
sessionID: string
messageID: string
abort: AbortSignal
agent?: string
}
export function isTeammateMember(member: TeamMember): member is TeamTeammateMember {
return member.agentType !== "team-lead"
}
export type ProcessShutdownApprovedInput = z.infer<typeof ProcessShutdownApprovedInputSchema>