checkpoint: extract shared getSessionTree for session-level reads · Entire
checkpoint: extract shared getSessionTree for session-level reads
089e4b6→main·
Soph·3w ago·1 file·+33 added/-64 removed
The four SessionReader methods (ReadSessionMetadata, ReadSessionPrompts, ReadSessionMetadataAndPrompts, ReadSessionContent) each repeated the same prologue: context check, getFetchingTree, navigate to the checkpoint tree, then the session subtree, with identical ErrCheckpointNotFound wrapping.
Extract that navigation into getSessionTree so each reader is just "resolve session tree, read the files it needs." Behavior is unchanged — the helper returns the same ErrCheckpointNotFound (wrapping "session N not found" when the session subtree is missing).
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Sessions
9cd97a095ddaView transcript
Changes
1
cmd/entire/cli/checkpoint
Mpersistent.go+33/-64
1072 unmodified lines
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1077
1078
1079
1080
1081
1102
1103
1083
1084
1085
1086
1087
1088
1089
1090
1104
1105
1106
1107
17 unmodified lines
1125
1126
1127
1114
1115
1116
1117
1118
1128
1129
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1130
1131
1132
1133
19 unmodified lines
1153
1154
1155
1156
1157
1158
1159
1160
1156
1157
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1158
1159
1160
1161
13 unmodified lines
1175
1176
1177
1192
1193
1194
1195
1196
1178
1179
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1180
1181
1182
1183
1072 unmodified lines
// ReadSessionMetadata reads only the metadata.json for a specific session within a checkpoint.
// This is a lightweight read that avoids fetching transcript/prompt blobs.
// sessionIndex is 0-based.
// getSessionTree resolves the FetchingTree for a single session within a
// checkpoint. It returns ErrCheckpointNotFound when the checkpoint or session
// is missing; all session-level reads share this navigation.
func (s *GitStore) getSessionTree(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*FetchingTree, error) {
if err := ctx.Err(); err != nil {
return nil, err //nolint:wrapcheck // Propagating context cancellation
}
ft, err := s.getFetchingTree(ctx)
if err != nil {
return nil, ErrCheckpointNotFound
}
checkpointTree, err := ft.Tree(checkpointID.Path())
if err != nil {
return nil, ErrCheckpointNotFound
}
sessionTree, err := checkpointTree.Tree(strconv.Itoa(sessionIndex))
if err != nil {
return nil, fmt.Errorf("%w: session %d not found: %w", ErrCheckpointNotFound, sessionIndex, err)
}
return sessionTree, nil
}
func (s *GitStore) ReadSessionMetadata(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*Metadata, error) {
if err := ctx.Err(); err != nil {
return nil, err //nolint:wrapcheck // Propagating context cancellation
}
ft, err := s.getFetchingTree(ctx)
sessionTree, err := s.getSessionTree(ctx, checkpointID, sessionIndex)
if err != nil {
return nil, ErrCheckpointNotFound
}
checkpointPath := checkpointID.Path()
sessionPath := fmt.Sprintf("%s/%d", checkpointPath, sessionIndex)
sessionTree, err := ft.Tree(sessionPath)
if err != nil {
return nil, fmt.Errorf("%w: session %d not found: %w", ErrCheckpointNotFound, sessionIndex, err)
return nil, err
}
metadataFile, err := sessionTree.File(paths.MetadataFileName)
17 unmodified lines
// ReadSessionMetadataAndPrompts reads session metadata and prompt text without
// requiring the raw transcript blob.
func (s *GitStore) ReadSessionMetadataAndPrompts(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error) {
if err := ctx.Err(); err != nil {
return nil, err //nolint:wrapcheck // Propagating context cancellation
}
ft, err := s.getFetchingTree(ctx)
sessionTree, err := s.getSessionTree(ctx, checkpointID, sessionIndex)
if err != nil {
return nil, ErrCheckpointNotFound
}
checkpointTree, err := ft.Tree(checkpointID.Path())
if err != nil {
return nil, ErrCheckpointNotFound
}
sessionTree, err := checkpointTree.Tree(strconv.Itoa(sessionIndex))
if err != nil {
return nil, fmt.Errorf("%w: session %d not found: %w", ErrCheckpointNotFound, sessionIndex, err)
return nil, err
}
result := &SessionContent{}
19 unmodified lines
}
func (s *GitStore) ReadSessionPrompts(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (string, error) {
if err := ctx.Err(); err != nil {
return "", err //nolint:wrapcheck // Propagating context cancellation
}
ft, err := s.getFetchingTree(ctx)
sessionTree, err := s.getSessionTree(ctx, checkpointID, sessionIndex)
if err != nil {
return "", ErrCheckpointNotFound
}
checkpointTree, err := ft.Tree(checkpointID.Path())
if err != nil {
return "", ErrCheckpointNotFound
}
sessionTree, err := checkpointTree.Tree(strconv.Itoa(sessionIndex))
if err != nil {
return "", fmt.Errorf("%w: session %d not found: %w", ErrCheckpointNotFound, sessionIndex, err)
return "", err
}
file, err := sessionTree.File(paths.PromptFileName)
13 unmodified lines
// Returns ErrCheckpointNotFound if the checkpoint or session doesn't exist.
// Returns ErrNoTranscript if the session exists but has no transcript.
func (s *GitStore) ReadSessionContent(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error) {
if err := ctx.Err(); err != nil {
return nil, err //nolint:wrapcheck // Propagating context cancellation
}
ft, err := s.getFetchingTree(ctx)
sessionTree, err := s.getSessionTree(ctx, checkpointID, sessionIndex)
if err != nil {
return nil, ErrCheckpointNotFound
}
checkpointPath := checkpointID.Path()
checkpointTree, err := ft.Tree(checkpointPath)
if err != nil {
return nil, ErrCheckpointNotFound
}
// Get the session subdirectory
sessionDir := strconv.Itoa(sessionIndex)
sessionTree, err := checkpointTree.Tree(sessionDir)
if err != nil {
return nil, fmt.Errorf("%w: session %d not found: %w", ErrCheckpointNotFound, sessionIndex, err)
return nil, err
}
result := &SessionContent{}
Mcmd/entire/cli/checkpoint/persistent.go+33/-64