149 lines
4.5 KiB
Julia
149 lines
4.5 KiB
Julia
"""
|
|
session/jsonl_repo.jl - JSONL session repository
|
|
|
|
This module provides a JSONL-based session repository implementation.
|
|
"""
|
|
|
|
module JsonlRepo
|
|
|
|
using ..Types: *
|
|
using ..SessionStorage: SessionStorage, SessionMetadata
|
|
using ..JsonlStorage: JsonlSessionStorage, headerToSessionMetadata
|
|
using ..MemoryRepo: createSessionId, createTimestamp, getEntriesToFork, toSession
|
|
using ..HarnessTypes: SessionRepo, SessionForkOptions
|
|
|
|
# ============================================================================
|
|
# JSONL session repository
|
|
# ============================================================================
|
|
|
|
mutable struct JsonlSessionRepo <: SessionRepo{
|
|
JsonlSessionMetadata,
|
|
JsonlSessionCreateOptions,
|
|
JsonlSessionListOptions
|
|
}
|
|
fs::Any
|
|
sessions_root_input::String
|
|
sessions_root::Union{String, Nothing}
|
|
|
|
function JsonlSessionRepo(; sessions_root::String, fs::Any)
|
|
new(fs, sessions_root, nothing)
|
|
end
|
|
end
|
|
|
|
# ============================================================================
|
|
# Session repo methods
|
|
# ============================================================================
|
|
|
|
function create(repo::JsonlSessionRepo, options::JsonlSessionCreateOptions)::Session
|
|
id = if haskey(options, :id) && !isnothing(options[:id])
|
|
options[:id]
|
|
else
|
|
createSessionId()
|
|
end
|
|
created_at = createTimestamp()
|
|
|
|
session_dir = getSessionDir(repo, options.cwd)
|
|
|
|
file_path = createSessionFilePath(repo, options.cwd, id, created_at)
|
|
|
|
storage = JsonlSessionStorage(
|
|
file_path,
|
|
SessionHeader(
|
|
"session",
|
|
3,
|
|
id,
|
|
created_at,
|
|
options.cwd,
|
|
get(options, :parentSessionPath, nothing),
|
|
get(options, :metadata, nothing),
|
|
),
|
|
SessionTreeEntry[],
|
|
nothing,
|
|
)
|
|
|
|
return toSession(storage)
|
|
end
|
|
|
|
function open(repo::JsonlSessionRepo, metadata::JsonlSessionMetadata)::Session
|
|
# TODO: Open existing file
|
|
return toSession(JsonlSessionStorage(
|
|
metadata.path,
|
|
SessionHeader(
|
|
"session",
|
|
3,
|
|
metadata.id,
|
|
metadata.created_at,
|
|
metadata.cwd,
|
|
metadata.parent_session_path,
|
|
metadata.metadata,
|
|
),
|
|
SessionTreeEntry[],
|
|
nothing,
|
|
))
|
|
end
|
|
|
|
function list(repo::JsonlSessionRepo, options::JsonlSessionListOptions=JsonlSessionListOptions())::Vector{JsonlSessionMetadata}
|
|
# TODO: List sessions
|
|
return JsonlSessionMetadata[]
|
|
end
|
|
|
|
function delete(repo::JsonlSessionRepo, metadata::JsonlSessionMetadata)::Nothing
|
|
# TODO: Delete session file
|
|
return nothing
|
|
end
|
|
|
|
function fork(repo::JsonlSessionRepo, source::JsonlSessionMetadata, options::Dict{String, Any})::Session
|
|
# TODO: Fork session
|
|
return create(repo, JsonlSessionCreateOptions(
|
|
cwd=get(options, "cwd", ""),
|
|
id=get(options, "id", createSessionId()),
|
|
))
|
|
end
|
|
|
|
# ============================================================================
|
|
# Helper functions
|
|
# ============================================================================
|
|
|
|
function getSessionsRoot(repo::JsonlSessionRepo)::String
|
|
if isnothing(repo.sessions_root)
|
|
repo.sessions_root = getFileSystemResultOrThrow(
|
|
absolutePath(repo.fs, repo.sessions_root_input),
|
|
"Failed to resolve sessions root $(repo.sessions_root_input)",
|
|
)
|
|
end
|
|
return repo.sessions_root
|
|
end
|
|
|
|
function getSessionDir(repo::JsonlSessionRepo, cwd::String)::String
|
|
return getFileSystemResultOrThrow(
|
|
joinPath(repo.fs, [getSessionsRoot(repo), encodeCwd(cwd)]),
|
|
"Failed to resolve session directory for $(cwd)",
|
|
)
|
|
end
|
|
|
|
function encodeCwd(cwd::String)::String
|
|
result = replace(cwd, r"^[/\\]" => "")
|
|
result = replace(result, r"[/\\:]" => "-")
|
|
return "--$(result)--"
|
|
end
|
|
|
|
function createSessionFilePath(repo::JsonlSessionRepo, cwd::String, session_id::String, timestamp::String)::String
|
|
return getFileSystemResultOrThrow(
|
|
joinPath(repo.fs, [
|
|
getSessionDir(repo, cwd),
|
|
"$(replace(timestamp, r"[:.]" => "-"))_$(session_id).jsonl",
|
|
]),
|
|
"Failed to resolve session file path for $(session_id)",
|
|
)
|
|
end
|
|
|
|
function getFileSystemResultOrThrow(result::Result, message::String)
|
|
if !result.ok
|
|
code = result.error.code == "not_found" ? "not_found" : "storage"
|
|
throw(SessionError(code, "$(message): $(result.error.message)", result.error))
|
|
end
|
|
return result.value
|
|
end
|
|
|
|
end
|