schedule

package
v0.81.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 2, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package schedule provides schedule-related AI agent utilities.

Package schedule provides schedule-related AI agent utilities.

Package schedule provides schedule-related AI agent utilities.

Package schedule provides schedule-related AI agent utilities.

Package schedule provides schedule-related AI agent utilities.

Package schedule provides timezone-aware validation for schedule creation. This module handles Daylight Saving Time (DST) edge cases including:

  • Invalid local times (spring forward gap)
  • Ambiguous local times (fall back duplicate)

Index

Constants

View Source
const (
	ErrCodeMissingStartTime = "MISSING_START_TIME"
	ErrCodePastTime         = "PAST_TIME"
	ErrCodeTimeTooFar       = "TIME_TOO_FAR"
	ErrCodeEndBeforeStart   = "END_BEFORE_START"
	ErrCodeTimeConflict     = "TIME_CONFLICT"
)

PrecheckError codes for schedule validation errors.

View Source
const (
	WarnCodeBufferConflict      = "BUFFER_CONFLICT"
	WarnCodeLongDuration        = "LONG_DURATION"
	WarnCodeOutsideWorkHours    = "OUTSIDE_WORK_HOURS"
	WarnCodeLongTitle           = "LONG_TITLE"
	WarnCodeWeekendSchedule     = "WEEKEND_SCHEDULE"
	WarnCodeConflictCheckFailed = "CONFLICT_CHECK_FAILED"
)

PrecheckWarning codes for schedule validation warnings.

View Source
const (
	BufferMinutes      = 15  // Minimum gap between schedules (minutes)
	MaxDurationMinutes = 480 // Maximum schedule duration (8 hours)
	WorkStartHour      = 8   // Work hours start
	WorkEndHour        = 22  // Work hours end
	MaxTitleLength     = 100 // Maximum title length
	MaxFutureYears     = 1   // Maximum years in advance for scheduling
)

Business rule constants.

View Source
const (
	// Validation constants.
	MaxInputLength = 500 // characters
)

Variables

View Source
var ErrTimeServiceNotConfigured = errors.New("time service not configured")

ErrTimeServiceNotConfigured is returned when time service is not available.

Functions

func FormatConfirmationMessage

func FormatConfirmationMessage(schedule *ScheduleRequest, confidence float64) string

FormatConfirmationMessage formats the confirmation message for display.

func MarshalReminders

func MarshalReminders(reminders []*v1pb.Reminder) (string, error)

MarshalReminders converts protobuf reminders to JSON string.

func UnmarshalReminders

func UnmarshalReminders(data string) ([]*v1pb.Reminder, error)

UnmarshalReminders converts JSON to protobuf reminders.

Types

type Action

type Action struct {
	Data  any    `json:"data,omitempty"`
	Type  string `json:"type"`
	Label string `json:"label"`
}

Action represents a user action button.

type AgentResponse

type AgentResponse struct {
	Type    ResponseType   `json:"type"`
	Message string         `json:"message"`
	Data    map[string]any `json:"data,omitempty"`
	Actions []Action       `json:"actions,omitempty"`
}

AgentResponse represents the response from the fast create handler.

type AlternativeSlot

type AlternativeSlot struct {
	StartTime time.Time `json:"start_time"`
	EndTime   time.Time `json:"end_time"`
	Label     string    `json:"label"` // "同日稍后", "明天同一时间"
}

AlternativeSlot represents an available time slot.

type BatchCreateRequest

type BatchCreateRequest struct {
	StartTime  time.Time       `json:"start_time"`
	Recurrence *RecurrenceRule `json:"recurrence"`
	EndDate    *time.Time      `json:"end_date,omitempty"`
	Title      string          `json:"title"`
	Location   string          `json:"location,omitempty"`
	Duration   int             `json:"duration"`
	Count      int             `json:"count,omitempty"`
}

BatchCreateRequest represents a batch schedule creation request.

type BatchCreateResult

type BatchCreateResult struct {
	Request        *BatchCreateRequest `json:"request,omitempty"`
	Preview        []*ScheduleRequest  `json:"preview,omitempty"`
	MissingFields  []string            `json:"missing_fields,omitempty"`
	TotalCount     int                 `json:"total_count"`
	Confidence     float64             `json:"confidence"`
	CanBatchCreate bool                `json:"can_batch_create"`
}

BatchCreateResult represents the result of batch schedule parsing.

type BatchScheduleParser

type BatchScheduleParser struct {
	// contains filtered or unexported fields
}

BatchScheduleParser parses user input for batch schedule creation.

func NewBatchScheduleParser

func NewBatchScheduleParser(timeSvc *aitime.Service) *BatchScheduleParser

NewBatchScheduleParser creates a new BatchScheduleParser.

func (*BatchScheduleParser) Parse

Parse parses user input for batch schedule creation.

type BatchScheduleService

type BatchScheduleService struct {
	// contains filtered or unexported fields
}

BatchScheduleService provides batch schedule operations.

func NewBatchScheduleService

func NewBatchScheduleService(timeSvc *aitime.Service) *BatchScheduleService

NewBatchScheduleService creates a new BatchScheduleService.

func (*BatchScheduleService) GenerateSchedules

func (s *BatchScheduleService) GenerateSchedules(req *BatchCreateRequest) ([]*ScheduleRequest, error)

GenerateSchedules generates the actual schedule objects from a validated request.

func (*BatchScheduleService) ParseAndPreview

func (s *BatchScheduleService) ParseAndPreview(ctx context.Context, input string) (*BatchCreateResult, error)

ParseAndPreview parses input and returns a preview of schedules.

func (*BatchScheduleService) ValidateRequest

func (s *BatchScheduleService) ValidateRequest(req *BatchCreateRequest) error

ValidateRequest validates a batch create request.

type ClassifyResult

type ClassifyResult struct {
	Intent     ScheduleIntent
	Confidence float32
	UsedLLM    bool // Whether LLM was used for classification
}

ClassifyResult holds the classification result.

type DSTTransition

type DSTTransition struct {
	Time        time.Time
	ZoneName    string
	ZoneNameNew string
	Type        DSTTransitionType
	FromOffset  int
	ToOffset    int
}

DSTTransition represents a DST transition event.

func (*DSTTransition) String

func (t *DSTTransition) String() string

String returns a human-readable description of the transition.

type DSTTransitionType

type DSTTransitionType int

DSTTransitionType represents the type of DST transition.

const (
	DSTTransitionTypeUnknown   DSTTransitionType = iota
	DSTTransitionSpringForward                   // Clocks move forward (gap in time)
	DSTTransitionFallBack                        // Clocks move back (repeated hour)
)

type FastCreateHandler

type FastCreateHandler struct {
	// contains filtered or unexported fields
}

FastCreateHandler handles fast schedule creation.

func NewFastCreateHandler

func NewFastCreateHandler(parser *FastCreateParser) *FastCreateHandler

NewFastCreateHandler creates a new FastCreateHandler.

func (*FastCreateHandler) Handle

func (h *FastCreateHandler) Handle(ctx context.Context, userID int32, input string) (*AgentResponse, error)

Handle processes user input for fast schedule creation.

func (*FastCreateHandler) TryFastCreate

func (h *FastCreateHandler) TryFastCreate(ctx context.Context, userID int32, input string) (*FastCreateResult, bool)

TryFastCreate attempts fast creation and returns whether it succeeded. This can be used by the scheduler agent to decide whether to use fast path.

type FastCreateParser

type FastCreateParser struct {
	// contains filtered or unexported fields
}

FastCreateParser parses user input for fast schedule creation.

func NewFastCreateParser

func NewFastCreateParser(timeSvc *aitime.Service, habitApplier *habit.HabitApplier) *FastCreateParser

NewFastCreateParser creates a new FastCreateParser.

func (*FastCreateParser) Parse

func (p *FastCreateParser) Parse(ctx context.Context, userID int32, input string) (*FastCreateResult, error)

Parse parses user input and returns a FastCreateResult.

type FastCreateResult

type FastCreateResult struct {
	Schedule      *ScheduleRequest
	MissingFields []string
	Confidence    float64
	CanFastCreate bool
}

FastCreateResult represents the result of fast create parsing.

type ParseResult

type ParseResult struct {
	Recurrence  *RecurrenceRule
	Title       string
	Description string
	Location    string
	Timezone    string
	Reminders   []*v1pb.Reminder
	StartTs     int64
	EndTs       int64
	AllDay      bool
}

ParseResult represents the parsed schedule information.

func (*ParseResult) ToSchedule

func (r *ParseResult) ToSchedule() *v1pb.Schedule

ToSchedule converts ParseResult to v1pb.Schedule.

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser handles natural language parsing for schedules.

func NewParser

func NewParser(llmService ai.LLMService, timezone string) (*Parser, error)

NewParser creates a new schedule parser.

func (*Parser) Parse

func (p *Parser) Parse(ctx context.Context, text string) (*ParseResult, error)

Parse parses natural language text and returns schedule information.

type PrecheckError

type PrecheckError struct {
	Code    string `json:"code"`            // Error code like "TIME_CONFLICT"
	Message string `json:"message"`         // Human-readable message
	Field   string `json:"field,omitempty"` // Field that caused the error
}

PrecheckError represents a validation error.

type PrecheckRequest

type PrecheckRequest struct {
	StartTime time.Time `json:"start_time"`
	EndTime   time.Time `json:"end_time"`
	Title     string    `json:"title"`
	Location  string    `json:"location,omitempty"`
	Duration  int       `json:"duration"`
}

PrecheckRequest represents a schedule precheck request.

type PrecheckResponse

type PrecheckResponse struct {
	Errors      []PrecheckError      `json:"errors,omitempty"`
	Warnings    []PrecheckWarning    `json:"warnings,omitempty"`
	Suggestions []PrecheckSuggestion `json:"suggestions,omitempty"`
	Valid       bool                 `json:"valid"`
}

PrecheckResponse represents a schedule precheck result.

type PrecheckService

type PrecheckService struct {
	// contains filtered or unexported fields
}

PrecheckService provides schedule precheck functionality.

func NewPrecheckService

func NewPrecheckService(scheduleStore ScheduleStore) *PrecheckService

NewPrecheckService creates a new PrecheckService.

func (*PrecheckService) Precheck

func (s *PrecheckService) Precheck(ctx context.Context, userID int32, req *PrecheckRequest) *PrecheckResponse

Precheck validates a schedule creation request before actual creation.

type PrecheckSuggestion

type PrecheckSuggestion struct {
	Value any    `json:"value"`
	Type  string `json:"type"`
}

PrecheckSuggestion represents a suggestion for schedule correction.

type PrecheckWarning

type PrecheckWarning struct {
	Code    string `json:"code"`    // Warning code like "OUTSIDE_WORK_HOURS"
	Message string `json:"message"` // Human-readable message
}

PrecheckWarning represents a validation warning.

type RecurrenceIterator

type RecurrenceIterator struct {
	// contains filtered or unexported fields
}

RecurrenceIterator provides lazy-loading iteration over recurrence instances. This is more memory-efficient than generating all instances upfront.

func (*RecurrenceIterator) CountInRange

func (it *RecurrenceIterator) CountInRange(startTs, endTs int64) int

CountInRange returns the number of instances in the given range without materializing all of them.

func (*RecurrenceIterator) GetUntil

func (it *RecurrenceIterator) GetUntil(endTs int64) []int64

GetUntil returns all instances up to the given end timestamp. Results are cached for efficient repeated calls with increasing ranges.

func (*RecurrenceIterator) Next

func (it *RecurrenceIterator) Next() int64

Next returns the next instance in the sequence, or 0 if exhausted.

func (*RecurrenceIterator) Reset

func (it *RecurrenceIterator) Reset()

Reset resets the iterator to the beginning.

type RecurrenceRule

type RecurrenceRule struct {
	Type     RecurrenceType `json:"type"`
	Weekdays []int          `json:"weekdays"`
	Interval int            `json:"interval"`
	MonthDay int            `json:"month_day"`
}

RecurrenceRule represents a simplified recurrence rule. We use a custom JSON format instead of full RFC 5545 RRULE for simplicity.

func ParseRecurrence

func ParseRecurrence(jsonStr string) (*RecurrenceRule, error)

ParseRecurrence is an alias for ParseRecurrenceRuleFromJSON.

func ParseRecurrenceRule

func ParseRecurrenceRule(text string) (*RecurrenceRule, error)

ParseRecurrenceRule parses a natural language recurrence pattern. Examples:

  • "每天" → {Type: RecurrenceTypeDaily, Interval: 1}
  • "每3天" → {Type: RecurrenceTypeDaily, Interval: 3}
  • "每周一" → {Type: RecurrenceTypeWeekly, Weekdays: [1]}
  • "每周" → {Type: RecurrenceTypeWeekly, Interval: 1}
  • "每两周" → {Type: RecurrenceTypeDaily, Interval: 14}
  • "每月15号" → {Type: RecurrenceTypeMonthly, MonthDay: 15}

func ParseRecurrenceRuleFromJSON

func ParseRecurrenceRuleFromJSON(jsonStr string) (*RecurrenceRule, error)

ParseRecurrenceRuleFromJSON parses a recurrence rule from JSON string.

func (*RecurrenceRule) GenerateInstances

func (r *RecurrenceRule) GenerateInstances(startTs int64, endTs int64) []int64

GenerateInstances generates all occurrence timestamps within a time range. startTs: The start timestamp of the first occurrence (Unix timestamp, always UTC) endTs: The end timestamp for generating instances (0 means no limit) Returns a slice of timestamps for each occurrence (Unix timestamps).

Note on timezone handling: - Unix timestamps are always UTC - The startTs is assumed to be pre-converted to UTC by the caller based on user's timezone - For example, if user in Asia/Shanghai (UTC+8) schedules 9:00 AM, startTs is 01:00 UTC - Instances are generated using UTC arithmetic (adding 24h for daily, 7 days for weekly, etc.) - This ensures consistent behavior across timezones and simplifies the implementation

For proper timezone-aware scheduling (e.g., "9:00 AM local time" regardless of DST changes), the caller should handle timezone conversion before/after calling this method.

func (*RecurrenceRule) Iterator

func (r *RecurrenceRule) Iterator(startTs int64) *RecurrenceIterator

Iterator creates a new iterator for this recurrence rule.

func (*RecurrenceRule) ToJSON

func (r *RecurrenceRule) ToJSON() (string, error)

ToJSON converts the recurrence rule to JSON string.

func (*RecurrenceRule) Validate

func (r *RecurrenceRule) Validate() error

Validate checks if the recurrence rule is valid.

type RecurrenceType

type RecurrenceType string

RecurrenceType represents the type of recurrence pattern.

const (
	// RecurrenceTypeDaily represents daily recurrence.
	RecurrenceTypeDaily RecurrenceType = "daily"
	// RecurrenceTypeWeekly represents weekly recurrence.
	RecurrenceTypeWeekly RecurrenceType = "weekly"
	// RecurrenceTypeMonthly represents monthly recurrence.
	RecurrenceTypeMonthly RecurrenceType = "monthly"
)

func (RecurrenceType) IsValid

func (rt RecurrenceType) IsValid() bool

IsValid checks if the recurrence type is valid.

func (RecurrenceType) String

func (rt RecurrenceType) String() string

String returns the string representation of RecurrenceType.

type ResponseType

type ResponseType string

ResponseType represents the type of agent response.

const (
	ResponseTypeFastCreate ResponseType = "fast_create"
	ResponseTypeFallback   ResponseType = "fallback"
	ResponseTypeError      ResponseType = "error"
)

type ScheduleIntent

type ScheduleIntent int

ScheduleIntent represents the type of schedule task intent.

const (
	// IntentUnknown is for unrecognized intents.
	IntentUnknown ScheduleIntent = iota
	// IntentSimpleCreate is for simple single schedule creation.
	IntentSimpleCreate
	// IntentSimpleQuery is for simple schedule queries.
	IntentSimpleQuery
	// IntentSimpleUpdate is for simple schedule modifications.
	IntentSimpleUpdate
	// IntentBatchCreate is for batch schedule creation (e.g., "每天", "每周").
	IntentBatchCreate
)

func (ScheduleIntent) String

func (i ScheduleIntent) String() string

String returns the string representation of ScheduleIntent.

type ScheduleIntentClassifier

type ScheduleIntentClassifier struct {
	// contains filtered or unexported fields
}

ScheduleIntentClassifier classifies user input into schedule task intents. It uses rule-based matching first (0ms) and falls back to RouterService (~400ms).

func NewScheduleIntentClassifier

func NewScheduleIntentClassifier(routerService router.RouterService) *ScheduleIntentClassifier

NewScheduleIntentClassifier creates a new ScheduleIntentClassifier.

func (*ScheduleIntentClassifier) Classify

Classify determines the schedule intent of the user input. Returns the intent, confidence score (0-1), and whether LLM was used.

func (*ScheduleIntentClassifier) ClassifyAndRoute

func (c *ScheduleIntentClassifier) ClassifyAndRoute(ctx context.Context, input string) (ScheduleIntent, bool, float32)

ClassifyAndRoute is a convenience method that classifies and returns execution mode.

func (*ScheduleIntentClassifier) ShouldUsePlanExecute

func (c *ScheduleIntentClassifier) ShouldUsePlanExecute(intent ScheduleIntent) bool

ShouldUsePlanExecute returns true if the intent should use Plan-Execute mode.

type ScheduleRequest

type ScheduleRequest struct {
	StartTime       time.Time `json:"start_time"`
	EndTime         time.Time `json:"end_time"`
	Title           string    `json:"title"`
	Location        string    `json:"location,omitempty"`
	Description     string    `json:"description,omitempty"`
	Duration        int       `json:"duration"`
	ReminderMinutes int       `json:"reminder_minutes,omitempty"`
}

ScheduleRequest represents a schedule creation request.

type ScheduleStore

type ScheduleStore interface {
	ListSchedules(ctx context.Context, find *store.FindSchedule) ([]*store.Schedule, error)
}

ScheduleStore defines the interface for schedule storage operations.

type TimeHardener

type TimeHardener struct {
	// contains filtered or unexported fields
}

TimeHardener provides time parsing hardening for LLM outputs. It preprocesses various time formats before delegating to TimeService.

func NewTimeHardener

func NewTimeHardener(timeService aitime.TimeService, timezone *time.Location) *TimeHardener

NewTimeHardener creates a new TimeHardener instance.

func (*TimeHardener) HardenTime

func (h *TimeHardener) HardenTime(ctx context.Context, input string) (time.Time, error)

3. Validate the result for reasonableness.

func (*TimeHardener) HardenTimeWithDefaults

func (h *TimeHardener) HardenTimeWithDefaults(ctx context.Context, input string, defaultHour int) (time.Time, error)

HardenTimeWithDefaults parses time with default values for missing components. defaultHour is used when time has a period but no specific hour.

func (*TimeHardener) ValidateTimeRange

func (h *TimeHardener) ValidateTimeRange(start, end time.Time) error

ValidateTimeRange validates a time range.

func (*TimeHardener) WithTimezone

func (h *TimeHardener) WithTimezone(tz *time.Location) *TimeHardener

WithTimezone returns a new TimeHardener with the specified timezone.

type TimeRangeValidationResult

type TimeRangeValidationResult struct {
	StartValidTime time.Time
	EndValidTime   time.Time
	Warnings       []string
	IsValid        bool
}

TimeRangeValidationResult contains the result of validating a time range.

type TimezoneValidator

type TimezoneValidator struct {
	// contains filtered or unexported fields
}

TimezoneValidator handles DST edge cases for a specific timezone.

func NewTimezoneValidator

func NewTimezoneValidator(tz string) *TimezoneValidator

NewTimezoneValidator creates a new validator for the given timezone.

func (*TimezoneValidator) GetDSTTransitionInfo

func (v *TimezoneValidator) GetDSTTransitionInfo(startTs, endTs int64) []*DSTTransition

GetDSTTransitionInfo returns information about upcoming DST transitions for the given date range.

func (*TimezoneValidator) GetLocation

func (v *TimezoneValidator) GetLocation() *time.Location

GetLocation returns the validator's timezone location.

func (*TimezoneValidator) GetTimezone

func (v *TimezoneValidator) GetTimezone() string

GetTimezone returns the validator's timezone name.

func (*TimezoneValidator) ValidateLocalTime

func (v *TimezoneValidator) ValidateLocalTime(year int, month time.Month, day, hour, min int) *ValidationResult

ValidateLocalTime validates and normalizes a local time, handling DST edge cases.

Parameters:

  • year, month, day, hour, min: The local time components to validate

Returns:

  • ValidationResult: Contains the validated time and any warnings

DST Edge Cases Handled:

  1. Spring Forward (Invalid Time): When clocks "spring forward", times in the gap don't exist. Example: In America/New_York on 2024-03-10, time jumps from 1:59:59 AM to 3:00:00 AM. Times like 2:30 AM don't exist - they're adjusted forward to 3:00 AM.

  2. Fall Back (Ambiguous Time): When clocks "fall back", the same hour occurs twice. Example: In America/New_York on 2024-11-03, 1:30 AM occurs twice (before and after the switch). The first occurrence (Eastern Daylight Time) is used by default.

func (*TimezoneValidator) ValidateTimeRange

func (v *TimezoneValidator) ValidateTimeRange(startTs, endTs int64) *TimeRangeValidationResult

ValidateTimeRange validates both start and end times for a schedule.

func (*TimezoneValidator) ValidateTimestamp

func (v *TimezoneValidator) ValidateTimestamp(ts int64) *ValidationResult

ValidateTimestamp validates a Unix timestamp, converting it to the local timezone and checking for any issues.

type ValidationResult

type ValidationResult struct {
	ValidTime time.Time // The validated time (adjusted if necessary)
	Warnings  []string  // Any warnings about time adjustments
	IsValid   bool      // Whether the validation passed
}

ValidationResult contains the result of validating a local time.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL