anyllm_proxy 0.9.5

HTTP proxy translating Anthropic Messages API to OpenAI Chat Completions
Documentation
import { useSearchParams } from 'react-router-dom'
import { useAudit } from '../../api/queries'
import Pagination from '../../components/shared/Pagination'
import AsyncBoundary from '../../components/shared/AsyncBoundary'

export default function Audit() {
  const [params, setParams] = useSearchParams()
  const page = Math.max(1, Number(params.get('page') ?? '1') || 1)
  function setPage(updater: (p: number) => number) {
    const next = new URLSearchParams(params)
    const newPage = updater(page)
    if (newPage <= 1) next.delete('page'); else next.set('page', String(newPage))
    setParams(next, { replace: true })
  }
  const query = useAudit({ page, page_size: 50 })

  return (
    <div>
      <AsyncBoundary
        query={query}
        errorTitle="Failed to load audit log"
        empty={{
          when: (d) => d.entries.length === 0 && page === 1,
          render: () => (
            <div className="empty-cta">
              <div className="empty-cta-title">No audit entries yet</div>
              <div className="empty-cta-body">
                Admin actions (creating keys, editing routes, managing backends) are recorded here.
              </div>
            </div>
          ),
        }}
      >
        {(data) => (
          <>
            <table className="route-table">
              <thead>
                <tr><th>Time</th><th>Action</th><th>Target</th><th>Detail</th><th>IP</th></tr>
              </thead>
              <tbody>
                {data.entries.map((e) => (
                  <tr key={e.id}>
                    <td className="mono dim">{e.timestamp.slice(0, 19)}</td>
                    <td className="mono">{e.action}</td>
                    <td className="dim">{e.target_type}{e.target_id ? ` #${e.target_id}` : ''}</td>
                    <td className="dim audit-detail">{e.detail ?? '—'}</td>
                    <td className="mono dim">{e.source_ip ?? '—'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            <Pagination
              page={page}
              hasMore={data.has_more}
              onPrev={() => setPage((p) => Math.max(1, p - 1))}
              onNext={() => setPage((p) => p + 1)}
            />
          </>
        )}
      </AsyncBoundary>
    </div>
  )
}