// 技能库纯逻辑:按 scope 分组、档位文案。 // 对齐 C3 扩(GET /skills,只读注册表视图)。纯逻辑,便于 node 环境单测。 import type { SkillView } from "@/lib/api/types"; export type SkillScope = "builtin" | "custom" | "community"; export const SCOPE_LABELS: Record = { builtin: "内置", custom: "自定义", community: "社区", }; export const TIER_LABELS: Record = { writer: "写手", analyst: "分析", light: "轻量", }; export function scopeLabel(scope: string): string { return SCOPE_LABELS[scope] ?? scope; } export function tierLabel(tier: string): string { return TIER_LABELS[tier] ?? tier; } export type SkillGroups = { scope: string; skills: SkillView[] }[]; export interface SkillCount { key: string; count: number; } export interface SkillsSummary { total: number; readonlyCount: number; writableCount: number; scopes: SkillCount[]; tiers: SkillCount[]; readableTables: string[]; writableTables: string[]; } // 按 scope 分组(保持服务端 name 升序);scope 顺序按首次出现。 export function groupByScope( skills: readonly SkillView[] | undefined, ): SkillGroups { const order: string[] = []; const map = new Map(); for (const skill of skills ?? []) { if (!map.has(skill.scope)) { order.push(skill.scope); map.set(skill.scope, []); } map.get(skill.scope)?.push(skill); } return order.map((scope) => ({ scope, skills: map.get(scope) ?? [] })); } export function summarizeSkills( skills: readonly SkillView[] | undefined, ): SkillsSummary { const scopeCounts = new Map(); const tierCounts = new Map(); const readableTables = new Set(); const writableTables = new Set(); let writableCount = 0; for (const skill of skills ?? []) { scopeCounts.set(skill.scope, (scopeCounts.get(skill.scope) ?? 0) + 1); tierCounts.set(skill.tier, (tierCounts.get(skill.tier) ?? 0) + 1); for (const table of skill.reads ?? []) { readableTables.add(table); } if (skill.writes && skill.writes.length > 0) { writableCount += 1; for (const table of skill.writes) { writableTables.add(table); } } } return { total: skills?.length ?? 0, readonlyCount: (skills?.length ?? 0) - writableCount, writableCount, scopes: countsFromMap(scopeCounts), tiers: countsFromMap(tierCounts), readableTables: [...readableTables].sort(), writableTables: [...writableTables].sort(), }; } function countsFromMap(map: Map): SkillCount[] { return [...map.entries()].map(([key, count]) => ({ key, count })); }