返回 DeepSeek-Reasonix
session_v5_migration_recovery.go
根目录 / desktop / session_v5_migration_recovery.go
1 package main
2
3 import (
4 "path/filepath"
5 "strings"
6
7 "reasonix/internal/agent"
8 "reasonix/internal/store"
9 )
10
11 // Recovery copies are durable safety artifacts, not ordinary conversations.
12 // Classification uses the historical writer's identity markers, never titles,
13 // text equality or the mere presence of a parent (which also marks user forks).
14 // Missing display metadata must still allow ordinary history to migrate.
15 func desktopMigrationAutomaticRecovery(path string) bool {
16 if agent.LooksLikeRecoveryFilename(path) {
17 return true
18 }
19 meta, found, err := agent.LoadBranchMeta(path)
20 return err == nil && found && (meta.Recovered || meta.EffectiveVersionKind() == agent.VersionRecovery || strings.TrimSpace(meta.RecoveryDigest) != "")
21 }
22
23 // Carry the exclusion through paired stores and conversion ancestry. Original
24 // files can be gone, so consult the immutable archived metadata as well. This
25 // only controls discovery; it never deletes or rewrites any recovery artifact.
26 func desktopMigrationRecoveryStores(nodes map[string]desktopMigrationStoredSource) map[string]bool {
27 hidden := map[string]bool{}
28 var recovery func(desktopMigrationStoredSource, map[string]bool) bool
29 recovery = func(node desktopMigrationStoredSource, seen map[string]bool) bool {
30 key := canonicalRuntimeRoot(node.dir)
31 if seen[key] || len(seen) >= 32 {
32 return false
33 }
34 seen[key] = true
35 if agent.LooksLikeRecoveryFilename(node.manifest.SessionID+".jsonl") ||
36 desktopMigrationAutomaticRecovery(filepath.Join(filepath.Dir(filepath.Dir(node.dir)), "sessions", node.manifest.SessionID+".jsonl")) {
37 return true
38 }
39 source := node.manifest.Source
40 if source == nil {
41 return false
42 }
43 if store.IsSessionTranscriptName(filepath.Base(source.Path)) && (source.Version == "" || source.Version == "legacy") {
44 return desktopMigrationAutomaticRecovery(source.Path) ||
45 desktopMigrationAutomaticRecovery(filepath.Join(node.dir, "legacy", filepath.Base(source.Path)))
46 }
47 if parent, found := nodes[canonicalRuntimeRoot(source.Path)]; found {
48 return recovery(parent, seen)
49 }
50 dir := filepath.Join(node.dir, "legacy", "prototype")
51 manifest, err := readDesktopMigrationManifest(dir)
52 return err == nil && recovery(desktopMigrationStoredSource{dir: dir, manifest: manifest}, seen)
53 }
54 for key, node := range nodes {
55 if recovery(node, map[string]bool{}) {
56 hidden[key] = true
57 }
58 }
59 return hidden
60 }
61
61 lines GO