/ internal / agent / delta.go
delta.go
 1  package agent
 2  
 3  import (
 4  	"fmt"
 5  	"time"
 6  )
 7  
 8  // DeltaKind identifies the type of mid-run state change.
 9  type DeltaKind string
10  
11  const (
12  	DeltaDateRollover   DeltaKind = "date_rollover"
13  	DeltaToolCapability DeltaKind = "tool_capability" // v1.1
14  )
15  
16  // Delta represents a mid-run state change to inject into the conversation.
17  type Delta struct {
18  	Kind    DeltaKind
19  	Message string
20  }
21  
22  // DeltaProvider is polled at each loop iteration boundary. Implementations
23  // return pending deltas since last call. Only inject a delta when it can
24  // change the model's very next decision.
25  // Implementations are called from a single goroutine (the agent loop) and
26  // do not need to be safe for concurrent use.
27  type DeltaProvider interface {
28  	Check() []Delta
29  }
30  
31  // TemporalDelta detects calendar day rollover during long-running sessions.
32  type TemporalDelta struct {
33  	lastYear    int
34  	lastYearDay int
35  }
36  
37  // NewTemporalDelta creates a TemporalDelta anchored to the current date.
38  func NewTemporalDelta() *TemporalDelta {
39  	now := time.Now()
40  	return &TemporalDelta{
41  		lastYear:    now.Year(),
42  		lastYearDay: now.YearDay(),
43  	}
44  }
45  
46  func (t *TemporalDelta) Check() []Delta {
47  	now := time.Now()
48  	if now.Year() == t.lastYear && now.YearDay() == t.lastYearDay {
49  		return nil
50  	}
51  	t.lastYear = now.Year()
52  	t.lastYearDay = now.YearDay()
53  	return []Delta{{
54  		Kind:    DeltaDateRollover,
55  		Message: fmt.Sprintf("The date has changed to %s. References to \"today\", \"tomorrow\", and relative dates should now be interpreted from this new date.", now.Format("2006-01-02")),
56  	}}
57  }