import { getBackend } from './backend.ts'
import {
ensureSchema,
getSkillOrThrow,
listSkillRevisions,
sqlRows,
type SkillVersionRow,
} from './db.ts'
export type SkillHistoryInput = {
id: string
path?: string
limit?: number
}
export type SkillHistoryItem = {
version_id: number
path: string
replaced_at: string
content_length: number
/** Present on the repo backend: git commit that holds the restored content. */
commit_oid?: string
}
async function historyLegacy(
id: string,
path: string,
limit: number,
): Promise<SkillHistoryItem[]> {
await ensureSchema()
await getSkillOrThrow(id)
const rows = path
? await sqlRows<SkillVersionRow>(
`SELECT id, skill_id, path, content, replaced_at
FROM skill_versions
WHERE skill_id = ? AND path = ?
ORDER BY id DESC
LIMIT ?`,
[id, path, limit],
)
: await sqlRows<SkillVersionRow>(
`SELECT id, skill_id, path, content, replaced_at
FROM skill_versions
WHERE skill_id = ?
ORDER BY id DESC
LIMIT ?`,
[id, limit],
)
return rows.map((row) => ({
version_id: Number(row.id),
path: row.path,
replaced_at: row.replaced_at,
content_length: String(row.content ?? '').length,
}))
}
async function historyRepo(
id: string,
path: string,
limit: number,
): Promise<SkillHistoryItem[]> {
await getSkillOrThrow(id)
const rows = await listSkillRevisions({
skill_id: id,
path: path || undefined,
limit,
})
return rows.map((row) => ({
version_id: Number(row.id),
path: row.path,
replaced_at: row.replaced_at,
content_length: Number(row.content_length),
commit_oid: row.commit_oid,
}))
}
/**
* Recent skill version metadata (not full content).
* On the repo backend, each version maps to a git commit (`commit_oid`).
*
* @example
* import skillHistory from 'kody:@kody/skills/skill-history'
* const history = await skillHistory({ id: 'writing-style', limit: 10 })
*/
export default async function skillHistory(
params: SkillHistoryInput = {} as SkillHistoryInput,
): Promise<SkillHistoryItem[]> {
const id = String(params.id ?? '').trim()
if (!id) throw new Error('skill_history requires `id`.')
const path = params.path == null ? '' : String(params.path).trim()
const limit = Math.max(1, Math.min(200, Number(params.limit ?? 50) || 50))
const backend = await getBackend()
return backend === 'repo'
? historyRepo(id, path, limit)
: historyLegacy(id, path, limit)
}