feat: menu + — Compétences-skills « Gérer » + « Parcourir » — phase 2/8 (v7.52.0)
- Sous-menu « Compétences-skills » : 11 skills builtin + skills enregistrés,
libellés affichés « Deep research » (/research) et « Skill-creator »
(/create-new-skill) via FD_SKILL_ALIAS (slugs intacts) ; le clic épingle le
skill au contexte, même chemin que la palette /.
- « Gérer les compétences » : section du menu + formulaire intégré (nom,
description, prompt) — création, édition, suppression (chip épinglé nettoyé),
export JSON téléchargé, import fichier avec overwrite (pas de doublon).
- « Parcourir les compétences » : section galerie filtrable (nom/description/
slug), installation en 1 clic (installGallerySkill réutilisé).
- PATCH /api/agent/skills/{skill_id} créé : édition partielle, whitelist de
colonnes, 400/401/404/409. OpenAPI régénéré : 515 chemins, version 7.52.0.
- En-tête ← + titre de section dans le menu (navigation à 3 niveaux).
- Fix : épingler un skill enregistré n'efface plus le message déjà tapé
(_pinDbSkill ne vide le composer que s'il est vide).
- Tests : tests/test_v752_skills_menu.py (7) + test_v751 adapté. Suite
complète 1280 verts (-n auto), ruff 0, eslint 0 problème.
This commit is contained in:
@@ -181,8 +181,20 @@ body.fd-ap-resizing *{cursor:col-resize!important}
|
||||
.fd-mention-empty,.fd-mention-load{padding:11px 12px;font-size:12px;color:var(--text-dim,#aaa);text-align:center}
|
||||
|
||||
/* Menu + (sections) — réutilise le skin du menu de mentions */
|
||||
.fd-ap-plus-menu{max-height:min(340px,60vh)}
|
||||
.fd-ap-plus-menu .fd-mention-item.disabled{opacity:.45;cursor:default;background:none}
|
||||
.fd-ap-plus-menu .fd-mention-item.disabled:hover{background:none}
|
||||
.fd-plus-head{display:flex;align-items:center;gap:8px;padding:7px 11px 6px;border-bottom:1px solid var(--border,rgba(255,255,255,.08));margin-bottom:3px}
|
||||
.fd-plus-back{background:none;border:1px solid var(--border,rgba(255,255,255,.14));color:var(--text,#ddd);border-radius:7px;width:26px;height:22px;cursor:pointer;line-height:1;flex-shrink:0}
|
||||
.fd-plus-back:hover{background:var(--bg-hover,#2b2b2b)}
|
||||
.fd-plus-title{font-size:11px;font-weight:600;color:var(--text-secondary,#ddd);text-transform:uppercase;letter-spacing:.4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.fd-plus-filter{padding:7px 11px 2px}
|
||||
.fd-plus-filter input{width:100%;background:var(--bg-tertiary,#232323);border:1px solid var(--border,rgba(255,255,255,.14));border-radius:8px;color:var(--text,#fff);font-size:12.5px;padding:6px 8px;outline:none;box-sizing:border-box}
|
||||
.fd-plus-form{padding:4px 11px 12px}
|
||||
.fd-plus-form label{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-dim,#999);margin:9px 0 3px}
|
||||
.fd-plus-form input,.fd-plus-form textarea{width:100%;background:var(--bg-tertiary,#232323);border:1px solid var(--border,rgba(255,255,255,.14));border-radius:8px;color:var(--text,#fff);font-size:12.5px;padding:7px 8px;outline:none;font-family:inherit;box-sizing:border-box}
|
||||
.fd-plus-form textarea{min-height:110px;resize:vertical;line-height:1.5}
|
||||
.fd-plus-file{display:none}
|
||||
.fd-plus-chev{margin-left:auto;color:var(--text-dim,#999);opacity:.75;font-size:15px;flex-shrink:0}
|
||||
.fd-plus-crumb{display:flex;gap:5px;flex-wrap:wrap;padding:7px 11px 3px;font-size:11px;border-bottom:1px solid var(--border,rgba(255,255,255,.08));margin-bottom:3px}
|
||||
.fd-plus-crumb-it{color:var(--accent,#2383E2);cursor:pointer;white-space:nowrap}
|
||||
@@ -389,6 +401,13 @@ body.fd-ap-resizing *{cursor:col-resize!important}
|
||||
</template>
|
||||
</div>
|
||||
<div class="fd-ap-mention-menu fd-ap-plus-menu" :class="{show: plusOpen}" x-ref="plusMenu">
|
||||
<div class="fd-plus-head" x-show="plusSection!=='root'" x-cloak>
|
||||
<button class="fd-plus-back" type="button" @click="plusBack()" title="Retour" aria-label="Retour">←</button>
|
||||
<span class="fd-plus-title" x-text="plusTitle"></span>
|
||||
</div>
|
||||
<div class="fd-plus-filter" x-show="plusSection==='skills-gallery'" x-cloak>
|
||||
<input type="search" placeholder="Filtrer les compétences…" aria-label="Filtrer les compétences" x-model="galleryFilter">
|
||||
</div>
|
||||
<div class="fd-plus-crumb" x-show="plusSection==='browse'">
|
||||
<span class="fd-plus-crumb-it" @click="plusGoto(-1)">Racine</span>
|
||||
<template x-for="(c, ci) in plusCrumb" :key="c.id">
|
||||
@@ -399,7 +418,8 @@ body.fd-ap-resizing *{cursor:col-resize!important}
|
||||
<div class="fd-mention-empty" x-show="plusSection==='browse' && !plusLoading && !plusItems.length" x-cloak>Dossier vide</div>
|
||||
<template x-for="(it, i) in plusItems" :key="it.key">
|
||||
<div>
|
||||
<div class="fd-mention-item" :class="{focus: i===plusFocus, disabled: !!it.disabled}"
|
||||
<div class="fd-mention-sep" x-show="it._sep" x-text="it._sep"></div>
|
||||
<div class="fd-mention-item" x-show="!it._sep" :class="{focus: i===plusFocus, disabled: !!it.disabled}"
|
||||
@click="plusAction(it)" @mouseenter="it.disabled ? null : plusFocus = i">
|
||||
<span class="fd-mention-ico" x-text="it.icon"></span>
|
||||
<div class="fd-mention-main">
|
||||
@@ -410,6 +430,21 @@ body.fd-ap-resizing *{cursor:col-resize!important}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="fd-plus-form" x-show="plusSection==='skills-edit'" x-cloak>
|
||||
<label for="fd-plus-skill-name">Nom</label>
|
||||
<input id="fd-plus-skill-name" type="text" x-model="skillForm.name" placeholder="ex. synthese-reunion" @keydown.enter.prevent="saveSkill()">
|
||||
<label for="fd-plus-skill-desc">Description</label>
|
||||
<input id="fd-plus-skill-desc" type="text" x-model="skillForm.description" placeholder="Une phrase">
|
||||
<label for="fd-plus-skill-prompt">Prompt (consigne appliquée à la demande)</label>
|
||||
<textarea id="fd-plus-skill-prompt" x-model="skillForm.prompt_template" placeholder="Fais…"></textarea>
|
||||
<div class="fd-proposal-bar">
|
||||
<button class="fd-proposal-btn primary" type="button" @click="saveSkill()">✓ Enregistrer</button>
|
||||
<button class="fd-proposal-btn" type="button" x-show="skillForm.id" @click="deleteSkill()" x-cloak>✕ Supprimer</button>
|
||||
<button class="fd-proposal-btn" type="button" x-show="skillForm.id" @click="exportSkill()" x-cloak>⤓ Export</button>
|
||||
<button class="fd-proposal-btn" type="button" @click="plusBack()">← Retour</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" accept="application/json,.json" x-ref="skillImport" class="fd-plus-file" aria-label="Importer un skill JSON" @change="importSkillFile($event)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fd-ap-chips" x-show="contextChips.length" x-cloak>
|
||||
|
||||
Reference in New Issue
Block a user