Files
ai-agent/backend/schemas/skills.py
Gabriel Vidal 091fafd881 feat(skills): one catalog card per skill name
`complete` ships in both the homelab and the ai-agent repo, so /api/skills
listed it twice with the same (name-keyed) usage, counted twice in the
totals. merge_same_name keeps the repo's copy (else the newest) and lists
the others under `copies` — shown as a +source badge on the card; their
share refs stay pickable in Settings → Users.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:47:16 +02:00

72 lines
2.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""The skills catalog (``backend/skills.py``)."""
from __future__ import annotations
from typing import Optional
from .base import Schema
__all__ = [
"SkillCopy",
"SkillSummary",
"SkillsTotals",
"SkillsResponse",
]
class SkillCopy(Schema):
"""Another on-disk copy of a skill that shares the card's name."""
source: str
sourceKind: str
dir: Optional[str] = None
path: Optional[str] = None
updatedAt: Optional[str] = None
shareRef: Optional[str] = None
sharedWithGuests: bool = False
class SkillSummary(Schema):
"""One skill card: what it is on disk + what its use has cost."""
name: str # the invocation name (its dir name)
title: str # frontmatter `name:`, falls back to `name`
description: str
# None for a built-in/plugin skill: nothing of it lives in this repo, so
# there is no file to link into the editor.
dir: Optional[str] = None
path: Optional[str] = None
source: str # "repo" | <project dir-name> | "builtin"
sourceKind: str # "repo" | "project" | "builtin"
# Frontmatter `trigger_words:` — the words that make the composer's
# auto-tag suggest this skill. Empty for a built-in (no SKILL.md here) and
# for a skill deliberately kept out of auto-tag.
triggerWords: list[str] = []
files: int
updatedAt: Optional[str] = None
count: int # total invocations across all transcripts
lastUsed: Optional[str] = None
conversations: int # distinct conversations that invoked it
contextTokens: Optional[int] = None
contextCost: Optional[float] = None
estSpend: Optional[float] = None # contextCost × count
sessionCost: float # total spend of the conversations using it
sessionTokens: int
# How the guest-sharing list names it: `name` (repo) or `<project>/<name>`.
# None for a built-in — there's no dir to hand a guest run.
shareRef: Optional[str] = None
sharedWithGuests: bool = False # in Settings → Users' shared-skills list
# The other dirs shipping a skill of the same name (one card per name —
# the repo's own copy leads). Empty for a skill with a single home.
copies: list[SkillCopy] = []
class SkillsTotals(Schema):
skills: int
used: int
invocations: int
contextCost: float
estSpend: float
class SkillsResponse(Schema):
skills: list[SkillSummary]
totals: SkillsTotals