返回 DeepSeek-Reasonix
goal.go
根目录 / internal / tool / goal.go
1 package tool
2
3 import "context"
4
5 // GoalReport is the model's structured per-turn goal disposition recorded via
6 // the update_goal tool. It only carries candidate state: the host commits the
7 // real FSM transition after the turn ends and Delivery readiness and budget
8 // checks pass.
9 type GoalReport struct {
10 // Status is one of "continue", "complete", or "blocked".
11 Status string
12 // Reason is the short explanation (required for continue and blocked).
13 Reason string
14 // NextAction is an optional concrete next step (recommended for continue).
15 NextAction string
16 }
17
18 // GoalTurnRecorder records the model's update_goal report for the active goal
19 // turn. The host controller implements it; it is absent in ordinary chat, where
20 // the update_goal tool must fail closed without changing any state.
21 type GoalTurnRecorder interface {
22 // RecordGoalReport validates the report against the turn's goal lifecycle
23 // (scope/epoch binding, idempotency, terminal-state conflicts) and returns
24 // the tool-result text shown to the model.
25 RecordGoalReport(r GoalReport) (string, error)
26 }
27
28 type goalTurnRecorderKey struct{}
29
30 // WithGoalTurnRecorder stamps ctx with the per-turn goal recorder so the
31 // update_goal tool can reach it from inside the run loop.
32 func WithGoalTurnRecorder(ctx context.Context, r GoalTurnRecorder) context.Context {
33 if r == nil {
34 return ctx
35 }
36 return context.WithValue(ctx, goalTurnRecorderKey{}, r)
37 }
38
39 // GoalTurnRecorderFromContext returns the active goal turn's recorder, if any.
40 func GoalTurnRecorderFromContext(ctx context.Context) (GoalTurnRecorder, bool) {
41 if ctx == nil {
42 return nil, false
43 }
44 r, ok := ctx.Value(goalTurnRecorderKey{}).(GoalTurnRecorder)
45 return r, ok && r != nil
46 }
47
47 lines GO