返回 DeepSeek-Reasonix
snapshot_copy.go
根目录 / internal / session / snapshot_copy.go
1 package session
2
3 import (
4 "reflect"
5
6 "reasonix/internal/provider"
7 )
8
9 func detachMessages(messages []provider.Message) []provider.Message {
10 if messages == nil {
11 return []provider.Message{}
12 }
13 return detachValue(reflect.ValueOf(messages)).Interface().([]provider.Message)
14 }
15
16 // Provider DTOs contain nested slices, pointers, maps and raw JSON. Copy their
17 // mutable containers, preserving every field without a lossy shadow schema.
18 func detachValue(value reflect.Value) reflect.Value {
19 switch value.Kind() {
20 case reflect.Pointer, reflect.Interface:
21 if value.IsNil() {
22 return reflect.Zero(value.Type())
23 }
24 inner := detachValue(value.Elem())
25 out := reflect.New(value.Type()).Elem()
26 if value.Kind() == reflect.Pointer {
27 out.Set(reflect.New(value.Type().Elem()))
28 out.Elem().Set(inner)
29 } else {
30 out.Set(inner)
31 }
32 return out
33 case reflect.Slice:
34 if value.IsNil() {
35 return reflect.Zero(value.Type())
36 }
37 out := reflect.MakeSlice(value.Type(), value.Len(), value.Len())
38 for i := range value.Len() {
39 out.Index(i).Set(detachValue(value.Index(i)))
40 }
41 return out
42 case reflect.Map:
43 if value.IsNil() {
44 return reflect.Zero(value.Type())
45 }
46 out := reflect.MakeMapWithSize(value.Type(), value.Len())
47 iter := value.MapRange()
48 for iter.Next() {
49 out.SetMapIndex(iter.Key(), detachValue(iter.Value()))
50 }
51 return out
52 case reflect.Struct:
53 out := reflect.New(value.Type()).Elem()
54 out.Set(value)
55 for i := range value.NumField() {
56 if out.Field(i).CanSet() && value.Field(i).CanInterface() {
57 out.Field(i).Set(detachValue(value.Field(i)))
58 }
59 }
60 return out
61 default:
62 return value
63 }
64 }
65
65 lines GO