diff --git a/messages/ar.json b/messages/ar.json index e7f50046..891760d2 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -160,7 +160,8 @@ "video": "فيديو", "audio": "صوت", "structured": "منظم", - "document": "مستند" + "document": "مستند", + "skill": "مهارة" }, "inputType": "أمر المستخدم", "outputType": "استجابة الذكاء الاصطناعي", @@ -168,9 +169,11 @@ "inputTypeDescription": "كيف يتم تنسيق الأمر الخاص بك", "outputTypeDescription": "أظهر للمجتمع كيف يعمل هذا الأمر عند تشغيله على أدوات الذكاء الاصطناعي. يمكنك إنشاء المخرجات بنفسك باستخدام تطبيق الذكاء الاصطناعي المفضل لديك.", "outputTypeStructuredNote": "الأوامر المنظمة يمكن أن تنتج أنواع مختلفة من المخرجات", + "outputTypeSkillNote": "المهارات توجه الوكلاء لإنشاء الكود. سينتج الذكاء الاصطناعي مخرجات كود بناءً على تعليمات مهارتك.", "inputTypes": { "text": "أمر نصي", - "structured": "منظم (JSON/YAML)" + "structured": "منظم (JSON/YAML)", + "skill": "مهارة (مهارات الوكيل)" }, "outputTypes": { "text": "نص", @@ -231,6 +234,7 @@ "run": "تشغيل", "downloadMarkdown": "تحميل MD", "downloadYaml": "تحميل YAML", + "downloadSkillMd": "تحميل SKILL.md", "copyMarkdownUrl": "نسخ رابط MD", "copyYamlUrl": "نسخ رابط YAML", "downloadStarted": "بدأ التحميل", diff --git a/messages/de.json b/messages/de.json index a523ab67..3d3ee237 100644 --- a/messages/de.json +++ b/messages/de.json @@ -160,7 +160,8 @@ "video": "Video", "audio": "Audio", "structured": "Strukturiert", - "document": "Dokument" + "document": "Dokument", + "skill": "Skill" }, "inputType": "Benutzer-Prompt", "outputType": "KI-Antwort", @@ -168,9 +169,11 @@ "inputTypeDescription": "Wie Ihr Prompt formatiert ist", "outputTypeDescription": "Zeigen Sie der Community, wie dieser Prompt funktioniert, wenn er mit KI-Tools ausgeführt wird. Sie können die Ausgaben selbst mit Ihrer bevorzugten KI-App generieren.", "outputTypeStructuredNote": "Strukturierte Prompts können verschiedene Ausgabetypen erzeugen", + "outputTypeSkillNote": "Skills weisen Agenten an, Code zu generieren. Die KI erzeugt Code-Ausgabe basierend auf Ihren Skill-Anweisungen.", "inputTypes": { "text": "Text-Prompt", - "structured": "Strukturiert (JSON/YAML)" + "structured": "Strukturiert (JSON/YAML)", + "skill": "Skill (Agent Skills)" }, "outputTypes": { "text": "Text", @@ -217,6 +220,7 @@ "run": "Ausführen", "downloadMarkdown": "MD herunterladen", "downloadYaml": "YAML herunterladen", + "downloadSkillMd": "SKILL.md herunterladen", "copyMarkdownUrl": "MD-Link kopieren", "copyYamlUrl": "YAML-Link kopieren", "downloadStarted": "Download gestartet", diff --git a/messages/el.json b/messages/el.json index 1089192f..6d189a49 100644 --- a/messages/el.json +++ b/messages/el.json @@ -160,7 +160,8 @@ "video": "Βίντεο", "audio": "Ήχος", "structured": "Δομημένο", - "document": "Έγγραφο" + "document": "Έγγραφο", + "skill": "Δεξιότητα" }, "inputType": "Prompt χρήστη", "outputType": "Απάντηση AI", @@ -168,9 +169,11 @@ "inputTypeDescription": "Πώς είναι μορφοποιημένο το prompt σας", "outputTypeDescription": "Δείξτε στην κοινότητα πώς αποδίδει αυτό το prompt όταν εκτελείται σε εργαλεία AI. Μπορείτε να δημιουργήσετε τα αποτελέσματα μόνοι σας χρησιμοποιώντας την αγαπημένη σας εφαρμογή AI.", "outputTypeStructuredNote": "Τα δομημένα prompts μπορούν να παράγουν διάφορους τύπους εξόδου", + "outputTypeSkillNote": "Οι δεξιότητες καθοδηγούν τους agents να παράγουν κώδικα. Η AI θα παράγει κώδικα με βάση τις οδηγίες δεξιοτήτων σας.", "inputTypes": { "text": "Prompt κειμένου", - "structured": "Δομημένο (JSON/YAML)" + "structured": "Δομημένο (JSON/YAML)", + "skill": "Δεξιότητα (Agent Skills)" }, "outputTypes": { "text": "Κείμενο", @@ -217,6 +220,7 @@ "run": "Εκτέλεση", "downloadMarkdown": "Λήψη MD", "downloadYaml": "Λήψη YAML", + "downloadSkillMd": "Λήψη SKILL.md", "copyMarkdownUrl": "Αντιγραφή συνδέσμου MD", "copyYamlUrl": "Αντιγραφή συνδέσμου YAML", "downloadStarted": "Η λήψη ξεκίνησε", diff --git a/messages/en.json b/messages/en.json index b1783c32..ae927418 100644 --- a/messages/en.json +++ b/messages/en.json @@ -160,7 +160,8 @@ "video": "Video", "audio": "Audio", "structured": "Structured", - "document": "Document" + "document": "Document", + "skill": "Skill" }, "inputType": "User Prompt", "outputType": "AI Response", @@ -168,9 +169,11 @@ "inputTypeDescription": "How your prompt is formatted", "outputTypeDescription": "Show the community how this prompt performs when run on AI tools. You can generate outputs yourself using your favorite AI app.", "outputTypeStructuredNote": "Structured prompts can produce various output types", + "outputTypeSkillNote": "Skills instruct agents to generate code. The AI will produce code output based on your skill instructions.", "inputTypes": { "text": "Text Prompt", - "structured": "Structured (JSON/YAML)" + "structured": "Structured (JSON/YAML)", + "skill": "Skill (Agent Skills)" }, "outputTypes": { "text": "Text", @@ -217,6 +220,7 @@ "run": "Run", "downloadMarkdown": "Download MD", "downloadYaml": "Download YAML", + "downloadSkillMd": "Download SKILL.md", "copyMarkdownUrl": "Copy MD Link", "copyYamlUrl": "Copy YAML Link", "downloadStarted": "Download started", diff --git a/messages/es.json b/messages/es.json index 35d3b738..90630a53 100644 --- a/messages/es.json +++ b/messages/es.json @@ -160,7 +160,8 @@ "video": "Video", "audio": "Audio", "structured": "Estructurado", - "document": "Documento" + "document": "Documento", + "skill": "Habilidad" }, "inputType": "Prompt del Usuario", "outputType": "Respuesta de IA", @@ -168,9 +169,11 @@ "inputTypeDescription": "Cómo está formateado tu prompt", "outputTypeDescription": "Muestra a la comunidad cómo funciona este prompt cuando se ejecuta en herramientas de IA. Puedes generar las salidas tú mismo usando tu aplicación de IA favorita.", "outputTypeStructuredNote": "Los prompts estructurados pueden producir varios tipos de salida", + "outputTypeSkillNote": "Las habilidades instruyen a los agentes para generar código. La IA producirá código basado en las instrucciones de tu habilidad.", "inputTypes": { "text": "Prompt de Texto", - "structured": "Estructurado (JSON/YAML)" + "structured": "Estructurado (JSON/YAML)", + "skill": "Habilidad (Agent Skills)" }, "outputTypes": { "text": "Texto", @@ -231,6 +234,7 @@ "run": "Ejecutar", "downloadMarkdown": "Descargar MD", "downloadYaml": "Descargar YAML", + "downloadSkillMd": "Descargar SKILL.md", "copyMarkdownUrl": "Copiar enlace MD", "copyYamlUrl": "Copiar enlace YAML", "downloadStarted": "Descarga iniciada", diff --git a/messages/fr.json b/messages/fr.json index a6524151..4cdd19f8 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -160,7 +160,8 @@ "video": "Vidéo", "audio": "Audio", "structured": "Structuré", - "document": "Document" + "document": "Document", + "skill": "Compétence" }, "inputType": "Prompt Utilisateur", "outputType": "Réponse IA", @@ -168,9 +169,11 @@ "inputTypeDescription": "Comment votre prompt est formaté", "outputTypeDescription": "Montrez à la communauté comment ce prompt fonctionne lorsqu'il est exécuté sur des outils IA. Vous pouvez générer les résultats vous-même en utilisant votre application IA préférée.", "outputTypeStructuredNote": "Les prompts structurés peuvent produire divers types de sortie", + "outputTypeSkillNote": "Les compétences instruisent les agents à générer du code. L'IA produira du code basé sur vos instructions de compétence.", "inputTypes": { "text": "Prompt Texte", - "structured": "Structuré (JSON/YAML)" + "structured": "Structuré (JSON/YAML)", + "skill": "Compétence (Agent Skills)" }, "outputTypes": { "text": "Texte", @@ -217,6 +220,7 @@ "run": "Exécuter", "downloadMarkdown": "Télécharger MD", "downloadYaml": "Télécharger YAML", + "downloadSkillMd": "Télécharger SKILL.md", "copyMarkdownUrl": "Copier le lien MD", "copyYamlUrl": "Copier le lien YAML", "downloadStarted": "Téléchargement démarré", diff --git a/messages/he.json b/messages/he.json index 2a65a991..d1413438 100644 --- a/messages/he.json +++ b/messages/he.json @@ -160,7 +160,8 @@ "video": "וידאו", "audio": "אודיו", "structured": "מובנה", - "document": "מסמך" + "document": "מסמך", + "skill": "מיומנות" }, "inputType": "פרומפט משתמש", "outputType": "תגובת AI", @@ -168,9 +169,11 @@ "inputTypeDescription": "איך הפרומפט שלך מעוצב", "outputTypeDescription": "הראה לקהילה איך הפרומפט הזה מתפקד כשהוא רץ בכלי AI. אתה יכול ליצור את התוצרים בעצמך באמצעות אפליקציית ה-AI המועדפת עליך.", "outputTypeStructuredNote": "פרומפטים מובנים יכולים לייצר סוגי פלט שונים", + "outputTypeSkillNote": "מיומנויות מנחות סוכנים ליצור קוד. הAI ייצר פלט קוד בהתאם להוראות המיומנות שלך.", "inputTypes": { "text": "פרומפט טקסט", - "structured": "מובנה (JSON/YAML)" + "structured": "מובנה (JSON/YAML)", + "skill": "מיומנות (Agent Skills)" }, "outputTypes": { "text": "טקסט", @@ -217,6 +220,7 @@ "run": "הפעל", "downloadMarkdown": "הורד MD", "downloadYaml": "הורד YAML", + "downloadSkillMd": "הורד SKILL.md", "copyMarkdownUrl": "העתק קישור MD", "copyYamlUrl": "העתק קישור YAML", "downloadStarted": "ההורדה החלה", diff --git a/messages/it.json b/messages/it.json index eaff20c4..6d5efe6c 100644 --- a/messages/it.json +++ b/messages/it.json @@ -160,7 +160,8 @@ "video": "Video", "audio": "Audio", "structured": "Strutturato", - "document": "Documento" + "document": "Documento", + "skill": "Abilità" }, "inputType": "Prompt Utente", "outputType": "Risposta AI", @@ -168,9 +169,11 @@ "inputTypeDescription": "Come è formattato il tuo prompt", "outputTypeDescription": "Mostra alla community come funziona questo prompt quando viene eseguito su strumenti AI. Puoi generare gli output tu stesso usando la tua app AI preferita.", "outputTypeStructuredNote": "I prompt strutturati possono produrre vari tipi di output", + "outputTypeSkillNote": "Le abilità istruiscono gli agenti a generare codice. L'IA produrrà codice basato sulle istruzioni della tua abilità.", "inputTypes": { "text": "Prompt Testuale", - "structured": "Strutturato (JSON/YAML)" + "structured": "Strutturato (JSON/YAML)", + "skill": "Abilità (Agent Skills)" }, "outputTypes": { "text": "Testo", @@ -217,6 +220,7 @@ "run": "Esegui", "downloadMarkdown": "Scarica MD", "downloadYaml": "Scarica YAML", + "downloadSkillMd": "Scarica SKILL.md", "copyMarkdownUrl": "Copia link MD", "copyYamlUrl": "Copia link YAML", "downloadStarted": "Download avviato", diff --git a/messages/ja.json b/messages/ja.json index 45a3267d..3f05a32a 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -160,7 +160,8 @@ "video": "動画", "audio": "音声", "structured": "構造化", - "document": "ドキュメント" + "document": "ドキュメント", + "skill": "スキル" }, "inputType": "ユーザープロンプト", "outputType": "AI応答", @@ -168,9 +169,11 @@ "inputTypeDescription": "プロンプトの形式", "outputTypeDescription": "AIツールでこのプロンプトを実行したときの結果をコミュニティに示しましょう。お気に入りのAIアプリを使って自分で出力を生成できます。", "outputTypeStructuredNote": "構造化プロンプトは様々な出力タイプを生成できます", + "outputTypeSkillNote": "スキルはエージェントにコードを生成するよう指示します。AIはスキルの指示に基づいてコードを出力します。", "inputTypes": { "text": "テキストプロンプト", - "structured": "構造化 (JSON/YAML)" + "structured": "構造化 (JSON/YAML)", + "skill": "スキル (Agent Skills)" }, "outputTypes": { "text": "テキスト", @@ -231,6 +234,7 @@ "run": "実行", "downloadMarkdown": "MDをダウンロード", "downloadYaml": "YAMLをダウンロード", + "downloadSkillMd": "SKILL.mdをダウンロード", "copyMarkdownUrl": "MDリンクをコピー", "copyYamlUrl": "YAMLリンクをコピー", "downloadStarted": "ダウンロード開始", diff --git a/messages/ko.json b/messages/ko.json index b9d4952a..366de083 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -160,7 +160,8 @@ "video": "비디오", "audio": "오디오", "structured": "구조화", - "document": "문서" + "document": "문서", + "skill": "스킬" }, "inputType": "사용자 프롬프트", "outputType": "AI 응답", @@ -168,9 +169,11 @@ "inputTypeDescription": "프롬프트 형식", "outputTypeDescription": "이 프롬프트가 AI 도구에서 실행될 때 어떻게 작동하는지 커뮤니티에 보여주세요. 좋아하는 AI 앱을 사용하여 직접 출력을 생성할 수 있습니다.", "outputTypeStructuredNote": "구조화된 프롬프트는 다양한 출력 유형을 생성할 수 있습니다", + "outputTypeSkillNote": "스킬은 에이전트에게 코드를 생성하도록 지시합니다. AI는 스킬 지침에 따라 코드 출력을 생성합니다.", "inputTypes": { "text": "텍스트 프롬프트", - "structured": "구조화 (JSON/YAML)" + "structured": "구조화 (JSON/YAML)", + "skill": "스킬 (Agent Skills)" }, "outputTypes": { "text": "텍스트", @@ -217,6 +220,7 @@ "run": "실행", "downloadMarkdown": "MD 다운로드", "downloadYaml": "YAML 다운로드", + "downloadSkillMd": "SKILL.md 다운로드", "copyMarkdownUrl": "MD 링크 복사", "copyYamlUrl": "YAML 링크 복사", "downloadStarted": "다운로드 시작", diff --git a/messages/pt.json b/messages/pt.json index 07d5869f..c9cc8976 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -160,7 +160,8 @@ "video": "Vídeo", "audio": "Áudio", "structured": "Estruturado", - "document": "Documento" + "document": "Documento", + "skill": "Habilidade" }, "inputType": "Prompt do Usuário", "outputType": "Resposta da IA", @@ -168,9 +169,11 @@ "inputTypeDescription": "Como seu prompt está formatado", "outputTypeDescription": "Mostre à comunidade como este prompt funciona quando executado em ferramentas de IA. Você pode gerar as saídas você mesmo usando seu aplicativo de IA favorito.", "outputTypeStructuredNote": "Prompts estruturados podem produzir vários tipos de saída", + "outputTypeSkillNote": "Habilidades instruem agentes a gerar código. A IA produzirá código baseado nas instruções da sua habilidade.", "inputTypes": { "text": "Prompt de Texto", - "structured": "Estruturado (JSON/YAML)" + "structured": "Estruturado (JSON/YAML)", + "skill": "Habilidade (Agent Skills)" }, "outputTypes": { "text": "Texto", @@ -217,6 +220,7 @@ "run": "Executar", "downloadMarkdown": "Baixar MD", "downloadYaml": "Baixar YAML", + "downloadSkillMd": "Baixar SKILL.md", "copyMarkdownUrl": "Copiar link MD", "copyYamlUrl": "Copiar link YAML", "downloadStarted": "Download iniciado", diff --git a/messages/ru.json b/messages/ru.json index 8070241d..c2a542b2 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -160,7 +160,8 @@ "video": "Видео", "audio": "Аудио", "structured": "Структурированный", - "document": "Документ" + "document": "Документ", + "skill": "Навык" }, "inputType": "Промпт пользователя", "outputType": "Ответ ИИ", @@ -168,9 +169,11 @@ "inputTypeDescription": "Как отформатирован ваш промпт", "outputTypeDescription": "Покажите сообществу, как работает этот промпт при запуске в инструментах ИИ. Вы можете сами сгенерировать результаты, используя ваше любимое ИИ-приложение.", "outputTypeStructuredNote": "Структурированные промпты могут создавать различные типы вывода", + "outputTypeSkillNote": "Навыки инструктируют агентов генерировать код. ИИ будет создавать код на основе ваших инструкций навыка.", "inputTypes": { "text": "Текстовый промпт", - "structured": "Структурированный (JSON/YAML)" + "structured": "Структурированный (JSON/YAML)", + "skill": "Навык (Agent Skills)" }, "outputTypes": { "text": "Текст", @@ -217,6 +220,7 @@ "run": "Запустить", "downloadMarkdown": "Скачать MD", "downloadYaml": "Скачать YAML", + "downloadSkillMd": "Скачать SKILL.md", "copyMarkdownUrl": "Копировать ссылку MD", "copyYamlUrl": "Копировать ссылку YAML", "downloadStarted": "Загрузка началась", diff --git a/messages/tr.json b/messages/tr.json index 893af979..dbd76709 100644 --- a/messages/tr.json +++ b/messages/tr.json @@ -160,7 +160,8 @@ "video": "Video", "audio": "Ses", "structured": "Yapılandırılmış", - "document": "Doküman" + "document": "Doküman", + "skill": "Yetenek" }, "inputType": "Kullanıcı Promptu", "outputType": "AI Yanıtı", @@ -168,9 +169,11 @@ "inputTypeDescription": "Promptunuzun formatı", "outputTypeDescription": "Bu prompt AI araçlarında çalıştırıldığında nasıl performans gösterdiğini topluluğa gösterin. Çıktıları kendiniz favori AI uygulamanızı kullanarak oluşturabilirsiniz.", "outputTypeStructuredNote": "Yapılandırılmış promptlar çeşitli çıktı türleri üretebilir", + "outputTypeSkillNote": "Yetenekler, ajanları kod üretmeye yönlendirir. AI, yetenek talimatlarınıza göre kod çıktısı üretecektir.", "inputTypes": { "text": "Metin Promptu", - "structured": "Yapılandırılmış (JSON/YAML)" + "structured": "Yapılandırılmış (JSON/YAML)", + "skill": "Yetenek (Agent Skills)" }, "outputTypes": { "text": "Metin", @@ -217,6 +220,7 @@ "run": "Çalıştır", "downloadMarkdown": "MD İndir", "downloadYaml": "YAML İndir", + "downloadSkillMd": "SKILL.md İndir", "copyMarkdownUrl": "MD Linkini Kopyala", "copyYamlUrl": "YAML Linkini Kopyala", "downloadStarted": "İndirme başladı", diff --git a/messages/zh.json b/messages/zh.json index 9d6ae450..925a9907 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -160,7 +160,8 @@ "video": "视频", "audio": "音频", "structured": "结构化", - "document": "文档" + "document": "文档", + "skill": "技能" }, "inputType": "用户提示词", "outputType": "AI 响应", @@ -168,9 +169,11 @@ "inputTypeDescription": "您的提示词格式", "outputTypeDescription": "向社区展示此提示词在AI工具上运行时的表现。您可以使用您喜欢的AI应用自行生成输出。", "outputTypeStructuredNote": "结构化提示词可以产生多种输出类型", + "outputTypeSkillNote": "技能指导代理生成代码。AI将根据您的技能指令产生代码输出。", "inputTypes": { "text": "文本提示词", - "structured": "结构化 (JSON/YAML)" + "structured": "结构化 (JSON/YAML)", + "skill": "技能 (Agent Skills)" }, "outputTypes": { "text": "文本", @@ -217,6 +220,7 @@ "run": "运行", "downloadMarkdown": "下载 MD", "downloadYaml": "下载 YAML", + "downloadSkillMd": "下载 SKILL.md", "copyMarkdownUrl": "复制 MD 链接", "copyYamlUrl": "复制 YAML 链接", "downloadStarted": "开始下载", diff --git a/prisma/migrations/20251220202333_add_skill_type/migration.sql b/prisma/migrations/20251220202333_add_skill_type/migration.sql new file mode 100644 index 00000000..8a23f840 --- /dev/null +++ b/prisma/migrations/20251220202333_add_skill_type/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "PromptType" ADD VALUE 'SKILL'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e7b30b75..afd73f1c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -343,6 +343,7 @@ enum PromptType { VIDEO AUDIO STRUCTURED + SKILL } enum StructuredFormat { diff --git a/prisma/seed.ts b/prisma/seed.ts index 725affe9..c2025e5f 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -255,6 +255,16 @@ async function main() { update: {}, create: { name: "Agent", slug: "agent", color: "#14B8A6" }, }), + prisma.tag.upsert({ + where: { slug: "skill" }, + update: {}, + create: { name: "Skill", slug: "skill", color: "#8B5CF6" }, + }), + prisma.tag.upsert({ + where: { slug: "copilot" }, + update: {}, + create: { name: "Copilot", slug: "copilot", color: "#000000" }, + }), ]); console.log("✅ Created", tags.length, "tags"); @@ -510,6 +520,207 @@ variables: tagSlugs: ["workflow", "claude", "advanced"], authorId: bob.id }, + + // SKILL type prompts (Agent Skills) + { + title: "Code Refactoring Skill", + description: "An agent skill for refactoring code to improve quality and maintainability", + content: `# Code Refactoring Skill + +This skill helps refactor code to improve readability, maintainability, and performance. + +## Instructions + +When asked to refactor code: + +1. **Analyze the code structure** - Identify code smells, duplications, and areas for improvement +2. **Apply refactoring patterns** - Use appropriate design patterns and best practices +3. **Preserve functionality** - Ensure all existing behavior is maintained +4. **Add documentation** - Include clear comments explaining complex logic +5. **Optimize performance** - Look for opportunities to improve efficiency + +## Guidelines + +- Follow the language's style guide and conventions +- Break large functions into smaller, focused ones +- Use meaningful variable and function names +- Remove dead code and unused imports +- Add type annotations where applicable + +## Output Format + +Provide the refactored code with explanations of changes made.`, + type: "SKILL", + categorySlug: "coding", + tagSlugs: ["skill", "copilot", "advanced"], + authorId: admin.id + }, + { + title: "Test Generator Skill", + description: "An agent skill for generating comprehensive unit tests", + content: `# Test Generator Skill + +This skill generates comprehensive unit tests for code. + +## Instructions + +When generating tests: + +1. **Identify testable units** - Find functions, methods, and classes to test +2. **Cover edge cases** - Include tests for boundary conditions and error states +3. **Use appropriate assertions** - Match assertions to expected outcomes +4. **Mock dependencies** - Isolate units from external dependencies +5. **Follow naming conventions** - Use descriptive test names + +## Test Categories + +- **Happy path tests** - Normal expected behavior +- **Edge case tests** - Boundary conditions +- **Error handling tests** - Exception and error scenarios +- **Integration tests** - Component interactions + +## Framework Guidelines + +- Use the project's existing test framework +- Follow AAA pattern (Arrange, Act, Assert) +- Keep tests independent and isolated +- Aim for high code coverage`, + type: "SKILL", + categorySlug: "coding", + tagSlugs: ["skill", "copilot", "beginner"], + authorId: demo.id + }, + { + title: "Documentation Writer Skill", + description: "An agent skill for generating comprehensive documentation", + content: `# Documentation Writer Skill + +This skill creates clear, comprehensive documentation for code and APIs. + +## Instructions + +When writing documentation: + +1. **Understand the code** - Analyze functionality and purpose +2. **Write clear descriptions** - Explain what the code does in plain language +3. **Document parameters** - List all inputs with types and descriptions +4. **Include examples** - Provide usage examples for common scenarios +5. **Note edge cases** - Document any limitations or special behaviors + +## Documentation Types + +### Function/Method Documentation +- Purpose and description +- Parameters with types +- Return values +- Exceptions thrown +- Usage examples + +### API Documentation +- Endpoint descriptions +- Request/response formats +- Authentication requirements +- Rate limits and errors + +### README Documentation +- Project overview +- Installation instructions +- Quick start guide +- Configuration options`, + type: "SKILL", + categorySlug: "technical-writing", + tagSlugs: ["skill", "copilot", "beginner"], + authorId: alice.id + }, + { + title: "Git Commit Message Skill", + description: "An agent skill for writing clear, conventional commit messages", + content: `# Git Commit Message Skill + +This skill writes clear, conventional commit messages following best practices. + +## Instructions + +When writing commit messages: + +1. **Use conventional commit format** - type(scope): description +2. **Be concise but descriptive** - Summarize changes clearly +3. **Use imperative mood** - "Add feature" not "Added feature" +4. **Reference issues** - Link to relevant tickets or issues +5. **Separate concerns** - One logical change per commit + +## Commit Types + +- **feat**: New feature +- **fix**: Bug fix +- **docs**: Documentation changes +- **style**: Code style changes (formatting, etc.) +- **refactor**: Code refactoring +- **test**: Adding or updating tests +- **chore**: Maintenance tasks + +## Format + +\`\`\` +type(scope): short description + +Longer description if needed. Explain what and why, +not how. + +Refs: #issue-number +\`\`\``, + type: "SKILL", + categorySlug: "devops", + tagSlugs: ["skill", "copilot", "beginner"], + authorId: bob.id + }, + { + title: "Code Review Skill", + description: "An agent skill for performing thorough code reviews", + content: `# Code Review Skill + +This skill performs comprehensive code reviews with actionable feedback. + +## Instructions + +When reviewing code: + +1. **Check correctness** - Verify logic and functionality +2. **Review code style** - Ensure consistency with project standards +3. **Identify security issues** - Look for vulnerabilities +4. **Assess performance** - Find potential bottlenecks +5. **Evaluate maintainability** - Consider future maintenance + +## Review Checklist + +### Functionality +- [ ] Code works as intended +- [ ] Edge cases are handled +- [ ] Error handling is appropriate + +### Code Quality +- [ ] Code is readable and well-organized +- [ ] Functions are focused and not too long +- [ ] No code duplication +- [ ] Variable names are descriptive + +### Security +- [ ] Input validation is present +- [ ] No hardcoded secrets +- [ ] SQL injection prevention +- [ ] XSS prevention + +## Feedback Format + +Provide specific, actionable feedback with: +- Line references +- Suggested improvements +- Code examples when helpful`, + type: "SKILL", + categorySlug: "coding", + tagSlugs: ["skill", "copilot", "advanced"], + authorId: charlie.id + }, ]; for (const promptData of prompts) { @@ -526,7 +737,7 @@ variables: title: promptData.title, description: promptData.description, content: promptData.content, - type: promptData.type as "TEXT" | "IMAGE" | "VIDEO" | "AUDIO" | "STRUCTURED", + type: promptData.type as "TEXT" | "IMAGE" | "VIDEO" | "AUDIO" | "STRUCTURED" | "SKILL", structuredFormat: (promptData as { structuredFormat?: "JSON" | "YAML" }).structuredFormat, authorId: promptData.authorId, categoryId: category?.id, diff --git a/src/app/api/prompts/[id]/raw/route.ts b/src/app/api/prompts/[id]/raw/route.ts index a285e463..c7526298 100644 --- a/src/app/api/prompts/[id]/raw/route.ts +++ b/src/app/api/prompts/[id]/raw/route.ts @@ -2,16 +2,23 @@ import { NextRequest, NextResponse } from "next/server"; import { db } from "@/lib/db"; type OutputFormat = "md" | "yml"; +type FileType = "prompt" | "skill"; /** - * Extracts the prompt ID and format from a URL parameter + * Extracts the prompt ID, format, and file type from a URL parameter * Supports formats: "abc123.prompt.md", "abc123_some-slug.prompt.md", "abc123.prompt.yml" + * Also supports: "abc123.SKILL.md", "abc123_some-slug.SKILL.md" (SKILL only has .md format) */ -function parseIdParam(idParam: string): { id: string; format: OutputFormat } { +function parseIdParam(idParam: string): { id: string; format: OutputFormat; fileType: FileType } { let param = idParam; let format: OutputFormat = "md"; + let fileType: FileType = "prompt"; - if (param.endsWith(".prompt.yml")) { + if (param.endsWith(".SKILL.md")) { + format = "md"; + fileType = "skill"; + param = param.slice(0, -".SKILL.md".length); + } else if (param.endsWith(".prompt.yml")) { format = "yml"; param = param.slice(0, -".prompt.yml".length); } else if (param.endsWith(".prompt.md")) { @@ -25,7 +32,7 @@ function parseIdParam(idParam: string): { id: string; format: OutputFormat } { param = param.substring(0, underscoreIndex); } - return { id: param, format }; + return { id: param, format, fileType }; } /** @@ -50,11 +57,11 @@ export async function GET( { params }: { params: Promise<{ id: string }> } ) { const { id: idParam } = await params; - const { id, format } = parseIdParam(idParam); + const { id, format, fileType } = parseIdParam(idParam); const prompt = await db.prompt.findFirst({ where: { id, deletedAt: null, isPrivate: false, isUnlisted: false }, - select: { title: true, description: true, content: true }, + select: { title: true, description: true, content: true, type: true }, }); if (!prompt) { @@ -64,8 +71,11 @@ export async function GET( let output: string; let contentType: string; + // Use skill format if requested via .SKILL.md URL or if prompt type is SKILL + const isSkill = fileType === "skill" || prompt.type === "SKILL"; + if (format === "yml") { - // Format as structured YAML with messages array + // YAML format (only for regular prompts, not skills) const lines = [ `name: ${prompt.title}`, ]; @@ -83,14 +93,25 @@ export async function GET( output = lines.join("\n"); contentType = "text/yaml; charset=utf-8"; } else { - // Format as markdown with YAML frontmatter - const frontmatter = [ - "---", - `name: ${prompt.title}`, - prompt.description ? `description: ${prompt.description}` : null, - "---", - ].filter(Boolean).join("\n"); - output = `${frontmatter}\n${prompt.content}`; + if (isSkill) { + // Format as SKILL.md (Agent Skills specification) + const frontmatter = [ + "---", + `name: ${prompt.title}`, + prompt.description ? `description: ${prompt.description}` : null, + "---", + ].filter(Boolean).join("\n"); + output = `${frontmatter}\n\n${prompt.content}`; + } else { + // Format as markdown with YAML frontmatter + const frontmatter = [ + "---", + `name: ${prompt.title}`, + prompt.description ? `description: ${prompt.description}` : null, + "---", + ].filter(Boolean).join("\n"); + output = `${frontmatter}\n${prompt.content}`; + } contentType = "text/plain; charset=utf-8"; } diff --git a/src/app/api/prompts/[id]/route.ts b/src/app/api/prompts/[id]/route.ts index 963afc87..a2fd632e 100644 --- a/src/app/api/prompts/[id]/route.ts +++ b/src/app/api/prompts/[id]/route.ts @@ -10,7 +10,7 @@ const updatePromptSchema = z.object({ title: z.string().min(1).max(200).optional(), description: z.string().max(500).optional(), content: z.string().min(1).optional(), - type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO"]).optional(), // Output type only + type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO", "SKILL"]).optional(), // Output type or SKILL structuredFormat: z.enum(["JSON", "YAML"]).optional().nullable(), categoryId: z.string().optional().nullable(), tagIds: z.array(z.string()).optional(), diff --git a/src/app/api/prompts/route.ts b/src/app/api/prompts/route.ts index 98da879c..2d0027ce 100644 --- a/src/app/api/prompts/route.ts +++ b/src/app/api/prompts/route.ts @@ -12,7 +12,7 @@ const promptSchema = z.object({ title: z.string().min(1).max(200), description: z.string().max(500).optional(), content: z.string().min(1), - type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO"]), // Output type only + type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO", "SKILL"]), // Output type or SKILL structuredFormat: z.enum(["JSON", "YAML"]).nullish(), // Input type indicator categoryId: z.string().optional(), tagIds: z.array(z.string()), diff --git a/src/app/prompts/[id]/edit/page.tsx b/src/app/prompts/[id]/edit/page.tsx index c8518889..db779a1d 100644 --- a/src/app/prompts/[id]/edit/page.tsx +++ b/src/app/prompts/[id]/edit/page.tsx @@ -87,7 +87,7 @@ export default async function EditPromptPage({ params }: EditPromptPageProps) { title: prompt.title, description: prompt.description || "", content: prompt.content, - type: ((prompt.type === "IMAGE" || prompt.type === "VIDEO" || prompt.type === "AUDIO") ? prompt.type : "TEXT") as "TEXT" | "IMAGE" | "VIDEO" | "AUDIO", + type: ((prompt.type === "IMAGE" || prompt.type === "VIDEO" || prompt.type === "AUDIO" || prompt.type === "SKILL") ? prompt.type : "TEXT") as "TEXT" | "IMAGE" | "VIDEO" | "AUDIO" | "SKILL", structuredFormat: prompt.structuredFormat ? (prompt.structuredFormat as "JSON" | "YAML") : undefined, categoryId: prompt.categoryId || undefined, tagIds: prompt.tags.map((t) => t.tagId), diff --git a/src/app/prompts/[id]/page.tsx b/src/app/prompts/[id]/page.tsx index b5bf67bf..affa9bfb 100644 --- a/src/app/prompts/[id]/page.tsx +++ b/src/app/prompts/[id]/page.tsx @@ -429,6 +429,7 @@ export default async function PromptPage({ params }: PromptPageProps) { parentCategoryName={prompt.category?.parent?.name} promptId={prompt.id} promptSlug={prompt.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")} + promptType={prompt.type} /> ) : ( )} diff --git a/src/components/prompts/download-prompt-dropdown.tsx b/src/components/prompts/download-prompt-dropdown.tsx index 34135fee..752d4feb 100644 --- a/src/components/prompts/download-prompt-dropdown.tsx +++ b/src/components/prompts/download-prompt-dropdown.tsx @@ -16,21 +16,26 @@ import { toast } from "sonner"; interface DownloadPromptDropdownProps { promptId: string; promptSlug?: string; + promptType?: string; } -export function DownloadPromptDropdown({ promptId, promptSlug }: DownloadPromptDropdownProps) { +export function DownloadPromptDropdown({ promptId, promptSlug, promptType }: DownloadPromptDropdownProps) { const t = useTranslations("prompts"); const [copiedFormat, setCopiedFormat] = useState<"md" | "yml" | null>(null); + + const isSkill = promptType === "SKILL"; const getFileName = (format: "md" | "yml") => { const base = promptSlug ? `${promptId}_${promptSlug}` : promptId; - return `${base}.prompt.${format}`; + const filePrefix = isSkill ? "SKILL" : "prompt"; + return `${base}.${filePrefix}.${format}`; }; const getFileUrl = (format: "md" | "yml") => { if (typeof window === "undefined") return ""; const base = promptSlug ? `${promptId}_${promptSlug}` : promptId; - return `${window.location.origin}/prompts/${base}.prompt.${format}`; + const filePrefix = isSkill ? "SKILL" : "prompt"; + return `${window.location.origin}/prompts/${base}.${filePrefix}.${format}`; }; const handleDownload = async (format: "md" | "yml") => { @@ -68,6 +73,16 @@ export function DownloadPromptDropdown({ promptId, promptSlug }: DownloadPromptD } }; + // For SKILL type, show a simple button instead of dropdown + if (isSkill) { + return ( + + ); + } + return ( diff --git a/src/components/prompts/interactive-prompt-content.tsx b/src/components/prompts/interactive-prompt-content.tsx index a91c5eae..7e30cc6d 100644 --- a/src/components/prompts/interactive-prompt-content.tsx +++ b/src/components/prompts/interactive-prompt-content.tsx @@ -11,6 +11,7 @@ import { RunPromptButton } from "./run-prompt-button"; import { TranslateButton } from "./translate-button"; import { DownloadPromptDropdown } from "./download-prompt-dropdown"; import { CodeView } from "@/components/ui/code-view"; +import { CodeEditor } from "@/components/ui/code-editor"; import { prettifyJson } from "@/lib/format"; interface Variable { @@ -30,6 +31,7 @@ interface InteractivePromptContentProps { parentCategoryName?: string; promptId?: string; promptSlug?: string; + promptType?: string; } // Parse ${variablename:defaultvalue} or ${variablename} patterns @@ -149,7 +151,8 @@ export function InteractivePromptContent({ categoryName, parentCategoryName, promptId, - promptSlug + promptSlug, + promptType }: InteractivePromptContentProps) { const t = useTranslations("common"); const [copied, setCopied] = useState(false); @@ -255,8 +258,46 @@ export function InteractivePromptContent({ setTranslatedContent(translated); }, []); + // Check if this is a SKILL type prompt + const isSkill = promptType === "SKILL"; + // If no variables, render simple content if (variables.length === 0) { + if (isSkill) { + // SKILL type: render with Monaco editor (read-only markdown) + return ( +
+
+
+ {title &&

{title}

} + +
+
+ {promptId && } + +
+
+ {}} + language="markdown" + minHeight="400px" + className="text-sm" + readOnly={true} + /> +
+ ); + } if (isStructured) { return (
@@ -270,7 +311,7 @@ export function InteractivePromptContent({ />
- {promptId && } + {promptId && }
- {promptId && } + {promptId && } )} - {promptId && } + {promptId && } )} - {promptId && } + {promptId && } string) => z.object({ title: z.string().min(1, t("titleRequired")).max(200), description: z.string().max(500).optional(), content: z.string().min(1, t("contentRequired")), - type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO"]), // Output type only + type: z.enum(["TEXT", "IMAGE", "VIDEO", "AUDIO", "SKILL"]), // Output type or SKILL structuredFormat: z.enum(["JSON", "YAML"]).optional(), categoryId: z.string().optional(), tagIds: z.array(z.string()), @@ -301,7 +301,7 @@ export function PromptForm({ categories, tags, initialData, initialContributors title: string; description: string; content: string; - type: "TEXT" | "IMAGE" | "VIDEO" | "AUDIO"; + type: "TEXT" | "IMAGE" | "VIDEO" | "AUDIO" | "SKILL"; structuredFormat?: "JSON" | "YAML"; categoryId?: string; tagIds: string[]; @@ -721,12 +721,17 @@ export function PromptForm({ categories, tags, initialData, initialContributors
{isStructuredInput && ( @@ -810,7 +816,20 @@ export function PromptForm({ categories, tags, initialData, initialContributors render={({ field }) => ( - {isStructuredInput ? ( + {promptType === "SKILL" ? ( +
+ + +
+ ) : isStructuredInput ? (
{/* ===== OUTPUT SECTION ===== */} -
-
-

{t("outputType")}

-

{t("outputTypeDescription")}

-
- - {/* Output Type selector as grouped buttons */} -
- {(["TEXT", "IMAGE", "VIDEO", "AUDIO"] as const).map((type, index) => ( - - ))} + {promptType === "SKILL" ? ( + /* SKILL type shows a code output preview - code generated BY the skill */ +
+
+

{t("outputType")}

+

{t("outputTypeSkillNote")}

+
+ + {/* Code output preview - what the agent generates */} +
+ {/* Editor title bar */} +
+
+
+
+
+
+ generated-code.ts +
+ {/* Code output content */} +
+
// Code generated by skill...
+
export function handler() {'{'}
+
return "...";
+
{'}'}
+
+
+ ) : ( +
+
+

{t("outputType")}

+

{t("outputTypeDescription")}

+
+ + {/* Output Type selector as grouped buttons */} +
+ {(["TEXT", "IMAGE", "VIDEO", "AUDIO"] as const).map((type, index) => ( + + ))} +
- {/* Output Preview based on type */} -
- {promptType === "TEXT" && ( -
- {t("outputPreview.text")} -
- )} - {promptType === "IMAGE" && ( -
-
- - {t("outputPreview.imageUpload")} + {/* Output Preview based on type */} +
+ {promptType === "TEXT" && ( +
+ {t("outputPreview.text")}
- -
- )} - {promptType === "VIDEO" && ( -
-
-
- -
- )} - {promptType === "AUDIO" && ( -
-
- - {t("outputPreview.audio")} -
- {/* Fake audio player bar */} -
- -
-
+ )} + {promptType === "IMAGE" && ( +
+
+ + {t("outputPreview.imageUpload")}
- 0:00 +
-
- )} + )} + {promptType === "VIDEO" && ( +
+
+
+ +
+ )} + {promptType === "AUDIO" && ( +
+
+ + {t("outputPreview.audio")} +
+ {/* Fake audio player bar */} +
+ +
+
+
+ 0:00 +
+
+ )} +
-
+ )}