///|
priv struct MoonSessionMeta {
  provider_id : String
  session_id : String
  title : String?
  summary : String?
  project_dir : String?
  created_at : Int64?
  last_active_at : Int64?
  source_path : String?
  resume_command : String?
}

///|
priv struct MoonSessionMessage {
  role : String
  content : String
  ts : Int64?
}

///|
priv struct MoonDeleteSessionRequest {
  provider_id : String
  session_id : String
  source_path : String
}

///|
priv struct MoonDeleteSessionOutcome {
  provider_id : String
  session_id : String
  source_path : String
  success : Bool
  error : String?
}

///|
priv struct MoonSessionTerminalLaunch {
  program : String
  args : Array[String]
}

///|
let moon_session_title_max_chars : Int = 80

///|
let moon_session_read_cap : Int = 256 * 1024

///|
async fn moon_list_sessions_json() -> Json {
  let sessions = moon_scan_sessions()
  moon_sort_sessions_desc(sessions)
  Json::array(sessions.map(fn(session) { session.to_json() }))
}

///|
async fn moon_get_session_messages_json(
  provider_id : String,
  source_path : String,
) -> Result[Json, String] {
  match moon_load_session_messages(provider_id, source_path) {
    Ok(messages) => Ok(Json::array(messages.map(message => message.to_json())))
    Err(error) => Err(error)
  }
}

///|
async fn moon_delete_session_json(
  provider_id : String,
  session_id : String,
  source_path : String,
) -> Result[Json, String] {
  match moon_delete_session(provider_id, session_id, source_path) {
    Ok(deleted) => Ok(Json::boolean(deleted))
    Err(error) => Err(error)
  }
}

///|
async fn moon_delete_sessions_json(
  items : Array[MoonDeleteSessionRequest],
) -> Json {
  let outcomes = []
  for item in items {
    let outcome = match
      moon_delete_session(item.provider_id, item.session_id, item.source_path) {
      Ok(true) =>
        MoonDeleteSessionOutcome::{
          provider_id: item.provider_id,
          session_id: item.session_id,
          source_path: item.source_path,
          success: true,
          error: None,
        }
      Ok(false) =>
        {
          provider_id: item.provider_id,
          session_id: item.session_id,
          source_path: item.source_path,
          success: false,
          error: Some("Session was not deleted"),
        }
      Err(error) =>
        {
          provider_id: item.provider_id,
          session_id: item.session_id,
          source_path: item.source_path,
          success: false,
          error: Some(error),
        }
    }
    outcomes.push(outcome.to_json())
  }
  Json::array(outcomes)
}

///|
fn moon_delete_session_requests_from_json(
  value : Json?,
) -> Array[MoonDeleteSessionRequest]? {
  let raw_items = match value {
    Some(Array(items)) => Some(items)
    _ => None
  }
  guard raw_items is Some(raw_items) else { return None }
  let items = []
  for raw in raw_items {
    match moon_delete_session_request_from_json(raw) {
      Some(item) => items.push(item)
      None => return None
    }
  }
  Some(items)
}

///|
async fn moon_launch_session_terminal_json(
  command : String,
  cwd : String?,
  custom_config : String?,
  preferred_terminal : String?,
) -> Result[Json, String] {
  if command.trim().is_empty() {
    return Err("Resume command is empty")
  }
  let target = moon_session_terminal_target(preferred_terminal)
  let launch = match
    moon_session_terminal_launch(target, command, cwd, custom_config) {
    Ok(launch) => launch
    Err(error) => return Err(error)
  }
  let result = @spawn.spawn(
    launch.program,
    launch.args.map(arg => arg[:]),
    timeout=5000,
  ) catch {
    err => return Err("Failed to launch terminal: \{err}")
  }
  if result.status == 0 {
    Ok(Json::boolean(true))
  } else {
    let detail = if result.stderr.trim().is_empty() {
      result.stdout.trim()
    } else {
      result.stderr.trim()
    }
    Err(
      if detail.is_empty() {
        "Terminal command execution failed"
      } else {
        detail.to_owned()
      },
    )
  }
}

///|
fn MoonSessionMeta::to_json(self : MoonSessionMeta) -> Json {
  let obj : Map[String, Json] = {
    "providerId": Json::string(self.provider_id),
    "sessionId": Json::string(self.session_id),
  }
  match self.title {
    Some(value) => obj["title"] = Json::string(value)
    None => ()
  }
  match self.summary {
    Some(value) => obj["summary"] = Json::string(value)
    None => ()
  }
  match self.project_dir {
    Some(value) => obj["projectDir"] = Json::string(value)
    None => ()
  }
  match self.created_at {
    Some(value) => obj["createdAt"] = Json::number(value.to_double())
    None => ()
  }
  match self.last_active_at {
    Some(value) => obj["lastActiveAt"] = Json::number(value.to_double())
    None => ()
  }
  match self.source_path {
    Some(value) => obj["sourcePath"] = Json::string(value)
    None => ()
  }
  match self.resume_command {
    Some(value) => obj["resumeCommand"] = Json::string(value)
    None => ()
  }
  Json::object(obj)
}

///|
fn MoonSessionMessage::to_json(self : MoonSessionMessage) -> Json {
  let obj : Map[String, Json] = {
    "role": Json::string(self.role),
    "content": Json::string(self.content),
  }
  match self.ts {
    Some(value) => obj["ts"] = Json::number(value.to_double())
    None => ()
  }
  Json::object(obj)
}

///|
fn MoonDeleteSessionOutcome::to_json(self : MoonDeleteSessionOutcome) -> Json {
  let obj : Map[String, Json] = {
    "providerId": Json::string(self.provider_id),
    "sessionId": Json::string(self.session_id),
    "sourcePath": Json::string(self.source_path),
    "success": Json::boolean(self.success),
  }
  match self.error {
    Some(value) => obj["error"] = Json::string(value)
    None => ()
  }
  Json::object(obj)
}

///|
fn moon_delete_session_request_from_json(
  value : Json,
) -> MoonDeleteSessionRequest? {
  guard value is Object(obj) else { return None }
  guard json_string_from_map(obj, "providerId") is Some(provider_id) else {
    return None
  }
  guard json_string_from_map(obj, "sessionId") is Some(session_id) else {
    return None
  }
  guard json_string_from_map(obj, "sourcePath") is Some(source_path) else {
    return None
  }
  Some({ provider_id, session_id, source_path })
}

///|
fn moon_session_terminal_target(preferred : String?) -> String {
  match preferred {
    Some(value) => {
      let target = value.trim().to_lower()
      match target {
        "" => "terminal"
        "iterm2" => "iterm"
        _ => target.to_owned()
      }
    }
    None => "terminal"
  }
}

///|
fn moon_session_terminal_from_settings(settings : Json) -> String? {
  match settings {
    Object(obj) =>
      match json_string_from_map(obj, "preferredTerminal") {
        Some(value) if !value.trim().is_empty() => Some(value)
        _ => None
      }
    _ => None
  }
}

///|
async fn moon_session_terminal_launch(
  target : String,
  command : String,
  cwd : String?,
  custom_config : String?,
) -> Result[MoonSessionTerminalLaunch, String] {
  match target {
    "terminal" => Ok(moon_session_terminal_app_launch(command, cwd))
    "iterm" | "iTerm" => Ok(moon_session_iterm_launch(command, cwd))
    "ghostty" => Ok(moon_session_ghostty_launch(command, cwd))
    "kitty" => Ok(moon_session_kitty_launch(command, cwd))
    "wezterm" => Ok(moon_session_wezterm_like_launch("WezTerm", command, cwd))
    "kaku" => Ok(moon_session_wezterm_like_launch("Kaku", command, cwd))
    "alacritty" => Ok(moon_session_alacritty_launch(command, cwd))
    "custom" => moon_session_custom_launch(command, cwd, custom_config)
    "warp" => moon_session_warp_launch(command, cwd)
    _ => Err("Unsupported terminal target: \{target}")
  }
}

///|
async fn moon_session_warp_launch(
  command : String,
  cwd : String?,
) -> Result[MoonSessionTerminalLaunch, String] {
  guard cwd is Some(dir) && !dir.trim().is_empty() else {
    return Err("Failed to resume session without cwd")
  }
  guard @fsx.exists(dir) else {
    return Err(
      "Failed to create temporary script file for launching Warp: cwd not found: \{dir}",
    )
  }
  let script_dir = @pathx.join(
    @moonsuite.product_home_for_workspace_root(dir, "moongate").tmp_path,
    "warp",
  )
  @fsx.make_directory(script_dir, recursive=true, exists_ok=true) catch {
    error =>
      return Err(
        "Failed to create temporary script directory for Warp: \{error}",
      )
  }
  let script_path = @pathx.join(script_dir, "warp-\{moongate_random_id()}.sh")
  let script = [
    "#!/usr/bin/env sh",
    "",
    "rm -- \"$0\"",
    "",
    "exec \{command}",
    "",
  ].join("\n")
  @fsx.write_to_file(script_path, script, create=0o755) catch {
    error =>
      return Err("Failed to write to temporary script file for Warp: \{error}")
  }
  Ok({
    program: "open",
    args: [
      "-a",
      "Warp",
      "warp://action/new_tab?path=\{moon_session_url_query_encode(script_path)}",
    ],
  })
}

///|
fn moon_session_terminal_app_launch(
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  let full_command = moon_session_shell_command(command, cwd)
  let escaped = moon_session_escape_osascript(full_command)
  let script = [
    "tell application \"Terminal\"",
    "    activate",
    "    do script \"\{escaped}\"",
    "end tell",
  ].join("\n")
  { program: "osascript", args: ["-e", script] }
}

///|
fn moon_session_iterm_launch(
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  let full_command = moon_session_shell_command(command, cwd)
  let escaped = moon_session_escape_osascript(full_command)
  let script = [
    "tell application \"iTerm\"",
    "    activate",
    "    create window with default profile",
    "    tell current session of current window",
    "        write text \"\{escaped}\"",
    "    end tell",
    "end tell",
  ].join("\n")
  { program: "osascript", args: ["-e", script] }
}

///|
fn moon_session_ghostty_launch(
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  let args : Array[String] = [
    "-na", "Ghostty", "--args", "--quit-after-last-window-closed=true",
  ]
  match cwd {
    Some(dir) if !dir.trim().is_empty() =>
      args.push("--working-directory=\{dir}")
    _ => ()
  }
  args.push("-e")
  args.push(moon_session_shell())
  args.push("-l")
  args.push("-c")
  args.push(command)
  { program: "open", args }
}

///|
fn moon_session_kitty_launch(
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  {
    program: "open",
    args: [
      "-na",
      "kitty",
      "--args",
      "-e",
      moon_session_shell(),
      "-l",
      "-c",
      moon_session_shell_command(command, cwd),
    ],
  }
}

///|
fn moon_session_wezterm_like_launch(
  app_name : String,
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  let args : Array[String] = ["-na", app_name, "--args", "start"]
  match cwd {
    Some(dir) if !dir.trim().is_empty() => {
      args.push("--cwd")
      args.push(dir)
    }
    _ => ()
  }
  args.push("--")
  args.push(moon_session_shell())
  args.push("-c")
  args.push(moon_session_shell_command(command, None))
  { program: "open", args }
}

///|
fn moon_session_alacritty_launch(
  command : String,
  cwd : String?,
) -> MoonSessionTerminalLaunch {
  let args : Array[String] = ["-na", "Alacritty", "--args"]
  match cwd {
    Some(dir) if !dir.trim().is_empty() => {
      args.push("--working-directory")
      args.push(dir)
    }
    _ => ()
  }
  args.push("-e")
  args.push(moon_session_shell())
  args.push("-c")
  args.push(moon_session_shell_command(command, None))
  { program: "open", args }
}

///|
fn moon_session_custom_launch(
  command : String,
  cwd : String?,
  custom_config : String?,
) -> Result[MoonSessionTerminalLaunch, String] {
  guard custom_config is Some(template) else {
    return Err("No custom terminal config provided")
  }
  if template.trim().is_empty() {
    return Err("Custom terminal command template is empty")
  }
  let dir = cwd.unwrap_or(".")
  let final_command = template
    .replace_all(old="{command}", new=command)
    .replace_all(old="{cwd}", new=dir)
  Ok({ program: "sh", args: ["-c", final_command] })
}

///|
fn moon_session_shell_command(command : String, cwd : String?) -> String {
  match cwd {
    Some(dir) if !dir.trim().is_empty() =>
      "cd \{moon_session_shell_escape(dir)} && \{command}"
    _ => command
  }
}

///|
fn moon_session_shell_escape(value : String) -> String {
  "\"" +
  value.replace_all(old="\\", new="\\\\").replace_all(old="\"", new="\\\"") +
  "\""
}

///|
fn moon_session_escape_osascript(value : String) -> String {
  value.replace_all(old="\\", new="\\\\").replace_all(old="\"", new="\\\"")
}

///|
fn moon_session_url_query_encode(value : String) -> String {
  let builder = StringBuilder::new()
  for ch in value {
    match ch {
      'A'..='Z' | 'a'..='z' | '0'..='9' | '-' | '_' | '.' | '~' =>
        builder.write_char(ch)
      _ => {
        let bytes = @encoding/utf8.encode(ch.to_string())
        for byte in bytes {
          let hex = byte.to_int()
          builder.write_char('%')
          builder.write_char(moon_session_hex_digit((hex >> 4) & 0xF))
          builder.write_char(moon_session_hex_digit(hex & 0xF))
        }
      }
    }
  }
  builder.to_string()
}

///|
fn moon_session_hex_digit(n : Int) -> Char {
  if n < 10 {
    ('0'.to_int() + n).unsafe_to_char()
  } else {
    ('A'.to_int() + n - 10).unsafe_to_char()
  }
}

///|
fn moon_session_shell() -> String {
  let shell = @os.getenv("SHELL") catch { _ => None }
  match shell {
    Some(value) if !value.trim().is_empty() => value
    _ => "/bin/zsh"
  }
}

///|
async fn moon_scan_sessions() -> Array[MoonSessionMeta] {
  let result = []
  for path in moon_collect_provider_session_files("codex") {
    match moon_parse_codex_session(path) {
      Some(meta) => result.push(meta)
      None => ()
    }
  }
  for path in moon_collect_provider_session_files("claude") {
    match moon_parse_claude_session(path) {
      Some(meta) => result.push(meta)
      None => ()
    }
  }
  for path in moon_collect_provider_session_files("gemini") {
    match moon_parse_gemini_session(path) {
      Some(meta) => result.push(meta)
      None => ()
    }
  }
  result.append(moon_scan_opencode_sessions())
  for path in moon_collect_provider_session_files("openclaw") {
    match moon_parse_generic_json_session(path, "openclaw") {
      Some(meta) => result.push(meta)
      None => ()
    }
  }
  result.append(moon_scan_hermes_sessions())
  result
}

///|
fn moon_sort_sessions_desc(sessions : Array[MoonSessionMeta]) -> Unit {
  sessions.sort_by(fn(left, right) {
    let left_key = moon_session_sort_key(left)
    let right_key = moon_session_sort_key(right)
    if left_key == right_key {
      right.session_id.compare(left.session_id)
    } else if left_key < right_key {
      1
    } else {
      -1
    }
  })
}

///|
fn moon_session_sort_key(session : MoonSessionMeta) -> Int64 {
  match session.last_active_at {
    Some(value) => value
    None =>
      match session.created_at {
        Some(value) => value
        None => 0L
      }
  }
}

///|
async fn moon_load_session_messages(
  provider_id : String,
  source_path : String,
) -> Result[Array[MoonSessionMessage], String] {
  let provider = moon_normalize_app_type(provider_id)
  if source_path.has_prefix("sqlite:") {
    return match provider {
      "opencode" => moon_load_opencode_sqlite_messages(source_path)
      "hermes" => moon_load_hermes_sqlite_messages(source_path)
      _ => Err("Unsupported SQLite session provider: \{provider_id}")
    }
  }
  guard @fsx.exists_as_file(source_path) else {
    return Err("session source not found: \{source_path}")
  }
  let content = moon_read_session_file_text(source_path) catch {
    error => return Err("Failed to open session file: \{error}")
  }
  match provider {
    "codex" => Ok(moon_load_codex_messages(content))
    "claude" => Ok(moon_load_claude_messages(content))
    "gemini" => Ok(moon_load_gemini_messages(content))
    "opencode" | "openclaw" | "hermes" =>
      Ok(moon_load_generic_json_messages(content))
    _ => Err("Unsupported provider: \{provider_id}")
  }
}

///|
async fn moon_delete_session(
  provider_id : String,
  session_id : String,
  source_path : String,
) -> Result[Bool, String] {
  let provider = moon_normalize_app_type(provider_id)
  if source_path.has_prefix("sqlite:") {
    return match provider {
      "opencode" => moon_delete_opencode_sqlite_session(session_id, source_path)
      "hermes" => moon_delete_hermes_sqlite_session(session_id, source_path)
      _ => Err("Unsupported SQLite session provider: \{provider_id}")
    }
  }
  guard @fsx.exists_as_file(source_path) else {
    return Err("session source not found: \{source_path}")
  }
  let ok_root = moon_source_path_under_provider_roots(provider, source_path)
  guard ok_root else {
    return Err("Session source path is outside provider roots: \{source_path}")
  }
  let meta = match provider {
    "codex" => moon_parse_codex_session(source_path)
    "claude" => moon_parse_claude_session(source_path)
    "gemini" => moon_parse_gemini_session(source_path)
    "opencode" | "openclaw" | "hermes" =>
      moon_parse_generic_json_session(source_path, provider)
    _ => return Err("Unsupported provider: \{provider_id}")
  }
  match meta {
    Some(meta) if meta.session_id == session_id => ()
    Some(meta) =>
      return Err(
        "\{moon_session_provider_label(provider)} session ID mismatch: expected \{session_id}, found \{meta.session_id}",
      )
    None =>
      return Err(
        "Failed to parse \{moon_session_provider_label(provider)} session metadata: \{source_path}",
      )
  }
  @fsx.remove(source_path) catch {
    error =>
      return Err("Failed to delete session file \{source_path}: \{error}")
  }
  if provider == "claude" {
    let sibling = @pathx.join(
      @pathx.dirname(source_path),
      @pathx.stem(source_path),
    )
    if @fsx.exists(sibling) {
      @fsx.remove(sibling) catch {
        _ => ()
      }
    }
  }
  Ok(true)
}

///|
fn moon_session_provider_label(provider : String) -> String {
  match provider {
    "codex" => "Codex"
    "claude" => "Claude"
    "gemini" => "Gemini"
    "opencode" => "OpenCode"
    "openclaw" => "OpenClaw"
    "hermes" => "Hermes"
    _ => provider
  }
}

///|
async fn moon_source_path_under_provider_roots(
  provider : String,
  source_path : String,
) -> Bool {
  let source_resolved = @fsx.resolve(source_path) catch { _ => return false }
  for root in moon_session_provider_roots(provider) {
    if !@fsx.exists(root) {
      continue
    }
    let root_resolved = @fsx.resolve(root) catch { _ => continue }
    if moon_path_has_root(source_resolved, root_resolved) {
      return true
    }
  }
  false
}

///|
fn moon_path_has_root(path : String, root : String) -> Bool {
  let clean_root = moon_trim_trailing_slash(root)
  path == clean_root || path.has_prefix(clean_root + "/")
}

///|
fn moon_trim_trailing_slash(path : String) -> String {
  let mut value = path
  while value.length() > 1 && value.has_suffix("/") {
    value = value[:value.length() - 1].to_owned()
  }
  value
}

///|
async fn moon_collect_provider_session_files(
  provider : String,
) -> Array[String] {
  let files = []
  for root in moon_session_provider_roots(provider) {
    match provider {
      "gemini" => moon_collect_gemini_chat_files(root, files)
      "hermes" => moon_collect_session_files(root, files, max_depth=1)
      _ => moon_collect_session_files(root, files, max_depth=8)
    }
  }
  files
}

///|
fn moon_session_provider_roots(provider : String) -> Array[String] {
  match moon_normalize_app_type(provider) {
    "codex" =>
      [
        @pathx.join(moon_config_dir("codex"), "sessions"),
        @pathx.join(moon_config_dir("codex"), "archived_sessions"),
      ]
    "claude" => [@pathx.join(moon_config_dir("claude"), "projects")]
    "gemini" => [@pathx.join(moon_config_dir("gemini"), "tmp")]
    "opencode" => [moon_opencode_data_dir()]
    "openclaw" => [@pathx.join(moon_config_dir("openclaw"), "agents")]
    "hermes" => [@pathx.join(moon_config_dir("hermes"), "sessions")]
    _ => []
  }
}

///|
fn moon_opencode_data_dir() -> String {
  let xdg = @os.getenv("XDG_DATA_HOME") catch { _ => None }
  match xdg {
    Some(base) if !base.trim().is_empty() =>
      @pathx.join(base.trim(), "opencode")
    _ => @pathx.join(@pathx.join(moon_home_dir(), ".local/share"), "opencode")
  }
}

///|
fn moon_opencode_db_path() -> String {
  @pathx.join(moon_opencode_data_dir(), "opencode.db")
}

///|
fn moon_hermes_db_path() -> String {
  @pathx.join(moon_config_dir("hermes"), "state.db")
}

///|
async fn moon_scan_opencode_sessions() -> Array[MoonSessionMeta] {
  let sqlite_sessions = moon_scan_opencode_sqlite_sessions()
  let result = sqlite_sessions.copy()
  for path in moon_collect_provider_session_files("opencode") {
    match moon_parse_generic_json_session(path, "opencode") {
      Some(meta) if !moon_session_has_id(sqlite_sessions, meta.session_id) =>
        result.push(meta)
      _ => ()
    }
  }
  result
}

///|
async fn moon_scan_hermes_sessions() -> Array[MoonSessionMeta] {
  let sqlite_sessions = moon_scan_hermes_sqlite_sessions()
  let result = sqlite_sessions.copy()
  for path in moon_collect_provider_session_files("hermes") {
    match moon_parse_generic_json_session(path, "hermes") {
      Some(meta) if !moon_session_has_id(sqlite_sessions, meta.session_id) =>
        result.push(meta)
      _ => ()
    }
  }
  result
}

///|
fn moon_session_has_id(
  sessions : Array[MoonSessionMeta],
  session_id : String,
) -> Bool {
  sessions.any(fn(session) { session.session_id == session_id })
}

///|
async fn moon_scan_opencode_sqlite_sessions() -> Array[MoonSessionMeta] {
  let db_path = moon_opencode_db_path()
  if !@fsx.exists_as_file(db_path) {
    return []
  }
  let rows = match
    moon_sqlite_json_rows(
      db_path,
      "SELECT id, title, directory, time_created, time_updated FROM session ORDER BY time_updated DESC",
      read_only=true,
    ) {
    Ok(rows) => rows
    Err(_) => return []
  }
  moon_opencode_sqlite_rows_to_sessions(db_path, rows)
}

///|
fn moon_opencode_sqlite_rows_to_sessions(
  db_path : String,
  rows : Array[Json],
) -> Array[MoonSessionMeta] {
  let sessions = []
  for row in rows {
    guard row is Object(obj) else { continue }
    guard moon_json_string(obj.get("id")) is Some(session_id) else { continue }
    let directory = moon_json_string(obj.get("directory")).unwrap_or("")
    let raw_title = moon_json_string(obj.get("title")).unwrap_or("")
    let display_title = if raw_title.is_empty() {
      moon_path_basename(directory)
    } else {
      Some(raw_title)
    }
    sessions.push(MoonSessionMeta::{
      provider_id: "opencode",
      session_id,
      title: display_title,
      summary: display_title,
      project_dir: if directory.is_empty() {
        None
      } else {
        Some(directory)
      },
      created_at: moon_json_int64(obj.get("time_created")),
      last_active_at: moon_json_int64(obj.get("time_updated")),
      source_path: Some("sqlite:\{db_path}:\{session_id}"),
      resume_command: Some("opencode session resume \{session_id}"),
    })
  }
  sessions
}

///|
async fn moon_scan_hermes_sqlite_sessions() -> Array[MoonSessionMeta] {
  let db_path = moon_hermes_db_path()
  if !@fsx.exists_as_file(db_path) {
    return []
  }
  let rows = match
    moon_sqlite_json_rows(
      db_path,
      "SELECT * FROM sessions ORDER BY rowid DESC LIMIT 500",
      read_only=true,
    ) {
    Ok(rows) => rows
    Err(_) => return []
  }
  moon_hermes_sqlite_rows_to_sessions(db_path, rows)
}

///|
fn moon_hermes_sqlite_rows_to_sessions(
  db_path : String,
  rows : Array[Json],
) -> Array[MoonSessionMeta] {
  let sessions = []
  for row in rows {
    guard row is Object(obj) else { continue }
    guard moon_json_string(obj.get("id")) is Some(session_id) else { continue }
    let title = match moon_json_string(obj.get("title")) {
      Some(value) if !value.is_empty() =>
        Some(moon_truncate_summary(value, moon_session_title_max_chars))
      _ => None
    }
    let cwd = match
      moon_first_string(
        moon_json_string(obj.get("cwd")),
        moon_json_string(obj.get("directory")),
      ) {
      Some(value) if !value.is_empty() => Some(value)
      _ => None
    }
    let started_at = moon_first_timestamp(
      moon_json_timestamp_ms(obj.get("started_at")),
      moon_json_timestamp_ms(obj.get("created_at")),
    )
    let ended_at = moon_first_timestamp(
      moon_json_timestamp_ms(obj.get("ended_at")),
      moon_json_timestamp_ms(obj.get("updated_at")),
    )
    sessions.push(MoonSessionMeta::{
      provider_id: "hermes",
      session_id,
      title,
      summary: None,
      project_dir: cwd,
      created_at: started_at,
      last_active_at: moon_first_timestamp(ended_at, started_at),
      source_path: Some("sqlite:\{db_path}#\{session_id}"),
      resume_command: None,
    })
  }
  sessions
}

///|
async fn moon_collect_session_files(
  root : String,
  files : Array[String],
  max_depth~ : Int,
) -> Unit {
  moon_collect_session_files_at(root, files, depth=0, max_depth~)
}

///|
async fn moon_collect_session_files_at(
  dir : String,
  files : Array[String],
  depth~ : Int,
  max_depth~ : Int,
) -> Unit {
  if depth > max_depth || !@fsx.exists(dir) {
    return
  }
  let entries = @fsx.list_directory(dir) catch { _ => return }
  for entry in entries {
    if entry.kind is Directory {
      moon_collect_session_files_at(
        entry.path,
        files,
        depth=depth + 1,
        max_depth~,
      )
    } else if entry.kind is Regular && moon_session_file_name(entry.name) {
      files.push(entry.path)
    }
  }
}

///|
fn moon_session_file_name(name : String) -> Bool {
  name.has_suffix(".jsonl") || name.has_suffix(".json")
}

///|
async fn moon_collect_gemini_chat_files(
  tmp_dir : String,
  files : Array[String],
) -> Unit {
  if !@fsx.exists(tmp_dir) {
    return
  }
  let projects = @fsx.list_directory(tmp_dir) catch { _ => return }
  for project in projects {
    if !(project.kind is Directory) {
      continue
    }
    let chats_dir = @pathx.join(project.path, "chats")
    let chats = @fsx.list_directory(chats_dir) catch { _ => continue }
    for chat in chats {
      if chat.kind is Regular && moon_session_file_name(chat.name) {
        files.push(chat.path)
      }
    }
  }
}

///|
async fn moon_parse_codex_session(path : String) -> MoonSessionMeta? {
  let lines = moon_read_nonempty_lines(path)
  if lines.is_empty() {
    return None
  }
  moon_parse_codex_session_lines(lines, path)
}

///|
fn moon_parse_codex_session_lines(
  lines : Array[String],
  path : String,
) -> MoonSessionMeta? {
  let head = moon_head_lines(lines, 10)
  let tail = moon_tail_lines(lines, 30)
  let mut session_id : String? = None
  let mut project_dir : String? = None
  let mut created_at : Int64? = None
  let mut first_user_message : String? = None
  for line in head {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if created_at is None {
      created_at = moon_json_timestamp_ms(moon_json_get(value, "timestamp"))
    }
    if json_string_from_json(moon_json_get(value, "type")) ==
      Some("session_meta") {
      if moon_json_get(value, "payload") is Some(Object(payload)) {
        if moon_is_subagent_source(payload.get("source")) {
          return None
        }
        if session_id is None {
          session_id = json_string_from_map(payload, "id")
        }
        if project_dir is None {
          project_dir = json_string_from_map(payload, "cwd")
        }
        match moon_json_timestamp_ms(payload.get("timestamp")) {
          Some(ts) if created_at is None => created_at = Some(ts)
          _ => ()
        }
      }
    }
    if first_user_message is None &&
      json_string_from_json(moon_json_get(value, "type")) ==
      Some("response_item") &&
      moon_json_get(value, "payload") is Some(Object(payload)) &&
      json_string_from_map(payload, "type") == Some("message") &&
      json_string_from_map(payload, "role") == Some("user") {
      let text = moon_extract_json_text(payload.get("content"))
      match moon_codex_title_candidate(text) {
        Some(title) => first_user_message = Some(title)
        None => ()
      }
    }
  }
  let mut last_active_at : Int64? = None
  let mut summary : String? = None
  for line in moon_reversed_lines(tail) {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if last_active_at is None {
      last_active_at = moon_json_timestamp_ms(moon_json_get(value, "timestamp"))
    }
    if summary is None &&
      json_string_from_json(moon_json_get(value, "type")) ==
      Some("response_item") &&
      moon_json_get(value, "payload") is Some(Object(payload)) &&
      json_string_from_map(payload, "type") == Some("message") {
      let text = moon_extract_json_text(payload.get("content"))
      if !text.trim().is_empty() {
        summary = Some(moon_truncate_summary(text, 160))
      }
    }
  }
  let id = match session_id {
    Some(value) => value
    None => moon_infer_session_id_from_filename(path).unwrap_or("")
  }
  if id.is_empty() {
    return None
  }
  let title = match first_user_message {
    Some(value) =>
      Some(moon_truncate_summary(value, moon_session_title_max_chars))
    None =>
      match project_dir {
        Some(dir) => moon_path_basename(dir)
        None => None
      }
  }
  Some({
    provider_id: "codex",
    session_id: id,
    title,
    summary,
    project_dir,
    created_at,
    last_active_at,
    source_path: Some(path),
    resume_command: Some("codex resume \{id}"),
  })
}

///|
async fn moon_parse_claude_session(path : String) -> MoonSessionMeta? {
  if @pathx.basename(path).has_prefix("agent-") {
    return None
  }
  let lines = moon_read_nonempty_lines(path)
  if lines.is_empty() {
    return None
  }
  moon_parse_claude_session_lines(lines, path)
}

///|
fn moon_parse_claude_session_lines(
  lines : Array[String],
  path : String,
) -> MoonSessionMeta? {
  let head = moon_head_lines(lines, 10)
  let tail = moon_tail_lines(lines, 30)
  let mut session_id : String? = None
  let mut project_dir : String? = None
  let mut created_at : Int64? = None
  let mut first_user_message : String? = None
  for line in head {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if session_id is None {
      session_id = json_string_from_json(moon_json_get(value, "sessionId"))
    }
    if project_dir is None {
      project_dir = json_string_from_json(moon_json_get(value, "cwd"))
    }
    if created_at is None {
      created_at = moon_json_timestamp_ms(moon_json_get(value, "timestamp"))
    }
    if first_user_message is None {
      let is_user = json_string_from_json(moon_json_get(value, "type")) ==
        Some("user") ||
        (
          moon_json_get(value, "message") is Some(Object(message)) &&
          json_string_from_map(message, "role") == Some("user")
        )
      if is_user && moon_json_get(value, "message") is Some(Object(message)) {
        let text = moon_extract_json_text(message.get("content"))
        let trimmed = text.trim()
        if !trimmed.is_empty() &&
          !trimmed.contains("") &&
          !trimmed.has_prefix("") {
          first_user_message = Some(trimmed.to_owned())
        }
      }
    }
  }
  let mut last_active_at : Int64? = None
  let mut summary : String? = None
  let mut custom_title : String? = None
  for line in moon_reversed_lines(tail) {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if last_active_at is None {
      last_active_at = moon_json_timestamp_ms(moon_json_get(value, "timestamp"))
    }
    if custom_title is None &&
      json_string_from_json(moon_json_get(value, "type")) ==
      Some("custom-title") {
      match json_string_from_json(moon_json_get(value, "customTitle")) {
        Some(value) if !value.trim().is_empty() =>
          custom_title = Some(value.trim().to_owned())
        _ => ()
      }
    }
    if summary is None &&
      moon_json_get(value, "isMeta") != Some(Json::boolean(true)) &&
      moon_json_get(value, "message") is Some(Object(message)) {
      let text = moon_extract_json_text(message.get("content"))
      if !text.trim().is_empty() {
        summary = Some(moon_truncate_summary(text, 160))
      }
    }
  }
  let id = match session_id {
    Some(value) => value
    None => moon_infer_session_id_from_filename(path).unwrap_or("")
  }
  if id.is_empty() {
    return None
  }
  let title = match custom_title {
    Some(value) =>
      Some(moon_truncate_summary(value, moon_session_title_max_chars))
    None =>
      match first_user_message {
        Some(value) =>
          Some(moon_truncate_summary(value, moon_session_title_max_chars))
        None =>
          match project_dir {
            Some(dir) => moon_path_basename(dir)
            None => None
          }
      }
  }
  Some({
    provider_id: "claude",
    session_id: id,
    title,
    summary,
    project_dir,
    created_at,
    last_active_at,
    source_path: Some(path),
    resume_command: Some("claude --resume \{id}"),
  })
}

///|
async fn moon_parse_gemini_session(path : String) -> MoonSessionMeta? {
  let lines = moon_read_nonempty_lines(path)
  if lines.is_empty() {
    return None
  }
  moon_parse_gemini_session_lines(lines, path)
}

///|
fn moon_parse_gemini_session_lines(
  lines : Array[String],
  path : String,
) -> MoonSessionMeta? {
  let mut session_id = moon_infer_session_id_from_filename(path).unwrap_or("")
  let mut project_dir : String? = None
  let mut created_at : Int64? = None
  let mut last_active_at : Int64? = None
  let mut first_user_message : String? = None
  let mut summary : String? = None
  for line in lines {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if value is Object(obj) {
      match json_string_from_map_any(obj, ["sessionId", "id"]) {
        Some(value) if !value.is_empty() => session_id = value
        _ => ()
      }
      if project_dir is None {
        project_dir = json_string_from_map_any(obj, [
          "cwd", "projectDir", "project_dir",
        ])
      }
    }
    match
      moon_first_timestamp(
        moon_json_timestamp_ms(moon_json_get(value, "timestamp")),
        moon_json_timestamp_ms(moon_json_get(value, "ts")),
      ) {
      Some(ts) => {
        if created_at is None {
          created_at = Some(ts)
        }
        last_active_at = Some(ts)
      }
      None => ()
    }
    let role = moon_first_string(
      json_string_from_json(moon_json_get(value, "role")),
      match moon_json_get(value, "message") {
        Some(Object(message)) => json_string_from_map(message, "role")
        _ => None
      },
    )
    let content = moon_extract_json_text(
      match moon_json_get(value, "content") {
        Some(Null) | None =>
          match moon_json_get(value, "message") {
            Some(Object(message)) => message.get("content")
            _ => None
          }
        other => other
      },
    )
    if !content.trim().is_empty() {
      if role == Some("user") && first_user_message is None {
        first_user_message = Some(content.trim().to_owned())
      }
      summary = Some(moon_truncate_summary(content, 160))
    }
  }
  if session_id.is_empty() {
    return None
  }
  Some({
    provider_id: "gemini",
    session_id,
    title: first_user_message.map(fn(value) {
      moon_truncate_summary(value, moon_session_title_max_chars)
    }),
    summary,
    project_dir,
    created_at,
    last_active_at,
    source_path: Some(path),
    resume_command: None,
  })
}

///|
async fn moon_parse_generic_json_session(
  path : String,
  provider : String,
) -> MoonSessionMeta? {
  let lines = moon_read_nonempty_lines(path)
  if lines.is_empty() {
    return None
  }
  moon_parse_generic_json_session_lines(
    lines,
    path,
    moon_normalize_app_type(provider),
  )
}

///|
fn moon_parse_generic_json_session_lines(
  lines : Array[String],
  path : String,
  provider : String,
) -> MoonSessionMeta? {
  let mut session_id : String? = None
  let mut title : String? = None
  let mut project_dir : String? = None
  let mut first_user_message : String? = None
  let mut created_at : Int64? = None
  let mut last_active_at : Int64? = None
  for line in lines {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if value is Object(obj) {
      if session_id is None {
        session_id = json_string_from_map_any(obj, [
          "id", "sessionId", "session_id",
        ])
      }
      if title is None {
        title = json_string_from_map(obj, "title")
      }
      if project_dir is None {
        project_dir = json_string_from_map_any(obj, [
          "cwd", "directory", "projectDir", "project_dir",
        ])
      }
      let value_type = json_string_from_map(obj, "type")
      let message = match obj.get("message") {
        Some(Object(message)) => Some(message)
        _ => None
      }
      let role = moon_first_string(
        json_string_from_map(obj, "role"),
        match message {
          Some(message) => json_string_from_map(message, "role")
          None => None
        },
      )
      let content = moon_extract_json_text(
        match obj.get("content") {
          Some(value) => Some(value)
          None =>
            match message {
              Some(message) => message.get("content")
              None => None
            }
        },
      )
      if role == Some("user") &&
        first_user_message is None &&
        !content.trim().is_empty() {
        first_user_message = Some(content.trim().to_owned())
      }
      let ts = moon_first_timestamp(
        moon_json_timestamp_ms(obj.get("timestamp")),
        moon_json_timestamp_ms(obj.get("ts")),
      )
      match ts {
        Some(ts) => {
          if created_at is None {
            created_at = Some(ts)
          }
          last_active_at = Some(ts)
        }
        None => ()
      }
      if value_type == Some("session") || value_type == Some("init") {
        continue
      }
    }
  }
  let id = match session_id {
    Some(value) if !value.is_empty() => value
    _ => moon_infer_session_id_from_filename(path).unwrap_or("")
  }
  if id.is_empty() {
    return None
  }
  Some({
    provider_id: provider,
    session_id: id,
    title: moon_first_string(
      title,
      first_user_message.map(fn(value) {
        moon_truncate_summary(value, moon_session_title_max_chars)
      }),
    ),
    summary: first_user_message.map(fn(value) {
      moon_truncate_summary(value, 160)
    }),
    project_dir,
    created_at,
    last_active_at,
    source_path: Some(path),
    resume_command: None,
  })
}

///|
priv struct MoonSqliteSessionSource {
  db_path : String
  session_id : String
}

///|
async fn moon_load_opencode_sqlite_messages(
  source_path : String,
) -> Result[Array[MoonSessionMessage], String] {
  guard moon_parse_opencode_sqlite_source(source_path) is Some(source) else {
    return Err("Invalid SQLite source reference: \{source_path}")
  }
  let query = (
    #|SELECT
    #|  m.id AS message_id,
    #|  m.time_created AS ts,
    #|  m.data AS message_data,
    #|  json_group_array(p.data) AS parts
    #|FROM message m
    #|LEFT JOIN part p ON p.session_id = m.session_id AND p.message_id = m.id
    #|WHERE m.session_id = $SESSION
    #|GROUP BY m.id, m.time_created, m.data
    #|ORDER BY m.time_created ASC;
  ).replace_all(old="$SESSION", new=moon_sqlite_quote(source.session_id))
  let rows = match
    moon_sqlite_json_rows(source.db_path, query, read_only=true) {
    Ok(rows) => rows
    Err(error) => return Err(error)
  }
  Ok(moon_opencode_sqlite_rows_to_messages(rows))
}

///|
fn moon_opencode_sqlite_rows_to_messages(
  rows : Array[Json],
) -> Array[MoonSessionMessage] {
  let messages = []
  for row in rows {
    guard row is Object(obj) else { continue }
    guard moon_json_string(obj.get("message_data")) is Some(message_data) else {
      continue
    }
    let message_value = @json.parse(message_data) catch { _ => Json::null() }
    let role = (match message_value {
      Object(message) => json_string_from_map(message, "role")
      _ => None
    }).unwrap_or("unknown")
    let parts = match moon_json_string(obj.get("parts")) {
      Some(parts_json) => moon_opencode_parts_text(parts_json)
      None => ""
    }
    if parts.trim().is_empty() {
      continue
    }
    messages.push(MoonSessionMessage::{
      role,
      content: parts,
      ts: moon_json_int64(obj.get("ts")),
    })
  }
  messages
}

///|
fn moon_opencode_parts_text(parts_json : String) -> String {
  let parsed = @json.parse(parts_json) catch { _ => return "" }
  guard parsed is Array(parts) else { return "" }
  let texts = []
  for raw_part in parts {
    guard moon_json_string(Some(raw_part)) is Some(part_text) else { continue }
    let part_json = @json.parse(part_text) catch { _ => continue }
    match moon_opencode_part_text(part_json) {
      Some(text) if !text.trim().is_empty() => texts.push(text)
      _ => ()
    }
  }
  texts.join("\n")
}

///|
fn moon_opencode_part_text(part : Json) -> String? {
  guard part is Object(obj) else { return None }
  match json_string_from_map(obj, "type") {
    Some("text") =>
      match json_string_from_map(obj, "text") {
        Some(text) if !text.trim().is_empty() => Some(text)
        _ => None
      }
    Some("tool") =>
      Some("[Tool: \{json_string_from_map(obj, "tool").unwrap_or("unknown")}]")
    _ => None
  }
}

///|
async fn moon_load_hermes_sqlite_messages(
  source_path : String,
) -> Result[Array[MoonSessionMessage], String] {
  guard moon_parse_hermes_sqlite_source(source_path) is Some(source) else {
    return Err("Invalid SQLite source reference: \{source_path}")
  }
  let query = (
    #|SELECT role, content, created_at
    #|FROM messages
    #|WHERE session_id = $SESSION
    #|ORDER BY created_at ASC;
  ).replace_all(old="$SESSION", new=moon_sqlite_quote(source.session_id))
  let rows = match
    moon_sqlite_json_rows(source.db_path, query, read_only=true) {
    Ok(rows) => rows
    Err(error) => return Err(error)
  }
  let messages = []
  for row in rows {
    guard row is Object(obj) else { continue }
    guard moon_json_string(obj.get("role")) is Some(role) else { continue }
    guard moon_json_string(obj.get("content")) is Some(content) else {
      continue
    }
    if content.trim().is_empty() {
      continue
    }
    messages.push(MoonSessionMessage::{
      role,
      content,
      ts: moon_json_timestamp_ms(obj.get("created_at")),
    })
  }
  Ok(messages)
}

///|
async fn moon_delete_opencode_sqlite_session(
  session_id : String,
  source_path : String,
) -> Result[Bool, String] {
  moon_delete_opencode_sqlite_session_with_expected(
    session_id,
    source_path,
    moon_opencode_db_path(),
  )
}

///|
async fn moon_delete_opencode_sqlite_session_with_expected(
  session_id : String,
  source_path : String,
  expected_db_path : String,
) -> Result[Bool, String] {
  guard moon_parse_opencode_sqlite_source(source_path) is Some(source) else {
    return Err("Invalid SQLite source reference: \{source_path}")
  }
  if source.session_id != session_id {
    return Err(
      "OpenCode SQLite session ID mismatch: expected \{session_id}, found \{source.session_id}",
    )
  }
  match
    moon_validate_sqlite_db_path(source.db_path, expected_db_path, "OpenCode") {
    Ok(_) => ()
    Err(error) => return Err(error)
  }
  let deleted = match
    moon_sqlite_count_session(source.db_path, "session", "id", session_id) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let quoted = moon_sqlite_quote(session_id)
  let query = (
    #|BEGIN;
    #|DELETE FROM part WHERE session_id = $SESSION;
    #|DELETE FROM message WHERE session_id = $SESSION;
    #|DELETE FROM session WHERE id = $SESSION;
    #|COMMIT;
  ).replace_all(old="$SESSION", new=quoted)
  match moon_sqlite_exec(source.db_path, query) {
    Ok(_) => ()
    Err(error) => return Err(error)
  }
  Ok(deleted > 0)
}

///|
async fn moon_delete_hermes_sqlite_session(
  session_id : String,
  source_path : String,
) -> Result[Bool, String] {
  moon_delete_hermes_sqlite_session_with_expected(
    session_id,
    source_path,
    moon_hermes_db_path(),
  )
}

///|
async fn moon_delete_hermes_sqlite_session_with_expected(
  session_id : String,
  source_path : String,
  expected_db_path : String,
) -> Result[Bool, String] {
  guard moon_parse_hermes_sqlite_source(source_path) is Some(source) else {
    return Err("Invalid SQLite source reference: \{source_path}")
  }
  if source.session_id != session_id {
    return Err(
      "Hermes SQLite session ID mismatch: expected \{session_id}, found \{source.session_id}",
    )
  }
  match
    moon_validate_sqlite_db_path(source.db_path, expected_db_path, "Hermes") {
    Ok(_) => ()
    Err(error) => return Err(error)
  }
  let deleted = match
    moon_sqlite_count_session(source.db_path, "sessions", "id", session_id) {
    Ok(value) => value
    Err(error) => return Err(error)
  }
  let quoted = moon_sqlite_quote(session_id)
  ignore(
    moon_sqlite_exec(
      source.db_path,
      "DELETE FROM messages WHERE session_id = \{quoted};",
    ),
  )
  match
    moon_sqlite_exec(
      source.db_path,
      "DELETE FROM sessions WHERE id = \{quoted};",
    ) {
    Ok(_) => ()
    Err(error) => return Err(error)
  }
  Ok(deleted > 0)
}

///|
fn moon_parse_opencode_sqlite_source(
  source : String,
) -> MoonSqliteSessionSource? {
  guard source.has_prefix("sqlite:") else { return None }
  let rest = source["sqlite:".length():].to_owned()
  let sep = moon_last_index_of(rest, ":ses_")
  guard sep >= 0 else { return None }
  let db_path = rest[:sep].to_owned()
  let session_id = rest[sep + 1:].to_owned()
  if db_path.is_empty() || session_id.is_empty() {
    None
  } else {
    Some({ db_path, session_id })
  }
}

///|
fn moon_parse_hermes_sqlite_source(source : String) -> MoonSqliteSessionSource? {
  guard source.has_prefix("sqlite:") else { return None }
  let rest = source["sqlite:".length():].to_owned()
  let sep = moon_last_index_of(rest, "#")
  guard sep >= 0 else { return None }
  let db_path = rest[:sep].to_owned()
  let session_id = rest[sep + 1:].to_owned()
  if db_path.is_empty() || session_id.is_empty() {
    None
  } else {
    Some({ db_path, session_id })
  }
}

///|
fn moon_last_index_of(value : String, needle : String) -> Int {
  let mut offset = 0
  let mut last = -1
  while offset < value.length() {
    match value[offset:].find(needle) {
      Some(index) => {
        last = offset + index
        offset = last + 1
      }
      None => return last
    }
  }
  last
}

///|
async fn moon_validate_sqlite_db_path(
  db_path : String,
  expected_path : String,
  provider_label : String,
) -> Result[Unit, String] {
  let db_resolved = @fsx.resolve(db_path) catch {
    error => return Err("Failed to canonicalize SQLite database path: \{error}")
  }
  let expected_resolved = @fsx.resolve(expected_path) catch {
    error =>
      return Err(
        "Failed to canonicalize expected \{provider_label} database path: \{error}",
      )
  }
  if db_resolved != expected_resolved {
    return Err("SQLite path does not match expected \{provider_label} database")
  }
  Ok(())
}

///|
async fn moon_sqlite_count_session(
  db_path : String,
  table : String,
  id_column : String,
  session_id : String,
) -> Result[Int, String] {
  let rows = match
    moon_sqlite_json_rows(
      db_path,
      "SELECT COUNT(*) AS deleted FROM \{table} WHERE \{id_column} = \{moon_sqlite_quote(session_id)};",
      read_only=true,
    ) {
    Ok(rows) => rows
    Err(error) => return Err(error)
  }
  guard rows.length() > 0 && rows[0] is Object(obj) else { return Ok(0) }
  Ok(moon_json_int64(obj.get("deleted")).unwrap_or(0L).to_int())
}

///|
async fn moon_sqlite_json_rows(
  db_path : String,
  query : String,
  read_only~ : Bool,
) -> Result[Array[Json], String] {
  let process = try {
    if read_only {
      @spawn.spawn(
        "sqlite3",
        ["-readonly", "-json", db_path, query],
        timeout=10000,
      )
    } else {
      @spawn.spawn("sqlite3", ["-json", db_path, query], timeout=10000)
    }
  } catch {
    error => return Err("SQLite query failed \{db_path}: \{error}")
  }
  if process.status != 0 {
    return Err("SQLite query failed \{db_path}: \{process.stderr.trim()}")
  }
  if process.stdout.trim().is_empty() {
    return Ok([])
  }
  let parsed = @json.parse(process.stdout) catch {
    error => return Err("SQLite JSON parse failed: \{error}")
  }
  guard parsed is Array(rows) else {
    return Err("SQLite JSON output was not an array")
  }
  Ok(rows)
}

///|
async fn moon_sqlite_exec(
  db_path : String,
  query : String,
) -> Result[Unit, String] {
  let process = @spawn.spawn("sqlite3", [db_path, query], timeout=10000) catch {
    error => return Err("SQLite query failed \{db_path}: \{error}")
  }
  if process.status != 0 {
    return Err("SQLite query failed \{db_path}: \{process.stderr.trim()}")
  }
  Ok(())
}

///|
fn moon_sqlite_quote(value : String) -> String {
  "'\{value.replace_all(old="'", new="''")}'"
}

///|
fn moon_json_string(value : Json?) -> String? {
  match value {
    Some(String(value)) => Some(value)
    Some(Number(n, ..)) => Some(n.to_string())
    _ => None
  }
}

///|
fn moon_json_int64(value : Json?) -> Int64? {
  match value {
    Some(Number(n, ..)) => Some(n.to_int64())
    Some(String(raw)) =>
      Some(@string.parse_int64(raw.trim().to_owned(), base=10)) catch {
        _ => None
      }
    _ => None
  }
}

///|
fn moon_load_codex_messages(content : String) -> Array[MoonSessionMessage] {
  let messages = []
  for line in moon_nonempty_lines_from_content(content) {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    guard json_string_from_json(moon_json_get(value, "type")) ==
      Some("response_item") else {
      continue
    }
    guard moon_json_get(value, "payload") is Some(Object(payload)) else {
      continue
    }
    let payload_type = json_string_from_map(payload, "type").unwrap_or("")
    let (role, message) = match payload_type {
      "message" =>
        (
          json_string_from_map(payload, "role").unwrap_or("unknown"),
          moon_extract_json_text(payload.get("content")),
        )
      "function_call" =>
        (
          "assistant",
          "[Tool: \{json_string_from_map(payload, "name").unwrap_or("unknown")}]",
        )
      "function_call_output" =>
        ("tool", json_string_from_map(payload, "output").unwrap_or(""))
      _ => continue
    }
    if message.trim().is_empty() {
      continue
    }
    messages.push(MoonSessionMessage::{
      role,
      content: message,
      ts: moon_json_timestamp_ms(moon_json_get(value, "timestamp")),
    })
  }
  messages
}

///|
fn moon_load_claude_messages(content : String) -> Array[MoonSessionMessage] {
  let messages = []
  for line in moon_nonempty_lines_from_content(content) {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    if moon_json_get(value, "isMeta") == Some(Json::boolean(true)) {
      continue
    }
    guard moon_json_get(value, "message") is Some(Object(message)) else {
      continue
    }
    let mut role = json_string_from_map(message, "role").unwrap_or("unknown")
    match message.get("content") {
      Some(Array(items)) if role == "user" &&
        !items.is_empty() &&
        items.all(fn(item) {
          item is Object(obj) &&
          json_string_from_map(obj, "type") == Some("tool_result")
        }) => role = "tool"
      _ => ()
    }
    let text = moon_extract_json_text(message.get("content"))
    if text.trim().is_empty() {
      continue
    }
    messages.push(MoonSessionMessage::{
      role,
      content: text,
      ts: moon_json_timestamp_ms(moon_json_get(value, "timestamp")),
    })
  }
  messages
}

///|
fn moon_load_gemini_messages(content : String) -> Array[MoonSessionMessage] {
  moon_load_generic_json_messages(content)
}

///|
fn moon_load_generic_json_messages(
  content : String,
) -> Array[MoonSessionMessage] {
  let messages = []
  for line in moon_nonempty_lines_from_content(content) {
    guard moon_parse_json_line(line) is Some(value) else { continue }
    let (role, content_value, ts_value) = match value {
      Object(obj) =>
        if json_string_from_map(obj, "type") == Some("message") &&
          obj.get("message") is Some(Object(message)) {
          (
            json_string_from_map(message, "role"),
            message.get("content"),
            moon_first_json(obj.get("timestamp"), message.get("ts")),
          )
        } else {
          (
            json_string_from_map(obj, "role"),
            obj.get("content"),
            moon_first_json(obj.get("timestamp"), obj.get("ts")),
          )
        }
      _ => (None, None, None)
    }
    guard role is Some(role) else { continue }
    let text = moon_extract_json_text(content_value)
    if text.trim().is_empty() {
      continue
    }
    messages.push(MoonSessionMessage::{
      role,
      content: text,
      ts: moon_json_timestamp_ms(ts_value),
    })
  }
  messages
}

///|
async fn moon_read_nonempty_lines(path : String) -> Array[String] {
  let content = moon_read_session_file_text(path) catch { _ => return [] }
  moon_nonempty_lines_from_content(content)
}

///|
async fn moon_read_session_file_text(path : String) -> String {
  let file = @fs.open(path, mode=ReadOnly)
  defer file.close()
  let size = file.size() catch { _ => moon_session_read_cap.to_int64() }
  let limit = if size < moon_session_read_cap.to_int64() {
    size.to_int()
  } else {
    moon_session_read_cap
  }
  if limit <= 0 {
    return ""
  }
  let buf = FixedArray::make(limit, b'\x00')
  let n = file.read_at(buf, position=0L, len=limit) catch { _ => 0 }
  if n <= 0 {
    return ""
  }
  let bytes = buf.unsafe_reinterpret_as_bytes()
  @encoding/utf8.decode(bytes[:n])
}

///|
fn moon_nonempty_lines_from_content(content : String) -> Array[String] {
  let lines = []
  for raw in content.split("\n") {
    let line = raw.trim()
    if !line.is_empty() {
      lines.push(line.to_owned())
    }
  }
  lines
}

///|
fn moon_head_lines(lines : Array[String], count : Int) -> Array[String] {
  let result = []
  let limit = if lines.length() < count { lines.length() } else { count }
  for i in 0.. Array[String] {
  let result = []
  let start = if lines.length() > count { lines.length() - count } else { 0 }
  for i in start.. Array[String] {
  let result = []
  if lines.is_empty() {
    return result
  }
  for i = lines.length() - 1; i >= 0; i = i - 1 {
    result.push(lines[i])
  }
  result
}

///|
fn moon_parse_json_line(line : String) -> Json? {
  let parsed = @json.parse(line) catch { _ => return None }
  Some(parsed)
}

///|
fn moon_json_get(value : Json, key : String) -> Json? {
  match value {
    Object(obj) => obj.get(key)
    _ => None
  }
}

///|
fn moon_first_string(first : String?, second : String?) -> String? {
  match first {
    Some(value) => Some(value)
    None => second
  }
}

///|
fn moon_first_timestamp(first : Int64?, second : Int64?) -> Int64? {
  match first {
    Some(value) => Some(value)
    None => second
  }
}

///|
fn moon_first_json(first : Json?, second : Json?) -> Json? {
  match first {
    Some(value) => Some(value)
    None => second
  }
}

///|
fn moon_json_timestamp_ms(value : Json?) -> Int64? {
  match value {
    Some(Number(n, ..)) => {
      let raw = n.to_int64()
      if raw > 1_000_000_000_000L {
        Some(raw)
      } else {
        Some(raw * 1000L)
      }
    }
    Some(String(raw)) => {
      let trimmed = raw.trim()
      if trimmed.is_empty() {
        None
      } else {
        let parsed_int = try
          @string.parse_int64(trimmed.to_owned(), base=10)
        catch {
          _ => None
        } noraise {
          parsed => Some(parsed)
        }
        match parsed_int {
          Some(raw) =>
            if raw > 1_000_000_000_000L {
              Some(raw)
            } else {
              Some(raw * 1000L)
            }
          None =>
            match parse_session_timestamp_seconds(trimmed.to_owned()) {
              Some(seconds) => Some(seconds.to_int64() * 1000L)
              None => None
            }
        }
      }
    }
    _ => None
  }
}

///|
fn json_string_from_json(value : Json?) -> String? {
  match value {
    Some(String(value)) => Some(value)
    _ => None
  }
}

///|
fn moon_extract_json_text(content : Json?) -> String {
  match content {
    Some(String(text)) => text
    Some(Array(items)) => {
      let parts = []
      for item in items {
        match moon_extract_json_text_item(item) {
          Some(text) if !text.trim().is_empty() => parts.push(text)
          _ => ()
        }
      }
      parts.join("\n")
    }
    Some(Object(obj)) => json_string_from_map(obj, "text").unwrap_or("")
    _ => ""
  }
}

///|
fn moon_extract_json_text_item(item : Json) -> String? {
  guard item is Object(obj) else { return None }
  let item_type = json_string_from_map(obj, "type").unwrap_or("")
  if item_type == "tool_use" {
    return Some(
      "[Tool: \{json_string_from_map(obj, "name").unwrap_or("unknown")}]",
    )
  }
  if item_type == "tool_result" {
    match obj.get("content") {
      Some(content) => {
        let text = moon_extract_json_text(Some(content))
        if text.is_empty() {
          return None
        }
        return Some(text)
      }
      None => return None
    }
  }
  for key in ["text", "input_text", "output_text"] {
    match json_string_from_map(obj, key) {
      Some(text) => return Some(text)
      None => ()
    }
  }
  match obj.get("content") {
    Some(content) => {
      let text = moon_extract_json_text(Some(content))
      if text.is_empty() {
        None
      } else {
        Some(text)
      }
    }
    None => None
  }
}

///|
fn moon_truncate_summary(text : String, max_chars : Int) -> String {
  let trimmed = text.trim()
  if trimmed.length() <= max_chars {
    trimmed.to_owned()
  } else {
    trimmed[:max_chars].to_owned() + "..."
  }
}

///|
fn moon_path_basename(value : String) -> String? {
  let trimmed = value.trim()
  if trimmed.is_empty() {
    None
  } else {
    let base = @pathx.basename(trimmed)
    if base.is_empty() {
      None
    } else {
      Some(base.to_owned())
    }
  }
}

///|
fn moon_infer_session_id_from_filename(path : String) -> String? {
  let stem = @pathx.stem(path).to_owned()
  if stem.is_empty() {
    None
  } else {
    Some(stem)
  }
}

///|
fn moon_is_subagent_source(source : Json?) -> Bool {
  match source {
    Some(String(value)) => value.to_lower().contains("subagent")
    Some(Object(obj)) =>
      json_string_from_map_any(obj, ["type", "kind"])
      .map(fn(value) { value.to_lower().contains("subagent") })
      .unwrap_or(false)
    _ => false
  }
}

///|
fn moon_codex_title_candidate(text : String) -> String? {
  let trimmed = text.trim()
  if trimmed.is_empty() {
    return None
  }
  let vscode_prefix = "# Context from my IDE setup:"
  if trimmed.has_prefix(vscode_prefix) {
    match trimmed.find("my request for codex") {
      Some(index) => {
        let candidate = trimmed[index + "my request for codex".length():].trim()
        if candidate.is_empty() {
          None
        } else {
          Some(candidate.to_owned())
        }
      }
      None => None
    }
  } else {
    Some(trimmed.to_owned())
  }
}