返回 DeepSeek-Reasonix
receipt_citation.go
根目录 / internal / evidence / receipt_citation.go
1 package evidence
2
3 import (
4 "strings"
5 )
6
7 // LookupReceipt returns a copy of a receipt by host-issued ID. Arguments are
8 // dropped: a citation resolves a fact, it never reopens the original call.
9 func (l *Ledger) LookupReceipt(id string) (Receipt, bool) {
10 id = strings.TrimSpace(id)
11 if l == nil || id == "" {
12 return Receipt{}, false
13 }
14 l.mu.Lock()
15 defer l.mu.Unlock()
16 for _, r := range l.receipts {
17 if r.ID == id {
18 r.Args = nil
19 return r, true
20 }
21 }
22 return Receipt{}, false
23 }
24
25 // ReceiptRef returns a bounded model-safe receipt projection.
26 func (l *Ledger) ReceiptRef(id string) (ReceiptRef, bool) {
27 r, ok := l.LookupReceipt(id)
28 if !ok {
29 return ReceiptRef{}, false
30 }
31 return r.Ref(), true
32 }
33
34 // CitableReceipts returns up to limit successful receipts from this turn, most
35 // recent first, so a rejection can list what the model may cite instead of
36 // asking it to guess a command string.
37 func (l *Ledger) CitableReceipts(limit int) []ReceiptRef {
38 if l == nil || limit <= 0 {
39 return nil
40 }
41 l.mu.Lock()
42 defer l.mu.Unlock()
43 out := make([]ReceiptRef, 0, limit)
44 for i := len(l.receipts) - 1; i >= 0 && len(out) < limit; i-- {
45 r := l.receipts[i]
46 if !r.Success || r.ToolName == "complete_step" || r.ToolName == "todo_write" {
47 continue
48 }
49 r.Args = nil
50 out = append(out, r.Ref())
51 }
52 return out
53 }
54
54 lines GO