Documentation
¶
Overview ¶
Package lfs provides a pure-HTTP client for the Git LFS Batch API. No git-lfs binary required. Uses the batch API for blob upload/download.
The client implements the Git LFS Batch API spec: https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md
Index ¶
- Variables
- func ComputeOID(content []byte) string
- func DownloadAndVerifyObject(action *Action, expectedOID string) ([]byte, error)
- func DownloadObject(action *Action) ([]byte, error)
- func EnsureSessionsGitignore(sessionsDir string) error
- func FormatPointer(oid string, size int64) string
- func IsPointerFile(path string) bool
- func ParsePointer(content string) (oid string, size int64, err error)
- func UpdateMetaSummary(sessionPath, summary string) error
- func UploadObject(action *Action, content []byte) error
- func UploadSessionFiles(client *Client, sessionPath string, logger *slog.Logger) (map[string]FileRef, error)
- func VerifyObject(action *Action, oid string, size int64) error
- func WritePointerFile(path string, ref FileRef) error
- func WritePointerFiles(dir string, files map[string]FileRef) ([]string, error)
- func WriteSessionMeta(sessionPath string, meta *SessionMeta) error
- func WriteSessionMetaOnly(sessionPath string, meta *SessionMeta) error
- type Action
- type Actions
- type BatchObject
- type BatchResponse
- type BatchResponseObject
- type Client
- type DownloadResult
- type FileRef
- type HydrationStatus
- type ObjectError
- type SessionMeta
- type SessionMetaBuilder
- func (b *SessionMetaBuilder) Build() *SessionMeta
- func (b *SessionMetaBuilder) EntryCount(n int) *SessionMetaBuilder
- func (b *SessionMetaBuilder) Model(m string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) RepoID(id string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) StopReason(reason string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) Summary(s string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) Title(t string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) UserID(id string) *SessionMetaBuilder
- func (b *SessionMetaBuilder) WithFiles(f map[string]FileRef) *SessionMetaBuilder
- type UploadResult
Constants ¶
This section is empty.
Variables ¶
var ContentFiles = []string{
"raw.jsonl",
"summary.md",
"session.md",
"plan.md",
}
ContentFiles lists the session content files eligible for LFS upload. These are the files that get uploaded to LFS blob storage and replaced with pointer files in the git commit.
Functions ¶
func ComputeOID ¶
ComputeOID computes the SHA256 hex digest of content (the LFS OID).
func DownloadAndVerifyObject ¶ added in v0.6.0
DownloadAndVerifyObject downloads a blob and verifies its SHA256 matches the expected OID. Accepts both bare hex and canonical "sha256:<hex>" OID formats.
func DownloadObject ¶
DownloadObject downloads a single blob using the action href.
func EnsureSessionsGitignore ¶ added in v0.6.0
EnsureSessionsGitignore ensures the sessions/.gitignore exists in the ledger. LFS pointer files and meta.json are committed to git; pointer files (~130 bytes) reference uploaded LFS objects by OID to prevent garbage collection. Overwrites legacy .gitignore that excluded content file extensions.
func FormatPointer ¶ added in v0.3.0
FormatPointer returns canonical LFS pointer file content for the given OID and size. OID must include the "sha256:" prefix (matching FileRef.OID convention).
Per spec: version line first, then remaining keys in alphabetical order. "oid" < "size" lexicographically, so the ordering is: version, oid, size. Each line is "key SP value LF" with Unix line endings (\n, not \r\n).
func IsPointerFile ¶ added in v0.3.0
IsPointerFile reports whether the file at path is an LFS pointer. Returns false for missing files, content files, or read errors. Detection is by content format (version + oid + size), not by filename or .gitattributes — matching how git-lfs itself identifies pointers.
func ParsePointer ¶ added in v0.3.0
ParsePointer parses LFS pointer file content and returns the OID and size. Returns an error if the content is not a valid LFS pointer.
Per spec: version line must appear first; remaining keys ("oid", "size") are in alphabetical order. Unknown keys (e.g. "ext-0-*") are silently ignored, allowing forward compatibility with spec extensions.
func UpdateMetaSummary ¶ added in v0.2.0
UpdateMetaSummary reads meta.json from sessionPath, updates the Summary field, and re-writes it atomically. Used by push-summary to replace the local summary with the AI-generated title.
func UploadObject ¶
UploadObject uploads a single blob using the action href from the batch response.
func UploadSessionFiles ¶ added in v0.6.0
func UploadSessionFiles(client *Client, sessionPath string, logger *slog.Logger) (map[string]FileRef, error)
UploadSessionFiles uploads session content files to LFS and returns the filename->FileRef manifest for inclusion in meta.json.
The caller provides the LFS client (credential resolution is caller's responsibility — CLI and daemon resolve credentials differently).
Flow:
- Read all content files from session dir
- Compute SHA256 OIDs + sizes
- Call LFS batch API to get upload actions
- Upload all blobs in parallel
- Return filename->FileRef map for meta.json
func VerifyObject ¶ added in v0.6.0
VerifyObject confirms a blob was received by the server by POSTing to the verify action href per the Git LFS batch API spec. The server responds 200 if the object exists with matching OID and size.
func WritePointerFile ¶ added in v0.3.0
WritePointerFile writes a standard LFS pointer file at path. Replaces any existing file (content is already uploaded to LFS).
func WritePointerFiles ¶ added in v0.3.0
WritePointerFiles writes LFS pointer files for each entry in files. Keys are filenames written as dir/<key>. Returns sorted absolute paths of written files. Both sessions and imports use this to create the standard git-lfs pointer files that prevent garbage collection.
func WriteSessionMeta ¶
func WriteSessionMeta(sessionPath string, meta *SessionMeta) error
WriteSessionMeta writes meta.json to the given session directory. When meta.Files is populated, also replaces content files with LFS pointer files (standard git-lfs naming). Pointer write failures are non-fatal — session data is safe in LFS + meta.json regardless.
Callers that need to push content files to git BEFORE replacing them with pointer stubs should use WriteSessionMetaOnly followed by WritePointerFiles after a successful push.
func WriteSessionMetaOnly ¶ added in v0.6.0
func WriteSessionMetaOnly(sessionPath string, meta *SessionMeta) error
WriteSessionMetaOnly writes meta.json without replacing content files with LFS pointer stubs. Use this when content files must remain intact until a successful git push — call WritePointerFiles separately after the push so that push failure never leaves a session with pointer stubs but no remote copy.
Types ¶
type Action ¶
type Action struct {
Href string `json:"href"`
Header map[string]string `json:"header,omitempty"`
ExpiresIn int `json:"expires_in,omitempty"` // seconds
ExpiresAt string `json:"expires_at,omitempty"` // RFC3339
}
Action is a single LFS action with an href and optional headers.
type Actions ¶
type Actions struct {
Upload *Action `json:"upload,omitempty"`
Download *Action `json:"download,omitempty"`
Verify *Action `json:"verify,omitempty"`
}
Actions contains the upload/download actions returned by the batch API.
type BatchObject ¶
type BatchObject struct {
OID string `json:"oid"` // SHA256 hex digest
Size int64 `json:"size"` // bytes
}
BatchObject identifies a single LFS object by its SHA256 OID and size.
type BatchResponse ¶
type BatchResponse struct {
Transfer string `json:"transfer"` // "basic"
Objects []BatchResponseObject `json:"objects"`
}
BatchResponse is the server response from the batch API.
type BatchResponseObject ¶
type BatchResponseObject struct {
OID string `json:"oid"`
Size int64 `json:"size"`
Authenticated bool `json:"authenticated,omitempty"`
Actions *Actions `json:"actions,omitempty"`
Error *ObjectError `json:"error,omitempty"`
}
BatchResponseObject is a single object in the batch response.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client communicates with a Git LFS Batch API server (e.g., GitLab).
func NewClient ¶
NewClient creates an LFS client for the given git repo URL. repoURL should be the git clone URL (e.g., https://git.sageox.io/sageox/ledger.git). Auth uses HTTP Basic per the Git LFS spec: username:token base64-encoded.
func NewClientFromLedger ¶ added in v0.6.0
NewClientFromLedger creates an LFS client using the ledger's git remote URL and credentials loaded for the given endpoint. This is a convenience constructor for callers that already have the ledger path (e.g., daemon session finalization).
func (*Client) BatchDownload ¶
func (c *Client) BatchDownload(objects []BatchObject) (*BatchResponse, error)
BatchDownload requests download URLs for the given objects.
func (*Client) BatchUpload ¶
func (c *Client) BatchUpload(objects []BatchObject) (*BatchResponse, error)
BatchUpload requests upload URLs for the given objects.
type DownloadResult ¶
DownloadResult tracks the outcome of a single download.
func DownloadAll ¶
func DownloadAll(resp *BatchResponse, maxConcurrent int) []DownloadResult
DownloadAll downloads multiple blobs in parallel. Returns results for every object so callers can see all errors, not just the first.
type FileRef ¶
FileRef identifies a content file by its LFS OID and size.
func NewFileRef ¶
NewFileRef creates a FileRef from content bytes.
func ReadPointerFile ¶ added in v0.3.0
ReadPointerFile reads and parses an LFS pointer file, returning the FileRef.
type HydrationStatus ¶
type HydrationStatus string
HydrationStatus describes whether a session's content files are present locally.
const ( // HydrationStatusHydrated means all content files are present locally. HydrationStatusHydrated HydrationStatus = "hydrated" // HydrationStatusDehydrated means no content files are present (only meta.json). HydrationStatusDehydrated HydrationStatus = "dehydrated" // HydrationStatusPartial means some content files are present. HydrationStatusPartial HydrationStatus = "partial" )
func CheckHydrationStatus ¶
func CheckHydrationStatus(sessionPath string, meta *SessionMeta) HydrationStatus
CheckHydrationStatus checks which content files are present as real content (not LFS pointers) for a session. Files that are missing or contain only an LFS pointer are considered dehydrated.
type ObjectError ¶
ObjectError is returned when the server cannot process an object.
type SessionMeta ¶
type SessionMeta struct {
Version string `json:"version"` // "1.0"
SessionName string `json:"session_name"`
Username string `json:"username"` // email of author
UserID string `json:"user_id,omitempty"`
AgentID string `json:"agent_id"`
AgentType string `json:"agent_type"` // "claude-code", "cursor", etc.
Model string `json:"model,omitempty"`
Title string `json:"title,omitempty"`
CreatedAt time.Time `json:"created_at"`
EntryCount int `json:"entry_count,omitempty"`
Summary string `json:"summary,omitempty"`
StopReason string `json:"stop_reason,omitempty"` // how session ended: "stopped", "aborted", "recovered", ""
RepoID string `json:"repo_id,omitempty"`
Files map[string]FileRef `json:"files"` // OID manifest: filename -> ref
}
SessionMeta is the git-tracked metadata + OID manifest for a session. Stored as meta.json in each session folder. When Files is populated, WriteSessionMeta also writes LFS pointer files (standard git-lfs naming) to replace content files, preventing LFS garbage collection.
func ReadSessionMeta ¶
func ReadSessionMeta(sessionPath string) (*SessionMeta, error)
ReadSessionMeta reads meta.json from the given session directory.
type SessionMetaBuilder ¶ added in v0.2.0
type SessionMetaBuilder struct {
// contains filtered or unexported fields
}
SessionMetaBuilder constructs SessionMeta with required fields and optional setters.
func NewSessionMeta ¶ added in v0.2.0
func NewSessionMeta(sessionName, username, agentID, agentType string, createdAt time.Time) *SessionMetaBuilder
NewSessionMeta creates a builder with required fields pre-filled.
func (*SessionMetaBuilder) Build ¶ added in v0.2.0
func (b *SessionMetaBuilder) Build() *SessionMeta
Build returns the constructed SessionMeta.
func (*SessionMetaBuilder) EntryCount ¶ added in v0.2.0
func (b *SessionMetaBuilder) EntryCount(n int) *SessionMetaBuilder
func (*SessionMetaBuilder) Model ¶ added in v0.2.0
func (b *SessionMetaBuilder) Model(m string) *SessionMetaBuilder
func (*SessionMetaBuilder) RepoID ¶ added in v0.2.0
func (b *SessionMetaBuilder) RepoID(id string) *SessionMetaBuilder
func (*SessionMetaBuilder) StopReason ¶ added in v0.5.0
func (b *SessionMetaBuilder) StopReason(reason string) *SessionMetaBuilder
func (*SessionMetaBuilder) Summary ¶ added in v0.2.0
func (b *SessionMetaBuilder) Summary(s string) *SessionMetaBuilder
func (*SessionMetaBuilder) Title ¶ added in v0.2.0
func (b *SessionMetaBuilder) Title(t string) *SessionMetaBuilder
func (*SessionMetaBuilder) UserID ¶ added in v0.2.0
func (b *SessionMetaBuilder) UserID(id string) *SessionMetaBuilder
func (*SessionMetaBuilder) WithFiles ¶ added in v0.2.0
func (b *SessionMetaBuilder) WithFiles(f map[string]FileRef) *SessionMetaBuilder
type UploadResult ¶
UploadResult tracks the outcome of a single upload.
func UploadAll ¶
func UploadAll(resp *BatchResponse, files map[string][]byte, maxConcurrent int) []UploadResult
UploadAll uploads multiple blobs in parallel. files maps OID -> content. Uses objects from the batch response to find upload actions.