返回 DeepSeek-Reasonix
session_errors.go
根目录 / desktop / session_errors.go
1 package main
2
3 import (
4 "errors"
5 "log/slog"
6 "syscall"
7
8 "reasonix/internal/agent"
9 )
10
11 // Sanitized errors surfaced when a destructive or restore session operation
12 // hits a real filesystem blocker. Like errSessionBusyElsewhere, they
13 // intentionally carry no path, so raw OS error text never reaches the UI.
14 var (
15 errSessionFileLocked = errors.New("a session file is temporarily locked by another program (often antivirus or sync tools) — wait a moment and retry")
16 errSessionFileAccessDenied = errors.New("access to a session file was denied — close programs that may be using it or check folder permissions, then retry")
17 errSessionDiskFull = errors.New("not enough disk space to finish the operation — free some space and retry")
18 errSessionHistoryUnreadable = errors.New("session history could not be loaded safely; the session files were left unchanged")
19 )
20
21 // friendlySessionLoadError keeps decoder details and local paths in logs while
22 // preserving the already path-free replay-budget error for the startup banner.
23 // A failed authoritative event log must never be hidden by opening an empty
24 // session or falling back to an older checkpoint.
25 func friendlySessionLoadError(err error) error {
26 if err == nil || errors.Is(err, agent.ErrSessionReplayLimitExceeded) {
27 return err
28 }
29 if friendly := friendlySessionFileError(err); !errors.Is(friendly, err) {
30 return friendly
31 }
32 slog.Warn("desktop: session history load failed", "err", err)
33 return errSessionHistoryUnreadable
34 }
35
36 // friendlySessionFileError rewrites raw OS-level filesystem errors from the
37 // session trash/restore/purge flows (e.g. a Windows sharing violation while a
38 // scanner holds a transcript) into the actionable, path-free errors above.
39 // The original error is logged so diagnostics keep the path and errno.
40 // Unrecognized errors — including already-sanitized ones like
41 // errSessionBusyElsewhere — pass through unchanged.
42 func friendlySessionFileError(err error) error {
43 if err == nil {
44 return nil
45 }
46 var errno syscall.Errno
47 if !errors.As(err, &errno) {
48 return err
49 }
50 var friendly error
51 switch {
52 case isFileInUseErrno(errno):
53 friendly = errSessionFileLocked
54 case isAccessDeniedErrno(errno):
55 friendly = errSessionFileAccessDenied
56 case isDiskFullErrno(errno):
57 friendly = errSessionDiskFull
58 default:
59 return err
60 }
61 slog.Warn("desktop: session file operation blocked", "err", err)
62 return friendly
63 }
64
64 lines GO