refactor(agent): split AgentForm into BaseAgentForm and specific types

Improve type safety by separating AgentForm into BaseAgentForm for shared fields and specific types for add/update operations. This better reflects the actual usage patterns in the API client and modal components.
This commit is contained in:
icarus 2025-09-18 18:21:52 +08:00
parent 21ce139df0
commit 259f2157f6
3 changed files with 20 additions and 15 deletions

View File

@ -1,6 +1,6 @@
import { formatAgentServerError } from '@renderer/utils'
import {
AgentForm,
AddAgentForm,
AgentServerErrorSchema,
CreateAgentRequest,
CreateAgentResponse,
@ -9,6 +9,7 @@ import {
GetAgentResponseSchema,
type ListAgentsResponse,
ListAgentsResponseSchema,
UpdateAgentForm,
UpdateAgentRequest,
UpdateAgentResponse,
UpdateAgentResponseSchema
@ -71,12 +72,10 @@ export class AgentApiClient {
}
}
public async createAgent(agent: AgentForm): Promise<CreateAgentResponse> {
public async createAgent(agent: AddAgentForm): Promise<CreateAgentResponse> {
const url = this.agentPaths.base
try {
const payload = {
...agent
} satisfies CreateAgentRequest
const payload = agent satisfies CreateAgentRequest
const response = await this.axios.post(url, payload)
const data = CreateAgentResponseSchema.parse(response.data)
return data
@ -105,12 +104,10 @@ export class AgentApiClient {
}
}
public async updateAgent(id: string, agent: Partial<AgentForm>): Promise<UpdateAgentResponse> {
public async updateAgent(id: string, agent: UpdateAgentForm): Promise<UpdateAgentResponse> {
const url = this.agentPaths.withId(id)
try {
const payload = {
...agent
} satisfies UpdateAgentRequest
const payload = agent satisfies UpdateAgentRequest
const response = await this.axios.patch(url, payload)
const data = UpdateAgentResponseSchema.parse(response.data)
return data

View File

@ -21,7 +21,7 @@ import ClaudeIcon from '@renderer/assets/images/models/claude.png'
import { useAgents } from '@renderer/hooks/agents/useAgents'
import { useTimer } from '@renderer/hooks/useTimer'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { AgentEntity, AgentForm, isAgentType } from '@renderer/types'
import { AgentEntity, AgentForm, BaseAgentForm, isAgentType } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { ChangeEvent, FormEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -44,7 +44,7 @@ interface AgentTypeOption extends Option {
type ModelOption = Option
const buildAgentForm = (existing?: AgentEntity): AgentForm => ({
const buildAgentForm = (existing?: AgentEntity): BaseAgentForm => ({
type: existing?.type ?? 'claude-code',
name: existing?.name ?? 'Claude Code',
description: existing?.description,
@ -162,7 +162,7 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
}
setForm((prev) => ({
...prev,
type: e.target.value as AgentForm['type'],
type: e.target.value as AgentType,
name: newName
}))
},
@ -229,7 +229,7 @@ export const AgentModal: React.FC<Props> = ({ agent, trigger, isOpen: _isOpen, o
return
}
let resultAgent: AgentEntity
let resultAgent: BaseAgentForm
if (isEditing(agent)) {
if (!agent) {
throw new Error('Agent is required for editing mode')

View File

@ -118,8 +118,8 @@ export interface SessionMessageContent {
// - mcps: Optional array of MCP (Model Control Protocol) tool IDs
// - allowed_tools: Optional array of permitted tool IDs
// - configuration: Optional agent settings (temperature, top_p, etc.)
export type AgentForm = {
type: AgentType
export interface BaseAgentForm {
// These fileds should be editable by user.
name: string
description?: string
instructions?: string
@ -127,6 +127,14 @@ export type AgentForm = {
accessible_paths: string[]
}
export interface AddAgentForm extends BaseAgentForm {
type: AgentType
}
export type UpdateAgentForm = Partial<BaseAgentForm>
export type AgentForm = AddAgentForm | UpdateAgentForm
// ------------------------
// API Data Transfer Object
// ------------------------