fix(web): match the API's skill name and description limits

The API lowered the description cap to 200 and the name cap to 64 so that
every visible skill fits in the model's prompt index. These constants are
duplicated here with no shared package, so the form accepted descriptions
the API rejects, and never checked name length at all.

Adds the name check to both validation paths -- the editor and the
SKILL.md upload -- and gives the name field the counter and maxLength the
description field already had.

Source of truth: apps/api/src/lib/brain/skills/validation.ts in the mono repo.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Sreeram Sreedhar 2026-07-31 12:32:05 +05:30
parent 5065673af8
commit 94cb71a6c0
2 changed files with 16 additions and 2 deletions

View file

@ -1,4 +1,5 @@
export const SKILL_DESCRIPTION_MAX_LENGTH = 1024
export const SKILL_NAME_MAX_LENGTH = 64
export const SKILL_DESCRIPTION_MAX_LENGTH = 200
export const SKILL_BODY_MAX_LENGTH = 16 * 1024
export type SkillScope = "personal" | "org"
@ -85,6 +86,9 @@ export function skillDraftPayload(draft: SkillDraft): SkillDraft {
const { name, description, body } = normalized
if (!name) throw new Error("Give the skill a name.")
if (name.length > SKILL_NAME_MAX_LENGTH) {
throw new Error(`Keep the name to ${SKILL_NAME_MAX_LENGTH} characters.`)
}
if (!description) throw new Error("Add a short description.")
if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
throw new Error(
@ -219,6 +223,9 @@ export function parseSkillMarkdown(source: string): SkillMarkdown {
const name = attributes.name?.trim() ?? ""
const description = attributes.description?.trim() ?? ""
if (!name) throw new Error("Skill frontmatter needs a name.")
if (name.length > SKILL_NAME_MAX_LENGTH) {
throw new Error(`Keep the name to ${SKILL_NAME_MAX_LENGTH} characters.`)
}
if (!description) throw new Error("Skill frontmatter needs a description.")
if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
throw new Error(

View file

@ -25,6 +25,7 @@ import {
canSelectSkillScope,
SKILL_BODY_MAX_LENGTH,
SKILL_DESCRIPTION_MAX_LENGTH,
SKILL_NAME_MAX_LENGTH,
setSkillDraftScope,
skillDraftPayload,
skillDraftForRole,
@ -277,12 +278,18 @@ export function SkillEditor({
</p>
) : null}
<label className="flex min-w-0 shrink-0 flex-col gap-1.5">
<span className={labelClass}>Name</span>
<span className="flex items-center justify-between gap-2">
<span className={labelClass}>Name</span>
<span className="text-[10px] text-[#596270]">
{draft.name.length} / {SKILL_NAME_MAX_LENGTH}
</span>
</span>
<input
value={draft.name}
onChange={(event) => set("name", event.target.value)}
readOnly={!canManage}
disabled={busy}
maxLength={SKILL_NAME_MAX_LENGTH}
placeholder="e.g. Incident status updates"
className={cn(inputClass, "h-9")}
/>