From 2b8b5375235c7cae0a3cd2ce553fe206db8d2e5c Mon Sep 17 00:00:00 2001 From: Acbox Date: Mon, 2 Feb 2026 22:48:06 +0800 Subject: [PATCH] feat: make max-calls of schedule nullable --- agent/src/modules/chat.ts | 2 +- agent/src/tools/schedule.ts | 7 +----- agent/src/types.ts | 2 +- internal/schedule/service.go | 12 ++++++---- internal/schedule/types.go | 39 ++++++++++++++++++++++++++++++--- packages/shared/src/schedule.ts | 2 +- 6 files changed, 48 insertions(+), 16 deletions(-) diff --git a/agent/src/modules/chat.ts b/agent/src/modules/chat.ts index 67e53d41..151b4e5d 100644 --- a/agent/src/modules/chat.ts +++ b/agent/src/modules/chat.ts @@ -41,7 +41,7 @@ const ScheduleBody = z.object({ name: z.string().min(1, 'Schedule name is required'), description: z.string().min(1, 'Schedule description is required'), pattern: z.string().min(1, 'Schedule pattern is required'), - maxCalls: z.number().optional(), + maxCalls: z.number().nullable().optional(), command: z.string().min(1, 'Schedule command is required'), }), }).and(ChatBody) diff --git a/agent/src/tools/schedule.ts b/agent/src/tools/schedule.ts index 0d740b90..e3b1ad66 100644 --- a/agent/src/tools/schedule.ts +++ b/agent/src/tools/schedule.ts @@ -7,17 +7,12 @@ export type ScheduleToolParams = { } const ScheduleSchema = z.object({ - id: z.string(), name: z.string(), description: z.string(), pattern: z.string(), max_calls: z.number().nullable().optional(), - current_calls: z.number().optional(), - created_at: z.string().optional(), - updated_at: z.string().optional(), enabled: z.boolean(), command: z.string(), - user_id: z.string().optional(), }) export const getScheduleTools = ({ fetch }: ScheduleToolParams) => { @@ -47,7 +42,7 @@ export const getScheduleTools = ({ fetch }: ScheduleToolParams) => { name: z.string(), description: z.string(), pattern: z.string(), - max_calls: z.number().optional(), + max_calls: z.number().nullable().optional().default(null).describe('Max calls (optional, empty for unlimited)'), enabled: z.boolean().optional(), command: z.string(), }), diff --git a/agent/src/types.ts b/agent/src/types.ts index 28d068ad..9421cf65 100644 --- a/agent/src/types.ts +++ b/agent/src/types.ts @@ -16,7 +16,7 @@ export interface Schedule { name: string description: string pattern: string - maxCalls?: number + maxCalls?: number | null command: string } diff --git a/internal/schedule/service.go b/internal/schedule/service.go index b7f92eb3..88e796b5 100644 --- a/internal/schedule/service.go +++ b/internal/schedule/service.go @@ -77,8 +77,8 @@ func (s *Service) Create(ctx context.Context, userID string, req CreateRequest) return Schedule{}, err } maxCalls := pgtype.Int4{Valid: false} - if req.MaxCalls != nil { - maxCalls = pgtype.Int4{Int32: int32(*req.MaxCalls), Valid: true} + if req.MaxCalls.Set && req.MaxCalls.Value != nil { + maxCalls = pgtype.Int4{Int32: int32(*req.MaxCalls.Value), Valid: true} } enabled := true if req.Enabled != nil { @@ -164,8 +164,12 @@ func (s *Service) Update(ctx context.Context, id string, req UpdateRequest) (Sch command = *req.Command } maxCalls := existing.MaxCalls - if req.MaxCalls != nil { - maxCalls = pgtype.Int4{Int32: int32(*req.MaxCalls), Valid: true} + if req.MaxCalls.Set { + if req.MaxCalls.Value == nil { + maxCalls = pgtype.Int4{Valid: false} + } else { + maxCalls = pgtype.Int4{Int32: int32(*req.MaxCalls.Value), Valid: true} + } } enabled := existing.Enabled if req.Enabled != nil { diff --git a/internal/schedule/types.go b/internal/schedule/types.go index 29a04d8a..ccb88341 100644 --- a/internal/schedule/types.go +++ b/internal/schedule/types.go @@ -1,6 +1,9 @@ package schedule -import "time" +import ( + "encoding/json" + "time" +) type Schedule struct { ID string `json:"id"` @@ -16,11 +19,41 @@ type Schedule struct { UserID string `json:"user_id"` } +type NullableInt struct { + Value *int + Set bool +} + +func (n NullableInt) IsZero() bool { + return !n.Set +} + +func (n NullableInt) MarshalJSON() ([]byte, error) { + if !n.Set || n.Value == nil { + return []byte("null"), nil + } + return json.Marshal(*n.Value) +} + +func (n *NullableInt) UnmarshalJSON(data []byte) error { + n.Set = true + if string(data) == "null" { + n.Value = nil + return nil + } + var value int + if err := json.Unmarshal(data, &value); err != nil { + return err + } + n.Value = &value + return nil +} + type CreateRequest struct { Name string `json:"name"` Description string `json:"description"` Pattern string `json:"pattern"` - MaxCalls *int `json:"max_calls,omitempty"` + MaxCalls NullableInt `json:"max_calls,omitempty"` Command string `json:"command"` Enabled *bool `json:"enabled,omitempty"` } @@ -29,7 +62,7 @@ type UpdateRequest struct { Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` Pattern *string `json:"pattern,omitempty"` - MaxCalls *int `json:"max_calls,omitempty"` + MaxCalls NullableInt `json:"max_calls,omitempty"` Command *string `json:"command,omitempty"` Enabled *bool `json:"enabled,omitempty"` } diff --git a/packages/shared/src/schedule.ts b/packages/shared/src/schedule.ts index bec96523..e08ca076 100644 --- a/packages/shared/src/schedule.ts +++ b/packages/shared/src/schedule.ts @@ -4,5 +4,5 @@ export interface Schedule { name: string description: string command: string - maxCalls?: number + maxCalls?: number | null } \ No newline at end of file