๐Ÿ“„ session.ts  โ€ข  8074 bytes
import { t, getLang } from '../i18n.js'

/**
 * ๅค„็† /session ็ณปๅˆ—ๅ‘ฝไปค๏ผšlist / read / delete / cleanup
 * ไปฅๅŠ /card /sessions /history ๅˆซๅ
 */
export async function handleSessionCommand(
  trimmed: string,
  color: any,
  ACCENT: string,
  MUTED: string,
  SUCCESS: string,
  ERROR: string,
  WARN: string,
  askQuestion: (q: string) => Promise<string>
): Promise<boolean> {
  const currentLang = getLang()

  // /session list
  if (trimmed === '/session' || trimmed === '/session list') {
    const { listPlaintextSessions } = await import('../apikeys.js')

    const sessions = listPlaintextSessions()
    console.log('')
    console.log(`  ${ACCENT}๐Ÿ“‹ ${t('session.list_title')}${color.reset}`)
    console.log(`  ${ACCENT}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
    if (sessions.length === 0) {
      console.log(`  ${MUTED}${t('session.no_records')}${color.reset}`)
    } else {
      sessions.forEach((s: any, i: number) => {
        const time = new Date(s.updatedAt).toLocaleString(getLang() === 'zh' ? 'zh-CN' : 'en-US')
        console.log(`  ${ACCENT}[${i + 1}] ${s.id}${color.reset}`)
        console.log(`      ${t("session.messages")}: ${s.messageCount} ยท ${time}`)
        if (s.preview) console.log(`      ${t("session.preview")}: ${s.preview.substring(0, 50)}`)
        console.log('')
      })
      console.log(`  ${MUTED}${t('session.total')}: ${sessions.length}${color.reset}`)
    }
    console.log(`  ${MUTED}${t("session.read_hint")}${color.reset}`)
    console.log(`  ${MUTED}${t("session.commands_hint")}${color.reset}`)
    return true
  }

  // /session read <id>
  if (trimmed.startsWith('/session read ')) {
    const { readSession } = await import('../apikeys.js')
    const match = trimmed.match(/\/session read\s+(\S+)/)
    if (!match) {
      console.log(`  ${ERROR}${t("session.specify_id")}${color.reset}`)
      return true
    }
    const sessionId = match[1]
    const result = readSession(sessionId)
    if (!result) {
      console.log(`  ${ERROR}${t("session.not_found")} ${sessionId}${color.reset}`)
    } else {
      console.log('')
      console.log(`  ${ACCENT}๐Ÿ“– ${t("session.detail_title")} ${sessionId}${color.reset}`)
      console.log(`  ${ACCENT}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
      console.log(`  ${t("session.detail_count")} ${result.messages.length}`)
      console.log(`  ${t("session.detail_size")} ${(result.size / 1024).toFixed(1)} KB`)
      console.log(`  ${t('session.detail_created')} ${new Date(result.createdAt).toLocaleString(currentLang === 'zh' ? 'zh-CN' : 'en-US')}`)
      console.log(`  ${t('session.detail_modified')} ${new Date(result.updatedAt).toLocaleString(currentLang === 'zh' ? 'zh-CN' : 'en-US')}`)
      console.log('')
      console.log(`  ${ACCENT}${t("session.detail_content")}${color.reset}\n`)
      let lineCount = 0
      const PAGE_SIZE = 50
      let aborted = false
      for (let mi = 0; mi < result.messages.length && !aborted; mi++) {
        const m: any = result.messages[mi]
        const content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content)
        const truncated = content.length > 1000 ? content.substring(0, 1000) + `\n... ${t('session.truncated')}` : content
        const lines = truncated.split('\n')
        const roleLine = `[${mi + 1}] ${m.role || 'unknown'}`
        console.log(`  ${MUTED}${roleLine}${color.reset}`)
        console.log(`  ${lines.join('\n  ')}`)
        console.log('')
        lineCount += lines.length + 2
        // ๅˆ†้กต๏ผšๆฏ50่กŒๆš‚ๅœ๏ผˆๅธฆ่ฟ›ๅบฆๆŒ‡็คบ๏ผ‰
        if (lineCount >= PAGE_SIZE && mi < result.messages.length - 1) {
          const progress = `[${mi + 1}/${result.messages.length}]`
          console.log(`  ${WARN}โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”${color.reset}`)
          const cont = await askQuestion(`  ${WARN}${t("session.page_hint")} ${MUTED}${progress}${color.reset} `)
          console.log(`  ${WARN}โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”${color.reset}`)
          if (cont.trim().toLowerCase() === 'q') {
            aborted = true
          }
          lineCount = 0
        }
      }
      console.log(`  ${MUTED}${t("session.back_hint")}${color.reset}`)
    }
    return true
  }

  // /session delete <id>
  if (trimmed.startsWith('/session delete ')) {
    const { deleteSession } = await import('../apikeys.js')
    const match = trimmed.match(/\/session delete\s+(\S+)/)
    if (!match) {
      console.log(`  ${ERROR}${t("session.specify_delete_id")}${color.reset}`)
      return true
    }
    const sessionId = match[1]
    const confirm = await askQuestion(`  ${WARN}${t("session.confirm_delete", {id: sessionId})} ${color.reset}`)
    if (confirm.toLowerCase() !== 'y') {
      console.log(`  ${MUTED}${t("model.cancelled")}${color.reset}`)
      return true
    }
    if (deleteSession(sessionId)) {
      console.log(`  ${SUCCESS}โœ“ ${t("session.deleted")} ${sessionId}${color.reset}`)
    } else {
      console.log(`  ${ERROR}โœ— ${t("session.delete_failed")} ${sessionId}${color.reset}`)
    }
    return true
  }

  // /session cleanup
  if (trimmed === '/session cleanup' || trimmed === '/session clean') {
    const { analyzeSessionQuality, deleteSession } = await import('../apikeys.js')
    const analyzed = analyzeSessionQuality()
    const lowValue = analyzed.filter((s: any) => s.isLowValue)

    if (lowValue.length === 0) {
      console.log(`  ${SUCCESS}โœ“ ${t("session.cleanup_no_low")}${color.reset}`)
      return true
    }

    console.log('')
    console.log(`  ${ACCENT}๐Ÿ” ${t("session.cleanup_found", {count: lowValue.length})}${color.reset}`)
    console.log(`  ${ACCENT}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
    lowValue.forEach((s: any, i: number) => {
      console.log(`  ${ACCENT}[${i + 1}] ${s.id}${color.reset}`)
      console.log(`      ${t("session.cleanup_reason")} ${s.reasons.join(', ')}`)
      console.log('')
    })

    // ็กฎ่ฎคๅŽๅˆ ้™ค
    const cleanupConfirm = await askQuestion(`  ${WARN}${t("session.cleanup_confirm", {count: lowValue.length})} ${color.reset}`)
    if (cleanupConfirm.toLowerCase() !== 'y') {
      console.log(`  ${MUTED}${t("model.cancelled")}${color.reset}`)
      return true
    }

    let deleted = 0, failed = 0
    for (const s of lowValue) {
      if (deleteSession(s.id)) deleted++
      else failed++
    }
    console.log(`  ${SUCCESS}โœ“ ${t("session.cleanup_done", {deleted})}${failed > 0 ? `๏ผŒ${t("session.cleanup_failed")} ${failed}` : ''}${color.reset}`)
    return true
  }

  // /card /sessions /history ๅˆซๅ
  if (trimmed === '/card' || trimmed === '/sessions' || trimmed === '/history') {
    const { listPlaintextSessions } = await import('../apikeys.js')
    const sessions = listPlaintextSessions()
    if (sessions.length === 0) {
      console.log(`  ${ACCENT}${t('session.no_records')}${color.reset}`)
    } else {
      console.log('')
      console.log(`  ${ACCENT}${t('session.list_title')}${color.reset}`)
      console.log(`  ${ACCENT}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
      for (const s of sessions) {
        console.log(`    ${ACCENT}${s.id}${color.reset}`)
        console.log(`    ${ACCENT}${t('session.msg_count')}${s.messageCount} ยท ${t('session.updated')}${s.updatedAt.slice(0, 19)}${color.reset}`)
        console.log('')
      }
    }
    return true
  }

  // ้žsessionๅ‘ฝไปค๏ผŒ่ฟ”ๅ›žfalse่ฎฉcli.ts็ปง็ปญๅค„็†
  return false
}